SpringBoot-统一异常处理
来源:互联网 发布:一个人开两家淘宝店 编辑:程序博客网 时间:2024/06/06 03:01
SpringBoot-统一异常处理
一、什么是异常处理
异常(exception) 是程序运行过程中发生的事件, 该事件可以中断程序指令的正常执行流程.
1当Java程序运行时出现问题时,系统会自动检测到该错误,并立即生成一个与该错误对应的异常对象2:然后把该异常对象提交给JAVA虚拟机3:JAVA虚拟机会自动寻找相应的处理代码来处理这个异常,如果没有找到,则程序终止4:程序员可以自己编写代码来扑捉可能出现的异常,并编写代码来处理相应的异常.
二、为什么要统一异常处理
例:需求:
获取某女生的年龄并判断:小于10,返回“应该在上小学”;大于10且小于16,返回“可能在上初中”;
需求:把System.out.println(bindingResult.getFieldError().getDefaultMessage());信息输出到网页
版本一:
GirlController:
@RestControllerpublic class GirlController { /** * getLogger方法中的参数与类名对应 */ private final static Logger logger = LoggerFactory.getLogger(GirlController.class); @Autowired private GirlRepository girlRepository; @Autowired private GirlService girlService; //添加一个女生 @PostMapping(value="/girls") public Girl girlAdd(@Valid Girl girl, BindingResult bindingResult) { if (bindingResult.hasErrors()) { System.out.println(bindingResult.getFieldError().getDefaultMessage()); return null; } girl.setCupSize(girl.getCupSize()); girl.setAge(girl.getAge()); return girlRepository.save(girl); }}
Girl:
@Entity //该注解表示该类在数据库中有对应的表 不用创建该表public class Girl { @Id @GeneratedValue private Integer id; @NotBlank(message = "这个字段必传") private String cupSize; /** * 给年龄加上限制:年龄必须大于18岁 * value:值 * message:提示信息 */ @Min(value =18,message = "年龄必须大于18岁") private Integer age; @NotNull(message = "金额必传") private Double money; public Girl() { } @Override public String toString() { return "Girl{" + "id=" + id + ", cupSize='" + cupSize + '\'' + ", age=" + age + '}'; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getCupSize() { return cupSize; } public void setCupSize(String cupSize) { this.cupSize = cupSize; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; }}
目前,金额必传是打印在控制台上的,现在需要打印在网页上:
修改方法:
版本二:
@PostMapping(value="/girls")public Object girlAdd(@Valid Girl girl, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return bindingResult.getFieldError().getDefaultMessage(); } girl.setCupSize(girl.getCupSize()); girl.setAge(girl.getAge()); return girlRepository.save(girl);}
结果:
问题:返回的格式不统一,对返回的格式作统一(失败和成功):
{ "code":1, "msg":"金额必传", "data":null}{ "code":0 "msg":"成功", "data":{ "id":20, "cupSize":"B", "age":25, "money":1.2 }}
版本三:
Result:
/** * Created by HCX on 2017/8/17. * http请求返回的最外层对象 */public class Result<T> { //错误码 private Integer code; //提示信息 private String msg; //具体的内容 private T data; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; }}
GirlController:
@RestControllerpublic class GirlController { /** * getLogger方法中的参数与类名对应 */ private final static Logger logger = LoggerFactory.getLogger(GirlController.class); @Autowired private GirlRepository girlRepository; @Autowired private GirlService girlService; //添加一个女生 @PostMapping(value="/girls") public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult) { if(bindingResult.hasErrors()){ Result result = new Result(); result.setCode(1); result.setMsg(bindingResult.getFieldError().getDefaultMessage()); result.setData(null); return result; } girl.setCupSize(girl.getCupSize()); girl.setAge(girl.getAge()); Result result = new Result(); result.setCode(0); result.setMsg("成功"); result.setData(girlRepository.save(girl)); return result; }}
运行结果:
可见代码重复了,进行优化:版本四
定义返回结果的工具类ResultUtil:
public class ResultUtil { public static Result success(Object object){ Result result = new Result(); result.setCode(0); result.setMsg("成功"); result.setData(object); return result; } public static Result success(){ return success(null); } public static Result error(Integer code,String msg){ Result result = new Result(); result.setCode(code); result.setMsg(msg); return result; }}
GirlController:
@RestControllerpublic class GirlController { /** * getLogger方法中的参数与类名对应 */ private final static Logger logger = LoggerFactory.getLogger(GirlController.class); @Autowired private GirlRepository girlRepository; @Autowired private GirlService girlService; //添加一个女生 @PostMapping(value="/girls") public Result<Girl> girlAdd(@Valid Girl girl, BindingResult bindingResult) { if(bindingResult.hasErrors()){ return ResultUtil.error(1,bindingResult.getFieldError().getDefaultMessage()); } girl.setCupSize(girl.getCupSize()); girl.setAge(girl.getAge()); return ResultUtil.success(girlRepository.save(girl)); }}
三、案例
需求:获取某女生的年龄并判断,小于10,返回“应该在上小学”;大于10且小于16,返回“可能在上初中”
GirlController:
@RestControllerpublic class GirlController { /** * getLogger方法中的参数与类名对应 */ private final static Logger logger = LoggerFactory.getLogger(GirlController.class); @Autowired private GirlRepository girlRepository; @Autowired private GirlService girlService; @GetMapping(value = "girls/getAge/{id}") public void getAge(@PathVariable("id") Integer id) throws Exception{ girlService.getAge(id); }}
GirlService:
@Servicepublic class GirlService { @Autowired private GirlRepository girlRepository; public void getAge(Integer id) throws Exception{ Girl girl = girlRepository.findOne(id); Integer age = girl.getAge(); if(age<10){ //返回“你可能在上小学” code=100 throw new Exception("你可能在上小学"); }else if(age>10 && age<16){ //返回“你可能在上初中” code=101 throw new Exception("你可能在上初中"); } }}
ExceptionHandle:
@ControllerAdvicepublic class ExceptionHandle { /** * @ExceptionHandler(value = Exception.class):声明要捕获的异常类 * @return */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result handle(Exception e){ return ResultUtil.error(100,e.getMessage()); }}
此时,已经按照我们所期望的格式返回了:
问题:返回的错误码都是一样的,但是在实际问题中,我们希望定位的错误更准确,希望不同的错误可以返回不同的错误码,所以可以自定义一个Exception:
GirlException:
public class GirlException extends RuntimeException{ /** * 注意要继承自RuntimeException,底层RuntimeException继承了Exception, * spring框架只对抛出的异常是RuntimeException才会进行事务回滚, * 如果是抛出的是Exception,是不会进行事物回滚的 */ private Integer code; public GirlException(Integer code,String message) { //父类的构造方法本身会传message进去 super(message); this.code = code; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; }}
ExceptionHandle:
@ControllerAdvicepublic class ExceptionHandle { /** * @ExceptionHandler(value = Exception.class):声明要捕获的异常类 * @return */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result handle(Exception e){ if(e instanceof GirlException){ GirlException girlException = (GirlException)e; return ResultUtil.error(girlException.getCode(),girlException.getMessage()); }else { return ResultUtil.error(-1,"未知错误"); } }}
GirlService:
@Servicepublic class GirlService { @Autowired private GirlRepository girlRepository; public void getAge(Integer id) throws Exception{ Girl girl = girlRepository.findOne(id); Integer age = girl.getAge(); if(age<10){ //返回“你可能在上小学” code=100 throw new GirlException(100,"你可能在上小学"); }else if(age>10 && age<16){ //返回“你可能在上初中” code=101 throw new GirlException(101,"你可能在上初中"); } }}
GirlController:
@RestControllerpublic class GirlController { /** * getLogger方法中的参数与类名对应 */ private final static Logger logger = LoggerFactory.getLogger(GirlController.class); @Autowired private GirlRepository girlRepository; @Autowired private GirlService girlService; @GetMapping(value = "girls/getAge/{id}") public void getAge(@PathVariable("id") Integer id) throws Exception{ girlService.getAge(id); }}
运行结果:
当抛出的是系统异常时,可以通过日志进行记录:
ExceptionHandle:
@ControllerAdvicepublic class ExceptionHandle { //记录系统异常 private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class); /** * @ExceptionHandler(value = Exception.class):声明要捕获的异常类 * @return */ @ExceptionHandler(value = Exception.class) @ResponseBody public Result handle(Exception e){ if(e instanceof GirlException){ GirlException girlException = (GirlException)e; return ResultUtil.error(girlException.getCode(),girlException.getMessage()); }else { logger.error("【系统异常】 {}",e); return ResultUtil.error(-1,"未知错误"); } }}
问题:在自定义异常的错误码和信息时,如果过多,没有统一管理,则会出现重复。使用枚举统一管理code和message:
ResultEnum:
public enum ResultEnum { UNKNOW_ERROR(-1,"未知错误"), SUCCESS(0,"成功"), PRIMARY_SCHOOL(100,"你可能在上小学"), MIDDLE_SCHOOL(101,"你可能在上初中"), ; private Integer code; private String msg; ResultEnum(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public String getMsg() { return msg; }}
GirlException:
public class GirlException extends RuntimeException{ /** * 注意要继承自RuntimeException,底层RuntimeException继承了Exception, * spring框架只对抛出的异常是RuntimeException才会进行事务回滚, * 如果是抛出的是Exception,是不会进行事物回滚的 */ private Integer code; public GirlException(ResultEnum resultEnum) { //父类的构造方法本身会传message进去 super(resultEnum.getMsg()); this.code = resultEnum.getCode(); } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; }}
GirlService:
@Servicepublic class GirlService { @Autowired private GirlRepository girlRepository; public void getAge(Integer id) throws Exception{ Girl girl = girlRepository.findOne(id); Integer age = girl.getAge(); if(age<10){ //返回“你可能在上小学” code=100 throw new GirlException(ResultEnum.PRIMARY_SCHOOL); }else if(age>10 && age<16){ //返回“你可能在上初中” code=101 throw new GirlException(ResultEnum.MIDDLE_SCHOOL); } }}
GirlController:
@RestControllerpublic class GirlController { /** * getLogger方法中的参数与类名对应 */ private final static Logger logger = LoggerFactory.getLogger(GirlController.class); @Autowired private GirlRepository girlRepository; @Autowired private GirlService girlService; @GetMapping(value = "girls/getAge/{id}") public void getAge(@PathVariable("id") Integer id) throws Exception{ girlService.getAge(id); }}
- SpringBoot--统一异常处理
- SpringBoot-统一异常处理
- springboot统一异常处理
- SpringBoot统一异常处理
- SpringBoot 统一异常处理
- SpringBoot 统一异常处理
- springboot统一异常处理
- springboot统一异常处理机制
- SpringBoot(4) 统一异常处理
- SpringBoot之统一异常处理
- spring 或 springboot统一异常处理
- SpringBoot 和 SpringMVC的异常统一处理
- SpringBoot 统一异常处理 @ControllerAdvice 失效
- SpringBoot 统一异常处理--- @ControllerAdvice 使用
- Springboot-系统异常统一处理(接口编程异常处理)
- springboot统一异常处理器
- SpringBoot初始教程之统一异常处理(三)
- SpringBoot初始教程之统一异常处理(三)
- Android模块化入门:)
- PowerDesigner逆向工程导入MYSQL数据库总结 / win7 64位数据库连接问题:在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
- Welcome to my blog!
- ubuntu 启动错误:filesystem check or mount failed.
- OPENCV+JAVA 人脸识别
- SpringBoot-统一异常处理
- iOS 事件的产生和传递
- Tsung的安装与tigase的压测
- 在docker中使用alembic管理数据库的问题
- redis必杀高级:安全
- JavaScript复选框单选
- MYSQL数据库知识点
- 在div中写了el表达式会错误解决办法
- 【简单题】泥塑课