springboot:通过WebMvcConfigurer和HandlerInterceptor配置多个拦截器

1、创建俩个类实现HandlerInterceptor接口
会实现下面三个方法:
preHandle:调用Controller某个方法之前
postHandle:Controller之后调用,视图渲染之前,如果控制器Controller出现了异常,则不会执行此方法
afterCompletion:不管有没有异常,这个afterCompletion都会被调用,用于资源清理

@Slf4j
@Component
public class OneHandlerInterceptor implements HandlerInterceptor {

    /**
     * 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
     * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
     * 如性能监控中我们可以在此记录结束时间并输出消耗时间,
     * 还可以进行一些资源清理,类似于try-catch-finally中的finally,
     * 但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }

    /**
     * 预处理回调方法,实现处理器预处理
     * 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或者处理器
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果不是映射到方法直接放行
        if(!(handler instanceof HandlerMethod)){
            return true;
        }
        // todo 还可配置白名单黑名单
        /**
         * 可配合接口注解使用
         * 1、在接口上添加角色注解
         * 2、通过判断请求接口上是否有注解
         * 3、获取用户角色,判断是否与接口角色配对
         */
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(ActionRoles.class)) {
            //方法上面是否有某个角色注解?
            ActionRoles annotation = method.getAnnotation(ActionRoles.class);
            String[] roles = annotation.value();
        }
        return true;
    }
}

2、Web配置文件中注入拦截器
在实现WebMvcConfigurer之后可以选择你要重写的方法,这里重写addInterceptors这个方法来添加自定义的拦截器。
addInterceptor:用于添加你自定义的拦截器实例
addPathPatterns:用于添加要拦截的url,可以写多个。
excludePathPatterns:用于添加不需要拦截的url,可以写多个。

@Configuration
public class WebWvcConfig implements WebMvcConfigurer {

    @Autowired
    private OneHandlerInterceptor oneHandlerInterceptor;
    @Autowired
    private TwoHandlerInterceptor twoHandlerInterceptor;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /*
            指定静态资源的访问路径前缀以及静态资源所处路径不被拦截
            然后在添加自定义拦截器时忽略静态资源的路径前缀
         */
        //第一个方法设置访问路径前缀,第二个方法设置资源路径
        registry.addResourceHandler("/resources/**","/public/**")
                .addResourceLocations("classpath:/resources/","classpath:/public/");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // 拦截所有路径   多个拦截器组成一个拦截器链
        // 注册自定义两个拦截器
        // addPathPatterns  用来添加拦截规则,/** 表示拦截所有请求  /*/表示拦截目录
        // excludePatterns  用户排除拦截
        //拦截器的拦截顺序,是按照Web配置文件中注入拦截器的顺序执行的

        registry.addInterceptor(oneHandlerInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login")
                .excludePathPatterns("/open/**")
                .excludePathPatterns("/api/**");

        registry.addInterceptor(twoHandlerInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login")
                .excludePathPatterns("/open/**")
                .excludePathPatterns("/api/**");
    }
}

这里需要注意,在springboot中使用多个继承WebMvcConfigurationSupport的类是行不通的,而且使用注解@configuration去加载配置类只能挂载一个继承WebMvcConfigurationSupport,如果有多个而且在不同级包中,那么会优先加载最外层包的配置类,其他继承WebMvcConfigurationSupport的类是不会加载。
原因:WebMvcConfigurationSupport调用模板类resourceHandlerMapping生成bean,其实是调用父类的模板类,去加载下一个发现已经有了就不会调用resourceHandlerMapping(bean的id相同)。
但貌似这种情况的解决方法就是都实现父类 webMvcConfigurer 接口 ,这样都能挂载,但试了不太行,原因也不知了。因此保险还是尽可能不去实现多个webMvcConfigurer 吧。

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
拦截器Spring Boot应用程序中一个很常见的组件,用于在请求开始或结束时执行一些操作,例如验证请求、记录请求信息等。下面是一个简单的拦截器示例,用于记录请求开始和结束时间: ``` import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; @Component public class RequestInterceptor implements HandlerInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(RequestInterceptor.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { LOGGER.info("Request URL::" + request.getRequestURL().toString() + ":: Start Time=" + System.currentTimeMillis()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { LOGGER.info("Request URL::" + request.getRequestURL().toString() + ":: Time Taken=" + (System.currentTimeMillis() - (Long)request.getAttribute("startTime")) + "ms"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // This method is called after the response is sent to the client. } } ``` 可以看到,在这里我们实现了HandlerInterceptor接口,并重写了其中的三个方法:preHandle、postHandle和afterCompletion。在preHandle方法中记录请求的开始时间,在postHandle方法中计算请求处理时间,最终输出日志信息。在这个拦截器中,我们没有实现任何额外的验证逻辑,但在实际应用中,我们可以在这些方法中编写更多的代码,如验证用户身份、检查请求参数等。 接下来,我们需要将这个拦截器注册到Spring Boot应用程序中。可以通过在我们的Spring Boot配置类中添加以下@Bean方法来实现: ``` @Configuration public class AppConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new RequestInterceptor()); } } ``` 这里我们扩展了WebMvcConfigurer接口,并重写了其中的addInterceptors方法,以将我们的拦截器注册到拦截器链中。现在,我们的拦截器已经可以在每个请求中截取HTTP请求并输出日志信息了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值