本篇内容主要讲解“springBoot2.X配置全局捕获异常的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springBoot2.X配置全局捕获异常的方法”吧!
springBoot2.X配置全局捕获异常
先来看一段代码:当传入的id是0的时候,就会报异常。
@RestControllerpublic class HelloController { @GetMapping("/getUser") public String getUser(int id) { int j = 1 / id; return "SUCCESS" + j; }}
访问时:
我们知道这个页面要是给用户看到,用户可能不知道这是什么。
方法一:将异常捕获
@GetMapping("/getUser") public String getUser(int id) { int j; try { j = 1 / id; } catch (Exception e) { return "系统异常"; } return "SUCCESS" + j; }
这种方法当然可以,但是当我们有很多方法时,需要在每个方法上都加上。
哎,太鸡肋了吧。
那么都没有全局的拦截处理呢?
当然了
方法二:通过@ControllerAdvice注解配置
@ControllerAdvice(basePackages = "com.yiyang.myfirstspringdemo.controller")public class GlobalExceptionHandler { @ExceptionHandler(RuntimeException.class) @ResponseBody public Map<String,Object> errorResult() { Map<String, Object> 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 全局异常处理的正确方式
在web项目中,异常堆栈信息是非常敏感的。因此,需要一个全局的异常处理,捕获异常,给客户端以友好的错误信息提示。基于 Spring boot 很容易实现全局异常处理。
相关jar依赖引入
<!-- Spring Boot 启动父依赖 --><parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --></parent><properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version></properties><dependencies> <!-- Spring Boot Web 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency></dependencies>
全局异常控制器
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;@Slf4j@RestControllerAdvicepublic class GlobalExceptionHandler { @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; } @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()); } @ExceptionHandler(ValidationException.class) public Result handleValidationException(ValidationException ex) { return Result.renderErr(CodeEnum.REQUEST_ERR).withRemark(ex.getCause().getMessage()); } @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()); } @ExceptionHandler(MissingServletRequestParameterException.class) public Result handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) { return Result.renderErr(CodeEnum.REQUEST_ERR).withRemark(ex.getMessage()); } @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class) public Result handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) { return Result.renderErr(CodeEnum.METHOD_NOT_ALLOWED); } @ExceptionHandler(value = Exception.class) public Result handleException(Exception ex) { log.error(ex.getMessage(), ex); return Result.renderErr(CodeEnum.SERVER_ERR); }}
个性化异常处理
自定义异常
在实际web开发过程中,往往会遇到在某些场景下需要终止当前流程,直接返回。那么,通过抛出自定义异常,并在全局异常中捕获,用以友好的提示客户端。
@Datapublic 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; }}
使用方式如下:
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;@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
到此,相信大家对“springBoot2.X配置全局捕获异常的方法”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!