【SpringMVC】| SpringMVC拦截器 我就是我 2024-03-27 11:30 22阅读 0赞 **目录** 一:SpringMVC拦截器 1. 拦截器介绍 2. HandlerInterceptor接口分析 3. 自定义拦截器实现权限验证 -------------------- ## 一:SpringMVC拦截器 ## > SpringMVC 中的 Interceptor 拦截器,它的主要作用是拦截指定的用户请求,并进行相应的预处理与后处理。其拦截的时间点在“处理器映射器根据用户提交的请求映射出了所要执行的处理器类,并且也找到了要执行该处理器类的处理器适配器,在处理器适配器执行处理器之前”。当然,在处理器映射器映射出所要执行的处理器类时,已经将拦截器与处理器组合为了一个处理器执行链,并返回给了中央调度器。 #### 1. 拦截器介绍 #### (1)拦截器的应用场景 > 针对请求和响应进行的额外的处理,在请求和响应的过程中添加**预处理、后处理和最终处理**;主要应用在以下场景当中: > > ①日志记录:记录请求信息的日志。 > > ②权限检查:如登录检查。 > > ③性能检测:检测方法的执行时间。 (2)拦截器的执行原理 ![5d461b7410834eb28c5a853df3d53e46.png][] > **①preHandle():**在请求被处理之前进行操作;**预处理**。 > **②postHandle():**在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果;**后处理。** > **③afterCompletion:**所有的请求响应结束后执行善后工作,清理对象、关闭资源 ;**最终处理.。** **(3)拦截器实现的两种方式** > ①**继承HandlerInterceptorAdapter【处理程序拦截适配器】**的父类。 > ②**实现HandlerInterceptor【处理程序拦截器】接口**,推荐使用实现接口的方式,因为继承是单继承的。 #### 2. HandlerInterceptor接口分析 #### **自定义拦截器,需要实现 HandlerInterceptor 接口;并且该接口中含有三个方法:** **(1)preHandle** > 该方法在处理器方法执行之前执行。其返回值为 boolean类型,若为 true,则紧接着会执行处理器方法,且会将 afterCompletion()方法放入到一个专门的方法栈中等待执行。 (2)postHandle > 该方法在处理器方法执行之后执行。**处理器方法若最终未被执行,则该方法不会执行**。由于该方法是在处理器方法执行完后执行,且该方法参数中包含 ModelAndView,所以该方法可以修改处理器方法的处理结果数据,且可以修改跳转方向。 (3)afterCompletion > **当preHandle()方法返回 true 时**,会将该方法放到专门的方法栈中,等到对请求进行响应的所有工作完成之后才执行该方法。即该方法是在中央调度器渲染(数据填充)了响应页面之后执行的,此时对 ModelAndView 再操作也对响应无济于事。**afterCompletion 最后执行的方法,清除资源,例如在 Controller 方法中加入数据等。** #### 3. 自定义拦截器实现权限验证 #### (1)改造登录方法,在session中存储用户信息,用于进行权限验证 > **细节:**一定要注意我们登录界面login.jsp跳转到的是/login还是/login.action;有没有带action直接决定我们后面拦截器exclude-mapping通行的路径带不带.action! package com.bjpowernode.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; @Controller public class WebInfAction { // 首先要跳转到登录页面 @RequestMapping("/showLogin") public String submit(){ System.out.println("访问login.jsp进行登录"); return "login"; } // 跳转到login.jsp后,在进行判断 @RequestMapping("/login") public String login(String name, String pwd, HttpServletRequest request){ // 与前端保持一致,提交的数据自动吸过来 if ("root".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){ // 在session中存储用户信息(把name存进去),用于权限验证 request.getSession().setAttribute("user",name); return "main"; }else { request.setAttribute("msg","用户名或者密码不正确"); return "login"; } } } (2)开发拦截器的功能,实现HandlerInterceptor接口,重写preHandle()方法 package com.bjpowernode.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginInterceptor implements HandlerInterceptor { // 重写preHandle方法 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 是否登录的判断 if(request.getSession().getAttribute("user") == null){ // 能取出来,表示登录过 // 没有登录,打回到登录的页面,并给出提示 request.setAttribute("msg","请先去登录!"); request.getRequestDispatcher("WEB-INF/jsp/login.jsp").forward(request,response); return false; } // 如果登录过,就放行往下走 return true; } } (3)在springmvc.xml文件中注册拦截器 > 拦截器中可以配置一个拦截器链,层层把关;这里我们只需要配置一个,总共配置三部分: > > ①映射要拦截的请求,一般设置为全部拦截。 > > ②然后在设置要放行的请求。 > > ③配置具体的拦截器实现功能的类。 <!--注册拦截器--> <mvc:interceptors> <mvc:interceptor> <!--映射要拦截的请求--> <mvc:mapping path="/**"/> <!--配置要放行的请求--> <mvc:exclude-mapping path="/showLogin"/><!--登录的页面--> <mvc:exclude-mapping path="/login"/><!--登录验证的页面--> <!--配置具体的拦截器实现功能的类--> <bean class="com.bjpowernode.interceptor.LoginInterceptor"/> </mvc:interceptor> </mvc:interceptors> (4)测试: 在登录之前,我们还是知道showMain或者showIndex,直接访问是不能访问的,被拦截了 ![1099e782971943da89575e918ca57029.png][] 在成功登录之后,我们不关闭当前会话,重新开一个窗口, 直接访问就可以访问了 ![0e045c19ab7149429b5f82b891c4abf9.png][] [5d461b7410834eb28c5a853df3d53e46.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/27/9945e1a95aa54205a5d7029a997a0702.png [1099e782971943da89575e918ca57029.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/27/12890029707a406b92e54a1da4a47f56.png [0e045c19ab7149429b5f82b891c4abf9.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/03/27/a9a211d63bf445f3a22b9a833b31eb91.png
还没有评论,来说两句吧...