Spring 拦截器(附代码链接)

最后附有网盘链接(程序打包+数据库)

Spring 拦截器

1、定义与应用场景

拦截器是spring中的一个重要概念(类似于Filter过滤器)。他被注册到spring,拦截指定规则的请求,基于回调机制执行。一般来说,拦截器只会拦截action请求,这一点与过滤器不同。

应用场景:
权限检查:如是否已经登录,或则对某些数据具有增删改查等权限;

日志记录:可以记录请求信息的日志,以便进行信息监控,信息统计等;

性能监控:慢日志等。

2、拦截器接口

1.处理器拦截器(HandlerIntercepto):

public interface HandlerInterceptor {

   /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
   */
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

   /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
   */
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

   /**
    * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
   */
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

3、拦截流程

拦截器执行顺序按照Spring配置文件中定义的顺序执行;

首先按照执行顺序执行所有拦截器的preHandle()方法【用于预处理等】,如果遇到返回值是false,则不会执行还未执行的拦截器,而是直接倒序执行afterCompletion()方法,如果为true,则依次执行剩下的拦截器;

如果所有拦截器的preHandle()方法返回值都为true,则执行相应的控制层接口(controller),如果在该接口中有异常抛出,则和preHandle()方法返回false一样,不会执行postHandle(),而是直接倒序执行afterCompletion()方法;

如果接口(controller)中业务逻辑执行完成(页面还未渲染数据),会倒序执行postHandle()方法,渲染完数据后,然后倒序执行afterCompletton()方法。

4、来个流程图解释

本次以两个拦截器更深度地解释
在这里插入图片描述
运行结果

01:04:46.196 [http-nio-8080-exec-2] INFO org.springframework.web.servlet.DispatcherServlet - Completed initialization in 1301 ms
01:04:46.205 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - GET "/springmvc/fileUploadPage", parameters={}
01:04:46.210 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped to init.wuji.springboot.mvc.fileupload.action.FileUploadAction#fileUploadPage()
=======MyHandlerInterceptor==========>preHandle
-------------MySecondInterceptor==========preHandle
-------------MySecondInterceptor==========postHandle
=======MyHandlerInterceptor==========>postHandle
01:04:46.233 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.view.JstlView - View name 'success', model {}
01:04:46.239 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.view.JstlView - Forwarding to [/views/success.jsp]
-------------MySecondInterceptor==========afterCompletion
=======MyHandlerInterceptor==========>afterCompletion
01:04:46.245 [http-nio-8080-exec-2] DEBUG org.springframework.web.servlet.DispatcherServlet - Completed 200 OK

注意顺序

上代码

首先两个拦截器代码
第一个文件名:/springmvc/src/main/java/init/wuji/springboot/mvc/interceptor/MyHandlerInterceptor.java
代码:

package init.wuji.springboot.mvc.interceptor;

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

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

public class MyHandlerInterceptor implements HandlerInterceptor{

	/**
	 * preHandle方法在handler方法执行之前拦截用户的请求,如果返回false,表示中断后续操作,如果返回true,表示向下继续执行。
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("=======MyHandlerInterceptor==========>preHandle");
		return true;
	}

	/**
	 * postHandle 该方法在handler方法调用之后,解析视图之前执行;我们可以通过此方法对请求域中的modle和view进行修改
	 */
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		//request.getParameter();
		if(modelAndView != null) {
			modelAndView.setViewName("success");
		}
		
		System.out.println("=======MyHandlerInterceptor==========>postHandle");
	}

	/**
	 * afterCompletion 此方法在handler方法执行完毕之后(视图渲染结束),我们可以通过此方法释放资源,记录日志等操作,及异常处理
	 */
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("=======MyHandlerInterceptor==========>afterCompletion");
	}

	
	
}

第二个拦截器
文件名:/springmvc/src/main/java/init/wuji/springboot/mvc/interceptor/MySecondInterceptor.java
代码:

package init.wuji.springboot.mvc.interceptor;

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

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

public class MySecondInterceptor implements HandlerInterceptor{

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("-------------MySecondInterceptor==========preHandle");
		return true;
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("-------------MySecondInterceptor==========postHandle");
	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("-------------MySecondInterceptor==========afterCompletion");
	}

}

然后是上下文的配置
文件名:/springmvc/src/main/resources/config/applicationContext-mvc.xml
代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
        ">
    <context:component-scan base-package="init.wuji.springboot.mvc.*.action"></context:component-scan>    
	
	<!-- 
	配置视图解析器
	 -->
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>	
		
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 上传文件的最大值, 单位为:字节  50*1024*1024 
		
		-->
		<property name="maxUploadSize" value="#{50*1024*1024}" />
	</bean>

	<mvc:annotation-driven>
		 <mvc:message-converters>
		 	<!-- register-defaults="true"表示使用默认的消息转换器 -->
            <!-- FastJson(Spring4.2x以上版本设置) -->
            <!-- 使用@responsebody注解并且返回值类型为String时,返回的string字符串带有双引号"{'user':'songfs'}",其原因是直接将string类型转成了json字符串,应该在json解析器之前添加字符串解析器-->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            <!-- FastJsonHttpMessageConverter4 使@ResponseBody支持返回Map<String,Object>等类型,它会自动转换为json-->
            <!-- 需要返回json时需要配置 produces = "application/json"。不需要再指定utf-8-->
            <bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <!-- 加入支持的媒体类型 -->
                <property name="supportedMediaTypes">
                    <list>
                        <!-- 这里顺序不能反,一定先写text/html,不然IE执行AJAX时,返回JSON会出现下载文件 -->
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                        <value>application/xml;charset=UTF-8</value>
                    </list>
                </property>
                <property name="fastJsonConfig">
                    <bean class="com.alibaba.fastjson.support.config.FastJsonConfig">
                        <property name="features">
                            <list>
                                <value>AllowArbitraryCommas</value>
                                <value>AllowUnQuotedFieldNames</value>
                                <value>DisableCircularReferenceDetect</value>
                            </list>
                        </property>
                        <property name="dateFormat" value="yyyy-MM-dd HH:mm:ss"/>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
	</mvc:annotation-driven>
	
	<mvc:interceptors>
		<mvc:interceptor>
			<!-- mvc:mapping 中配置需要拦截的路径 -->
			<mvc:mapping path="/**"/>
			
			<!--exclude-mapping 中配置需要剔除拦截的路径 -->
			<mvc:exclude-mapping path="/ws/userWsList"/>
			<bean class="init.wuji.springboot.mvc.interceptor.MyHandlerInterceptor"></bean>
		</mvc:interceptor>
		
		<mvc:interceptor>
			<!-- mvc:mapping 中配置需要拦截的路径 -->
			<mvc:mapping path="/userInfoRest/**"/>
			<bean class="init.wuji.springboot.mvc.interceptor.MySecondInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>
	<!-- 
	SSM:spirng springmvc  mybatis
	
	spirngboot 
	尽量不要将业务代码 与 框架配置信息放到一起
	<mvc:view-controller path="/userInfo/userAddInit" view-name="user/add"/>
	 -->
</beans>

下课

链接

链接:https://pan.baidu.com/s/1_8Hs6V06GdX7ia5fYV4MlQ
提取码:7s8u

发布了21 篇原创文章 · 获赞 25 · 访问量 4323

猜你喜欢

转载自blog.csdn.net/weixin_43419816/article/details/104230506