补充

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

  1.结果集包装类 

package com.example.demo.bean;

/**
* 结果包装
*
* @author zcc ON 2018/2/9
**/
public class Result<T> {
/**
* 错误代码(可以设定例如500表示错误)
*/
private Integer code;
/**
* 提示信息
*/
private String msg;
/**
* 数据内容
*/
private T data; public Result() {
} 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;
}
}

Resultde

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

  2.使用包装结果集

@PostMapping(value = "/girls")
public Result<Girl> addGirl(@Valid Girl girl, BindingResult bindingResult) {
Result<Girl> result = new Result<>();
// 表单验证逻辑
if (bindingResult.hasErrors()) {
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
StringBuffer sb = new StringBuffer();
for (FieldError fieldError : fieldErrors) {
sb.append(fieldError.getDefaultMessage());
}
result.setCode(500);
result.setMsg(sb.toString());
return result;
}
result.setCode(200);
result.setMsg("success");
result.setData(girlRepository.save(girl));
return result;
}

    3。改进结果集

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

/**
* 结果集的工具类
*
* @author zcc ON 2018/2/9
**/
public class ResultUtils { public static Result<Object> success(Object data) {
Result<Object> result = new Result<>();
result.setCode(200);
result.setMsg("success");
result.setData(data); return result;
} public static Result<Object> error(String msg) {
Result<Object> result = new Result<>();
result.setCode(500);
result.setMsg(msg);
return result;
}
}

    使用:

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

一、概述

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

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

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

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

二、问题提出

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

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

  service:

public void getAge(Integer id) {
Integer age = girlRepository.findOne(id).getAge();
if (age < 12) {
// 小学生
} else {
// 上初中了
}
}

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

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

三、统一异常处理

   1.基本用法

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

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

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

public void getAge(Integer id) throws Exception{
Integer age = girlRepository.findOne(id).getAge();
if (age < 12) {
// 小学生
throw new Exception("小学生!");
} else {
// 上初中了
throw new Exception("初中生!");
}
}

  统一异常处理类:

package com.example.demo.handle;

import com.example.demo.bean.Result;
import com.example.demo.utils.ResultUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; /**
* 异常处理类
* 添加@ControllerAdvice标记为异常处理类
* @author zcc ON 2018/2/9
**/
@ControllerAdvice
public class MyExceptionHandler { /**
* 如果不在这里加@ResponseBody,则需要在类上加
* @param e 异常
* @return
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handle(Exception e) {
return ResultUtils.error(e.getMessage());
}
}

  2.自定义异常

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

package com.example.demo.exception;

/**
* 自定义异常
* 继承RuntimeException才能使得spring进行异常时的回滚
* @author zcc ON 2018/2/9
**/
public class MyException extends RuntimeException{
private Integer code; public MyException(Integer code, String msg) {
super(msg);
this.code = code;
} public Integer getCode() {
return code;
} public void setCode(Integer code) {
this.code = code;
}
}

    异常处理类:

package com.example.demo.handle;

import com.example.demo.bean.Result;
import com.example.demo.exception.MyException;
import com.example.demo.utils.ResultUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; /**
* 异常处理类
* 添加@ControllerAdvice标记为异常处理类
* @author zcc ON 2018/2/9
**/
@ControllerAdvice
public class MyExceptionHandler { /**
* 如果不在这里加@ResponseBody,则需要在类上加
* @param e 异常
* @return
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handle(Exception e) {
// 先判断捕获的是不是我们定义的异常
if (e instanceof MyException) {
MyException me = (MyException) e;
return ResultUtils.exp(me.getCode(), me.getMessage());
} else {
return ResultUtils.error("未知错误!");
}
}
}

  其他地方需要注意:

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

    ResultUtils根据需要微调一些

  统一404、500异常处理

  @ExceptionHandler(value = Exception.class)
@ResponseBody
public ResponseData defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
logger.error("", e);
ResponseData r = new ResponseData();
r.setMessage(e.getMessage());
if (e instanceof org.springframework.web.servlet.NoHandlerFoundException) {
r.setCode(404);
} else {
r.setCode(500);
}

三、使用枚举优化管理

  1.枚举

package com.example.demo.enums;

/**
* 结果集的枚举管理类
* 不用给出setter了,因为枚举不会再去set了
* @author zcc
**/
public enum ResultEnum {
UNKNOWN(-1, "未知错误"),
SUCCESS(200, "success"),
PRIMARY(100, "小学生"),
MIDDLE(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;
}
}

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

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

/**
* 自定义异常
* 继承RuntimeException才能使得spring进行异常时的回滚
* @author zcc ON 2018/2/9
**/
public class MyException extends RuntimeException{
private Integer code; public MyException(ResultEnum resultEnum) {
super(resultEnum.getMsg());
this.code = resultEnum.getCode();
} public Integer getCode() {
return code;
} public void setCode(Integer code) {
this.code = code;
}
}

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

 public void getAge(Integer id) {
Integer age = girlRepository.findOne(id).getAge();
if (age < 12) {
// 小学生
throw new MyException(ResultEnum.PRIMARY);
} else {
// 上初中了
throw new MyException(ResultEnum.MIDDLE);
}
}

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. 禅道Bug管理工具环境搭建

    下载地址:http://sourceforge.net/projects/zentao/files/8.2/ZenTaoPMS.8.2.stable.exe/download 1.解压ZenTaoPM ...

  2. Linux学习之CentOS(四)----Linux各目录的介绍

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...

  3. oracle使用索引和不使用索引性能分析

    首先准备一张百万条数据的表,这样分析数据差距更形象! 下面用分页表数据对表进行分析,根据EMP_ID 字段排序,使用索引和不使用索引性能差距! sql查询语法准备,具体业务根据具体表书写sql语法: ...

  4. 转:JavaBean 、 Serverlet 总结

    Serverlet简介: Servlet(Server Applet),全称Java Servlet,未有中文译文.是用Java编写的服务器端程序.其主要功能在于交互式地浏览和修改数据,生成动态Web ...

  5. url用法

    url中的name用法: 0.定义主rul.py urlpatterns = [ url(r'^sinfors/', include('sinfors.urls', namespace="s ...

  6. zabbix日常监控项mysql(七)

    参考文档: percona官方文档:https://www.percona.com/doc/percona-monitoring-plugins/LATEST/zabbix/index.html za ...

  7. 超强IIS站点工具一键设置PHP,支持多个PHP同时运行

    PHPWAMP8.8.8.8IN支持三大主流Web服务器:iis.apache.nginx NGINX站点管理.IIS站点管理.Apache站点管理均支持php多版本同时运行,无限自定义mysql.p ...

  8. C#综合揭秘——分部类和分部方法

    在面向对象的“封装闭合性”开发原则中,一向提倡的是把独立的功能封装在一个类里面的!但从Visual Studio 2005开发,系统提供了一个分部类的开发方式一直受到争议,很多人认为把同一类的功能分布 ...

  9. C++编译器符号表有哪些内容?

    http://blog.csdn.net/wangbingcsu/article/details/48340479 C++编译器符号表有哪些内容? 很早就想写一篇关于符号表的学习小结,可是迟迟不能下笔 ...

  10. [CEOI2017]Building Bridges

    题目 斜率优化思博题,不想写了 之后就一直\(95\)了,于是靠肮脏的打表 就是更新了一下凸壳上二分斜率的写法,非常清爽好写 就当是挂个板子了 #include<algorithm> #i ...