十一,Spring Boot 当中配置拦截器的“两”种方式

打印 上一主题 下一主题

主题 829|帖子 829|积分 2487

十一,Spring Boot 当中配置拦截器的“两”种方式

@
目录

在Spring Boot项目中,拦截器是开发中常用本领,要来做登录验证,性能检查,日记记录等。
基本步调:
1. 准备工作:

在 pom.xml 文件当中,导入相关的 jar 包文件。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5.     <modelVersion>4.0.0</modelVersion>
  6.     <groupId>com.rainbowsea</groupId>
  7.     <artifactId>springboot_usersys</artifactId>
  8.     <version>1.0-SNAPSHOT</version>
  9.    
  10.     <parent>
  11.         <groupId>org.springframework.boot</groupId>
  12.         <artifactId>spring-boot-starter-parent</artifactId>
  13.         <version>2.5.3</version>
  14.     </parent>
  15.    
  16.    
  17.     <dependencies>
  18.         <dependency>
  19.             <groupId>org.springframework.boot</groupId>
  20.             <artifactId>spring-boot-starter-web</artifactId>
  21.         </dependency>
  22.         
  23.         <dependency>
  24.             <groupId>org.projectlombok</groupId>
  25.             <artifactId>lombok</artifactId>
  26.         </dependency>
  27.         
  28.         <dependency>
  29.             <groupId>org.springframework.boot</groupId>
  30.             <artifactId>spring-boot-starter-thymeleaf</artifactId>
  31.         </dependency>
  32.         
  33.         <dependency>
  34.             <groupId>org.projectlombok</groupId>
  35.             <artifactId>lombok</artifactId>
  36.         </dependency>
  37.     </dependencies>
  38. </project>
复制代码
编写相关项目的启动场景。
  1. package com.rainbowsea.springboot;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication // 项目启动标志
  5. public class Application {
  6.     public static void main(String[] args) {
  7.         SpringApplication.run(Application.class,args);
  8.     }
  9. }
复制代码
对应的 Bean 类
  1. package com.rainbowsea.springboot.bean;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. @Data
  5. @NoArgsConstructor  // 无参数
  6. public class Admin {
  7.     private String name;
  8.     private String password;
  9. }
复制代码
  1. package com.rainbowsea.springboot.bean;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. @Data
  6. @NoArgsConstructor // 无参数
  7. @AllArgsConstructor  // 全参数
  8. public class User {
  9.     private Integer id;
  10.     private String name;
  11.     private String password;
  12.     private Integer age;
  13.     private String email;
  14. }
复制代码
编写相关 thymeleaf 视图,HTML文件。
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>管理后台</title>
  6. </head>
  7. <body>
  8. <a target="_blank" href="https://www.cnblogs.com/#">返回管理界面</a> <a target="_blank" href="https://www.cnblogs.com/#">安全推出</a>
  9. <hr>
  10.     <h1>管理员</h1>
  11.     <table border="1px" cellspacing="0" bordercolor="green" >
  12.         <tr bgcolor="pink">
  13.             <td>id</td>
  14.             <td>name</td>
  15.             <td>pwd</td>
  16.             <td>email</td>
  17.             <td>age</td>
  18.         </tr>
  19.         <tr bgcolor="#7fffd4"  th:each="user:${users}">
  20.             <td th:text="${user.id}"></td>
  21.             <td th:text="${user.name}"></td>
  22.             <td th:text="${user.password}"></td>
  23.             <td th:text="${user.email}"></td>
  24.             <td th:text="${user.age}"></td>
  25.         </tr>
  26.     </table>
  27. </body>
  28. </html>
复制代码
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>login</title>
  6. </head>
  7. <body>
  8.     <h1>用户登录</h1>
  9.     <form action="#" th:action="@{/login}" method="post">
  10.         <label  th:text="${msg}"></label>
  11.         用户名: <input type="text"  name="name">
  12.         密码: <input type="password"  name="password">
  13.         <input type="submit" value="登录">
  14.         <input type="reset" value="重新填写">
  15.     </form>
  16. </body>
  17. </html>
复制代码
相关的 controller 控制器,处理请求内容。
  1. package com.rainbowsea.springboot.controller;
  2. import com.rainbowsea.springboot.bean.Admin;
  3. import com.rainbowsea.springboot.bean.User;
  4. import com.sun.org.apache.xpath.internal.operations.Mod;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.ui.Model;
  7. import org.springframework.util.StringUtils;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.PostMapping;
  10. import javax.jws.WebParam;
  11. import javax.servlet.http.HttpSession;
  12. import java.util.ArrayList;
  13. @Controller
  14. public class AdminController {
  15.     @PostMapping("/login")
  16.     public String login(Admin admin, HttpSession session, Model model) {
  17.         // 验证用户是否合法
  18.         if(StringUtils.hasText(admin.getName()) && "666".equals(admin.getPassword())) {
  19.             // 将登录用户保险到 session会话域当中
  20.             session.setAttribute("loginAdmin",admin);
  21.             // 合法,重定向到manage.html
  22.             // 请小伙伴回忆,Java web ,不使用请求转发是防止刷新页面会重复提交
  23.             // 这里老师为什么写的是 manage.html,因为这样可以更加明确的表示到哪个页面
  24.             // manage.html 表示要去找方法的映射路径为: manage.html
  25.             return "redirect:/manage.html";
  26.         } else {
  27.             // 不合法,就重新登录,请求转发
  28.             model.addAttribute("msg","账号/用户错误");
  29.             return "adminLogin";  // 视图解析
  30.         }
  31.     }
  32.     // 处理用户的请求到 manage.html
  33.     // 是重定向——>get
  34.     @GetMapping("/manage.html")
  35.     public String mainPage(Model model,HttpSession session){
  36.         // 可以这里集合~模板数据,放入到request域中,并显示
  37.         ArrayList<User> users = new ArrayList<>();
  38.         users.add(new User(1,"关羽","666",28,"gy@ohu.com"));
  39.         users.add(new User(2,"关羽","666",28,"gy@ohu.com"));
  40.         users.add(new User(3,"关羽","666",28,"gy@ohu.com"));
  41.         users.add(new User(4,"关羽","666",28,"gy@ohu.com"));
  42.         users.add(new User(5,"关羽","666",28,"gy@ohu.com"));
  43.         model.addAttribute("users",users);  // 放入到请求域当中
  44.         return "manage";  // 视图解析器
  45.         // 拦截器处理
  46.         // 获取到 session会话域当中的信息,判断用户是否登录过,进行一个过滤
  47.         /*Object loginAdmin = session.getAttribute("loginAdmin");
  48.         if(null != loginAdmin) {  // 说明成功登录过
  49.             // 可以这里集合~模板数据,放入到request域中,并显示
  50.             ArrayList<User> users = new ArrayList<>();
  51.             users.add(new User(1,"关羽","666",28,"gy@ohu.com"));
  52.             users.add(new User(2,"关羽","666",28,"gy@ohu.com"));
  53.             users.add(new User(3,"关羽","666",28,"gy@ohu.com"));
  54.             users.add(new User(4,"关羽","666",28,"gy@ohu.com"));
  55.             users.add(new User(5,"关羽","666",28,"gy@ohu.com"));
  56.             model.addAttribute("users",users);  // 放入到请求域当中
  57.             return "manage";  // 视图解析器
  58.         } else {
  59.             // 说明没有登录过,
  60.             // 这里就返回登录页,并给出提示
  61.             model.addAttribute("msg","你没有登录/请登录");  // 请求域
  62.             return "adminLogin"; // 请求转发到 adminLogin.html视图解析
  63.         }*/
  64.     }
  65. }
复制代码
  1. package com.rainbowsea.springboot.controller;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.GetMapping;
  4. @Controller
  5. public class IndexController {
  6.     // 编写方法,转发到登录页面
  7.     /*
  8.     解释:
  9.     1.因为我们引入了 starter-thymeleaf
  10.     2.这里就会直接使用视图解析到thymeleaf下的模板文件admin
  11.      */
  12.     @GetMapping(value = {"/","/login"})
  13.     public String login(){
  14.         return "adminLogin";
  15.     }
  16. }
复制代码
演示:拦截器:这里我们演示,登录页面的拦截:


  • 当用户没有登录过的时候,不可以访问后面的内容
  • 当用户登录过了,就可以访问后面的内容了。


2. Spring Boot当中配置拦截器的第一种方式:通过配置类的方式

首先我们需要定义一个类,而且该类要实现  implements HandlerInterceptor 接口,同时重写其中的 :preHandle( ),postHandle( ),afterCompletion( ) 的三个方法。根据业务拦截的需要,在这个三个方法中,编写,拦截的业务处理。

  1. package com.rainbowsea.springboot.interceptor;
  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. import javax.servlet.http.HttpSession;
  8. @Slf4j
  9. public class LoginInterceptor implements HandlerInterceptor {
  10.     @Override
  11.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  12.         // 为了让大家看到访问的URI
  13.         String requestURI = request.getRequestURI();
  14.         String requestURL = request.getRequestURL().toString();
  15.         log.info("preHandle 拦截到的请求URI={}", requestURI);
  16.         log.info("preHandle 拦截到的请求URL={}", requestURL);
  17.         // 进行登录的校验
  18.         HttpSession session = request.getSession();
  19.         Object loginAdmin = session.getAttribute("loginAdmin");
  20.         if (null != loginAdmin) { // 说明该用户已经成功登录
  21.             // 返回 true 就是放行
  22.             return true;
  23.         } else {
  24.             // 拦截,重新返回到登录页面
  25.             request.setAttribute("msg", "你没有登录/请登录~~~");
  26.             // 注意:因为这里我们只有一个内容被拦截了,而且该内容的 uri路径就是我们要跳转进入的路径
  27.             request.getRequestDispatcher("/").forward(request, response);  // 重定向
  28.             return false; // 拦截了,不放行
  29.         }
  30.     }
  31.     @Override
  32.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  33.         log.info("postHandle执行了...");
  34.     }
  35.     @Override
  36.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  37.         log.info("afterCompletion执行了...");
  38.     }
  39. }
  40. // HandlerInterceptor
复制代码
定义一个配置类,在配置类当中,编写我们要拦截哪些请求路径映射,放行哪些请求路径的映射。
注意:

  • 添加上:@Configuration 注解  // 标注是配置类
  • 该类要实现:implements WebMvcConfigurer 类
  • 重写其中的:public void addInterceptors(InterceptorRegistry registry) 方法。
  1. package com.rainbowsea.springboot.config;
  2. import com.rainbowsea.springboot.interceptor.LoginInterceptor;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  7. @Configuration  // 标注是配置类,配置拦截器,
  8. public class WebConfig
  9.         implements WebMvcConfigurer {
  10.     @Override
  11.     public void addInterceptors(InterceptorRegistry registry) {
  12.         // 注册自定义拦截器LoginInterceptor
  13.         registry.addInterceptor(new LoginInterceptor())
  14.                 .addPathPatterns("/**")  // 拦截所有的请求
  15.                 .excludePathPatterns("/","/login","/images/**"); // 还要放行视图的内容,因为上面是
  16.         // 拦截所有,注意不要: templates ,因为sprinboot的默认配置,就是以templates为根路径往下找的
  17.         // 所以添加就错了,就成了 /templates/templates/images/**了。
  18.     }
  19. }
复制代码
注意点:
  1. @Override
  2.     public void addInterceptors(InterceptorRegistry registry) {
  3.         // 注册自定义拦截器LoginInterceptor
  4.         registry.addInterceptor(new LoginInterceptor())
  5.                 .addPathPatterns("/**")  // 拦截所有的请求
  6.                 .excludePathPatterns("/","/login","/images/**"); // 还要放行视图的内容,因为上面是
  7.         // 拦截所有,注意不要: templates ,因为sprinboot的默认配置,就是以templates为根路径往下找的
  8.         // 所以添加就错了,就成了 /templates/templates/images/**了。
  9.     }
复制代码


  1. // 还要放行视图的内容,因为上面是
  2.         // 拦截所有,注意不要: templates ,因为sprinboot的默认配置,就是以templates为根路径往下找的
  3.         // 所以添加就错了,就成了 /templates/templates/images/**了。
复制代码
注意:配置了拦截器的话,图片之类的一些静态资源的访问以及一些文件上传下载,也是要注意放行的,已经视图解析器也是放行的,要放行视图的内容,由于上面是addPathPatterns("/**")  // 拦截所有的请求拦截所有,注意不要: templates ,由于sprinboot的默认配置,就是以templates为根路径往下找的,所以再添加 templates 就错了,就成了 /templates/templates/images 了。
简朴的就是:记着注意好 Spring Boot的根路径是从哪里开始的,以哪里为根路径的,大概有多个标准/参照路径。
3. Spring Boot 当中配置拦截器的第二种方式:

基于第一种方式修改,webconfig 配置类即可。
  1. package com.rainbowsea.springboot.config;
  2. import com.rainbowsea.springboot.interceptor.LoginInterceptor;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  7. @Configuration  // 标注配置类,配置拦截器
  8. public class WebConfig {
  9.     @Bean
  10.     public WebMvcConfigurer webMvcConfigurer() {
  11.         return new WebMvcConfigurer() {
  12.             @Override
  13.             public void addInterceptors(InterceptorRegistry registry) {
  14.                 System.out.println("addInterceptors~~~");
  15.                 // 注册拦截器
  16.                 registry.addInterceptor(new LoginInterceptor())
  17.                         .addPathPatterns("/**")
  18.                         .excludePathPatterns("/","/login","/images/**");
  19.             }
  20.         };
  21.     }
  22. }
复制代码
4. 增补:URI 和 URL 的区别

1.URI 和 URL 的区别
URI = Universal Resource Identifier
URL = Universal Resource Locator
  1.   // 为了让大家看到访问的URI
  2.         String requestURI = request.getRequestURI(); // preHandle 拦截到的请求URI=/manage.html
  3.         String requestURL = request.getRequestURL().toString();  // preHandle 拦截到的请求URL=http://localhost:8080/manage.html
复制代码
5. 总结:

  1. // 还要放行视图的内容,因为上面是
  2.         // 拦截所有,注意不要: templates ,因为sprinboot的默认配置,就是以templates为根路径往下找的
  3.         // 所以添加就错了,就成了 /templates/templates/images/**了。
复制代码
注意:配置了拦截器的话,图片之类的一些静态资源的访问以及一些文件上传下载,也是要注意放行的,已经视图解析器也是放行的,要放行视图的内容,由于上面是addPathPatterns("/**")  // 拦截所有的请求拦截所有,注意不要: templates ,由于sprinboot的默认配置,就是以templates为根路径往下找的,所以再添加 templates 就错了,就成了 /templates/templates/images 了。
简朴的就是:记着注意好 Spring Boot的根路径是从哪里开始的,以哪里为根路径的,大概有多个标准/参照路径。
6. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

魏晓东

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表