补充

  springboot中也是一样的可以对结果进行统一格式的包装,这样也就方便了前台的统一接收处理了;

  1.结果集包装类 

  1. package com.example.demo.bean;
  2.  
  3. /**
  4. * 结果包装
  5. *
  6. * @author zcc ON 2018/2/9
  7. **/
  8. public class Result<T> {
  9. /**
  10. * 错误代码(可以设定例如500表示错误)
  11. */
  12. private Integer code;
  13. /**
  14. * 提示信息
  15. */
  16. private String msg;
  17. /**
  18. * 数据内容
  19. */
  20. private T data;
  21.  
  22. public Result() {
  23. }
  24.  
  25. public Integer getCode() {
  26. return code;
  27. }
  28.  
  29. public void setCode(Integer code) {
  30. this.code = code;
  31. }
  32.  
  33. public String getMsg() {
  34. return msg;
  35. }
  36.  
  37. public void setMsg(String msg) {
  38. this.msg = msg;
  39. }
  40.  
  41. public T getData() {
  42. return data;
  43. }
  44.  
  45. public void setData(T data) {
  46. this.data = data;
  47. }
  48. }

Resultde

    可以参考之前SSM中的包装类http://www.cnblogs.com/jiangbei/p/7080955.html

  2.使用包装结果集

  1. @PostMapping(value = "/girls")
  2. public Result<Girl> addGirl(@Valid Girl girl, BindingResult bindingResult) {
  3. Result<Girl> result = new Result<>();
  4. // 表单验证逻辑
  5. if (bindingResult.hasErrors()) {
  6. List<FieldError> fieldErrors = bindingResult.getFieldErrors();
  7. StringBuffer sb = new StringBuffer();
  8. for (FieldError fieldError : fieldErrors) {
  9. sb.append(fieldError.getDefaultMessage());
  10. }
  11. result.setCode(500);
  12. result.setMsg(sb.toString());
  13. return result;
  14. }
  15. result.setCode(200);
  16. result.setMsg("success");
  17. result.setData(girlRepository.save(girl));
  18. return result;
  19. }

    3。改进结果集

      通过代码观察或者对比SSM中的示例,都发现这样写在代码中是挺傻的,这样,我们提供一个工具类(或者在结果集中直接封装)

  1. /**
  2. * 结果集的工具类
  3. *
  4. * @author zcc ON 2018/2/9
  5. **/
  6. public class ResultUtils {
  7.  
  8. public static Result<Object> success(Object data) {
  9. Result<Object> result = new Result<>();
  10. result.setCode(200);
  11. result.setMsg("success");
  12. result.setData(data);
  13.  
  14. return result;
  15. }
  16.  
  17. public static Result<Object> error(String msg) {
  18. Result<Object> result = new Result<>();
  19. result.setCode(500);
  20. result.setMsg(msg);
  21. return result;
  22. }
  23. }

    使用:

  1. @PostMapping(value = "/girls")
  2. public Result<Object> addGirl(@Valid Girl girl, BindingResult bindingResult) {
  3. // 表单验证逻辑
  4. if (bindingResult.hasErrors()) {
  5. List<FieldError> fieldErrors = bindingResult.getFieldErrors();
  6. StringBuffer sb = new StringBuffer();
  7. for (FieldError fieldError : fieldErrors) {
  8. sb.append(fieldError.getDefaultMessage());
  9. }
  10. return ResultUtils.error(sb.toString());
  11. }
  12. return ResultUtils.success(girlRepository.save(girl));
  13. }

一、概述

  springboot提供了默认的统一异常处理,basicErrorController,这个controller提供了默认了错误处理方法,包括错误跳转的路径和渲染方法。

  因为默认的错误处理方法可能会不适合项目的需要,所以当需要自定义统一错误处理的时候,可以继承basicErrorController。或重新实现basicErrorController.

统一异常处理可配置400,404,500等状态异常错误处理。basicErrorController内部提供了针对accept=**的不同处理方法,可区别是普通调用还是ajax等其他调用。

  缺点:需要重写basicErrorController。并配置覆盖原来springboot的默认配置。当使用EmbeddedServletContainerCustomizer类配置400,404。500的时候,暂时不清楚调用springboot的处理方法。

二、问题提出

  假设需要根据girl的不同age作出不同的动作,controller如下:

  1. @GetMapping(value = "/girls/getAge/{id}")
  2. public void getAge(@PathVariable("id") Integer id) {
  3. // 判断应该交给service

  service:

  1. public void getAge(Integer id) {
  2. Integer age = girlRepository.findOne(id).getAge();
  3. if (age < 12) {
  4. // 小学生
  5. } else {
  6. // 上初中了
  7. }
  8. }

  如果只是简单的判断,不同年龄返回不同信息给前台,那确实可以通过返回一个String来进行

  但是,如果业务比较复杂,需要的不仅仅是返回一个字符串,而是需要其他动作,这个时候就显得有点力不从心了!

三、统一异常处理

   1.基本用法

   controller调用service,抛出异常即可:

  1. @GetMapping(value = "/girls/getAge/{id}")
  2. public void getAge(@PathVariable("id") Integer id) throws Exception{
  3. // 判断应该交给service
  4. girlService.getAge(id);
  5. }

  service也是,该抛异常就抛出异常:

  1. public void getAge(Integer id) throws Exception{
  2. Integer age = girlRepository.findOne(id).getAge();
  3. if (age < 12) {
  4. // 小学生
  5. throw new Exception("小学生!");
  6. } else {
  7. // 上初中了
  8. throw new Exception("初中生!");
  9. }
  10. }

  统一异常处理类:

  1. package com.example.demo.handle;
  2.  
  3. import com.example.demo.bean.Result;
  4. import com.example.demo.utils.ResultUtils;
  5. import org.springframework.web.bind.annotation.ControllerAdvice;
  6. import org.springframework.web.bind.annotation.ExceptionHandler;
  7. import org.springframework.web.bind.annotation.ResponseBody;
  8.  
  9. /**
  10. * 异常处理类
  11. * 添加@ControllerAdvice标记为异常处理类
  12. * @author zcc ON 2018/2/9
  13. **/
  14. @ControllerAdvice
  15. public class MyExceptionHandler {
  16.  
  17. /**
  18. * 如果不在这里加@ResponseBody,则需要在类上加
  19. * @param e 异常
  20. * @return
  21. */
  22. @ExceptionHandler(value = Exception.class)
  23. @ResponseBody
  24. public Result handle(Exception e) {
  25. return ResultUtils.error(e.getMessage());
  26. }
  27. }

  2.自定义异常

    写自定义异常还是之前的基础篇的老套路,基本就是几个构造方法的编写,再根据需要加上自己的变量!

  1. package com.example.demo.exception;
  2.  
  3. /**
  4. * 自定义异常
  5. * 继承RuntimeException才能使得spring进行异常时的回滚
  6. * @author zcc ON 2018/2/9
  7. **/
  8. public class MyException extends RuntimeException{
  9. private Integer code;
  10.  
  11. public MyException(Integer code, String msg) {
  12. super(msg);
  13. this.code = code;
  14. }
  15.  
  16. public Integer getCode() {
  17. return code;
  18. }
  19.  
  20. public void setCode(Integer code) {
  21. this.code = code;
  22. }
  23. }

    异常处理类:

  1. package com.example.demo.handle;
  2.  
  3. import com.example.demo.bean.Result;
  4. import com.example.demo.exception.MyException;
  5. import com.example.demo.utils.ResultUtils;
  6. import org.springframework.web.bind.annotation.ControllerAdvice;
  7. import org.springframework.web.bind.annotation.ExceptionHandler;
  8. import org.springframework.web.bind.annotation.ResponseBody;
  9.  
  10. /**
  11. * 异常处理类
  12. * 添加@ControllerAdvice标记为异常处理类
  13. * @author zcc ON 2018/2/9
  14. **/
  15. @ControllerAdvice
  16. public class MyExceptionHandler {
  17.  
  18. /**
  19. * 如果不在这里加@ResponseBody,则需要在类上加
  20. * @param e 异常
  21. * @return
  22. */
  23. @ExceptionHandler(value = Exception.class)
  24. @ResponseBody
  25. public Result handle(Exception e) {
  26. // 先判断捕获的是不是我们定义的异常
  27. if (e instanceof MyException) {
  28. MyException me = (MyException) e;
  29. return ResultUtils.exp(me.getCode(), me.getMessage());
  30. } else {
  31. return ResultUtils.error("未知错误!");
  32. }
  33. }
  34. }

  其他地方需要注意:

    既然MyException继承RuntimeException了,那controller和service就不用抛出异常了

    ResultUtils根据需要微调一些

  统一404、500异常处理

  1. @ExceptionHandler(value = Exception.class)
  2. @ResponseBody
  3. public ResponseData defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
  4. logger.error("", e);
  5. ResponseData r = new ResponseData();
  6. r.setMessage(e.getMessage());
  7. if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
  8. r.setCode(404);
  9. } else {
  10. r.setCode(500);
  11. }

三、使用枚举优化管理

  1.枚举

  1. package com.example.demo.enums;
  2.  
  3. /**
  4. * 结果集的枚举管理类
  5. * 不用给出setter了,因为枚举不会再去set了
  6. * @author zcc
  7. **/
  8. public enum ResultEnum {
  9. UNKNOWN(-1, "未知错误"),
  10. SUCCESS(200, "success"),
  11. PRIMARY(100, "小学生"),
  12. MIDDLE(101, "中学生");
  13.  
  14. private Integer code;
  15. private String msg;
  16.  
  17. ResultEnum(Integer code, String msg) {
  18. this.code = code;
  19. this.msg = msg;
  20. }
  21.  
  22. public Integer getCode() {
  23. return code;
  24. }
  25.  
  26. public String getMsg() {
  27. return msg;
  28. }
  29. }

  更多枚举基础知识,参考:http://www.cnblogs.com/jiangbei/p/7580482.html

  2.调整自定义异常的构造方法

  1. /**
  2. * 自定义异常
  3. * 继承RuntimeException才能使得spring进行异常时的回滚
  4. * @author zcc ON 2018/2/9
  5. **/
  6. public class MyException extends RuntimeException{
  7. private Integer code;
  8.  
  9. public MyException(ResultEnum resultEnum) {
  10. super(resultEnum.getMsg());
  11. this.code = resultEnum.getCode();
  12. }
  13.  
  14. public Integer getCode() {
  15. return code;
  16. }
  17.  
  18. public void setCode(Integer code) {
  19. this.code = code;
  20. }
  21. }

  3.使用自定义枚举统一管理错误代码和错误信息之间的关系

  1. public void getAge(Integer id) {
  2. Integer age = girlRepository.findOne(id).getAge();
  3. if (age < 12) {
  4. // 小学生
  5. throw new MyException(ResultEnum.PRIMARY);
  6. } else {
  7. // 上初中了
  8. throw new MyException(ResultEnum.MIDDLE);
  9. }
  10. }

springboot-web进阶(三)——统一异常处理的更多相关文章

  1. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

  2. SpringBoot小技巧:统一异常处理

    SpringBoot小技巧:统一异常处理 情景描述 对于接口的定义,我们通常会有一个固定的格式,比如: 但是调用方在请求我们的API时把接口地址写错了,就会得到一个404错误,且不同于我们定义的数据格 ...

  3. springboot中web应用的统一异常处理

    在web应用中,请求处理过程中发生异常是非常常见的情况.springboot为我们提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异 ...

  4. Spring Boot中Web应用的统一异常处理

    我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来 ...

  5. Web应用的统一异常处理(二十四)

    我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来 ...

  6. [转] Spring Boot中Web应用的统一异常处理

    [From] http://blog.didispace.com/springbootexception/ 我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供 ...

  7. Spring Boot教程(二十四)Web应用的统一异常处理

    我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来 ...

  8. SpringBoot 2 快速整合 | 统一异常处理

    统一异常处理相关注解介绍 @ControllerAdvice 声明在类上用于指定该类为控制增强器类,如果想声明返回的结果为 RESTFull 风格的数据,需要在声明 @ExceptionHandler ...

  9. Web API系列(三)统一异常处理

    前面讲了webapi的安全验证和参数安全,不清楚的朋友,可以看看前面的文章,<Web API系列(二)接口安全和参数校验>,本文主要介绍Web API异常结果的处理.作为内部或者是对外提供 ...

  10. springBoot数据校验与统一异常处理

    概念 异常,在程序中经常发生,如果发生异常怎样给用户一个良好的反馈体验就是我们需要处理的问题.以前处理异常信息,经常都是给前端一个统一的响应,如数据错误,程序崩溃等等.没办法指出哪里出错了,这是一种对 ...

随机推荐

  1. git工具的使用

    Git工具的出现降低了软件版本维护的成本,极大的提高了工作效率,在这里列出了一些使用方法,方便以后查看. 1.Git的初始化->创建一个Git仓库:git init 2.创建信息:git con ...

  2. clean-css

    What is clean-css? Clean-css is a fast and efficient Node.js library for minifying CSS files. Accord ...

  3. 记录今天客户的SQLSERVER启动不起来( 错误9003)的解决过程2013-11-26

    记录今天客户的SQLSERVER启动不起来( 错误9003)的解决过程2013-11-26 今天一大早上班就接到客户的电话,说:SQLSERVER启动不起来,业务系统使用不了 于是我就使用QQ远程,帮 ...

  4. 通过office365门户修改邮箱大小限制

    1. 使用管理员账号登陆中国区office365管理中心 https://login.partner.microsoftonline.cn/logout.srf 2. 进入管理员中心 3. 进入管理中 ...

  5. UITableView中cell点击的绚丽动画效果

    UITableView中cell点击的绚丽动画效果 本人视频教程系类   iOS中CALayer的使用 效果图: 源码: YouXianMingCell.h 与 YouXianMingCell.m / ...

  6. 用UITextView加载rtfd文件

    用UITextView加载rtfd文件 效果 说明 使用此方法可以实现十分简易的富文本显示效果,包括图文混排等等效果. 源码 // // ViewController.m // Rtfd // // ...

  7. [C++] 用Xcode来写C++程序[3] Constants

    用Xcode来写C++程序[3] Constants 以下是一些基本数据的含义: 75 // int 75u // unsigned int 75l // long 75ul // unsigned ...

  8. 低级终端IO

    低级终端IO 程序会需要对输入输出进行比简单的文件操作更为精确的控制.POSX提供了一套接口允许程序控制终端驱动程序的行为,这套接口称为通用终端接口(GIT). 需要改变终端设置的例子 标准输入输出, ...

  9. Hadoop HBase概念学习系列之HBase的Shell(步骤非常清晰)(二十四)

    这部分知识点,是必须要熟练玩转的! 见 5 hbase-shell + hbase的java api 的进入HBase Shell   强烈建议,先看我上面的这篇博文,是实实际际的步骤. 另外,附上一 ...

  10. 【0】如何在电脑中使用多个python版本【python虚拟环境配置】

    问题: 该篇解决如何在同一个操作系统中可以便捷诶的使用多个python版本.有时候我们在开发的时候会同时需要python2 和python3环境,或者是需要不同的版本,都可以尽心如下配置. (1)在c ...