介绍
见名知意, 用于拦截 controller 请求, 在进入 controller 之前进行一些处理, 如果可以, 进入 controller 处理方法, 如果不可以, 则不会进入 controller 处理方法. 基本原理是采用 AOP 面相切面编程, 基于动态代理, 在所执行的 controller 方法前后添加代码, 这就是拦截器
拦截器不依赖任何 Servlet 容器
拦截器只能对 controller 处理方法的 url 进行拦截, 这里提到过滤器则可以对所有的请求进行过滤
在 controller 的生命周期中, 拦截器可以多次被调用, 而过滤器只能在容器初始化时被调用一次
实列 (IDEA)
创建简单的 SpringBoot 项目, 原始的即可, 不需要改动, 就用内置的 Tomcat 就行
编写 POJO 类
- @Data
- @AllArgsConstructor
- @RequiredArgsConstructor
- @NoArgsConstructor
- public class User implements Serializable {
- private Integer id;
- @NonNull private String name;
- @NonNull private String sex;
- private Integer age;
- /*
- * 类上面的注解是使用的 lombok 插件, 不知道的朋友可自行查阅资料
- * */
- }
创建 UserController 处理器类
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RestController;
- import javax.servlet.http.HttpSession;
- import java.util.List;
- @RestController
- @RequestMapping("/user/")
- public class UserController {
- // 模拟 user 的增删改查操作, 假设增删改必须有用户且已登录才可执行
- @RequestMapping("delete")
- public String delete(){
- return "delete 操作";
- }
- @RequestMapping("insert")
- public String insert(){
- return "insert 操作";
- }
- @RequestMapping("update")
- public String update(){
- return "update 操作";
- }
- @RequestMapping("login")
- public String login(HttpSession session){
- // 模拟登录效果, 不查询数据库
- User user = new User("admin","男");
- session.setAttribute("user",user);
- return "登录成功";
- }
- @RequestMapping("logout")
- public String logout(HttpSession session){
- // 登出
- session.removeAttribute("user");
- return "登出成功";
- }
- }
编写 LoginInterceptor 拦截器类
可以使用实现 HandlerInterceptor 接口, 也可直接继承 HandlerInterceptorAdapter 抽象类, 因为这个类就是对 HandlerInterceptor 接口的一个空实现, 看这边源码, 注意方法上面的文档注释, 如果选择 HandlerInterceptorAdapter, 再次重写这三个方法即可
- /*
- * Copyright 2002-2017 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.springframework.Web.servlet.handler;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.lang.Nullable;
- import org.springframework.Web.servlet.AsyncHandlerInterceptor;
- import org.springframework.Web.servlet.ModelAndView;
- /**
- * Abstract adapter class for the {@link AsyncHandlerInterceptor} interface,
- * for simplified implementation of pre-only/post-only interceptors.
- *
- * @author Juergen Hoeller
- * @since 05.12.2003
- */
- public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
- /**
- * This implementation always returns {@code true}.
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
- return true;
- }
- /**
- * This implementation is empty.
- */
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
- @Nullable ModelAndView modelAndView) throws Exception {
- }
- /**
- * This implementation is empty.
- */
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
- @Nullable Exception ex) throws Exception {
- }
- /**
- * This implementation is empty.
- */
- @Override
- public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response,
- Object handler) throws Exception {
- }
- }
此处我选择实现接口
- import org.springframework.Web.servlet.HandlerInterceptor;
- import org.springframework.Web.servlet.ModelAndView;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
- /**
- * 登录验证
- */
- public class LoginInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
- // 从 session 中取出 user, 如果取出的对象对空, 向响应流中给出信息, 并且返回 false, 不再进入 controller 方法
- // 如果取出的对象不为空, 表示用户已经登录, 则返回 true, 继续进入 controller 方法
- System.out.println("LoginInterceptor--preHandle");
- boolean hasAlready=false;
- Object user = request.getSession().getAttribute("user");
- if(user!=null) {
- hasAlready = true;
- }else {
- response.getWriter().write("<h1 style='color:red;'>not login</h1>");
- }
- return hasAlready;
- }
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
- System.out.println("LoginInterceptor--postHandle");
- }
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
- System.out.println("LoginInterceptor--afterCompletion");
- }
- }
编写 MvcConfigurer 类, 代码如下
- import cn.bdqn.ylm.sssmc.interceptor.LoginInterceptor;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.Web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.Web.servlet.config.annotation.WebMvcConfigurer;
- import java.util.ArrayList;
- import java.util.List;
- @Configuration
- public class MvcConfigurer implements WebMvcConfigurer {
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- LoginInterceptor li=new LoginInterceptor();
- List<String> pathPatterns=new ArrayList<>();
- List<String> excludePathPatterns=new ArrayList<>();
- pathPatterns.add("/**");
- excludePathPatterns.add("/user/log**");
- //pathPatterns 表示所有的信息需要拦截的请求, 这里写了 /**, 全部拦截
- //excludePathPatterns 表示不拦截的请求, 这里除了用户退出和登录操作以外, 其他的都需要由用户登录才可以操作
- registry.addInterceptor(li).addPathPatterns(pathPatterns).excludePathPatterns(excludePathPatterns);
- }
- }
OK, 可以在浏览器访问观察结果了
首先访问 / user/logout, 浏览器显示登出成功即为成功, 因为拦截器中设置了不拦截 / user/log** 请求
浏览器访问 / user / 增删改, 浏览器显示 not login 即可成功, 表示用户没有登录, 被拦截器拦下并且向响应流中写出内容
浏览器访问 / user/login, 浏览器显示登录成功, 此时 session 已经存在 user 对象, 再次访问 / user / 增删改, 如果增删改操作正常执行, 并且页面显示对应的操作的成功提示即为正常, 表示拦截器正常获取 session 中的对象判断对象状态放行拦截器
推荐进一步学习
拦截器的三个方法的执行时机, 特征等
拦截器链 (简单提一下: 多拦截器会形成拦截器链, 比如可以先用一个拦截器验证用户是否登录, 如果登录, 下一个拦截器再次验证权限问题)
过滤器, 监听器
拦截器与 ServletAPI 的过滤器, 监听器的不同
那么这些知识点我在这里并没有详细讲, 大家自己下去学习
来源: https://www.cnblogs.com/dreamyy/p/11122790.html