(六)搭建springboot商城--个人信息(上传头像)

1 上传头像-持久层

1.1 SQL语句的规划

将对应文件保存在操作系统上,然后再把这个文件路劲给记录下来,因为记录路径是非常便捷和方便,将来如果要打开这个文件可以依据这个路径去找到这个文件。在数据库中只需要保存这个文件的路径即可。将所有的静态资源(图片、文件、其他)放到某台电脑上,再将这台电脑作为一台单独的服务器使用。

对应的是一个更新用户avatar字段的SQL语句。

update t_user set avatar=?,modifier_user=?,modified_time=? where uid=?

1.2 设计接口和抽象方法 

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

 /**
     * @Param("SQL映射文件中#{}占位符的变量名"):解决的问题,当SQL语句的占位符
     * 和映射的接口方法参数名不一致时,需要将某个参数强行注入到某个占位符变量上时,
     * 可以使用@Param这个注解来标注映射的关系
     * 根据用户uid值来修改用户的头像
     * @param uid
     * @param avatar
     * @param modifiedUser
     * @param modifiedTime
     * @return
     */

    Integer updateAvatarByUid(@Param("uid") Integer uid,
                              @Param("avatar")String avatar,
                              @Param("modifiedUser")String modifiedUser,
                              @Param("modifiedTime")Date modifiedTime);

1.3  接口的映射

UserMapper.xml文件中编写映射的SQL语句。

 <update id="updateAvatarByUid">
        update t_user
        set
            avatar=#{avatar},
            modified_user=#{modifiedUser},
            modified_time=#{modifiedTime}
        where
            uid=#{uid}
    </update>

在测试类中编写测试的方法。

@Test
    public void updateAvatarByUid(){
        userMapper.updateAvatarByUid(9,"upload/avatar.png","管理有",new Date());
    }

2 上传头像-业务层

2.1 规划异常

1.用户数据不存在,找不到对应的用户数据

2.更新时候,各种未知异常产生。

无需重复开发

2.2 设计接口和抽象方法

 /**
     * 修改用户的头像
     * @param uid 用户的id
     * @param avatar 用户头像的路径
     * @param username 用户的名称
     */
     void changeAvatar(Integer uid,
             String avatar,
             String username
     );

2.3 实现抽象方法 

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

public void changeAvatar(Integer uid, String avatar, String username) {
        //查询当前的用户数据是否存在
        User result = userMapper.findByUid(uid);
        if(result==null||result.getIsDelete()==1){
            throw new UsernameNotFoundException("用户没有被找到");
        }
        Integer rows = userMapper.updateAvatarByUid(uid, avatar, username, new Date());
        if(rows !=1){
            throw new UpdateException("更新数据异常");
        }
    }

 测试业务层方法执行。

 @Test
    public void changeAvatar(){
        userService.changeAvatar(9,"/adada","DB");
    }

3上传头像-控制层

3.1 规划异常

文件异常的父类:

        FileUploadException 泛指文件上传的异常(父类)继承 RunTimeException

父类是:FileUploadException

FileEmptyException 文件为空的异常

FileSizeException 文件大小超出限制

FileTypeException 文件类型异常

FileUploadIoException 文件读写的异常

FileStateException 文件状态异常

五个构造方法显示的声明出来,去继承相关的父类。 

3.2 处理异常

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

else if (e instanceof FileEmptyException) {
            result.setState(6000);
            result.setMessage("文件为空的异常");
        }else if (e instanceof FileSizeException) {
            result.setState(6001);
            result.setMessage("文件大小的异常");
        }else if (e instanceof FileTypeException){
            result.setState(6002);
            result.setMessage("文件类型的异常");
        }else if (e instanceof FileStateException) {
            result.setState(6003);
            result.setMessage("文件状态的异常");
        }else if (e instanceof FileUploadIoException) {
            result.setState(6004);
            result.setMessage("文件读写的异常");
        }

在异常统一处理方法的参数列表上增加新的异常处理作为它的参数

@ExceptionHandler({ServiceException.class,FileUploadException.class})

3.3 设计请求

/users/change_avatar

POST(get提交数据为2Kb)

HttpSession session, MutipartFile file

JsonResult<String>

3.4 实现请求 

 /** 设置上传文件的最大值***/
    public static final  int AVATAR_MAX_SIZE= 10*1024*1024;
    /** 限制上传文件的类型**/
    public static final List<String> AVATAR_TYPE=new ArrayList<>();
    static {
        AVATAR_TYPE.add("images/jpeg");
        AVATAR_TYPE.add("images/png");
        AVATAR_TYPE.add("images/bmp");
        AVATAR_TYPE.add("images/gif");
    }
    /**
     * MultiPartFile 接口是SpringMVC提供的一个接口,这个接口为我们包装了
     * 获取文件类型的数据(任何类型的file都可以接收),SpringBoot整合了
     * SpringMvc,只需要在处理请求的方法参数列表上声明一个参数类型为
     * MultiPartFile的参数,然后SpringBoot会自动的将文件中的数据传递给服务的
     * 文件数据赋值给这个参数
     * @RequestParam 表示请求中的参数,将请求中的参数注入请求处理方法的某个参数上
     * 如果名称不一致,则可以使用@RequestParam注解进行标记和映射。
     * @param session
     * @param file
     * @return
     */
    @RequestMapping("change_avatar")
    public JsonResult<String> changeAvatar(
            HttpSession session,
            @RequestParam("file") MultipartFile 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
        String parent = session.getServletContext().getRealPath("upload");
        //File对象指向这个路径,file是否存在
        File dir = new File(parent);
        if(!dir.exists()){ //检测目录是否存在
            dir.mkdirs();//创建当前目录
        }
        // 获取到这个文件名称,UUID工具来生成一个新的字符串作为文件名
        String originalFilename = file.getOriginalFilename();
        System.out.println("originalFilename"+originalFilename);
        int index = originalFilename.lastIndexOf(".");
        String suffix = originalFilename.substring(index);
        String filename = UUID.randomUUID().toString().toUpperCase()+suffix;
        File dest =new File(dir,filename); //是一个空文件
        // 参数file中数据写入到这个空文件中
        try {
            file.transferTo(dest); //将file文件中数据写入到dest文件中,后缀需要一致
        } catch (FileStateException e){
            throw new FileStateException("文件状态异常");
        }
        catch (IOException e) {
            throw new FileUploadIoException("文件读写异常");
        }
        Integer uid = getUidFromSession(session);
        String username=getUsernameFromSession(session);
        //返回头像的路径 /upload/test.png
        String avatar="/upload/"+filename;
        userService.changeAvatar(uid,avatar,username);
        //返回用户头像的路径给前端页面,将来用于头像展示使用
        return new JsonResult<>(OK,avatar);
    }

4 上传头像-前端页面

在upload页面中编写上传头像的代码。

说明:如果直接使用表单进行文件的上传,需要给表单显示的添加一个属性enctype=”multipart/form-data“声明出来,不会将目标文件的数据结构做修改再上传,不同字符串。

5.解决Bug

5.1更改默认的大小限制

SpringMVC默认为1MB文件可以上传,手动去修改SpringMVC默认上传文件的大小。

方式1:直接在配置文件中进行配置。

spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=15MB

方式2:需要采用Java代码的形式来设置文件的上传大小限制。在主类进行配置,可以定义一个方法,必须使用@Bean修饰来修饰。在类的前面添加@Configuration注解进行修改。MutipartConfigElement类型。

@Bean
    public MultipartConfigElement getMultipartConfigElement(){
        //创建一个配置的工厂类对象
        MultipartConfigFactory factory=new MultipartConfigFactory();
        // 设置需要创建的对象的相关信息。
        factory.setMaxFileSize(DataSize.of(10, DataUnit.MEGABYTES));
        factory.setMaxRequestSize(DataSize.of(15,DataUnit.MEGABYTES));


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

5.2 显示头像

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

·serialize():可以将表单数据自动拼接成key=value的结构进行提交给服务器,一般提交是普通的控件类型中的数据(text\password\radio\checkbox)等等

·FormData类:将表单中数据保持原有的结构进行数据的提交。

        new FormData("#form")[0]; //文件类型的数据可以使用FormData对象进行存储

·ajax默认处理数据时按照字符串的形式进行处理,以及默认会采用字符串的形式进行提交数据,关闭这两个默认的功能。

processData:false,//处理数据的形式,关闭处理数据
contentType:false,//表示提交数据的形式,关闭默认提交数据的形式

5.3 登陆后显示头像

可以在更新头像成功后,将服务器返回的头像路径保存在客户端cookie中,然后每次检测到用户打开上传头像页面。在这个页面中通过ready()方法来自动检测去读取cookie中头像并设到src属性上。

1.设置cookie中的值:

导入cookie.js文件

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

调用cookie方法:

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

2.在upload.html页面先引入cookie.js文件

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

3.在upload.html页面通过ready()自动读取cookie中的数据。

$(document).ready(function () {
				let avatar=$.cookie("avatar")
				console.log(avatar);
				//将cookie中的值获取出来设置到头像的src属性上
				$("#img-avatar").attr(avatar)
			})

5.4 显示最新头像

在更改完头像后,将最新的头像地址,再次保存到cookie中,同名保存会覆盖有cookie中值。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值