Blogger Information
Blog 41
fans 0
comment 0
visits 25315
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
20、【转载】Spring Boot拦截器精讲
自由之上
Original
531 people have browsed it

我们对拦截器并不陌生,无论是 Struts 2 还是 Spring MVC 中都提供了拦截器功能,它可以根据 URL 对请求进行拦截,主要应用于登陆校验、权限验证、乱码解决、性能监控和异常处理等功能上。Spring Boot 同样提供了拦截器功能。

在 Spring Boot 项目中,使用拦截器功能通常需要以下 3 步:

  1. 定义拦截器;
  2. 注册拦截器;
  3. 指定拦截规则(如果是拦截所有,静态资源也会被拦截)。

1、定义拦截器

在 Spring Boot 中定义拦截器十分的简单,只需要创建一个拦截器类,并实现 HandlerInterceptor 接口即可。
HandlerInterceptor 接口中定义以下 3 个方法,如下表。

返回值类型 方法声明 描述
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 该方法在控制器处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) 该方法在控制器处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步修改。
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 该方法在视图渲染结束后执行,可以通过此方法实现资源清理、记录日志信息等工作。

示例1
以 spring-boot-adminex 项目为例,在 net.biancheng.www.componet 中创建一个名为 LoginInterceptor 的拦截器类,对登陆进行拦截,代码如下。

  1. package net.biancheng.www.componet;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.web.servlet.HandlerInterceptor;
  4. import org.springframework.web.servlet.ModelAndView;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. @Slf4j
  8. public class LoginInterceptor implements HandlerInterceptor {
  9. /**
  10. * 目标方法执行前
  11. *
  12. * @param request
  13. * @param response
  14. * @param handler
  15. * @return
  16. * @throws Exception
  17. */
  18. @Override
  19. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  20. Object loginUser = request.getSession().getAttribute("loginUser");
  21. if (loginUser == null) {
  22. //未登录,返回登陆页
  23. request.setAttribute("msg", "您没有权限进行此操作,请先登陆!");
  24. request.getRequestDispatcher("/index.html").forward(request, response);
  25. return false;
  26. } else {
  27. //放行
  28. return true;
  29. }
  30. }
  31. /**
  32. * 目标方法执行后
  33. *
  34. * @param request
  35. * @param response
  36. * @param handler
  37. * @param modelAndView
  38. * @throws Exception
  39. */
  40. @Override
  41. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  42. log.info("postHandle执行{}", modelAndView);
  43. }
  44. /**
  45. * 页面渲染后
  46. *
  47. * @param request
  48. * @param response
  49. * @param handler
  50. * @param ex
  51. * @throws Exception
  52. */
  53. @Override
  54. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  55. log.info("afterCompletion执行异常{}", ex);
  56. }
  57. }

2、注册拦截器

创建一个实现了 WebMvcConfigurer 接口的配置类(使用了 @Configuration 注解的类),重写 addInterceptors() 方法,并在该方法中调用 registry.addInterceptor() 方法将自定义的拦截器注册到容器中。
示例 2
在配置类 MyMvcConfig 中,添加以下方法注册拦截器,代码如下。

  1. @Configuration
  2. public class MyMvcConfig implements WebMvcConfigurer {
  3. ......
  4. @Override
  5. public void addInterceptors(InterceptorRegistry registry) {
  6. registry.addInterceptor(new LoginInterceptor());
  7. }
  8. }

3、指定拦截规则

修改 MyMvcConfig 配置类中 addInterceptors() 方法的代码,继续指定拦截器的拦截规则,代码如下。

  1. @Slf4j
  2. @Configuration
  3. public class MyMvcConfig implements WebMvcConfigurer {
  4. ......
  5. @Override
  6. public void addInterceptors(InterceptorRegistry registry) {
  7. log.info("注册拦截器");
  8. registry.addInterceptor(new LoginInterceptor())
  9. .addPathPatterns("/**") //拦截所有请求,包括静态资源文件
  10. .excludePathPatterns("/", "/login", "/index.html", "/user/login", "/css/**", "/images/**", "/js/**", "/fonts/**"); //放行登录页,登陆操作,静态资源
  11. }
  12. }

在指定拦截器拦截规则时,调用了两个方法,这两个方法的说明如下:

  • addPathPatterns:该方法用于指定拦截路径,例如拦截路径为“/**”,表示拦截所有请求,包括对静态资源的请求。
  • excludePathPatterns:该方法用于排除拦截路径,即指定不需要被拦截器拦截的请求。

至此,拦截器的基本功能已经完成,接下来,我们先实现 spring-boot-adminex 的登陆功能,为验证登陆拦截做准备。

4、实现登陆功能

1、将 AdminEx 模板中的 index.html 改名为 main.html,并移动到 src/main/resources/templates 中,结构如下图。

图1:main 页面

2、在 net.bianheng.www.controller 中创建一个 LoginController, 并在其中添加处理登陆请求的方法 doLogin(),代码如下。

  1. package net.biancheng.www.controller;
  2. import lombok.extern.slf4j.Slf4j;
  3. import net.biancheng.www.bean.User;
  4. import org.springframework.stereotype.Controller;
  5. import org.springframework.util.StringUtils;
  6. import org.springframework.web.bind.annotation.GetMapping;
  7. import org.springframework.web.bind.annotation.PostMapping;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import javax.servlet.http.HttpSession;
  10. import java.util.Map;
  11. @Slf4j
  12. @Controller
  13. public class LoginController {
  14. @RequestMapping("/user/login")
  15. public String doLogin(User user, Map<String, Object> map, HttpSession session) {
  16. if (user != null && StringUtils.hasText(user.getUsername()) && "123456".equals(user.getPassword())) {
  17. session.setAttribute("loginUser", user);
  18. log.info("登陆成功,用户名:" + user.getUsername());
  19. //防止重复提交使用重定向
  20. return "redirect:/main.html";
  21. } else {
  22. map.put("msg", "用户名或密码错误");
  23. log.error("登陆失败");
  24. return "login";
  25. }
  26. }
  27. /*
  28. @RequestMapping("/main.html")
  29. public String mainPage(){
  30. return "main";
  31. }*/
  32. }

3、 在配置类 MyMvcConfig 中添加视图映射,代码如下。

  1. @Configuration
  2. public class MyMvcConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addViewControllers(ViewControllerRegistry registry) {
  5. //当访问 “/” 或 “/index.html” 时,都直接跳转到登陆页面
  6. registry.addViewController("/").setViewName("login");
  7. registry.addViewController("/index.html").setViewName("login");
  8. //添加视图映射 main.html 指向 dashboard.html
  9. registry.addViewController("/main.html").setViewName("main");
  10. }
  11. ......
  12. }

4、在 login.html 适当位置添加以下代码,显示错误信息。

  1. <p style="color: red" th:text="${msg}" th:if="${not #strings.isEmpty(msg)}"></p>

5、验证登陆及登陆拦截功能
1、 启动 Spring Boot,在未登录的情况下,直接通过“http://localhost:8080/main.html”访问主页,结果如下图。

图1:登陆被拦截

2、在登陆页用户名和密码输入框内分别输入 “admin”和“admin123”,点击下方的登陆按钮,结果如下图。

图2:登陆失败

3、在登陆页用户名和密码输入框内分别输入 “admin”和“123456”,点击下方的登陆按钮,结果如下图。

图3:登陆成功

Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post