1. 说明
-
过滤器
依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
-
拦截器
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理
2. 拦截器应用场景
权限控制 检测登录 请求到达,先通过拦截器检测权限
日志记录 记录请求信息的日志,便于信息监控、信息统计
3. 配置步骤
创建一个拦截器,实现HandleInterceptor接口,重写三个方法
拦截器配置:
可以使用的通配符
符号 | 说明 |
---|---|
? | 匹配任何一个字符 |
* | 匹配任何长度的字符 |
** | 匹配多级目录的路径 |
preHandle:handle方法执行之前执行,返回true代表此次放行,false代表拦截下来
postHandle:Handle方法执行之后执行
afterHandle:页面渲染完毕之后执行
controller:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Demo1Controller {
@RequestMapping("/demo1")
public String demo1(Model model) {
model.addAttribute("msg","haha");
System.out.println("controller执行啦!");
return "/success.jsp";
}
}
拦截器1:
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor1 implements HandlerInterceptor {
/**
* handler方法执行之前执行
* @param request
* @param response
* @param handler:执行的Handler对象(HandleMethod)
* @return
* true:代表放行
* false:代表拦截
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(handler.getClass()); //class org.springframework.web.method.HandlerMethod
System.out.println("handle执行之前--1");
return true;
}
/**
* handle方法执行之后执行
* @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(handler.getClass());
modelAndView.setViewName("/index.jsp"); //修改handle方法中设置的视图
modelAndView.addObject("msg","heiheihei"); //添加参数
System.out.println("handler执行之后--1");
}
/**
* 页面渲染后执行
* @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(handler.getClass());
System.out.println("页面渲染之后--1");
}
}
拦截器2:
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("handle执行之前--2");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("handler执行之后--2");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("页面渲染之后--2");
}
}
Spring配置文件配置
<!--拦截器配置-->
<mvc:interceptors>
<!--配置单个拦截器-->
<mvc:interceptor>
<!--
path:拦截规则
?:匹配单个字符
*:代表匹配任意长度的字符(只能匹配单机目录)
**:代表匹配任意长度的多级目录
-->
<mvc:mapping path="/**"/>
<!--代表拦截/user下的所有请求-->
<mvc:mapping path="/user/*"/>
<!--代表放行/user/register请求-->
<mvc:exclude-mapping path="/user/register"/>
<!--配置拦截器-->
<bean class="com.cgr.interceptor.MyInterceptor1" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.cgr.interceptor.MyInterceptor2" />
</mvc:interceptor>
</mvc:interceptors>
探究拦截器执行顺序:
解决拦截器拦截静态资源问题
mvc:resource方式的解决:
在拦截器配置位置增加
<mvc:exclude-mapping path="/css/**"/>
<mvc:exclude-mapping path="/js/**"/>