SpringMVC_高级

SpringMVC_高级

1.文件上传

定义:指的是用户将自己本地计算机中的文件通过网络的形式上传到系统所在服务器上的过程,这个过程称之为文件上传。

注意:文件上传功能不是所有业务系统都需要的。

  • 什么时候需要文件上传功能?

    需要用户提交文件时,必须开发文件上传功能。
    
  • SpringMVC中如何开发文件上传?

    1. 引入文件上传的相关依赖

      <dependency>
          <groupId>commons-fileupload</groupId>
          <artifactId>commons-fileupload</artifactId>
          <version>1.3.1</version>
      </dependency>
      
    2. 在系统中开发一个可以进行文件上传的页面,包含一个form表单。在表单中开发一个可以选择本地计算机文件的入口:

      <form enctype="multipart/form-data" method="post" action="${pageContext.request.contextPath}/file/upload">
          选择文件:<input type="file" name="aa">
          <input type="submit" value="提交">
      </form>
      
      注意:
      a.form method提交方式必须是post
      b.form enctype属性的值 必须为 multipart/form-data(二进制文件)
      
    3. 开发Controller 在控制器方法中使用MultipartFile 进行文件的接收

      @Controller
      @RequestMapping("file")
      public class FileController {
      
          @RequestMapping("upload")
          public String upload(MultipartFile aa,HttpServletRequest request) throws IOException {
      
              System.out.println("文件名:"+aa.getOriginalFilename());
              System.out.println("文件大小:"+aa.getSize());
              System.out.println("文件类型:"+aa.getContentType());
      
              //文件上传
              //1.根据upload相对路径获取部署到服务之后的绝对路径
              String realPath = request.getSession().getServletContext().getRealPath("/upload");
              //2.将文件上传到upload对应路径
              File file = new File(realPath, aa.getOriginalFilename());
              aa.transferTo(file);
              return "index";
          }
      }
      
    4. 在springmvc配置文件中加入文件上传解析器的配置

      <!-- 配置文件解析器对象,要求id名称必须是multipartResolver -->
          <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
              <!-- 指定文件的最大大小,以字节为单位 -->
              <property name="maxUploadSize" value="10485760"/>
          </bean>
      

2.文件上传的细节

2.1 如何修改文件上传时文件的原始名称问题

问题:直接使用文件的原始名称作为上传文件的最终名称,可能会导致重名文件的覆盖问题。

解决:每次用户上传文件修改一个新的名称。

新文件名:UUID+文件后缀
//修改上传文件的名称
String filename = file.getOriginalFilename();
String extension = FilenameUtils.getExtension(filename);
String newFileName = UUID.randomUUID().toString().replace("-","")+"."+extension;

2.2 便于对上传的文件进行管理需要将用户每天上传的文件放入当天日期目录中

//生成当天的文件目录
LocalDate now = LocalDate.now();
File dateDir = new File(realPath, now.toString());
if (!dateDir.exists()){
    dateDir.mkdir();
}

2.3 springmvc中如何解决文件上传的大小限制

<!-- 配置文件上传解析器,且id必须为multipartResolver -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
    <!-- 限制上传文件大小限制为2M 即2,097,152字节 -->
    <property name="maxUploadSize" value="2097152"/>
</bean>

3.文件下载

定义:指的是用户将服务器上的文件下载到自己计算机中的过程,这个过程称之为文件下载。

  • 开发文件下载

    1. 定位系统中哪些文件需要用户下载

    2. 将需要用户下载的文件放入指定的目录中,如download文件夹

    3. 开发一个页面提供一个文件下载的链接

      <a href="${pageContext.request.contextPath}/file/download?fileName=aa.txt">下载文件:aa.txt</a>
      
    4. 开发下载Controller

      @RequestMapping("download")
      public String download(String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
          //文件下载
          //1.根据download相对路径获取部署到服务之后的绝对路径
          String realPath = request.getSession().getServletContext().getRealPath("/download");
          //2.获取想要下载的文件的绝对路径
          File file = new File(realPath, fileName);
          //3.获取文件从服务器磁盘到程序内存的字节文件输入流
          FileInputStream inputStream = new FileInputStream(file);
          //4.获取将文件从程序内存发送到客户端的字节输出流
          //4.1 设置文件的MIME类型
          response.setContentType("text/plain;charset=UTF-8");
          //4.2 设置文件为附件下载
          response.setHeader("content-disposition","attachment;fileName="+fileName);
          ServletOutputStream outputStream = response.getOutputStream();
          //5.处理下载流复制
           int len;
           byte[] bytes = new byte[1024];
          while ((len = inputStream.read(bytes))!=-1){
              outputStream.write(bytes,0,len);
          }
          //释放资源
          outputStream.close();
          inputStream.close();
          return "index";
      }
      

4.文件下载的细节

4.1 文件下载中的在线打开与附件下载

在设置下载文件的响应头时,可以设置"content-disposition"为attachment | inline,分别对应附件下载 |在线打开。实际开发中,常常为一个文件提供在线打开与附件下载的选项。代码如下控制:

  • jsp页面中:

    aa.txt
    <a href="${pageContext.request.contextPath}/file/download?fileName=aa.txt">在线打开</a>
    <!-- 为附件下载增加openStyle的参数 -->
    <a href="${pageContext.request.contextPath}/file/download?fileName=aa.txt&openStyle=attach">附件下载</a>
    
  • Controller中:

    @RequestMapping("download")
    //接收浏览器传入的openStyle参数
    public String download(String openStyle,String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {
        ...
        //4.2 设置文件为附件下载
        //判断参数是否为空
        openStyle =  openStyle == null?"inline":"attachment";
        //动态通过openStyle的设置下载打开方式
        response.setHeader("content-disposition",openStyle+";fileName="+fileName);
        ServletOutputStream outputStream = response.getOutputStream();
        ...
    }
    

4.2 commons-fileupload提供的处理下载流复制的方式

//5.处理下载流复制
//针对io流用 IOUtils,针对file 用 FileUtils
//简便的流复制的方法
IOUtils.copy(inputStream,outputStream);
//优雅的资源释放
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);

4.3 中文文件名乱码的问题

在设置"fileName="+fileName时,需要将中文文件名进行转码,才能进行IO流传输:

response.setHeader("content-disposition",openStyle+";fileName="+ URLEncoder.encode(fileName,"UTF-8"));

5.SpringMVC与AJAX的集成

@ResponseBody:为了进一步方便控制器与ajax的集成,SpringMVC提供了@ResponseBody注解。该注解用在方法上或方法的返回值上。可以将方法的返回值转换为json格式字符串并响应到前台,省去了通过第三方工具转换json的过程。

  1. 引入相关依赖

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.11.2</version>
    </dependency>
    
  2. 开发控制器

    @Controller
    @RequestMapping("json")
    public class JsonController {
    
        @RequestMapping("test")
        @ResponseBody//该注解自动将返回值map转换为json字符串
        public Map<String,String> test(){
            Map<String,String> map = new HashMap<String,String>();
            map.put("1","你好");
            return map;
        }
    }
    
  3. 开发网页展示数据

    <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
    <html>
    <head>
        <title>Json测试</title>
        <script src="${pageContext.request.contextPath}/js/jquery-1.8.3.min.js"></script>
        <script>
    
            $(function () {
                $("#btn").click(function () {
                    $.ajax({
                        url:"${pageContext.request.contextPath}/json/test",
                        type:"POST",
                        success:function (data) {
                            console.log(data)
    
                        },
                        dataType:"json"
    
                    });
                })
    
            })
        </script>
    </head>
    <body>
    
    <button id="btn">显示一群人</button>
    
    </body>
    </html>
    

    注意:

    • 使用jackson进行转换时,想要解决日期格式的问题,可以在实体类日期属性上加上@JsonFormat注解,里面有个pattern属性,可以指定日期格式。

6.SpringMVC中的拦截器

  1. 作用

作用:类似于javaweb中的Filter,用来对请求进行拦截,可以将多个Controller中执行的共同代码放入拦截器中执行,减少Controller类中代码的冗余.

  1. 特点
  • 拦截器器只能拦截Controller的请求,不能拦截jsp

  • 拦截器可中断用户的请求轨迹

  • 请求先经过拦截器,之后之后还会经过拦截器
  1. 开发拦截器
//自定义拦截器
public class MyInterceptor implements HandlerInterceptor {
    //请求最先经过的方法 返回为true放行请求  返回为false中断请求
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("1");
        return true;
    }
		//控制器方法执行完成之后进入这个方法执行
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("3");
    }
		//最后执行的方法
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("4");
    }
}
  1. 配置拦截器
    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 配置拦截器 -->
        <mvc:interceptor>
            <!-- 你要拦截的具体的方法 -->
            <mvc:mapping path="/user/*"/>
            <!-- 你不要拦截的方法 -->
            <mvc:exclude-mapping path="/user/find"/>
            <!-- 配置拦截器对象 -->
            <bean id="myInterceptor1" class="cn.itcast.interceptor.MyInterceptor1"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

/*``: 代表拦截所有请求路径

7.SpringMVC全局异常处理

  1. 作用

当控制器中某个方法在运行过程中突然发生运行时异常时,为了增加用户体验对于用户不能出现500错误代码,应该给用户良好展示错误界面,全局异常处理就能更好解决这个问题

  1. 全局异常处理开发
public class CustomerHanlderExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("500");//跳转到500页面
        return modelAndView;
    }
}
  1. 配置全局异常处理
<!--配置全局异常处理 -->
<bean class="com.baizhi.globalexception.CustomerHanlderExceptionResolver"></bean>