该博客仅为本人学习时笔记记录。不能保证没有错误,请结合自己思想参考。
项目源码:
github地址:https://github.com/JYG0723/springmvcpractice/tree/master
什么是拦截器
拦截器的作用:
1. 拦截器就是浏览器发送往wen服务器的请求。来对他请求的数据或者返回的数据 做一些更改,或者在请求的执行之前或者在请求的执行之后加入一些代码。 以此来对一些请求的功能进行增强
拦截器的应用场景:
1. 稍大一些的工程中,会有许多请求。许多请求中有一些共性的问题。这些共性的问题就可以放到拦截器中去处理,(比如乱码问题。权限验证问题and so forth)
拦截器的工作原理
如果不考虑拦截器和过滤器具体细节的时候。两者作用是非常相似的,对请求进行增强处理,同时对应用程序的一些功能进行增强的目的。
拦截器的实现
xmlns是XML Namespaces的缩写。XML命名空间
xsd是 XML结构定义。格式描述文件
- 编写拦截器类,实现 HandlerInterceptor 接口。
- 将拦截器注册进 SpringMVC 框架中。
- 配置拦截器的拦截规则。
TestInterceptor:
package nuc.jyg.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author Nuc YongGuang Ji
* Created by JiYongGuang on 2017/5/17.
*/
public class TestInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
mvc-dispatcher-servlet.xml:
<!-- Configure Interceptor -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/hello/testPut"/>
<bean class="nuc.jyg.interceptor.TestInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/interceptor"/>
<bean class="nuc.jyg.interceptor.TestInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
InterceptorController:
/**
* @Author Nuc YongGuang Ji
* Created by JiYongGuang on 2017/5/17.
*/
@Controller
public class InterceptorController {
@RequestMapping(value = "/interceptor")
public void testInterceptor(HttpServletResponse servletResponse) throws IOException {
PrintWriter pw = servletResponse.getWriter();
pw.print("hello interceptor");
pw.print("hello interceptor");
System.out.println("InterceptorController class");
}
}
HelloMvcController:
/**
* @Author Nuc YongGuang Ji
* Created by JiYongGuang on 2017/5/10.
*/
@Controller
@RequestMapping("/hello")
public class HelloMvcController {
Logger logger = LoggerFactory.getLogger(HelloMvcController.class);
/*
* Put Request Method Test From Form
*
* */
@RequestMapping(value = "/testPut", method = RequestMethod.PUT)
@ResponseBody
public String testGet() {
System.out.println(1);
return "putMethod";
}
拦截器方法介绍:
1.preHandle:请求被处理之前进行调用。决定是否将当前请求拦截下来。(返回true请求继续运行,返回false请求终止(Object arg 代表被拦截的目标对象(类)。可以通过这个参数获取到该对象其中的一些内容)
2.postHandle:请求被处理之后进行调用。(ModelAndView对象可以改变发往的视图(setViewName)或修改发往视图的信息内容(addObject方法的同名信息覆盖)。
3.afterCompletion:请求结束之后进行调用。表示视图显示之后再执行该方法。(一般用于资源的销毁,不会常用)
TestInterceptor:
package nuc.jyg.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author Nuc YongGuang Ji
* Created by JiYongGuang on 2017/5/17.
*/
public class TestInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
System.out.println(handler.getClass().toString());
System.out.println(handler.getClass().getDeclaredMethods().toString());
System.out.println("preHandle /======== =========/");
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
// modelAndView.setViewName("index.jsp");
// modelAndView.addObject("addd",23);
System.out.println("postHandle /======== =========/");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
多个拦截器应用
一个应用多个拦截器包裹的执行流程图:
可以结合上图来理解。
去的时候收费站1,收费站2(preHandler)
回来的时候收费站1,收费站2(postHandler)
回到家后收到的发票1,发票2(afterCompletion)
如果我们从出发地南方,去往目的地天安门。要先经过收费站1,然后经过收费站2.当我们返回的时候,需要先经过收费站2,再经过收费站1.当我们回到家后,肯定是先经过的收费站2的发票到达我们这里,然后才是后经过的收费站1的发票到达我们这里。
mvc-dispatcher-servlet.xml:
<!-- Configure Interceptor -->
<!-- 拦截所有请求 -->
<bean class="nuc.jyg.interceptor.TestInterceptor2"/>
<bean class="nuc.jyg.interceptor.TestInterceptor"/>
</mvc:interceptors>
多个拦截器执行的先手顺序取决于 配置拦截器的顺序。
拦截器的其他实现方式
实现 WebRequestInterceptor 接口。
方法名与原来的方法名一致,参数有所区别。同时 preHandler 方法没有返回值。所以不可以在 preHandler 方法中终止请求。所以一般用功能更齐全的 HandlerInterceptor 接口。
两者向 SpringMVC 配置文件的注册方式一致。
拦截器的使用场景
使用原则:处理所有请求的共性问题。
- 解决乱码问题。
- 解决权限验证问题。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("TestInterceptor2 preHandle");
//resolver garbled problems
request.setCharacterEncoding("utf8");
/*
System.out.println(handler.getClass().toString());
System.out.println(handler.getClass().getDeclaredMethods().toString());
System.out.println("TestInterceptor2 preHandle /======== =========/");
*/
//解决权限验证问题
if (request.getSession().getAttribute("user") == null) {
request.getRequestDispatcher("login.jsp").forward(request, response);
return false;
}
return true;
}
拦截器和过滤器的区别
不难发现拦截器和过滤器作用处非常相似。
过滤器:过滤器Filter依赖于Servlet容器。基于回调函数,过滤范围大。除了可以 过滤所有请求,还可以过滤一些资源
拦截器:拦截器Interceptor依赖于框架容器。基于反射机制,只过滤向 控制器中映射了的请求路径的请求。对于向未映射的路径的请求不予处理
总结
拦截器可以处理web应用请求中的一些共性问题。
共性问题在拦截器中处理,可以减少重复代码。便于维护。
SpringMVC整个模块流程图: