Spring统一功能处理:拦截器、响应与异常的统一管理

06-01 1802阅读

Spring统一功能处理:拦截器、响应与异常的统一管理


目录

一.拦截器

二.统一数据返回格式

三.统一异常处理


一.拦截器

拦截器是Spring框架提供的核⼼功能之⼀,主要⽤来拦截⽤⼾的请求,在指定⽅法前后,根据业务需要执⾏预先设定的代码。

也就是说,允许开发⼈员提前预定义⼀些逻辑,在⽤⼾的请求响应前后执⾏,也可以在⽤⼾请求前阻⽌其执⾏。

在拦截器当中,开发⼈员可以在应⽤程序中做⼀些通⽤性的操作,⽐如通过拦截器来拦截前端发来的请求,判断Session中是否有登录⽤⼾的信息,如果有就可以放⾏,如果没有就进⾏拦截。

Spring统一功能处理:拦截器、响应与异常的统一管理

添加拦截器后,在原先逻辑之前会先判断是否拦截

Spring统一功能处理:拦截器、响应与异常的统一管理

使用拦截器需要分为俩步骤:

  • 自定义拦截器
  • 配置拦截器 

    ⾃定义拦截器:需实现HandlerInterceptor接⼝,并重写其⽅法

    public interface HandlerInterceptor {
        //⽬标⽅法执⾏前执⾏,返回值表示是否拦截
        default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            return true;
        }
        
        //⽬标⽅法执⾏后执⾏
        default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        }
        
        //视图渲染完毕后执⾏
        default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        }
    }
    
    1. preHandle()⽅法:⽬标⽅法执⾏前执⾏,返回true:继续执⾏后续操作;返回false:中断后续操作.
    2. postHandle()⽅法:⽬标⽅法执⾏后执⾏
    3. afterCompletion()⽅法:视图渲染完毕后执⾏,最后执⾏(但是现在基于前后端分离的设计模式,一般不需要后端返回视图,故而很少用)

    添加拦截器后,执⾏Controller的⽅法之前,请求会先被拦截器拦截住执⾏ preHandle() ⽅法,这个⽅法需要返回⼀个布尔类型的值:如果返回true,就表⽰放⾏本次操作并且继续访问controller中的⽅法;如果返回false,则不会放⾏(controller中的⽅法也不会执⾏)。controller当中的⽅法执⾏完毕后,再回过来执⾏ postHandle() 这个⽅法以及afterCompletion() ⽅法,执⾏完毕之后,最终给浏览器响应数据。

    @Slf4j
    @Component
    public class LoginInterceptor implements HandlerInterceptor {
        
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("LoginInterceptor ⽬标⽅法执⾏前执⾏..");
            return true;
        }
        
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("LoginInterceptor ⽬标⽅法执⾏后执⾏");
        }
        
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("LoginInterceptor 视图渲染完毕后执⾏,最后执⾏");
        }
    }

    自定义完成拦截器后,我们还需要将其使用起来,也就是进行相关配置

    首先是要实现WebMvcConfigurer接口,为了将我们刚才自定义的拦截器进行注册,我们需要一个拦截器对象,通过依赖注入的方式注入其中。InterceptorRegistry表示拦截器注册类,我们通过该类的addInterceptor方法将注入的拦截器对象提交并且注册,通过addPathPatterns方法配置我们需要拦截的路径

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        //⾃定义的拦截器对象
        @Autowired
        private LoginInterceptor loginInterceptor;
        
        public void addInterceptors(InterceptorRegistry registry) {
            //注册⾃定义拦截器对象
            registry.addInterceptor(loginInterceptor)
                    .addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表⽰拦截所有请求)
        }
    }

    我们在注册配置拦截器的时候,通过 addPathPatterns() ⽅法指定要拦截哪些请求,也可以通过excludePathPatterns() 指定不拦截哪些请求。

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        //⾃定义的拦截器对象
        @Autowired
        private LoginInterceptor loginInterceptor;
        
        public void addInterceptors(InterceptorRegistry registry) {
            //注册自定义拦截器对象
            registry.addInterceptor(loginInterceptor)
                    .addPathPatterns("/**")
                    .excludePathPatterns("/user/login");
        }
    }

    对于拦截路径,有以下需要注意

    拦截路径含义举例
    /*一级路径能匹配/user,/book,/login,不能匹配 /user/login
    /**任意级路径能匹配/user,/book,/login,/user/login

    对于一些比较复杂比较多的路径,可以将其封装到一个集合中再统一导入,即下面俩者的效果是一样的。

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        //⾃定义的拦截器对象
        @Autowired
        private LoginInterceptor loginInterceptor;
        
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //注册⾃定义拦截器对象
            registry.addInterceptor(loginInterceptor)
                    .addPathPatterns("/**")
                    .excludePathPatterns("/user/login")
                    .excludePathPatterns("/**/*.js") 
                    .excludePathPatterns("/**/*.css")
                    .excludePathPatterns("/**/*.png")
                    .excludePathPatterns("/**/*.html");
        }
    }
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        //⾃定义的拦截器对象
        @Autowired
        private LoginInterceptor loginInterceptor;
        private List excludePaths = Arrays.asList(
                "/user/login",
                "/**/*.js",
                "/**/*.css",
                "/**/*.png",
                "/**/*.html"
        );
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            //注册⾃定义拦截器对象
            registry.addInterceptor(loginInterceptor)
                    .addPathPatterns("/**")
                    .excludePathPatterns(excludePaths);
        }
    }

    二.统一数据返回格式

    统⼀的数据返回格式使⽤ @ControllerAdvice 和 ResponseBodyAdvice 的⽅式实现,@ControllerAdvice 表⽰控制器通知类

    添加类 ResponseAdvice,实现 ResponseBodyAdvice 接⼝,并在类上添加@ControllerAdvice 注解,示例如下:

    @ControllerAdvice
    public class ResponseAdvice implements ResponseBodyAdvice {
        @Override
        public boolean supports(MethodParameter returnType, Class converterType) {
            return false;
        }
        
        @Override
        public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
            return null;
        }
    }
    

    supports⽅法:判断是否要执⾏beforeBodyWrite⽅法,true为执⾏,false不执⾏。通过该⽅法可以选择哪些类或哪些⽅法的response要进⾏处理,其他的不进⾏处理。

    beforeBodyWrite⽅法:对response⽅法进⾏具体操作处理。


    三.统一异常处理

    统⼀异常处理使⽤的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表⽰控制器通知类,@ExceptionHandler 是异常处理器,两个结合表⽰当出现异常的时候执⾏某个通知,也就是执⾏某个⽅法事件。

    示例代码如下:

    @ControllerAdvice
    public class ErrorAdvice {
        @ExceptionHandler
        public Object handler(Exception e) {
            return Result.fail(e.getMessage());
        }
    }
    

    以上代码表⽰,如果代码出现Exception异常(包括Exception的⼦类),就返回⼀个 Result的对象。

    我们可以针对不同的异常,返回不同的结果。

    @ControllerAdvice
    public class ErrorAdvice {
        @ExceptionHandler
        public Object handler(Exception e) {
            return Result.fail(e.getMessage());
        }
        
        @ExceptionHandler
        public Object handler(NullPointerException e) {
            return Result.fail("发⽣NullPointerException:"+e.getMessage());
        }
        
        @ExceptionHandler
        public Object handler(ArithmeticException e) {
            return Result.fail("发⽣ArithmeticException:"+e.getMessage());
        }
    }
    

    当有多个异常通知时,匹配顺序为当前类及其⼦类向上依次匹配。




    Spring统一功能处理:拦截器、响应与异常的统一管理 本次的分享就到此为止了,希望我的分享能给您带来帮助,创作不易也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!Spring统一功能处理:拦截器、响应与异常的统一管理如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!Spring统一功能处理:拦截器、响应与异常的统一管理有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见Spring统一功能处理:拦截器、响应与异常的统一管理

    Spring统一功能处理:拦截器、响应与异常的统一管理

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码