SpringMVC(下)


一、访问静态资源

在进行Spring MVC的配置时,通常我们会配置一个dispatcher servlet用于处理对应的URL

在设置url-pattern时可以设置三种形式

(1)/* :拦截所有 jsp js png .css 真的全拦截。不建议使用。

(2)/ :拦截所有,不包括jsp,包含.js .png.css 建议使用。

(3)**.action .do :拦截以do action 结尾的请求。



    mySpringMVC
    org.springframework.web.servlet.DispatcherServlet
    
    
    
        
        contextConfigLocation
        
        classpath:springmvc.xml
    
    
    1


    mySpringMVC
    /

url-pattern为 / 时,访问静态资源,会被拦截,找不到静态资源

解决方法:

(1)在springmvc.xml中配置


自动的根据访问地址看下是不是静态资源,如果是直接放行,如果不是就去找 @RequestMapping

(2)在springmvc.xml中配置 mvc:resources (推荐使用)

   
    
  

描述:

  • location元素表示webapp目录下的static包下的所有文件;
  • mapping元素表示以/static开头的所有请求路径,如/static/a 或者/static/a/b;
  • 该配置的作用是:DispatcherServlet不会拦截以/static开头的所有请求路径,并当作静态资源交由Servlet处理。

二、Json处理

概述

当前端使用Ajax发送请求时,服务器要以JSON的数据格式响应给浏览器。

使用方式

@ResponseBody来实现;注解方式

@ResponseBody

(1)添加 json处理 相关jar包

+ jackson 2.9.9
    - jackson-annotations-2.9.9.jar
    - jackson-core-2.9.9.jar
    - jackson-databind-2.9.9.jar

(2)在springmvc.xml配置文件当中写上


(3)设置映射方法的返回值为@ResponseBody

请求发送页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    Title
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
  
  
  
  

  <script>
    $(function () {
        $('#btn').click(function () {
            // 发送Ajax 请求
            $.post("${pageContext.request.contextPath}/getJson",function (data) {
                console.log(data);
            })
        });
    });
  </script>
  

方式1-直接返回一个对象
@Controller
public class MyController {
    @RequestMapping("getJson")
    @ResponseBody
    public User show(){
        User user = new User();
        user.setUsername("user2");
        user.setPassword("159357");
        user.setAge(20);
        user.setHobby(new String[]{"篮球","足球"});
        return user;
    }
}
方式2-返回一个List集合
@Controller
public class MyController {
    @RequestMapping("getJson")
    @ResponseBody
    public ArrayList show(){
        User user1 = new User();
        user1.setUsername("user2");
        user1.setPassword("159357");
        user1.setAge(20);
        user1.setHobby(new String[]{"篮球","足球"});

        User user2 = new User();
        user2.setUsername("user1");
        user2.setPassword("123456");
        user2.setAge(18);
        user2.setHobby(new String[]{"篮球","足球"});

        ArrayList users = new ArrayList<>();
        users.add(user1);
        users.add(user2);

        return users;
    }
}
方式3-返回一个Map集合
@Controller
public class MyController {
    @RequestMapping("getJson")
    @ResponseBody
    public HashMap show(){
        User user1 = new User();
        user1.setUsername("user2");
        user1.setPassword("159357");
        user1.setAge(20);
        user1.setHobby(new String[]{"篮球","足球"});

        User user2 = new User();
        user2.setUsername("user1");
        user2.setPassword("123456");
        user2.setAge(18);
        user2.setHobby(new String[]{"篮球","足球"});

        ArrayList users = new ArrayList<>();
        users.add(user1);
        users.add(user2);

        HashMap map = new HashMap<>();
        map.put("name", "hashmap");
        map.put("list", users);
        return map;
    }
}

表单序列化

serialize()

请求发送页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    Title
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
  
  

  

用户Id :

用户名 :

密码 :

性别 : 男 女

年龄 :

爱好 : 篮球 足球 排球 乒乓球

<script> $(function () { $('#btn').click(function () { // 获取表单所有参数,发送给服务器 var serialize = $('#myform').serialize(); console.log(serialize); // output: 参数=值&参数=值&参数=值 }); }); </script>

我们希望获取的是json格式的数据:

序列化转Json

(function($){
    $.fn.serializeJson=function(){
        var serializeObj={};
        var array=this.serializeArray();
        var str=this.serialize();
        $(array).each(function(){
            if(serializeObj[this.name]){
                if($.isArray(serializeObj[this.name])){
                    serializeObj[this.name].push(this.value);
                }else{
                    serializeObj[this.name]=[serializeObj[this.name],this.value];
                }
            }else{
                serializeObj[this.name]=this.value;
            }
        });
        return serializeObj;
    };
})(jQuery);

请求发送页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    Title
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
  
  

  

用户Id :

用户名 :

密码 :

性别 : 男 女

年龄 :

爱好 : 篮球 足球 排球 乒乓球

<script> (function($){ $.fn.serializeJson=function(){ var serializeObj={}; var array=this.serializeArray(); var str=this.serialize(); $(array).each(function(){ if(serializeObj[this.name]){ if($.isArray(serializeObj[this.name])){ serializeObj[this.name].push(this.value); }else{ serializeObj[this.name]=[serializeObj[this.name],this.value]; } }else{ serializeObj[this.name]=this.value; } }); return serializeObj; }; })(jQuery); $(function () { $('#btn').click(function () { // 获取表单所有参数,发送给服务器 var serialize = $('#myform').serializeJson(); console.log(serialize); }); }); </script>

这时候的 serialize 就是以json格式的数据,我们再把数据发送给服务器

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    Title
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
  
  

  

用户Id :

用户名 :

密码 :

性别 : 男 女

年龄 :

爱好 : 篮球 足球 排球 乒乓球

<script> (function($){ $.fn.serializeJson=function(){ var serializeObj={}; var array=this.serializeArray(); var str=this.serialize(); $(array).each(function(){ if(serializeObj[this.name]){ if($.isArray(serializeObj[this.name])){ serializeObj[this.name].push(this.value); }else{ serializeObj[this.name]=[serializeObj[this.name],this.value]; } }else{ serializeObj[this.name]=this.value; } }); return serializeObj; }; })(jQuery); $(function () { $('#btn').click(function () { // 获取表单所有参数,发送给服务器 var serialize = $('#myform').serializeJson(); console.log(serialize); $.post("${pageContext.request.contextPath}/formJson",serialize,function (data) { console.log(data); }) }); }); </script>

Controller

@Controller
public class MyController {
    @RequestMapping("formJson")
    @ResponseBody
    public String show(User user){
        System.out.println(user);
        return "success";
    }
}

发现问题

运行后会发现,当爱好选一个的时候可以正常运行,当选择大等于两个的时候,会报错。

当传递复杂类型的时候,服务器不能接收。

这是因为,默认情况下,在发送请求的时候 Content-Type 都是 application/x-www-form-urlencoded; 直接使用@RequestParam接收参数。 urlencoded 只能发送简单的 key-value 字符串类型。

@RequestBody

默认情况下我们发送的都是 Content-Type: application/x-www-form-urlencoded,直接使用@RequestParam接收参数。

如果不是Content-Type: application/x-www-form-urlencoded 编码的内容,例如application/json, application/xml等;使用@RequestBody接收。

解决方法

在发送的时候以 json 的形式发送,接受的时候以 json 的形式接收。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    Title
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
  
  

  

用户Id :

用户名 :

密码 :

性别 : 男 女

年龄 :

爱好 : 篮球 足球 排球 乒乓球

<script> (function($){ $.fn.serializeJson=function(){ var serializeObj={}; var array=this.serializeArray(); var str=this.serialize(); $(array).each(function(){ if(serializeObj[this.name]){ if($.isArray(serializeObj[this.name])){ serializeObj[this.name].push(this.value); }else{ serializeObj[this.name]=[serializeObj[this.name],this.value]; } }else{ serializeObj[this.name]=this.value; } }); return serializeObj; }; })(jQuery); $(function () { $('#btn').click(function () { // 获取表单所有参数,发送给服务器 var serialize = $('#myform').serializeJson(); console.log(serialize); $.ajax({ type:"post", url:"${pageContext.request.contextPath}/formJson", data:JSON.stringify(serialize), dataType:'json', contentType:'application/json', success:function (data) { console.log(data); } }); }); }); </script>

Controller

@Controller
public class MyController {
    @RequestMapping("formJson")
    @ResponseBody
    public String show(@RequestBody User user){
        System.out.println(user);
        return "success";
    }
}

这样当爱好选择两个以上的时候就可以接收复杂类型的数据。

现在还有一个小问题:当爱好选择一个时,服务器接收不了。

原因是 当选择一个时,json串中hobby的数据为String类型,而hobby需要数组类型,Content-Type:application/x-www-form-urlencoded; 会自动帮我们解析,而 application/json 不会。所以我们要自己解析。

解决方法:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    Title
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
  
  

  

用户Id :

用户名 :

密码 :

性别 : 男 女

年龄 :

爱好 : 篮球 足球 排球 乒乓球

<script> (function($){ $.fn.serializeJson=function(){ var serializeObj={}; var array=this.serializeArray(); var str=this.serialize(); $(array).each(function(){ if(serializeObj[this.name]){ if($.isArray(serializeObj[this.name])){ serializeObj[this.name].push(this.value); }else{ serializeObj[this.name]=[serializeObj[this.name],this.value]; } }else{ serializeObj[this.name]=this.value; } }); return serializeObj; }; })(jQuery); $(function () { $('#btn').click(function () { // 获取表单所有参数,发送给服务器 var serialize = $('#myform').serializeJson(); console.log(serialize); // 解析 if (typeof serialize.hobby == "string") { serialize.hobby = new Array(serialize.hobby); } $.ajax({ type:"post", url:"${pageContext.request.contextPath}/formJson", data:JSON.stringify(serialize), dataType:'json', contentType:'application/json', success:function (data) { // alert(data.responseText) console.log(data); } }); }); }); </script>

@RequestBody 获取文件信息

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    Title
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
  
  
  

Controller

@RequestMapping("myfile")
@ResponseBody
public String file(@RequestBody String file){
    System.out.println(file);
    return "success";
}

三、视图解析器

视图解析器

请求处理方法执行完成后,最终返回一个 ModelAndView 对象

对于那些返回 String,View 或 ModeMap 等类型的处理方法,Spring MVC 也会在内部将它们装配成一个 ModelAndView 对象。

它包含了逻辑名和模型对象的视图,Spring MVC 借助视图解析器(ViewResolver)得到最终的视图对象(View),最终的视图可以是 JSP 。

视图

视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户,视图对象由视图解析器负责实例化

在org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口

常见实现类:InternalResourceView,将JSP或其它资源封装成一个视图,是InternalResourceViewResoler默认使用的实现类。

源码分析

执行DispatcherServlet

(1)获取mapping映射

(2)获取适配器

(3)调用处理器,执行映射方法,返回MV

(4)处理转发页面

(5)在方法内部渲染页面

(6)创建视图对象

(7)调用View对象渲染页面

(8)在render内部解析数据

(9)转发到jsp页面

四、文件下载

请求页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    Title
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js"></script>
  
  
  下载背景.jpg
  

Controller

package com.ssm.web.controller;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLEncoder;

@Controller
public class MyController {
    @RequestMapping("/download/{filename:.+}")
    public ResponseEntity download(@PathVariable String filename, HttpSession session) throws Exception {
        System.out.println(filename);
        /* 1.获取文件路径 */
        // 获取 servletContext
        ServletContext servletContext = session.getServletContext();
        // 获取文件路径
        String realPath = servletContext.getRealPath("/download/" + filename);

        /* 2.把文件读取程序当中 */
        // 创建一个输入流
        InputStream io = new FileInputStream(realPath);
        byte[] body = new byte[io.available()];
        // 将文件流读到数组当中
        io.read(body);

        /* 3.创建响应头 */
        // 创建请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        // 对文件名进行中文编码
        filename = URLEncoder.encode(filename,"UTF-8");
        // 告诉浏览器以附件形式下载文件
        httpHeaders.add("Content-Disposition","attachment;filename="+filename);
        // 设置响应码
        HttpStatus statusCode = HttpStatus.OK;
        ResponseEntity responseEntity = new ResponseEntity<>(body, httpHeaders, statusCode);
        // 关闭流
        io.close();

        return responseEntity;
    }
}

注意

@RequestMapping("/download/{filename}") :只会传文件名,不会带后缀

@RequestMapping("/download/{filename:.+}") :会传文件名带后缀

五、文件上传

概述

Spring MVC 为文件上传提供了直接的支持,是通过即插即用的 MultipartResolver 实现的。

MultipartResolver是一个接口,Spring MVC 上下文中默认没有装配 MultipartResovler,如果想使用 Spring 的文件上传功能,就必须得要自己下载相关jar包,自己到配置文件当中装配到springMVC当中。

上传步骤

(1)导入相关jar包

- com.springsource.org.apache.commons.fileupload-1.2.0.jar
- com.springsource.org.apache.commons.io-1.4.0.jar
- com.springsource.org.apache.commons.logging-1.1.1.jar

(2)在springmvc配置文件当中装配MultipartResovler



    
    

(3)实现上传代码

@RequestMapping("/download/{filename:.+}")
public ResponseEntity download(@PathVariable String filename, HttpSession session) throws Exception {
    System.out.println(filename);
    /* 1.获取文件路径 */
    // 获取 servletContext
    ServletContext servletContext = session.getServletContext();
    // 获取文件路径
    String realPath = servletContext.getRealPath("/download/" + filename);

    /* 2.把文件读取程序当中 */
    // 创建一个输入流
    InputStream io = new FileInputStream(realPath);
    byte[] body = new byte[io.available()];
    // 将文件流读到数组当中
    io.read(body);

    /* 3.创建响应头 */
    // 创建请求头
    HttpHeaders httpHeaders = new HttpHeaders();
    // 对文件名进行中文编码
    filename = URLEncoder.encode(filename, "UTF-8");
    // 告诉浏览器以附件形式下载文件
    httpHeaders.add("Content-Disposition", "attachment;filename=" + filename);
    // 设置响应码
    HttpStatus statusCode = HttpStatus.OK;
    ResponseEntity responseEntity = new ResponseEntity<>(body, httpHeaders, statusCode);
    // 关闭流
    io.close();

    return responseEntity;
}

@RequestMapping("/upload")
public String upload(@RequestParam("file") CommonsMultipartFile file, HttpSession session) throws IOException {
    System.out.println("文件类型:" + file.getContentType());
    System.out.println("文件名:" + file.getOriginalFilename());
    System.out.println("文件大小:" + file.getSize());
    System.out.println("表单name属性:" + file.getName());

    // 确定上传的路径
    ServletContext servletContext = session.getServletContext();
    String realPath = servletContext.getRealPath("/upload");
    // 变成程序当中的路径
    File uploadPath = new File(realPath);
    if (!uploadPath.exists()) {
        // 如果路径不存在 ,创建一个新的
        uploadPath.mkdirs();
    }
    // 确认最终的路径  /文件夹/文件名    工程的名称/upload/java.png
    String fileName = file.getOriginalFilename();
    uploadPath = new File(uploadPath + "/" + fileName);

    // 开始上传
    file.transferTo(uploadPath);

    return "result.jsp";
}

多文件上传

WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。

文件上传的代码不动,只要前端页面加入WebUploader插件即可。

引入插件

- webuploader.css
- Uploader.swf
- webuploader.js
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title
    <%--引入css样式--%>
    
    <script src="${pageContext.request.contextPath}/js/jquery-3.3.1.min.js" type="text/javascript"></script>
    <%--引入文件上传插件--%>
    <script type="text/javascript" src="${pageContext.request.contextPath}/js/webuploader.js"></script>
    <script type="text/javascript">
        $(function () {
            var $ = jQuery,
                $list = $('#fileList'),
                //优化retina, 在retina下这个值是2
                ratio = window.devicePixelRatio || 1,
                // 缩略图大小
                thumbnailWidth = 100 * ratio,
                thumbnailHeight = 100 * ratio,
                // Web Uploader实例uploader;
                // 初始化Web Uploader
                uploader = WebUploader.create({
                    // 自动上传。
                    auto: false,
                    // swf文件路径
                    swf: '${pageContext.request.contextPath}/js/Uploader.swf',
                    // 文件接收服务端。
                    server: '${pageContext.request.contextPath}/upload',
                    fileVal: 'file',
                    threads: '30',      //同时运行30个线程传输
                    fileNumLimit: '10',   //文件总数量只能选择10个 
                    // 选择文件的按钮。可选。
                    pick: {
                        id: '#filePicker',  //选择文件的按钮
                        multiple: true        //允许可以同时选择多个图片
                    },
                    //图片质量,只有type为`image/jpeg`的时候才有效。
                    quality: 100,
                    //限制传输文件类型,accept可以不写 (用于显示文件类型筛选)
                    /* accept: {
                    title: 'Images',//描述
                    extensions: 'gif,jpg,jpeg,bmp,png,zip',//类型
                    mimeTypes: 'image/*'//mime类型
                   } */
                });

            // 当有文件添加进来的时候,创建img显示缩略图使用
            uploader.on('fileQueued', function (file) {
                var $li = $(
                    '
' + '' + '
' + file.name + '
' + '
' ), $img = $li.find('img'); // $list为容器jQuery实例 $list.append($li); // 创建缩略图 // 如果为非图片文件,可以不用调用此方法。 // thumbnailWidth x thumbnailHeight 为 100 x 100 uploader.makeThumb(file, function (error, src) { if (error) { $img.replaceWith('不能预览'); return; } $img.attr('src', src); }, thumbnailWidth, thumbnailHeight); }); // 文件上传过程中创建进度条实时显示。    // uploadProgress事件:上传过程中触发,携带上传进度。 // file文件对象 percentage传输进度 Number类型 uploader.on('uploadProgress', function (file, percentage) { console.log(percentage); }); // 文件上传成功时候触发,给item添加成功class, // 用样式标记上传成功。 // file:文件对象,    // response:服务器返回数据 uploader.on('uploadSuccess', function (file, response) { $('#' + file.id).addClass('upload-state-done'); //console.info(response); $("#upInfo").html("" + response._raw + ""); }); // 文件上传失败 // file:文件对象 , // code:出错代码 uploader.on('uploadError', function (file, code) { var $li = $('#' + file.id), $error = $li.find('div.error'); // 避免重复创建 if (!$error.length) { $error = $('
').appendTo($li); } $error.text('上传失败!'); }); // 不管成功或者失败, // 文件上传完成时触发。 // file: 文件对象 uploader.on('uploadComplete', function (file) { $('#' + file.id).find('.progress').remove(); }); //绑定提交事件 $("#btn").click(function () { console.log("上传..."); uploader.upload();   //执行手动提交 console.log("上传成功"); }); }); </script> <script> var contextpath = ${pageContext.request.contextPath}; </script>

多文件上传

 
选择文件

六、异常

概述

Spring MVC 通过 HandlerExceptionResolver 处理程序的异常,包括 Handler 映射、数据绑定以及目标方法执行时发生的异常。

SpringMVC 提供的 HandlerExceptionResolver 的实现类。

异常处理

处理 Handler 中用 @ExceptionHandler 注解定义的方法。

@RequestMapping("testException")
public String testException() {
    int i = 1 / 0;
    return "/result.jsp";
}

@ExceptionHandler(value = ArithmeticException.class)
public String handleException(Exception e) {
    System.out.println("出现异常" + e.getMessage());
    return "/error.jsp";
}

@ExceptionHandler优先级

根据继承关系,找继承关系比较近的那一个。

@ExceptionHandler(value = ArithmeticException.class)
public String handleException(Exception e) {
    System.out.println("出现异常1" + e.getMessage());
    return "/error.jsp";
}


@ExceptionHandler(value = RuntimeException.class)
public String handleException2(Exception e) {
    System.out.println("出现异常2" + e.getMessage());
    return "/error.jsp";
}

@ExceptionHandler(value = Exception.class)
public String handleException3(Exception e) {
    System.out.println("出现异常3" + e.getMessage());
    return "/error.jsp";

}

@ControllerAdvice

如果在当前类中没有找到 @ExceptionHanler ,则会到 @ControllerAdvice 中的 @ExceptionHandler 注解方法

@ControllerAdvice
public class ExceptionController {
    @ExceptionHandler(value = Exception.class)
    public String handleException(Exception e) {
        System.out.println("出现异常" + e.getMessage());
        return "/error.jsp";
    }
}

七、国际化

概述

SpringMVC 根据 Accept-Language 参数判断客户端的本地化类型,当接受到请求时,SpringMVC 会在上下文中查找一个本地化解析器(LocalResolver),找到后使用它获取请求所对应的本地化类型信息。

默认实现过程

(1)要先创建国际化的资源文件

+ resource
    - language_en_US.properties
    - language_zh_CN.properties

新建配置文件时确保编码正确。在IDEA中

language_en_US.properties

welcome = welcome
introduce = This is Demo
name = ZhangSan

language_zh_CN.properties

welcome = 欢迎光临
introduce = 这是一个国际化示例
name = 张三

(2)添加配置文件 springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>


    
    

    
    
    
    
    

    
    
        
    

(3)添加JSTL jar包

    - jstl-1.2.jar
    - standard-1.1.2.jar

(4)在页面当中编写标签

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>


    Title


local








谷歌浏览器中可以设置不同语言来查看

原理

如果没有显式定义本地化解析器, SpringMVC 会使用 AcceptHeaderLocaleResolver:根据 HTTP 请求头的 Accept-Language 参数确定本地化类型。

中英文切换

概述

默认情况是通过AccepHeaderLocaleResolver来从浏览器当中获取语言信息。

可以从请求参数中获取本次请求对应的本地化类型。获取到本地类型后, 给写入到session当中。

实现

配置文件
<?xml version="1.0" encoding="UTF-8"?>


    
    

    
    
    
    
    

    
    
        
    

    
    
    
        
            
        
    

属性文件

language_en_US.properties

language.cn=Chinese
language.en=English
welcome=welcome
introduce=This is Demo
name=ZhangSan

language_zh_CN.properties

language.cn=中文
language.en=英文
welcome=欢迎光临
introduce=这是一个国际化示例
name=张三	
页面信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>


    Title


local









八、拦截器

概述

Java 里的拦截器是动态拦截 action 调用的对象。可以在Controller中的方法执行之前与执行之后, 及页面显示完毕后,执行指定的方法。

自定义的拦截器必须实现HandlerInterceptor接口

方法介绍

preHandle()	 		// 在业务处理器处理请求之前被调用
postHandle   		// 在业务处理器处理完请求后
afterCompletion		// 在 DispatcherServlet 完全处理完请求后被调用

SpringMVC拦截器使用

(1)拦截所有请求

① 创建一个类实现HandlerInterceptor接口
package com.ssm.web.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyFirstInterceptor implements HandlerInterceptor {

    @Override
    // 在处理器方法执行之前调用
    // 返回值: true-放行; false-不放行-执行不了处理器方法
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("在处理器方法执行之前调用");
        return true;
    }

    @Override
    // 在处理器方法执行之后自动调用
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("在处理器方法执行之后自动调用");
    }

    @Override
    // 请求处理完毕之后会调用
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("请求处理完毕之后会调用");
    }
}
② 配置文件当中添加拦截器
<?xml version="1.0" encoding="UTF-8"?>


    
    

    
    
    
    


    
    
    
        
    

(2)拦截指定请求

<?xml version="1.0" encoding="UTF-8"?>


    
    

    
    
    
    


    
    
    
        
        

        
            
            
            
            
            
        
    

(3)配置多个拦截器执行顺序

从上面结果可以看出,preHandle 是按正序调用,postHandle 和 afterCompletion是倒序调用

源码分析

preHandle 是正序遍历,postHandle 和 afterCompletion是倒序遍历

九、总结