最后附有网盘链接(程序打包+数据库)
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