服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - springBoot2.X配置全局捕获异常的操作

springBoot2.X配置全局捕获异常的操作

2021-10-26 10:12刘翊扬 Java教程

这篇文章主要介绍了springBoot2.X配置全局捕获异常的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

springBoot2.X配置全局捕获异常

先来看一段代码:当传入的id是0的时候,就会报异常。

 @RestController public class HelloController { @GetMapping("/getUser") public String getUser(int id) { int j = 1 / id; return "SUCCESS" + j; } }

访问时:

springBoot2.X配置全局捕获异常的操作

我们知道这个页面要是给用户看到,用户可能不知道这是什么。

方法一:将异常捕获

 @GetMapping("/getUser") public String getUser(int id) { int j; try { j = 1 / id; } catch (Exception e) { return "系统异常"; } return "SUCCESS" + j; }

这种方法当然可以,但是当我们有很多方法时,需要在每个方法上都加上。

哎,太鸡肋了吧。

那么都没有全局的拦截处理呢?

当然了

方法二:通过@ControllerAdvice注解配置

 /** * @Author 刘翊扬 * @Date 2020/9/30 11:39 下午 * @Version 1.0 */ @ControllerAdvice(basePackages = "com.yiyang.myfirstspringdemo.controller") public class GlobalExceptionHandler { @ExceptionHandler(RuntimeException.class) @ResponseBody public Map errorResult()  { Map map = new HashMap<>(); map.put("errorCode", "500"); map.put("errorMsg", "全局捕获异常"); return map; } }
  • @ExceptionHandler 表示拦截异常
  • @ControllerAdvice 是 controller 的一个辅助类,最常用的就是作为全局异常处理的切面类
  • @ControllerAdvice 可以指定扫描范围

注意:下面还需要在启动类上加上,否则诶呦效果

 package com.yiyang.myfirstspringdemo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication(scanBasePackages = {"com.yiyang.myfirstspringdemo.error", "com.yiyang.myfirstspringdemo.controller"}) public class MyFirstSpringDemoApplication { public static void main(String[] args) { SpringApplication.run(MyFirstSpringDemoApplication.class, args); } }

在启动类上,将扫描包范围controller和全局异常处理类,加上去。

springBoot2.X配置全局捕获异常的操作

这样当我们在访问的时候,出现的异常提示信息就是我们在全局异常处理中设置的返回值。

springboot2.x 全局异常处理的正确方式

在web项目中,异常堆栈信息是非常敏感的。因此,需要一个全局的异常处理,捕获异常,给客户端以友好的错误信息提示。基于 Spring boot 很容易实现全局异常处理。

相关jar依赖引入

  org.springframework.bootspring-boot-starter-parent2.1.6.RELEASE UTF-8UTF-81.8  org.springframework.bootspring-boot-starter-web

全局异常控制器

 package com.yb.demo.common.handler; import com.yb.demo.common.enums.CodeEnum; import com.yb.demo.common.exception.BizException; import com.yb.demo.pojo.response.Result; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.validation.ValidationException; import java.util.StringJoiner; /** * 全局异常处理 * 

* 规范:流程跳转尽量避免使用抛 BizException 来做控制。 * * @author daoshenzzg@163.com * @date 2019-09-06 18:02 */ @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { /** * 处理自定义异常 * * @param ex * @return */ @ExceptionHandler(BizException.class) public Result handleBizException(BizException ex) { Result result = Result.renderErr(ex.getCode()); if (StringUtils.isNotBlank(ex.getRemark())) { result.withRemark(ex.getRemark()); } return result; } /** * 参数绑定错误 * * @param ex * @return */ @ExceptionHandler(BindException.class) public Result handleBindException(BindException ex) { StringJoiner sj = new StringJoiner(";"); ex.getBindingResult().getFieldErrors().forEach(x -> sj.add(x.getDefaultMessage())); return Result.renderErr(CodeEnum.REQUEST_ERR).withRemark(sj.toString()); } /** * 参数校验错误 * * @param ex * @return */ @ExceptionHandler(ValidationException.class) public Result handleValidationException(ValidationException ex) { return Result.renderErr(CodeEnum.REQUEST_ERR).withRemark(ex.getCause().getMessage()); } /** * 字段校验不通过异常 * * @param ex * @return */ @ExceptionHandler(MethodArgumentNotValidException.class) public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) { StringJoiner sj = new StringJoiner(";"); ex.getBindingResult().getFieldErrors().forEach(x -> sj.add(x.getDefaultMessage())); return Result.renderErr(CodeEnum.REQUEST_ERR).withRemark(sj.toString()); } /** * Controller参数绑定错误 * * @param ex * @return */ @ExceptionHandler(MissingServletRequestParameterException.class) public Result handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) { return Result.renderErr(CodeEnum.REQUEST_ERR).withRemark(ex.getMessage()); } /** * 处理方法不支持异常 * * @param ex * @return */ @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class) public Result handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) { return Result.renderErr(CodeEnum.METHOD_NOT_ALLOWED); } /** * 其他未知异常 * * @param ex * @return */ @ExceptionHandler(value = Exception.class) public Result handleException(Exception ex) { log.error(ex.getMessage(), ex); return Result.renderErr(CodeEnum.SERVER_ERR); } }

个性化异常处理

自定义异常

在实际web开发过程中,往往会遇到在某些场景下需要终止当前流程,直接返回。那么,通过抛出自定义异常,并在全局异常中捕获,用以友好的提示客户端。

 /** * 业务异常跳转。 * * @author daoshenzzg@163.com * @date 2019-09-09 14:57 */ @Data public class BizException extends RuntimeException { private static final long serialVersionUID = 1L; private CodeEnum code; private String remark; public BizException(CodeEnum code) { super(code.getMessage()); this.code = code; } public BizException withRemark(String remark) { this.remark = remark; return this; } }

使用方式如下:

 /** * 添加学生 * * @param student * @return */ public Student1DO addStudent(Student1DO student) { if (StringUtils.isNotBlank(student.getStudName())) { // 举例扔个业务异常,实际使用过程中,应该避免扔异常 throw new BizException(CodeEnum.REQUEST_ERR).withRemark("studName不能为空"); } student1Mapper.insert(student); return student; }

返回效果如下:

{
"code": -400,
"msg": "请求错误(studName不能为空)",
"data": {},
"ttl": 0
}

根据阿里巴巴规范,流程控制还是不要通过抛异常的方式。在正常开发过程中,应避免使用这种方式。

【强制】异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。

使用 Spring validation 完成数据后端校验

定义实体类,加上validation相关注解

 package com.yb.demo.pojo.model.db1; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import javax.validation.constraints.Min; import javax.validation.constraints.Size; /** * @author daoshenzzg@163.com * @date 2019-08-05 17:58 */ @Data @TableName("student") public class Student1DO { private Long id; @Size(max = 8, message = "studName长度不能超过8") private String studName; @Min(value = 12, message = "年龄不能低于12岁") private Integer studAge; private String studSex; @TableField(fill = FieldFill.INSERT) private Integer createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Integer updateTime; }

在Controller 方法上加上 @Validated 注解

 @PostMapping("/student/add") public Result addStudent(@Validated @RequestBody Student1DO student) { student = studentService.addStudent(student); return Result.renderOk(student); }

实际效果如下:

{
"code": -400,
"msg": "请求错误(年龄不能低于12岁)",
"data": {},
"ttl": 0
}

结束语

具体代码见:https://github.com/daoshenzzg/springboot2.x-example

以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://www.cnblogs.com/liufei2/p/13765947.html

延伸 · 阅读

精彩推荐
  • Java教程升级IDEA后Lombok不能使用的解决方法

    升级IDEA后Lombok不能使用的解决方法

    最近看到提示IDEA提示升级,寻思已经有好久没有升过级了。升级完毕重启之后,突然发现好多错误,本文就来介绍一下如何解决,感兴趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下...

    Java教程网2942020-09-17
  • Java教程Java8中Stream使用的一个注意事项

    Java8中Stream使用的一个注意事项

    最近在工作中发现了对于集合操作转换的神器,java8新特性 stream,但在使用中遇到了一个非常重要的注意点,所以这篇文章主要给大家介绍了关于Java8中S...

    阿杜7472021-02-04
  • Java教程Java BufferWriter写文件写不进去或缺失数据的解决

    Java BufferWriter写文件写不进去或缺失数据的解决

    这篇文章主要介绍了Java BufferWriter写文件写不进去或缺失数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java实现抢红包功能

    Java实现抢红包功能

    这篇文章主要为大家详细介绍了Java实现抢红包功能,采用多线程模拟多人同时抢红包,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    这篇文章主要介绍了Java使用SAX解析xml的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程20个非常实用的Java程序代码片段

    20个非常实用的Java程序代码片段

    这篇文章主要为大家分享了20个非常实用的Java程序片段,对java开发项目有所帮助,感兴趣的小伙伴们可以参考一下 ...

    lijiao5352020-04-06
  • Java教程小米推送Java代码

    小米推送Java代码

    今天小编就为大家分享一篇关于小米推送Java代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    富贵稳中求8032021-07-12