Spring MVC中的拦截器(Interceptor)类似于 Servlet中的过滤器(Filter),主要用于拦截用户的处理并做相应的处理。例如:通过拦截器可以进行权限验证、记录请求信息的日志等。
要使用Spring Mvc中的拦截器,就需要对拦截器进行定义和配置。
拦截器可以通过实现 HandlerInterceptor接口或者继承HandlerInterceptor接口的实现类HandlerInterceptorAdapter来定义。
HandlerInterceptor接口
package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
我们看到HandlerInterceptor存在3个方法,我们来介绍一下:
-
preHandle方法:springMVC接收到请求,在访问controller前自动执行该方法。preHandle方法返回true时,表示执行对应请求方法。否则,直接返回,不执行。 -
postHandle方法:在执行完controller方法后,进行视图渲染前自动调用该方法 -
afterCompletion方法:在视图渲染完成后,自动调用,主要用于清理数据
拦截器的执行顺序
当一个请求只被一个拦截器拦截的时候,我们很容易知道,方法之间的执行顺序是:
preHandle --> 对应请求方法 --> postHandle --> afterCompletion
那么当一个请求同时被多个拦截器拦截时,拦截器就组成了一个拦截链。那么,这个时候,各个方法之间的执行顺序又是怎么样的呢?
我们来看个图
看图可知:
-
拦截器的
preHandle方法的执行顺序是它们在配置文件的声明顺序 -
拦截器的
postHandle和afterCompletion方法的执行顺序与它们在配置文件的声明顺序相反
Interceptor的使用
项目目录如下:
HelloController.java
package com.xgc.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mv = new ModelAndView("hello");
mv.addObject("msg", "hello world");
System.out.println("hello world");
return mv;
}
}
LogInterceptor.java
package com.xgc.interceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LogInterceptor extends HandlerInterceptorAdapter {
/**
* springMVC接收到请求,在访问controller前自动执行该方法
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("执行了:preHandle========");
return true;
}
/**
* 在执行完controller方法后,进行视图渲染前自动调用该方法
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("执行了:postHandle=========");
}
/**
* 在视图渲染完成后,自动调用,主要用于清理数据
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("执行了:afterCompletion====");
}
}
springmvc.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="/hello" class="com.xgc.controller.HelloController"></bean>
</beans>
hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.xgc</groupId>
<artifactId>javaweb</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
</dependencies>
</project>
在浏览器输入 http://localhost:8080/javaweb_war_exploded/hello
得到页面如下
后台控制台输出如下