九点钟☆方向

记录成长点滴

欢迎来到我的个人博客~


SpringMVC笔记(四) SpringMVC文件上传及异常处理

目录

文件上传的回顾

文件上传的必要前提

  1. form 表单的 enctype 取值必须是:multipart/form-data(默认值是:application/x-www-form-urlencoded)

    enctype:是表单请求正文的类型

  2. method 属性取值必须是 Post

  3. 提供一个文件选择域 input type=”file”

文件上传的原理分析

当 form 表单的 enctype 取值不是默认值后, request.getParameter()将失效。
enctype=”application/x-www-form-urlencoded”时,form 表单的正文内容是:key=value&key=value&key=value
当 form 表单的 enctype 取值为 Mutilpart/form-data 时,请求正文内容就变成:
每一部分都是 MIME 类型描述的正文
-----------------------------7de1a433602ac 分界符
Content-Disposition: form-data; name="userName" 协议头
aaa 协议的正文
-----------------------------7de1a433602ac
Content-Disposition: form-data; name="file";
filename="C:\Users\zhy\Desktop\fileupload_demofile\b.txt"
Content-Type: text/plain 协议的类型( MIME 类型)
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-----------------------------7de1a433602ac--

借助第三方组件实现文件上传

使用 Commons-fileupload 组件实现文件上传,需要导入该组件相应的支撑 jar 包: Commons-fileupload 和 commons-io。 commons-io 不属于文件上传组件的开发 jar 文件,但Commons-fileupload 组件从 1.1 版本开始,它工作时需要 commons-io 包的支持。

springmvc文件上传

引入依赖

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

上传页面

<form action="/fileUpload" method="post" enctype="multipart/form-data">
    名称: <input type="text" name="picname"/><br/>
    图片: <input type="file" name="uploadFile"/><br/>
    <input type="submit" value="上传"/>
</form>

控制器

@Controller
public class FileUploadController {
    /**
    * 文件上传
    */
    @RequestMapping("/fileUpload")
    //MultipartFile类型的形参名要和上传页面中file的name保持一致
    public String testResponseJson(String picname,MultipartFile uploadFile,
                                   HttpServletRequest request) throws Exception{
        //定义文件名
        String fileName = "";
        //1.获取原始文件名
        String uploadFileName = uploadFile.getOriginalFilename();
        //2.截取文件扩展名
        String extendName = uploadFileName.substring(uploadFileName.lastIndexOf(".")+1,
                                                     uploadFileName.length());
        //3.把文件加上随机数,防止文件重复
        String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
        //4.判断是否输入了文件名
        if(!StringUtils.isEmpty(picname)) {
            fileName = uuid+"_"+picname+"."+extendName;
        }else {
        	fileName = uuid+"_"+uploadFileName;
        }
        System.out.println(fileName);
        //2.获取文件路径
        ServletContext context = request.getServletContext();
        String basePath = context.getRealPath("/uploads");
        //3.解决同一文件夹中文件过多问题
        String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        //4.判断路径是否存在
        File file = new File(basePath+"/"+datePath);
        if(!file.exists()) {
        	file.mkdirs();
        }
        //5.使用 MulitpartFile 接口中方法,把上传的文件写到指定位置
        uploadFile.transferTo(new File(file,fileName));
        return "success";
    }
}

配置文件解析器

<!-- 配置文件上传解析器  id值是固定的-->
<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置上传文件的最大尺寸为 5MB -->
    <property name="maxUploadSize">
    	<value>5242880</value>
    </property>
</bean>
注意:
文件上传的解析器 id 是固定的,不能起别的名称,否则无法实现请求参数的绑定。(不光是文件,其他字段也将无法绑定)

SpringMVC 中的异常处理 (基于xml方式)

异常处理的思路

系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。 系统的 dao、 service、 controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端控制器交由异常处理器进行异常处理,如下图:

4

实现步骤

自定义异常类

要继承Exception

public class CustomException extends Exception {
    private String message;//生成set/get 
    public CustomException(String message) {
        this.message = message;
    }
}

自定义异常处理器

要实现HandlerExceptionResolver接口

public class CustomExceptionResolver implements HandlerExceptionResolver {
    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response, 
                                         Object handler, Exception ex) {
        ex.printStackTrace();
        CustomException customException = null;
        //如果抛出的是系统自定义异常则直接转换
        if(ex instanceof CustomException){
            customException = (CustomException)ex;
        }else{
            //如果抛出的不是系统自定义异常则重新构造一个系统错误异常。
            customException = new CustomException("系统错误,请与系统管理 员联系! ");
        }
        ModelAndView modelAndView = new ModelAndView();
        //存入异常信息
        modelAndView.addObject("message", customException.getMessage());
        //设置错误页面
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

配置异常处理器

<!-- 配置自定义异常处理器 -->
<bean id="handlerExceptionResolver" class="com.mg.exception.CustomExceptionResolver"/>

错误页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>执行失败</title>
    </head>
    <body>
        执行失败!
        ${message }
    </body>
</html>

SpringMVC 中的异常处理 (基于注解方式)

自定义异常类(同XML方式)

要继承Exception

public class CustomException extends Exception {
    private String message;//生成set/get 
    public CustomException(String message) {
        this.message = message;
    }
}

定义全局异常处理类

@ControllerAdvice
public class CustomExceptionResolver implements HandlerExceptionResolver {
    @ExceptionHandler(value = CustomException.class)//定义异常处理方法
    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response,
                                         Object handler, Exception ex) {
        ex.printStackTrace();
        CustomException customException = null;
        //如果抛出的是系统自定义异常则直接转换
        if(ex instanceof CustomException){
            customException = (CustomException)ex;
        }else{
            //如果抛出的不是系统自定义异常则重新构造一个系统错误异常。
            customException = new CustomException("系统错误,请与系统管理 员联系! ");
        }
        ModelAndView modelAndView = new ModelAndView();
        //存入异常信息
        modelAndView.addObject("message", customException.getMessage());
        //设置错误页面
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

@ControllerAdvice字面理解就是控制器增强”, 是给控制器对象增强功能的使用@ControllerAdvice 修饰的类中可以使用@ExceptionHandler
当使用@RequestMapping 注解修饰的方法抛出异常时会执行@ControllerAdvice 修饰的类中的异常处理方法
@ControllerAdvice 是使用@Component 注解修饰的可以<context:component-scan>扫描到@ControllerAdvice 所在的类路径(包名) 创建对象

SpringMVC配置文件

ControllerAdvice注解所在的包名<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/mvc
                            http://www.springframework.org/schema/mvc/spring-mvc.xsd
                            http://www.springframework.org/schema/context
                            http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 注册组件扫描器,指定@ControllerAdvice注解所在的包名-->
    <context:component-scan base-package="com.mg"></context:component-scan>
    <!--注册注解驱动-->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>

错误页面(同xml方式)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>执行失败</title>
    </head>
    <body>
        执行失败!
        ${message }
    </body>
</html>

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦