springmvc拦截器
Spring Web MVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
1 常见应用场景:
1、日志记录:记录请求信息的日志,以便进行信息监控、信息统计等。
2、权限检查:如登录检测,进入处理器检测检测是否登录,如果没有直接返回到登录页面;
3、性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间;
4、通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,等,只要是多个处理器都需要的即可使用拦截器实现。
本质是AOP(面向切面编程),也就是说符合横切关注点的所有功能都可以放入拦截器实现。
2.拦截器接口:
拦截器接口HandlerInterceptor源码:
package org.springframework.web.servlet; public interface HandlerInterceptor { boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }
preHandle:预处理方法,在处理器映射器之前执行,实现处理器的预处理(如登录检查),第三个参数为响应的处理器;
返回值:true表示继续流程(如调用下一个拦截器或处理器);
false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应
postHandle:后处理方法,处理器执行器执行之后,ModelAndView返回之前执行。可以通过ModelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,ModelAndView也可能为null。
afterCompletion:整个请求处理完毕后的回调方法,即在视图渲染完毕时回调,如性能监控中可以在此记录结束时间并输出整个请求消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally。
Springmvc规定:凡是preHandle返回true,afterCompletion必须执行。
1.自定义拦截器:
package com.inter; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Interceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object o) throws Exception { System.out.println("拦截器1--Interceptor----------preHandle-----run!"); return true; } public void postHandle(HttpServletRequest req, HttpServletResponse resp, Object o, ModelAndView modelAndView) throws Exception { System.out.println("拦截器1--Interceptor----------postHandle-------run!"); } public void afterCompletion(HttpServletRequest req, HttpServletResponse resp, Object o, Exception e) throws Exception { System.out.println("拦截器1--Interceptor----------afterCompletion-------run!"); } }
2.自定义拦截器2:
package com.inter; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Interceptor2 implements HandlerInterceptor { public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object o) throws Exception { System.out.println("拦截器2--Interceptor----------preHandle-----run!"); return true; } public void postHandle(HttpServletRequest req, HttpServletResponse resp, Object o, ModelAndView modelAndView) throws Exception { System.out.println("拦截器2--Interceptor----------postHandle-------run!"); } public void afterCompletion(HttpServletRequest req, HttpServletResponse resp, Object o, Exception e) throws Exception { System.out.println("拦截器2--Interceptor----------afterCompletion-------run!"); } }
3.配置springmvc.xml文件 对URL为“findStuById.do”的地址进行拦截
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 添加注解模式 可以扫描controller、com.service、... 这里让扫描controller,指定controller的包--> <context:component-scan base-package="com"/> <!-- 配置注解处理器映射器,功能:寻找执行类Controller --> <mvc:annotation-driven></mvc:annotation-driven> <mvc:interceptors> <!--多个拦截器 按配置顺序执行--> <mvc:interceptor> <mvc:mapping path="/findStuById.do"/> <bean class="com.inter.Interceptor"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/findStuById.do"/> <bean class="com.inter.Interceptor2"/> </mvc:interceptor> </mvc:interceptors> <!-- 配置sprigmvc视图解析器:解析逻辑视图 后台返回逻辑视图:index 视图解析器解析出真正物理视图: 前缀+逻辑试图+后缀====/WEB-INF/jsps/index.jsp --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsps/"></property> <property name="suffix" value=".jsp"></property> </bean> </beans>
4.Controller层代码:
package com.controller; import com.dao.StuDao; import com.po.Student; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.service.StuService; @Controller public class StuController { @Autowired private StuService stuService; @RequestMapping("/findStuById.do") public ModelAndView findStuById(){ ModelAndView mv=new ModelAndView(); Student stu=stuService.FindStu(1); mv.addObject("stu",stu); mv.setViewName("stu"); System.out.println(stu); return mv; } }
5.进行测试:http://localhost:8080/findStuById.do
6.拦截器适配器
有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,不管我们需不需要,三个方法都必须实现。
为了方便实用,此时springmvc为我们提供了一个HandlerInterceptorAdapter适配器(一种适配器设计模式的实现),允许我们只实现需要的回调方法。