SpringMVC拦截器的配置与使用详解

     一、SpringMVC拦截器简介

     Spring MVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。在springmvc中,定义拦截器要实现HandlerInterceptor接口

     二、SpringMVC拦截器方法

  • preHandle

      预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器(如具体的Controller实现); 
返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;

  • postHandle

     后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null

  • afterCompletion

     整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,

但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion

     三、SpringMVC拦截器实例

 1)创建工程

    Eclipse下新建一个web项目,File>New>Dynamic Web Project

 2)配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
    id="WebApp_ID" version="3.1">
    <display-name>springmvc_6_interceptor</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <servlet>
        <servlet-name>springDispatcherServlet</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>springDispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

   3)添加首页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <form action="springmvc/testFileUpload" method="POST"
        enctype="multipart/form-data">
        File: <input type="file" name="file" /><br>
        <br> Desc: <input type="text" name="desc" /> <input
            type="submit" value="Submit" />
    </form>
    <br>
    <br>
</body>
</html>

   4)添加控制器Controller

package com.yyx.handlers;

import java.io.IOException;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@RequestMapping("/springmvc")
@Controller
/**
 * 
 * @author yyx 2018年7月19日
 */
public class SpringMVCTest {
    private static final String SUCCESS = "success";

    /**
     * 常用:单个文件上传 
     * 注意:需要在配置文件配置支持文件上传的bean
     * @param desc
     * @param file
     * @return
     */
    @RequestMapping("/testFileUpload")
    public String testFileUpload(
            @RequestParam(value = "desc", required = false) String desc,
            @RequestParam("file") MultipartFile file) {
        System.out.println("desc:" + desc);
        System.out.println("OriginalFilename:" + file.getOriginalFilename());
        try {
            System.out.println("InputStream:" + file.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return SUCCESS;
    }
}

   5)添加拦截器

package com.yyx.interceptors;

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

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

/**
 * 拦截器一
 * @author yyx 2018年7月19日
 */
public class FirstInterceptor implements HandlerInterceptor {

    /**
     * 渲染视图之后被调用. 释放资源
     */
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object obj, Exception ex)
            throws Exception {
        System.out.println("[FirstInterceptor] afterCompletion");
    }

    /**
     * 调用目标方法之后, 但渲染视图之前. 可以对请求域中的属性或视图做出修改.
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response,
            Object obj, ModelAndView mv) throws Exception {
        System.out.println("[FirstInterceptor] postHandle");
    }

    /**
     * 该方法在目标方法之前被调用. 若返回值为 true, 则继续调用后续的拦截器和目标方法. 若返回值为 false,
     * 则不会再调用后续的拦截器和目标方法.
     * 
     * 可以考虑做权限. 日志, 事务等.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
            Object obj) throws Exception {
        System.out.println("[FirstInterceptor] preHandle");
        return true;
    }

}
package com.yyx.interceptors;

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

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

/**
 * 拦截器二
 * @author yyx 2018年7月19日
 */
public class SecondInterceptor implements HandlerInterceptor {

    /**
     * 渲染视图之后被调用. 释放资源
     */
    @Override
    public void afterCompletion(HttpServletRequest arg0,
            HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {
        System.out.println("[SecondInterceptor] afterCompletion");
    }

    /**
     * 调用目标方法之后, 但渲染视图之前. 可以对请求域中的属性或视图做出修改.
     */
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2, ModelAndView arg3) throws Exception {
        System.out.println("[SecondInterceptor] postHandle");
    }

    /**
     * 该方法在目标方法之前被调用. 若返回值为 true, 则继续调用后续的拦截器和目标方法. 若返回值为 false,
     * 则不会再调用后续的拦截器和目标方法.
     * 
     * 可以考虑做权限. 日志, 事务等.
     */
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
            Object arg2) throws Exception {
        System.out.println("[SecondInterceptor] preHandle");
        return true;
    }

}

   6)配置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" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <mvc:annotation-driven />
    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.yyx.handlers"></context:component-scan>

    <!-- 配置视图解析器 :如何把 handlers 方法返回值解析为实际的物理视图 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 配置自定义的拦截器 -->
        <!-- <bean class="com.yyx.interceptors.FirstInterceptor"></bean> -->
        
        <!-- 配置拦截器(不)作用的路径 -->
        <mvc:interceptor>
            <mvc:mapping path="/springmvc/testFileUpload" />
            
            <!-- 拦截所有的请求,这个必须写在前面,也就是写在【不拦截】的上面 -->
            <!-- <mvc:mapping path="/**"/> -->
            
            <!-- 但是排除下面这些,也就是不拦截请求 -->
            <!-- <mvc:exclude-mapping path="/springmvc/testFileUpload"/> -->
            <bean class="com.yyx.interceptors.SecondInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <!-- 配置 MultipartResolver 文件上传 -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"></property>
        <property name="maxUploadSize" value="1024000"></property>
    </bean>
</beans>

  7)添加目标页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h2>Success Page</h2>
</body>
</html>

常见应用场景

  • 日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等 
  • 权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面 
  • 性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录) 
  • 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个处理器都需要的即可使用拦截器实现
  • OpenSessionInView:如Hibernate,在进入处理器打开Session,在完成后关闭Session

猜你喜欢

转载自www.cnblogs.com/xianya/p/9340352.html