【五一创作】基于springboot框架的电脑商城项目(三)

这篇具有很好参考价值的文章主要介绍了【五一创作】基于springboot框架的电脑商城项目(三)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

个人资料

(一)个人资料(持久层)

1.规划sql

根据用户id修改信息的SQL语句

update t_user set python=?,email=?,gender=?,modified_user=?,modified_time=? where uid=?

根据用户id查询的sql语句

select * from t_user where uid=?
2.接口与抽象方法

更新用户的信息方法的定义

   //根据id修改
    Integer updateInfoByUid(User user);

在UserMapper.xml文件中进行映射编写

<update id="updateInfoByUid" >
        update t_user set
         <!--if是条件判断标签,属性test接受的是一个返回值为boolean类型的条件,
            如果test条件的结果为true则执行if标签内部的语句,注意逗号也要在标签内-->
        <if test="phone!=null">phone=#{phone},</if>
        <if test="email!=null"> email=#{email},</if>
        <if test="gender!=null">gender=#{gender},</if>
                          modified_user=#{modifiedUser},
                          modified_time=#{modifiedTime}
                  where
                        uid=#{uid}
    </update>

(二)个人资料(业务层)

设计两个功能:
1.当打开页面时显示当前登录的用户的信息
2.点击修改按钮时更新用户的信息

1.异常规划

点击个人资料页面时可能找不到用户的数据
点击修改按钮时可能找不到用户数据,也可能修改时出现未知错误

2.设计接口和抽象方法及实现

业务层有两个功能模块,对应的是两个抽象方法的设计,并且这两个功能都涉及到用户是否存在的查询操作,所以需要在业务层设计根据用户uid查询数据的方法(持久层已经设计过该方法,但是没有在业务层实现该方法的调用)

 //修改个人资料  uid通过控制层在session中获取然后传递给业务层,并在业务层封装到User对象中
    void changeInfo(Integer uid,String username,User user);
    //根据id查询 
    User getByUid(Integer uid);

在实现类中实现当前的抽象方法

    @Override
    public void changeInfo(Integer uid, String username, User user) {
        //查询用户是否存在
       User user1=userMapper.findUid(uid);
if (user1==null || user1.getIsDelete()==1){
    throw new UsernameNotFoundException("用户不存在");
}
//User对象中的数据只有phone,email,gender,username,因为springboot进行依赖
    //注入的时候只注入表单中数据的值,所以需要手动将uid封装到user中
user.setUid(uid);
user.setUsername(username);
user.setModifiedUser(username);
user.setModifiedTime(new Date());
  Integer rows= userMapper.updateInfoByUid(user);
        if (rows!=1){
            throw new UpdateException("修改时出现未知异常");
        }


    }

    @Override
    public User getByUid(Integer uid) {
        User user1=userMapper.findUid(uid);
        if (user1==null || user1.getIsDelete()==1){
            throw new UsernameNotFoundException("用户不存在");
        }
        User user=new User();
        user.setUsername(user1.getUsername());
        // user.setModifiedUser(user1.getModifiedUser());
        // user.setModifiedTime( user1.getModifiedTime());
       user.setEmail( user1.getEmail());
       user.setPhone(user1.getPhone());
       user.setGender(user1.getGender());
        return user;
    }

(三)个人资料(控制层)

1.设计请求

1.设计一打开页面就发送当前用户数据的查询:

请求路径: /users/get_by_uid
请求方式:GET
请求参数:HttpSession session(用于获取uid)
响应结果:JsonResult< User>

2.点击修改按钮发送用户的数据修改操作

请求路径:users/change_info
请求方式:POST
请求参数:User user,HttpSession session(用于获取uid)
响应结果:JsonResult< Void>

2.处理请求
@GetMapping("/get_by_uid")
    public JsonResult<User> getbyUid(HttpSession session){
      User user=userService.getByUid(getuidfromsession(session));
        return new JsonResult<>(ok,user);
}
@PostMapping("/change_info")
    public JsonResult<Void> changeinfo(User user,HttpSession session){
    Integer getuidfromsession = getuidfromsession(session);
    String getusernamesession = getusernamesession(session);
    userService.changeInfo(getuidfromsession,getusernamesession,user);
    return new JsonResult<>(ok);
}

(四)个人资料(前端页面)

在打开userdata.html(个人资料)页面自动发送ajax请求(get_by_uid),查询到的数据填充到这个页面

$(document).ready(function () {
				$.ajax({
					url:"/users/get_by_uid",
					type:"GET",
					data:$("#form-change-info").serialize(),
					dataType:"JSON",
					//2.发送ajax()的异步请求来完成用户的注册功能
					success:function (json) {
						if (json.state==200){
                    $("#username").val(json.data.username);
                    $("#phone").val(json.data.phone);
                    $("#email").val(json.data.email);
                    var radio=json.data.gender==0 ?
							$("#gender-female") : $("#gender-male");
                    //prop()表示给某个元素添加属性及属性值
							radio.prop("checked","checked");
						}else{
							alert("用户数据不存在");
						}
					},
					error:function (xhr) {
						alert("查询用户信息产生未知异常"+xhr.message);
					}
				});

			});

在检测到用户点击了修改按钮后发送一个ajax请求(change_info)
(该ajax函数需要和上一个ajax同级)

//1.监听按钮是否被点击
			$("#btn-change-info").click(function () {
				$.ajax({
					url:"/users/change_info",
					type:"POST",
					data:$("#form-change-info").serialize(),
					dataType:"JSON",
					//2.发送ajax()的异步请求来完成用户的注册功能
					success:function (json) {
						if (json.state==200){
							alert("修改成功");
							//跳转系统主页index。html
							//相对路径
							location.href="userdata.html";
						}else{
							alert("修改失败失败");
						}
					},
					error:function (xhr) {
						alert("修改产生未知异常"+xhr.message);
					}
				});

			});

上传头像

(一)上传头像(持久层)

1.规划sql
update t_user set avatar=?,modified_user=?,modified_time=? where uid=?
2.接口设计和实现方法

在UserMapper接口中定义一个抽象方法用于修改用户的头像

 //修改用户头像
    Integer updateAvatarByUid(@Param("uid") Integer uid,
                              @Param("avatar") String avatar,
                              @Param("modifiedUser") String modifiedUser,
                              @Param("modifiedTime") Date modifiedTime);

在UserMapper.xml文件中进行映射编写

<!--    上传头像-->
    <update id="updateAvatarByUid">
        update t_user set
            avatar=#{avatar},
            modified_user=#{modifiedUser},
            modified_time=#{modifiedTime}
          where
            uid=#{uid}
    </update>

(二)上传头像(业务层)

1.规划异常

用户数据不存在,找不到对应的用户数据
更新的时候,出现未知异常
(前面已经写过)

2.设计接口和抽象方法及实现

uid,avatar,modifiedUser,modifiedTime,其中modifiedTime是在方法中创建的,uid和modifiedUser从session中获取,但是session对象是在控制层的并不会出现在业务层,所以业务层要保留这两个参数,以便控制层可以传递过来

    //修改头像
    void changeAvatar(Integer uid,String avatar,String username);

编写业务层的更新用户头像的方法

//修改头像
    @Override
    public void changeAvatar(Integer uid, String avatar, String username) {
        User user1 = userMapper.findUid(uid);
        if (user1==null || user1.getIsDelete()==1){
            throw new UsernameNotFoundException("用户不存在");
        }
   Integer rows= userMapper.updateAvatarByUid(user1.getUid(),avatar,username,new Date());

        if (rows!=1){
            throw new UpdateException("上传时出现未知异常");
        }

    }

(三)上传头像(控制层)

1.规划异常

上传文件时的异常都是文件异常,所以可以先创建一个文件异常类的基类FileUploadException并使其继承RuntimeException

FileEmptyException:文件为空的异常(没有选择上传的文件就提交了表单,或选择的文件是0字节的空文件)
FileSizeException:文件大小超出限制
FileTypeException:文件类型异常(上传的文件类型超出了限制)
FileUploadIOException:文件读写异常
FileStateException:文件状态异常(上穿文件时该文件正在打开状态)
2.处理异常

在基类BaseController中进行编写和统一处理

else if (e instanceof FileEmptyException){
            result.setState(6000);
        }else if (e instanceof FileSizeException) {
            result.setState(6001);
        } else if (e instanceof FileTypeException) {
            result.setState(6002);
        } else if (e instanceof FileStateException) {
            result.setState(6003);
        } else if (e instanceof FileUploadIOException) {
            result.setState(6004);
        }

异常统一处理方法的修饰符@ExceptionHandler(ServiceException.class)表明我们现在创建的FileUploadException异常类不会被拦截到该方法中,点进@ExceptionHandler注解可以发现传参可以传数组类型,所以可以将异常统一处理方法上的注解改为:
@ExceptionHandler({ServiceException.class,FileUploadException.class})

3.设计请求

请求路径:/users/change_avatar
请求方式:POST(GET请求提交数据只有2KB左右)
请求参数:HttpSession session(获取uid和username),MultipartFile file
响应结果:JsonResult< String>(不能是JsonResult< Void>)

4.处理请求
 @RequestMapping("change_avatar")
    public JsonResult<String> changeAvatar(HttpSession session,
                                           MultipartFile file) {
        /**
         * 1.参数名为什么必须用file:在upload.html页面的147行<input type=
         * "file" name="file">中的name="file",所以必须有一个方法的参数名
         * 为file用于接收前端传递的该文件.如果想要参数名和前端的name不一
         * 样:@RequestParam("file")MultipartFile ffff:把表单中name=
         * "file"的控件值传递到变量ffff上
         * 2.参数类型为什么必须是MultipartFile:这是springmvc中封装的一个
         * 包装接口,如果类型是MultipartFile并且参数名和前端上传文件的name
         * 相同,则会自动把整体的数据包传递给file
         */
        //判断文件是否为null
        if (file.isEmpty()) {
            throw new FileEmptyException("文件为空");
        }
        if (file.getSize()>AVATAR_MAX_SIZE) {
            throw new FileSizeException("文件超出限制");
        }
        //判断文件的类型是否是我们规定的后缀类型
        String contentType = file.getContentType();
        //如果集合包含某个元素则返回值为true
        if (!AVATAR_TYPE.contains(contentType)) {
            throw new FileTypeException("文件类型不支持");
        }

        //上传的文件路径:.../upload/文件名.png
        /**
         * session.getServletContext()获取当前Web应用程序的上下文
         * 对象(每次启动tomcat都会创建一个新的上下文对象)
         * getRealPath("/upload")的/代表当前web应用程序的根目录,通过该相
         * 对路径获取绝对路径,返回一个路径字符串,如果不能进行映射返回null,单
         * 斜杠可要可不要
         */
        String parent =
                session.getServletContext().getRealPath("/upload");
        System.out.println(parent);//调试用

        //File对象指向这个路径,通过判断File是否存在得到该路径是否存在
        File dir = new File(parent);
        if (!dir.exists()) {//检测目录是否存在
            dir.mkdirs();//创建当前目录
        }

        //获取这个文件名称(文件名+后缀,如avatar01.png,不包含父目录结构)用UUID
        // 工具生成一个新的字符串作为文件名(好处:避免了因文件名重复发生的覆盖)
        String originalFilename = file.getOriginalFilename();
        System.out.println("OriginalFilename="+originalFilename);
        int index = originalFilename.lastIndexOf(".");
        String suffix = originalFilename.substring(index);
        //filename形如SAFS1-56JHIOHI-HIUGHUI-5565TYRF.png
        String filename =
                UUID.randomUUID().toString().toUpperCase()+suffix;

        //在dir目录下创建filename文件(此时是空文件)
        File dest = new File(dir, filename);

        //java可以把一个文件的数据直接写到同类型的文件中,这里将参数file中的数据写入到空文件dest中
        try {
            file.transferTo(dest);//transferTo是一个封装的方法,用来将file文件中的数据写入到dest文件

            /**
             * 先捕获FileStateException再捕获IOException是
             * 因为后者包含前者,如果先捕获IOException那么
             * FileStateException就永远不可能会被捕获
             */
        } catch (FileStateException e) {
            throw new FileStateException("文件状态异常");
        } catch (IOException e) {
            //这里不用打印e,而是用自己写的FileUploadIOException类并
            // 抛出文件读写异常
            throw new FileUploadIOException("文件读写异常");
        }

        Integer uid = getUidFromSession(session);
        String username = getUsernameFromSession(session);
        String avatar = "/upload/"+filename;
        userService.changeAvatar(uid,avatar,username);
        //返回用户头像的路径给前端页面,将来用于头像展示使用
        return new JsonResult<>(OK,avatar);
    }

(四)上传头像(前端页面)

1.前端页面代码

在upload.html的上传头像的表单加上三个属性:
action=“/users/change_avatar”
method=“post”(get请求提交数据只有2KB左右)
enctype=“multipart/form-data”(如果直接使用表单进行文件的上传,需要给表单加该属性,这样不会将目标文件的数据结构做修改后再上传,这不同于字符串,字符串随意切割修改也能拼在一起,但文件不行)

2.前端页面优化

springmvc默认为1MB文件可以进行上传,如果超过则会报代码错误,自己在控制层设置的public static final int AVATAR_MAX_SIZE = 1010241024;需要在不超过原有大小的情况下才会起作用,所以要手动修改springmvc默认上传文件的大小

方式1:直接在配置文件application.properties中进行配置:

spring.servlet.multipart.max-file-size=10MB(表示上传的文件最大是多大)
spring.servlet.multipart.max-request-size=15MB(整个文件是放在了request中发送给服务器的,请求当中还会有消息头等其他携带的信息,这里设置请求最大为15MB)

方式2:采用java代码的形式来设置文件的上传大小的限制:

1.该代码必须在主类中进行配置,因为主类是最早加载的,而配置文件必须是最早加载的
2.在主类中定义一个方法,方法名无所谓,但方法需要用@bean修饰,表示该方法返回值是一个bean对象,并且该bean对象被bean修饰,也就是这个方法返回了一个对象,然后把该对象交给bean管理,类似spring中的bean标签,含义是一样的,只是这里改为了注解
3.用@Configuration修饰主类使@bean注解生效,但其实@SpringBootApplication是@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan三个注解的合并,所以可以不需要@Configuration
4.方法返回值是MultipartConfigElement类型,表示所要配置的目标的元素

@Bean
public MultipartConfigElement getMultipartConfigElement() {
    //1.创建一个配置的工厂类对象
    MultipartConfigFactory factory = new MultipartConfigFactory();

    //2.设置需要创建的对象的相关信息
    factory.setMaxFileSize(DataSize.of(10, DataUnit.MEGABYTES));
    factory.setMaxRequestSize(DataSize.of(15,DataUnit.MEGABYTES));

    //3.通过工厂类创建MultipartConfigElement对象
    return factory.createMultipartConfig();
}

3.头像回显

在页面中通过ajax请求来提交文件,提交完成后返回了json串,解析出json串中的data数据设置到img标签的src属性上

1.删掉在upload.html的上传头像的表单中加的三个属性:action=“/users/change_avatar”,method=“post”,enctype=“multipart/form-data”.加上id属性:id=“form-change-avatar”

2.把153行的input标签里面的type="submit"改为type=“button”(因为submit按钮不能添加事件,所以要改为普通的按钮)并加上属性id=“btn-change-avatar”

1.serialize():可以将表单数据自动拼接成key=value的结构提交给服务器,一般提交的是普通的控件类型中的数据(type=text/password/radio/checkbox等等)
2.FormData类:将表单中数据保持原有的结构进行数据提交.文件类型的数据可以使用FormData对象进行存储
使用方法:new FormData($(“form”)[0]);
这行代码的含义是将id="form"的表单的第一个元素的整体值作为创建FormData对象的数据
3.虽然我们把文件的数据保护下来了,但是ajax默认处理数据时按照字符串的形式进行处理,以及默认会采用字符串的形式进行数据提交.手动关闭这两个功能:
processData: false,//处理数据的形式,关闭处理数据
contentType: false,//提交数据的形式,关闭默认提交数据的形式

提交表单的代码

        <script>
            $("#btn-change-avatar").click(function () {
                $.ajax({
                    url: "/users/change_avatar",
                    type: "POST",
                    data: new FormData($("#form-change-avatar")[0]),
                    processData: false,//处理数据的形式,关闭处理数据
                    contentType: false,//提交数据的形式,关闭默认提交数据的形式
                    dataType: "JSON",
                    success: function (json) {
                        if (json.state == 200) {
                            alert("头像修改成功")
                            //将服务器端返回的头像地址设置到img标签的src属性上
                            //attr(属性,属性值)用来给某个属性设值
                            $("#img-avatar").attr("src",json.data);
                        } else {
                            alert("头像修改失败")
                        }
                    },
                    error: function (xhr) {
                        alert("修改头像时产生未知的异常!"+xhr.message);
                    }
                });
            });
        </script>

4.登录后显示头像

将头像上传后会显示头像,但是关闭浏览器后再进入个人头像页面就不会显示头像了,因为只有点击"上传"才能发送ajax请求并显示头像.

可以在每次用户登录成功后将avatar保存在cookie中,登录的业务层返回给控制层user对象,该对象包含uid,username,avatar.所以要在登录页面login.html中将服务器返回的头像路径设置到cookie中,然后每次检测到用户打开上传头像页面,在这个页面中通过ready()方法来自动读取cookie中头像路径并设到src属性上。

1.需要在login.html页面头部导入cookie.js文件

<script src="../bootstrap3/js/jquery.cookie.js" type="text/javascript" charset="utf-8"></script>

2.调用cookie方法保存路径

$.cookie(key,value,time);//time单位:天

在ajax请求原有的代码上加$.cookie(“avatar”,json.data.avatar,{expires: 7});

success: function (json) {
    if (json.state == 200) {
        location.href = "index.html";
        $.cookie("avatar",json.data.avatar,{expires: 7});
    } else {
        alert("登录失败")
    }
},

3.需要在upload.html获取cookie中的值,所以要在页面头部导入cookie.js文件

<script src="../bootstrap3/js/jquery.cookie.js" type="text/javascript" charset="utf-8"></script>

4.在upload.html的script标签中加ready()自动读取cookie数据

$(document).ready(function(){
    var avatar = $.cookie("avatar");
    console.log(avatar);//调试用
    $("#img-avatar").attr("src",avatar);
})

5.显示最新头像

上传头像后不重新登录而是浏览其他页面,然后再进入个人头像页面时展示的头像是上次上传的,因为此时cookie中的值是上次上传的头像的路径,所以需要上传头像后使用同名覆盖更改cookie中路径

在ajax函数的success属性值的if语句加:

$.cookie("avatar",json.data,{expires: 7});

后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹
文章来源地址https://www.toymoban.com/news/detail-439924.html

到了这里,关于【五一创作】基于springboot框架的电脑商城项目(三)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于springboot框架的电脑商城项目(四)

    🎁🎁静态资源及sql文件分享 链接:https://pan.baidu.com/s/1X-yjmQcPD3PqS21x0HplNA?pwd=23gr 提取码:23gr 在store数据库中创建t_address表 在entity包下创建实体类Address继承baseEntity类 1.规划sql 1.新增收货地址对应的是插入语句: 2.大部分平台都会规定一个用户的收货地址数量,这里规定最多20个

    2024年02月03日
    浏览(42)
  • 基于springboot框架的电脑商城项目(十)

    🎁🎁静态资源及sql文件分享 链接:https://pan.baidu.com/s/1X-yjmQcPD3PqS21x0HplNA?pwd=23gr 提取码:23gr 在store数据库中创建t_order和t_order_item数据表 在entity包下创建Order实体类并继承BaseEntity类 在com.cy.store.entity包下创建OrderItem实体类并继承BaseEntity类 1.规划sql 插入订单数据的SQL语句 插入

    2024年02月06日
    浏览(39)
  • 基于springboot框架的电脑商城项目(八)

    🎁🎁静态资源及sql文件分享 链接:https://pan.baidu.com/s/1X-yjmQcPD3PqS21x0HplNA?pwd=23gr 提取码:23gr 1.规划sql 这里需要将商品表和购物车表进行连表查询 2.设计接口和抽象方法 在store包下创建一个vo包,在该包下面创建CartVO类,不需要继承BaseController类,那相应的就需要单独实现Serializa

    2024年02月05日
    浏览(44)
  • 基于springboot框架的电脑商城项目(五)

    🎁🎁静态资源及sql文件分享 链接:https://pan.baidu.com/s/1X-yjmQcPD3PqS21x0HplNA?pwd=23gr 提取码:23gr 1.规划需要执行的SQL语句 其中order by is_default DESC是为了让默认收货地址展示在最上面,order by可以有多个子句,中间用逗号隔开,后面加的create_time DESC是为了让非默认收货地址创建的越晚

    2024年02月03日
    浏览(41)
  • Springboot+mysql+基于VUE框架的商城综合项目设计与实现 毕业设计-附源码111612

    基于VUE框架的商城综合项目设计与实现 随着科学技术的飞速发展,社会的方方面面、各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,商城综合项目当然也不能排除在外。商城综合项目是以实际运用为开发背景,运用软件工程原理和开发方法,采用

    2024年02月01日
    浏览(65)
  • SpringBoot项目--电脑商城【上传头像】

    把文件存到数据库中,需要图片时访问数据库,数据库将文件解析为字节流返回,最后写到本地的某一个文件.这种方法太耗费资源和时间了 将对应的文件保存在操作系统上,然后再把这个 文件路径记录下 来,因为在记录路径的时候是非常便捷和方便的,将来如果要打开这个文件可以

    2024年02月09日
    浏览(40)
  • SpringBoot项目--电脑商城【确认订单】

    用户在购物车列表页中通过随机勾选相关的商品,在点击\\\"结算\\\"按钮后跳转到\\\"确认订单页\\\",在这个页面中需要展示用户在上个页面所勾选的\\\"购物车列表页\\\"中对应的数据.说白了也就是列表展示,且展示的内容还是来自于购物车表.但是用户勾选了哪些商品呢,所 以\\\"购物车列表页\\\"需

    2024年02月09日
    浏览(40)
  • SpringBoot项目--电脑商城【新增收货地址】

    t_address 注意name是,所以需要用`` 在entity包下创建实体类Address继承BaseEntity类 当前收货地址功能模块: 第一个页面:列表的展示,修改,删除,设置默认 第二个页面:新增收货地址 开发顺序:新增收货地址-列表的展示-设置默认收货地址-删除收货地址-修改收货地址 1.新增收货地

    2024年02月09日
    浏览(46)
  • 【五一创作】MysqlFirst项目过程中遇到的困难

    解决办法:实体类字段属性不要使用基本数据类型(比如int ,long等),要使用Long,Integer等包装类 修改后就没报此错误了。 解决方法:使用input中的type为hidden 写到点击菜系跳转servlet这里 如何做批处理 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    2024年02月02日
    浏览(35)
  • 【五一创作】Python项目怎么部署到spring

    首先,需要确保Python项目已经编写完成并且可运行。然后,可以使用以下步骤将Python项目部署到Spring中: 1. 安装Jython:Jython是一个Java平台上的Python解释器。在Spring中使用Jython可以使Python代码能够与Java代码无缝集成。可以从Jython官方网站下载并安装Jython。 2. 将Python代码转换为

    2024年02月04日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包