Spring MVC 使用介绍(四)—— 拦截器

时间:2023-11-22 09:27:08

一、概述

1、接口定义

拦截器由HandlerInterceptor接口定义:

public interface HandlerInterceptor {
// 预处理方法
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
// 后处理方法
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
// 请求结束后处理方法
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}

详细说明:

  • preHandle预处理方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器;返回值:
    • true:表示继续流程(如调用下一个拦截器或处理器)
    • false:表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应
  • postHandle后处理方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null
  • afterCompletion整个请求处理完毕处理方法,即在视图渲染完毕时调用,可以进行性能监控或资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion

2、运行流程

正常流程:

Spring MVC 使用介绍(四)—— 拦截器

中断流程:

Spring MVC 使用介绍(四)—— 拦截器

详细可参考DispatcherServlet.doDispatch()方法源码

二、简单示例

拦截器

spring提供HandlerInterceptorAdapter适配器,提供HandlerInterceptor接口空的实现,允许我们只实现需要的方法,因此拦截器可继承自该接口

public class TestInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("this is preHandle");
return true;
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("this is postHandle");
} @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("this is afterCompletion");
}
}

控制器

public class TestController2 implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("this is TestController2");
return new ModelAndView("hello2");
}
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>Archetype Created Web Application</display-name> <servlet>
<servlet-name>test-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>test-servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

spring-mvc.xml:注册拦截器和控制器

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-4.2.xsd"> <!-- HandlerMapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="testInterceptor"/>
</list>
</property>
</bean> <!-- HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <!-- ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean> <bean name="/hello2" class="cn.matt.controller.TestController2"/> <bean name="testInterceptor" class="cn.matt.interceptor.TestInterceptor"/> </beans>

hello2.jsp

<%@ page language="java" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
hello2
</body>
</html>

访问http://localhost:8080/myweb/hello2,控制台输出:

this is preHandle
this is TestController2
this is postHandle
this is afterCompletion

推荐能使用servlet规范中的过滤器Filter实现的功能就用Filter实现,因为HandlerInteceptor只有在Spring Web MVC环境下才能使用,因此Filter是最通用的、最先应该使用的,详细使用可参考javaweb学习总结(四十二)——Filter(过滤器)学习

参考:

第五章 处理器拦截器详解——跟着开涛学SpringMVC

javaweb学习总结(四十二)——Filter(过滤器)学习