2.2.拦截器与过滤器
什么是过滤器(Filter)
依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。
拦截器与过滤器的区别
- 过滤器(filter)
1.filter属于Servlet技术,只要是web工程都可以使用
2.filter主要由于对所有请求过滤
3.filter的执行时机早于Interceptor - 拦截器(interceptor)
1.interceptor属于SpringMVC技术,必须要有SpringMVC环境才可以使用
2.interceptor通常由于对处理器Controller进行拦截
3.interceptor只能拦截dispatcherServlet处理的请求
2.3.应用场景
- 登录验证:在用户登录前,可以使用拦截器检查用户的用户名和密码是否正确,如果不正确则跳转到登录页面。
- 权限控制:在用户访问某个接口时,可以使用拦截器检查用户是否具有访问该接口的权限,如果没有权限则拒绝访问。
- 数据压缩:在返回响应给客户端之前,可以使用拦截器对响应数据进行压缩,从而减少网络传输量和提高响应速度。
- 日志记录:在控制器方法被调用时,可以使用拦截器记录请求和响应的详细信息,方便后期分析和调试。
- 跨域请求处理:在前端发起跨域请求时,可以在后端使用拦截器处理跨域问题,例如添加Access-Control-Allow-Origin头等。
2.4.拦截器快速入门
2.4.1.入门案例
拦截器(interceptor)
public class OneInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【OneInterceptor】:preHandle..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("【OneInterceptor】:postHandle..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("【OneInterceptor】:afterCompletion..."); } }
Spring-MVC.xml
<!--拦截器--> <mvc:interceptors> <bean class="com.csdn.xw.interceptor.OneInterceptor"></bean> </mvc:interceptors>
preHandle()的返回值为false就会拦截在此
注意:拦截器会根据preHandle()方法返回值进行拦截判断,返回了一个
true
值。这个返回值表示该拦截器已经处理了当前的请求,并且可以继续向下传递请求。如果返回false
,则表示该拦截器不处理当前请求,请求将被终止。
2.4.2.拦截器工作原理
- preHandle:用于对拦截到的请求进行预处理,方法接收布尔(true,false)类型的返回值,返回true:放行,false:不放行。
执行时机:在处理器方法执行前执行
参数 | 说明 |
request | 请求对象 |
response | 响应对象 |
handler | 拦截到的方法处理 |
- postHandle:用于对拦截到的请求进行后处理,可以在方法中对模型数据和视图进行修改
执行时机:在处理器的方法执行后,视图渲染之前
参数 | 说明 |
request | 请求对象 |
response | 响应对象 |
handler | 拦截到的处理器方法 |
ModelAndView | 处理器方法返回的模型和视图对象,可以在方法中修改模型和视图 |
- afterCompletion:用于在整个流程完成之后进行最后的处理,如果请求流程中有异常,可以在方法中获取对象
执行时机:视图渲染完成后(整个流程结束之后)
参数 | 说明 |
request | 请求参数 |
response | 响应对象 |
handler | 拦截到的处理器方法 |
ex | 异常对象 |
2.5.拦截器链
如果多个拦截器能够对相同的请求进行拦截,则多个拦截器会形成一个拦截器链,主要理解拦截器链中各个拦截器的执行顺序。拦截器链中多个拦截器的执行顺序,根拦截器的配置顺序有关,先配置的先执行。
拦截器(interceptor)
public class TwoInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【TwoInterceptor】:preHandle..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("【TwoInterceptor】:postHandle..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("【TwoInterceptor】:afterCompletion..."); } }
Spring-MVC.xml
<!-- 多拦截器(拦截器链)--> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.csdn.xw.interceptor.OneInterceptor"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/student/**"/> <bean class="com.csdn.xw.interceptor.TwoInterceptor"/> </mvc:interceptor> </mvc:interceptors>
这时候我们进行访问一下项目看看...
可以看到我们的两个拦截器都起到了作用。
2.6.用户登录权限案例
拦截器(interceptor)
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【implements】:preHandle..."); StringBuffer url = request.getRequestURL(); if (url.indexOf("/login") > 0 || url.indexOf("/logout") > 0){ // 如果是 登录、退出 中的一种 return true; } // 代表不是登录,也不是退出 // 除了登录、退出,其他操作都需要判断是否 session 登录成功过 String uname = (String) request.getSession().getAttribute("uname"); if (uname == null || "".equals(uname)){ response.sendRedirect("/xwzyssm/page/login"); return false; } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
Spring-MVC.xml
<!--用户登录案例--> <mvc:interceptors> <bean class="com.csdn.xw.interceptor.LoginInterceptor"></bean> </mvc:interceptors>
LoginController.java
@Controller public class LoginController { @RequestMapping("/login") public String login(HttpServletRequest req){ String uname = req.getParameter("uname"); HttpSession session = req.getSession(); if ("zs".equals(uname)){ session.setAttribute("uname",uname); } return "redirect:/student/list"; } @RequestMapping("/logout") public String logout(HttpServletRequest req){ req.getSession().invalidate(); return "redirect:/student/list"; } }
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登陆页面</title> </head> <body> <h1>登陆页面</h1> <form action="/login" method="post"> 用户名:<input name="uname"> <input type="submit"> </form> </body> </html>
总结:如果用户发送URL中的后缀包含"/login"或"/logout",则表示当前请求是登录或退出操作,直接返回true表示继续处理请求,后端进行判断“uname”是否为“zs”,如果不是zs则域对象不会保存,从而到拦截器判断域对象为空则会重定向到登良页面,如果不为空就执行后端返回的字符串到视图解析器解析跳转指定页面。
到这里我的分享就结束了,欢迎到评论区探讨交流!!
💖如果觉得有用的话还请点个赞吧 💖