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

一、概述

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、运行流程

正常流程:

                         

中断流程:

                         

详细可参考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(过滤器)学习

 

posted @ 2018-06-12 09:54  Matt_Cheng  阅读(288)  评论(0编辑  收藏  举报