SpringBoot-拦截器

  |   0 评论   |   0 浏览

SpringBoot-拦截器

1.基本介绍

  1. 在 Spring Boot 项目中, 拦截器是开发中常用手段,要来做登陆验证、性能检查、日志记录等。
  2. 基本步骤:

√ 编写一个拦截器实现 HandlerInterceptor 接口

√ 拦截器注册到配置类中(实现 WebMvcConfigurer 的 addInterceptors)

√ 指定拦截规则

image-20220807182359263

2.拦截器应用实例

1.需求: 使用拦截器防止用户非法登录, 如图 - 使用拦截器就不需要在每个方法验证了

● 浏览器输入 : http://localhost:8080/manage.html , 如果用户没有登录,则返回登录界面.

image-20220807183609295

2.代码实现

1.创建src\main\java\com\llp\springboot\interceptor\LoginInterceptor.java

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 目标方法执行之前执行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //看看requestURI 和 requestURL的区别
        String requestURI = request.getRequestURI();
        String requestURL = request.getRequestURL().toString();
        //URI=/manage.html
        log.info("preHandle拦截到的请求的URI={}", requestURI);
        //URL=http://localhost:8080/manage.html
        log.info("preHandle拦截到的请求的URL={}", requestURL);

        Object admin = request.getSession().getAttribute("admin");
        if (admin != null) {
            return true;
        }

        //拦截, 重新返回到登录页面
        //adminLogin.html 去除msg的方式是从request域获取
        request.setAttribute("msg", "您尚未登录,请登录");
        request.getRequestDispatcher("/").forward(request, response);
        return false;
    }

    /**
     * 在目标方法被执行后执行. 可以在方法中访问到目标方法返回的 ModelAndView 对象
     * 若 preHandle 返回 true, 则 afterCompletion 方法 在渲染视图之后被执行.
     * 若 preHandle 返回 false, 则 afterCompletion 方法不会被调用
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle 执行了。。。");
    }

    /**
     * 在渲染视图之后被执行.
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("afterCompletion 执行了。。。");
    }
}

2.创建src\main\java\com\llp\springboot\config\WebConfig.java对我们定义的拦截器进行注册拦截路径配置

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        /**
         * 1.拦截器会先拦截controller的路径映射
         * 2.如果找不到则去静态资源下查找
         * 3.这里配置/**会拦截所有的请求,包括静态资源
         * 4.这里不拦截静态资源,为什么直接写成 "/images/**","/css/**" ?
         * 5.在SpringBoot中引入了spring-boot-starter-web 依赖,每个starter都会对于的自动装配
         * 6.在WebProperties中配置了类路径映射,因此可以直接省略/static/
         * private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
         *              "classpath:/resources/", "classpath:/static/", "classpath:/public/" };
         *
         */
        registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/","/login","/images/**","/css/**");
    }

}

3.修改src\main\java\com\llp\springboot\controller\AdminController.java

@Controller
public class AdminController {

    @PostMapping("/login")
    public String login(Admin admin, HttpSession session, Model model) {
        if (StringUtils.hasText(admin.getUsername()) && "666".equals(admin.getPassword())) {
            //1.这里使用重定向,不适用请求转发,防止刷新页面表单重复提交
            //2./manage.html /会被解析成ip:port ,而manage.html是指定浏览器下一次请求访问的路径
            //3.重定向会发起get请求
            System.out.println(admin);
            session.setAttribute("admin", admin);
            return "redirect:/manage.html";
        } else {
            model.addAttribute("msg", "密码错误");
            return "adminLogin";
        }
    }

    @GetMapping("manage.html")
    public String manage(Model model, HttpSession session) {

            //可以这里集合-模拟用户数据, 放入到request域中,并显示
            ArrayList<User> users = new ArrayList<>();
            users.add(new User(1, "关羽~", "666666", 20, "gy@sohu.com"));
            users.add(new User(2, "张飞", "666666", 30, "zf@sohu.com"));
            users.add(new User(3, "赵云", "666666", 22, "zy@sohu.com"));
            users.add(new User(4, "马超", "666666", 28, "mc@sohu.com"));
            users.add(new User(5, "黄忠", "666666", 50, "hz@sohu.com"));

            //将数据放入到request域
            model.addAttribute("users", users);

            return "manage";
    }

}

测试效果

image-20220807183609295

image-20220807185059400

3.注意事项和细节

1、URI 和 URL 的区别

​ URI = Universal Resource Identifier URL = Universal Resource Locator Identifier:标识符,

​ Locator:定位器 从字面上来看, URI 可以唯一标识一个资源, URL 可以 提供找到该资源的路径

2、注册拦截器, 依然可以使用如下方式

@Configuration
public class WebConfig  {

    @Bean
    public WebMvcConfigurer webMvcConfigurer(){
        return new WebMvcConfigurer() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(new LocaleChangeInterceptor())
                        .addPathPatterns("/**")
                        .excludePathPatterns("/","/login","/images/**","/css/**");
            }
        };
    }
}

标题:SpringBoot-拦截器
作者:llp
地址:https://llinp.cn/articles/2022/08/09/1660052036208.html