java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring MVC拦截器应用

Spring MVC拦截器的快速应用代码示例

作者:zhaojiakang99

拦截器是Spring MVC中的一个重要概念,主要用于在请求处理之前、之后或异常抛出时执行特定的操作,这篇文章主要介绍了Spring MVC拦截器快速应用的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

基础

拦截器的生效位置

为什么preHandle是主流?(核心原因)

以后面的案例的「token 校验」为例,就能明白为什么大家优先用 preHandle

1. 「提前拦截」= 减少无效消耗(最核心)

如果 token 无效 / 不存在,preHandle 返回 false,请求会直接被拦截,不会进入控制器、不会调用 Service/DAO、不会操作数据库—— 相当于 “把坏人挡在门外”,而不是 “让坏人进屋里再赶出去”。

2.preHandle是唯一能「阻断请求」的方法

postHandleafterCompletion 都是 void 返回值,哪怕发现 token 无效,也无法阻止请求流程(因为控制器已经执行了),只能做一些 “补救”(比如修改响应体),但核心业务逻辑已经执行,失去了拦截的意义。而 preHandleboolean 返回值是 “生死开关”,这是实现「权限控制、token 校验、请求限流」等核心拦截逻辑的关键。

3. 符合 “拦截器” 的设计初衷

拦截器(Interceptor)的核心目的是「在请求处理前做校验 / 过滤,避免无效请求消耗资源」,而不是 “请求处理后做善后”——preHandle 完美契合这个初衷,而另外两个方法只是补充。

postHandle和afterCompletion什么时候用?

不是说这两个方法没用,而是它们的场景很特定,只适合「后置处理」,比如:

1.postHandle适用场景

2.afterCompletion适用场景

拦截器的使用步骤

1.1 创建拦截器

public class MyInterceptor implements HandlerInterceptor {
    /**
     * 1.执行handler之前调用的拦截方法;
     * 2.可以进行编码格式设置、登录保护、权限处理等。
     * @param request 请求对象
     * @param response 响应对象
     * @param handler handler是我们要调用的方法对象
     * @return true放行,false拦截
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("1.preHandle执行");
        return true;
    }

    /**
     * 1.当handler方法执行完成后,触发的方法,没有拦截机制了。
     * 2.此方法只有 preHandle中 return true时才会触发
     * 3.对结果进行处理,比如敏感词检查。
     * @param request 请求
     * @param response 响应
     * @param handler handler方法
     * @param modelAndView 返回的视图和模型数据
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("2.postHandle执行");
    }

    /**
     * 整体处理完毕,调用此方法
     * @param request 请求
     * @param response 响应
     * @param handler handler方法
     * @param ex 异常对象
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("3.afterCompletion执行");
    }
}
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //1.拦截所有请求
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**");
    }
}

1.2 注册拦截器

SpringMVC 的配置类中,通过实现 WebMvcConfigurer 接口并重写 addInterceptors 方法进行拦截器的注册。

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //1.拦截所有请求 
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/v1/**");
    }
}

1.2.1 拦截器配置方案

1.拦截全部请求

registry.addInterceptor(new MyInterceptor()) .addPathPatterns("/**");

2.拦截指定请求

示例: 拦截所有 /v1/user/ 开头的请求,使用 /v1/user/**

registry.addInterceptor(new MyInterceptor()) .addPathPatterns("/v1/user/**");

3.排除指定请求

示例: 拦截所有的 /v1/user/ 开头的请求, 但是不包含登录请求 /v1/user/login

registry
.addInterceptor(new MyInterceptor()) 
.addPathPatterns("/v1/user/**")
.excludePathPatterns("/v1/user/login");

实战

限定访问时间拦截器

要求: 项目工程中,限定所有请求只能在每天的: 06:00 - 22:59 之间进行访问;

public class TimeAccessInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
HttpServletResponse response, Object handler) throws Exception {
        System.out.println("进入访问时间限定拦截器");
        LocalTime now = LocalTime.now();//JDK中的时间对象
        int hour = now.getHour();//获取当前时间对应小时
        if (hour<6 || hour>22){
            throw new RuntimeException("请在06:00~22:00之间进行访问");
        }
        return true;
    }
}
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TimeAccessInterceptor())
                .addPathPatterns("/v1/user/**");
    }
}

权限校验拦截器

由后端进⾏⽤⼾⾝份验证,若不存在token或失效,则失败返回

采⽤拦截器来完成校验token的合法性

第1步:创建拦截器的类并实现拦截器功能;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        //从 header 中获取 token
        String jwtToken = request.getHeader("user_token");
        log.info("获取路径:{}", request.getRequestURI());
        log.info("从header中获取token:{}", jwtToken);
        //验证用户 token
        Claims claims = JWTUtil.parseJWT(jwtToken);
        if (null == claims){
            response.setStatus(401);
            return false;
        }
        log.info("令牌验证通过, 放行");
        return true;
    }
}

第2步:注册拦截器并添加拦截策略;

@Configuration
public class AppConfig implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginInterceptor;

    private final List<String> excludes = Arrays.asList(
            "/**/*.html",
            "/css/**",
            "/js/**",
            "/pic/**",
            "/*.jpg",
            "/favicon.ico",
            "/**/login",
            "/register",
            "/verification-code/send",
            "/winning-records/show"
    );

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludes);
    }
}

限流功能拦截器[扩展]

    因为系统处理能力有限,所以现在要对接口访问进行限流,实现方案是编写一个拦截器,对请求进行拦截和计算,要求: 单个IP限制在每分钟访问网站不能超过3次,超过3次则认为该客户端存在攻击风险,具体代码如下:

    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new RateLimitInterceptor())
                               .addPathPatterns("/v1/user/**");
        }
    }

    总结 

    到此这篇关于Spring MVC拦截器的快速应用的文章就介绍到这了,更多相关Spring MVC拦截器应用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    阅读全文