拦截自定义黑名单是什么意思(day13-自定义拦截器)
自定义拦截器
1.什么是拦截器
说明:
拦截器与过滤器的区别
SpringMVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似 ,它主要用于拦截用户的请求并做相应的处理 ,通常应用在权限验证 、记录请求信息的日志 、判断用户是否登录等功能上 。
SpringMVC 也可以使用拦截器对请求进行拦截处理 ,用户可以自定义拦截器来实现特定的功能
自定义的拦截器必须实现 HandlerInterceptor 接口
自定义拦截器的三个方法:
(1)preHandle():该方法在业务处理器处理请求之前被调用 ,在该方法中对用户请求 request 进行处理
(2)postHandle():该方法在目标方法处理完请求之后执行
(3)afterCompletion():该方法在完全处理完请求之后被调用 ,可以在该方法中进行一些资源清理的操作
2.自定义拦截器执行流程分析图
● 自定义拦截器执行流程说明
拦截器中方法的执行顺序是 preHandle -> Controller -> postHandle -> afterCompletion ,只有preHandle返回true ,才会执行后面的方法
如果 preHandle 方法返回 false, 则不再执行目标方法及之后的拦截方法 ,可以在该方法指定返回页面 postHandle 在目标方法被执行后执行 ,可以在 postHandle 方法中访问到目标方法返回的 ModelAndView 对象 若 preHandle 返回 true, 则 afterCompletion 方法在渲染视图之后被执行 若 preHandle 返回 false, 则 afterCompletion 方法不会被调用 配置拦截器时可以指定该拦截器对哪些请求生效 ,哪些请求不生效 ,如果不指定则默认对所有目标方法生效3.应用实例
3.1快速入门
完成一个自定义拦截器 ,学习如何配置拦截器和拦截器的运行流程 。
(1)创建拦截器 MyInterceptor01.java
package com.li.web.interceptor; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author 李 * @version 1.0 */ //需要标识为component注入到spring容器中 @Component public class MyInterceptor01 implements HandlerInterceptor { /** * 1.preHandle 方法在目标方法执行前被执行 * 2.如果 preHandle 方法返回了false,则目标方法不再被执行 * 3.preHandle方法可以获取到 request ,response ,handler * 4.如果该方法返回了 false,你可以指定跳转到哪个页面 * @param request * @param response * @param handler 要执行的处理器 * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("===MyInterceptor01--preHandle()==="); return true; } /** * 1.在目标方法执行后 ,会执行 postHandle 方法 * 2.postHandle 方法可以获取到目标方法返回的 modelAndView * @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("===MyInterceptor01--postHandle()==="); } /** * 1.afterCompletion 方法在视图渲染后被执行 * 2.在 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("===MyInterceptor01--afterCompletion()==="); } }(2)在 spring 的容器文件中配置拦截器
<!--配置自定义拦截器--> <mvc:interceptors> <!-- 1.第一种配置方式 2.直接使用ref引用到对应的 myInterceptor01 3.这种方式会拦截所有的目标方法 --> <ref bean="myInterceptor01"/> </mvc:interceptors>(3)测试 Controller
package com.li.web.interceptor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author 李 * @version 1.0 */ @Controller public class TestHandler { @RequestMapping(value = "/hi") public String hi() { System.out.println("===TestHandler--hi()==="); return "success"; } @RequestMapping(value = "/hello") public String hello() { System.out.println("===TestHandler--hello()==="); return "success"; } }(4)interceptor.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>测试自定义拦截器</title> </head> <body> <h1>测试自定义拦截器</h1> <a href="https://www.cnblogs.com/liyuelian/archive/2023/02/18/<%=request.getContextPath()%>/hi">测试自定义拦截器-hi</a><br/><br/> <a href="https://www.cnblogs.com/liyuelian/archive/2023/02/18/<%=request.getContextPath()%>/hello">测试自定义拦截器-hello</a> </body> </html>(5)启动 tomcat ,访问 interceptor.jsp ,分别点击两个超链接
后台输出如下:
可以看到方法的执行顺序为:preHandler-->目标方法-->postHandle-->afterCompletion ,并且拦截器对Controller 所有的方法都进行了拦截 。
3.2注意事项和使用细节
默认配置是对所有的目标方法都进行拦截 ,也可以指定拦截某个目标方法 ,如在 spring 容器文件中配置:
<!--配置自定义拦截器--> <mvc:interceptors> <!-- 1.第二种配置方式 2.mvc:mapping path="/hi" 指定要拦截的目标方法的路径 3.ref bean="myInterceptor01" 指定对哪个拦截器进行配置 --> <mvc:interceptor> <mvc:mapping path="/hi"/> <ref bean="myInterceptor01"/> </mvc:interceptor> </mvc:interceptors>mvc:mapping 支持通配符 ,同时可以指定不对哪些目标方法进行拦截 ,例如:
<!--配置自定义拦截器--> <mvc:interceptors> <!-- 1.第三种配置方式 2.mvc:mapping path="/h*" 表示拦截 /h 开头的路径的目标方法 3.mvc:exclude-mapping path="/hello" 表示不拦截指定路径的目标方法 4.ref bean="myInterceptor01" 指定对哪个拦截器进行配置 --> <mvc:interceptor> <!--h开头的目标方法都被拦截--> <mvc:mapping path="/h*"/> <mvc:exclude-mapping path="/hello"/> <ref bean="myInterceptor01"/> </mvc:interceptor> </mvc:interceptors>拦截器需要配置才生效 ,不配置是不生效的
如果 preHandle() 方法返回了 false ,就不会执行目标方法(前提是目标方法指定了拦截) ,你可以在该方法中根据业务指定要跳转的页面
3.3Debug执行流程
(1)在自定义拦截器 MyInterceptor01 的 preHandle 方法中打上断点 ,点击 debug
(2)浏览器访问页面 interceptor.jsp,点击第一个链接 ,访问目标方法 hi()
(3)后台光标跳转到断点处 ,此时 preHandle 方法已经拿到了目标方法,说明 preHandle 方法在目标方法前执行
(4)在目标方法 hi 中添加断点 ,点击 resume ,光标跳转到断点处
(5)在拦截器的 postHandle 方法中添加断点 ,点击 resume ,光标如期跳转到该断点处 。在该方法中可以拿到目标方法对应的 ModelAndView 对象 ,其中 view 就是指定的要返回的页面 ,model 就是目标方法的数据 。
(6)ModelAndView 对象在 DispatcherServlet 的 resolveViewName 方法进行解析 ,返回视图 ,视图在 render 方法中进行视图渲染
(7)在拦截器的 afterCompletion 方法中打上断点 ,点击 resume ,光标跳转到该断点处
(8)这一个拦截流程就结束了 ,再次点击 resume ,就会向客户端返回数据
4.多个拦截器
4.1多个拦截器执行流程示意图
4.2实例演示1-执行流程
4.2.1代码实现(1)在3.1中快速入门中已经创建了一个拦截器,现在创建第二个拦截器 MyInterceptor02.java
package com.li.web.interceptor; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author 李 * @version 1.0 */ @Component public class MyInterceptor02 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("===MyInterceptor02--preHandle()==="); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("===MyInterceptor02--postHandle()==="); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("===MyInterceptor02--afterCompletion()==="); } }(2)在 spring 的容器文件中配置拦截器
<!--配置自定义拦截器--> <mvc:interceptors> <mvc:interceptor> <!--h开头的目标方法都被拦截--> <mvc:mapping path="/h*"/> <mvc:exclude-mapping path="/hello"/> <ref bean="myInterceptor01"/> </mvc:interceptor> <!-- 第二个拦截器 多个拦截器在执行时 ,按照配置的顺序执行 --> <mvc:interceptor> <mvc:mapping path="/h*"/> <ref bean="myInterceptor02"/> </mvc:interceptor> </mvc:interceptors>(3)interceptor.jsp 不变
(4)完成测试 ,浏览器访问 jsp 页面,点击访问目标方法 hi
(5)后端输出如下:与分析的流程一致 。
(6)如果把第二个拦截器的 preHandle 方法返回值改为 false ,重新访问目标方法测试 ,后台输出如下:
4.2.2注意事项和使用细节如果第一个拦截器的 preHandle() 返回 false ,后面都不再执行 ,包括目标方法
如果第二个拦截器的 preHandle() 返回 false ,就直接执行第一个拦截器的 afterCompletion() 方法 ,如果拦截器更多 ,规则类似 。
以上两条规则 ,都是在目标方法符合被拦截条件的前提下 。
4.3实例演示2-跳转至指定页面
需求:如果用户提交的数据有禁用词(比如:病毒) ,则在第一个拦截器就返回 ,不执行目标方法 ,跳转至执行页面
4.3.1代码实现(1)修改 MyInterceptor01.java 的 preHandle 方法
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("===MyInterceptor01--preHandle()==="); //获取用户提交的关键字 String keyword = request.getParameter("keyword"); if ("病毒".equals(keyword)) { //请求转发到指定页面 request.getRequestDispatcher("/WEB-INF/pages/warning.jsp") .forward(request, response); return false; } System.out.println("keyword=" + keyword); return true; }(2)warning.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>警告</title> </head> <body> <h1>你的信息中含有违规词</h1> </body> </html>(3)在 postman 中进行测试
测试1:无违禁词
后台输出:
测试2:含违禁词
后台输出:
5.练习
将之前的 SpringMVC 文件上传 、自定义拦截器相关代码和案例过一遍 简述 SpringMVC 自定义拦截器工作流程 ,并画出示意图 debug 自定义拦截器源码,加深理 ,梳理流程创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!