当前位置: 首页 > news >正文

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


目录

一.拦截器

二.统一数据返回格式

三.统一异常处理


一.拦截器

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

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

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

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

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

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

⾃定义拦截器:需实现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 {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info("LoginInterceptor ⽬标⽅法执⾏前执⾏..");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("LoginInterceptor ⽬标⽅法执⾏后执⾏");}@Overridepublic 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 {//⾃定义的拦截器对象@Autowiredprivate LoginInterceptor loginInterceptor;public void addInterceptors(InterceptorRegistry registry) {//注册⾃定义拦截器对象registry.addInterceptor(loginInterceptor).addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表⽰拦截所有请求)}
}

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

@Configuration
public class WebConfig implements WebMvcConfigurer {//⾃定义的拦截器对象@Autowiredprivate 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 {//⾃定义的拦截器对象@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic 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 {//⾃定义的拦截器对象@Autowiredprivate LoginInterceptor loginInterceptor;private List<String> excludePaths = Arrays.asList("/user/login","/**/*.js","/**/*.css","/**/*.png","/**/*.html");@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册⾃定义拦截器对象registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns(excludePaths);}
}

二.统一数据返回格式

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

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

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return false;}@Overridepublic 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 {@ExceptionHandlerpublic Object handler(Exception e) {return Result.fail(e.getMessage());}
}

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

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

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

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




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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • MM 特殊采购类型
  • 加密简史:从古代到现代的方法
  • Linux网络编程之dpdk的环境配置详解
  • 自动化测试与手动测试的区别!
  • 时光不等人:java每日一练
  • python入门基础篇(一)
  • string.format()拼接参数
  • SpringBoot3里的文件上传
  • 将本地的业务写成成可供RPC远程调用的方法
  • 电脑添加虚拟网卡与ensp互联,互访
  • redis面试(五)删除策略和淘汰策略
  • Excel列名转换
  • 54、PHP 实现希尔排序
  • 选择 websim网站:一个用自然语言快速构建生成功能齐全的网站
  • 8月4号分析:CSGO市场行情如何,给几个操作建议
  • 03Go 类型总结
  • CentOS 7 修改主机名
  • Computed property XXX was assigned to but it has no setter
  • css选择器
  • js写一个简单的选项卡
  • Node + FFmpeg 实现Canvas动画导出视频
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • Python连接Oracle
  • Redux 中间件分析
  • SpringCloud集成分布式事务LCN (一)
  • ubuntu 下nginx安装 并支持https协议
  • Vue实战(四)登录/注册页的实现
  • Yii源码解读-服务定位器(Service Locator)
  • 阿里云应用高可用服务公测发布
  • 不上全站https的网站你们就等着被恶心死吧
  • 成为一名优秀的Developer的书单
  • 解决iview多表头动态更改列元素发生的错误
  • 前端之Sass/Scss实战笔记
  • 如何胜任知名企业的商业数据分析师?
  • 自动记录MySQL慢查询快照脚本
  • 走向全栈之MongoDB的使用
  • NLPIR智能语义技术让大数据挖掘更简单
  • ​​​​​​​开发面试“八股文”:助力还是阻力?
  • # .NET Framework中使用命名管道进行进程间通信
  • # centos7下FFmpeg环境部署记录
  • #{}和${}的区别是什么 -- java面试
  • #控制台大学课堂点名问题_课堂随机点名
  • (1)常见O(n^2)排序算法解析
  • (70min)字节暑假实习二面(已挂)
  • (floyd+补集) poj 3275
  • (翻译)terry crowley: 写给程序员
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (四)Linux Shell编程——输入输出重定向
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • ./和../以及/和~之间的区别
  • .Net Core 中间件与过滤器
  • .net6+aspose.words导出word并转pdf
  • @angular/cli项目构建--http(2)
  • @Conditional注解详解