springboot中使用拦截器进行拦截请求处理

应用场景

项目中要拦截指定url之外的所有请求,并在请求进入controller之前判断其中的参数是否合法正确.

  1. 注册拦截器:继承 WebMvcConfigurationSupport ,重写 addInterceptors 方法
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private JumpControllerInterceptor jumpControllerInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       # 这里添加的路径不包含项目的contextPath哦 registry.addInterceptor(jumpControllerInterceptor).addPathPatterns("/**").
                excludePathPatterns("/test");
        super.addInterceptors(registry);
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        String os = System.getProperty("os.name");

        //如果是Windows系统
//        if (os.toLowerCase().startsWith("win")) {
//            registry.addResourceHandler("/app_file/**")
//                    // /app_file/**表示在磁盘filePathWindow目录下的所有资源会被解析为以下的路径
//                    .addResourceLocations("file:" + filePathWindow);
//        } else {  //linux 和mac
//            registry.addResourceHandler("/app_file/**")
//                    .addResourceLocations("file:" + filePathLinux) ;
//        }

        registry.addResourceHandler("/jumpLogs/**").addResourceLocations("file:jumpLogs/");
        super.addResourceHandlers(registry);
    }
}
  1. 实现HandlerInterceptor这个接口

    @Component
    public class JumpControllerInterceptor implements HandlerInterceptor {
    
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    
     @Override
     public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object o) {
         String requestURI = req.getRequestURI();
         if(requestURI.startsWith("/jump/app/")){
             logger.info("正在检查pathVariable: appCode");
             Map pathVariables = (Map) req.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
             String appCode = (String)pathVariables.get("appCode");
             /* 2.判断是否IDP登录 */
             AppAddrMapping appAddrMapping = AppAddrMapping.ADDR_MAPPING_MAP.get(appCode);
             if (null == appAddrMapping) {
                 logger.error("当前url中的appCode : {} 和app.json中的不相匹配,请检查配置文件",appCode);
                 throw new ConfArgException("app不存在,请检查appcode是否正确");
             }
         }
         return true;
     }
    
     @Override
     public void postHandle(HttpServletRequest req, HttpServletResponse res, Object o, ModelAndView mav) {
    
     }
    
     @Override
     public void afterCompletion(HttpServletRequest req, HttpServletResponse rep, Object o, Exception e) {
    
     }
  2. 拦截器不起作用的原因
    a) 继承 WebMvcConfigurationSupport ,重写 addInterceptors 方法的类需用到@Configuration 注解
    b) addPathPatterns中的问题。拦截器最后路径一定要 /, 如果是目录的话则是 /*/
    c) excludePathPatterns 或 addPathPatterns 书写错误,前面添加了项目的ContextPath
  3. 拦截器的主要方法

    configurePathMatch:配置路由请求规则
    configureContentNegotiation:内容协商配置
    configureAsyncSupport
    configureDefaultServletHandling:默认静态资源处理器
    addFormatters:注册自定义转化器
    addInterceptors:拦截器配置
    addResourceHandlers:资源处理
    addCorsMappings:CORS配置
    addViewControllers:视图跳转控制器
    configureViewResolvers:配置视图解析
    addArgumentResolvers:添加自定义方法参数处理器
    addReturnValueHandlers:添加自定义返回结果处理器
    configureMessageConverters:配置消息转换器。重载会覆盖默认注册的HttpMessageConverter
    extendMessageConverters:配置消息转换器。仅添加一个自定义的HttpMessageConverter.
    configureHandlerExceptionResolvers:配置异常转换器
    extendHandlerExceptionResolvers:添加异常转化器
    getValidator
    getMessageCodesResolver
  4. 其中用的比较多的是一下三个接口:
    /** 解决跨域问题 **/
    public void addCorsMappings(CorsRegistry registry) ;
    
    /** 添加拦截器 **/
    void addInterceptors(InterceptorRegistry registry);
    
    /** 静态资源处理 **/
    void addResourceHandlers(ResourceHandlerRegistry registry);
@Configuration
public class AddCorsMappings extends WebMvcConfigurationSupport {
    /**
     * 跨域访问配置接口
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .allowCredentials(true)
                .allowedHeaders("*")
                .maxAge(3600);
    }
}

关于静态资源的处理

非常重要的提示:Springboot中只能有一个WebMvcConfigurationSupport配置类是真正起作用的,对于这个问题,其实可以通过implements WebMvcConfigurer来解决,多个不同的类实现这个接口后的配置都可以正常运行。


关于用Servlet获取URL地址。

在HttpServletRequest类里,有以下六个取URL的函数

getContextPath 取得项目名
getServletPath 取得Servlet名
getPathInfo 取得Servlet后的URL名,不包括URL参数
getRequestURL 取得不包括参数的URL
getRequestURI 取得不包括参数的URI,即去掉协议和服务器名的URL

具体如下图:

springboot中使用拦截器进行拦截请求处理_第1张图片

相对应的函数的值如下:

getContextPath:/ServletTest
getServletPath:/main
getPathInfo:/index/testpage/test
getRequestURL:http://localhost:8080/Servlet...
getRequestURI:/ServletTest/main/index/testpage/test

你可能感兴趣的