拦截器(Interceptor)
拦截器是spring提供的一种机制,可以对请求进行拦截或直接放行,
可以在进入控制器方法前后对请求做出相应的处理
主要执行的拦截:
前端请求后台服务器被DispatcherServlet拦截,DispatcherServlet
在执行Controller之前会执行preHandle()进行拦截,在执Controller之后会执行postHandle()拦截,在postHandle()中可以对Model和View中的数据进行处理,将处理之后的数据返回给DispacherServlet,DispatcherServlet再调用视图解析器将我们的逻辑视图转换为物理视图返回给DispatcherServlet,在返回的时候会被afterCompletion()拦截。
自定义拦截器
1、创建自定义拦截器类继承HandlerInterceptor,并实现三个方法
public class MyInterceptor implements HandlerInterceptor {
/**
* 作用:在处理器方法执行之前进行拦截处理
* @param request
* @param response
* @param handler 处理器方法的封装
* @return
* true:表示资源放行
* false:资源禁止访
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle run.....");
return true;
}
/**
* 作用:在处理器方法执行之后执行,但是如果任意一个拦截器的preHandle方法返回false,则不能执行
* @param request
* @param response
* @param handler 处理器方法的封装
* @param modelAndView 可以定义处理器方法执行完毕后,返回的视图的结果
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle run.....");
}
/**
* 作用:视图解析器解析完毕,响应物理视图之前执行
* 注意事项:只有当前的preHandle被执行,返回true才能执行对应的afterCompletion;
* @param request
* @param response
* @param handler 处理器方法的封装
* @param ex 处理器方法抛出的异常对象
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion run...");
}
}
在springMVC.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--开启注解扫描-->
<context:component-scan base-package="com.itheima"/>
<!--配置视图解析器:解析视图将逻辑视图转换成物理视图-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--视图的前缀-->
<property name="prefix" value="/WEB-INF/pages/"/>
<!--视图资源的后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!-- <mvc:annotation-driven/>-->
<mvc:annotation-driven/>
<!--配置拦截器-->
<mvc:interceptors>
<!--多拦截器配置下,自上而下,进行执行-->
<mvc:interceptor>
<!--
/* 只能匹配一级目录 eg: /aa /bbbb /asdfashdfaksdf
/** 匹配所有路径
-->
<mvc:mapping path="/**"/>
<!--排除被拦截的资源 路径/test2不被拦截-->
<mvc:exclude-mapping path="/test2"/>
<!--指定具体拦截的bean对象-->
<bean class="com.itheima.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
在InternalResourceViewResolver中的buildView方法打上断点进行调试,我们可以发现在buildView方法执行之后不会将数据直接返回给DespacherServlet,而是先经过拦截器中的afterCompletion方法,在执行完afterCompletion方法之后才将数据 返回给DespacherServlet。
//视图解析器
public class InternalResourceViewResolver extends UrlBasedViewResolver {
//视图最终会经过这个方法将解析后的视图返回给DespacherServlet
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
InternalResourceView view = (InternalResourceView)super.buildView(viewName);
if (this.alwaysInclude != null) {
view.setAlwaysInclude(this.alwaysInclude);
}
view.setPreventDispatchLoop(true);
return view;
}
}
总结
如果preHandle方法返回值为true,那么拦截器中的三个方法都会执行。如果返回值为false,那么postHandle与afterCompletion将不会执行。