springboot-web进阶(三)——统一异常处理
补充
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进阶(三)——统一异常处理的更多相关文章
- Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群
Redis总结(五)缓存雪崩和缓存穿透等问题 前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...
- SpringBoot小技巧:统一异常处理
SpringBoot小技巧:统一异常处理 情景描述 对于接口的定义,我们通常会有一个固定的格式,比如: 但是调用方在请求我们的API时把接口地址写错了,就会得到一个404错误,且不同于我们定义的数据格 ...
- springboot中web应用的统一异常处理
在web应用中,请求处理过程中发生异常是非常常见的情况.springboot为我们提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异 ...
- Spring Boot中Web应用的统一异常处理
我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来 ...
- Web应用的统一异常处理(二十四)
我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来 ...
- [转] Spring Boot中Web应用的统一异常处理
[From] http://blog.didispace.com/springbootexception/ 我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供 ...
- Spring Boot教程(二十四)Web应用的统一异常处理
我们在做Web应用的时候,请求处理过程中发生错误是非常常见的情况.Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来 ...
- SpringBoot 2 快速整合 | 统一异常处理
统一异常处理相关注解介绍 @ControllerAdvice 声明在类上用于指定该类为控制增强器类,如果想声明返回的结果为 RESTFull 风格的数据,需要在声明 @ExceptionHandler ...
- Web API系列(三)统一异常处理
前面讲了webapi的安全验证和参数安全,不清楚的朋友,可以看看前面的文章,<Web API系列(二)接口安全和参数校验>,本文主要介绍Web API异常结果的处理.作为内部或者是对外提供 ...
- springBoot数据校验与统一异常处理
概念 异常,在程序中经常发生,如果发生异常怎样给用户一个良好的反馈体验就是我们需要处理的问题.以前处理异常信息,经常都是给前端一个统一的响应,如数据错误,程序崩溃等等.没办法指出哪里出错了,这是一种对 ...
随机推荐
- LeetCode题解之 two sum 问题
1.题目描述 2.题目分析 考虑使用hashMap的方式将数组中的每个元素和下表对应存储起来,然后遍历数组,计算target 和 数组中每个元素的差值,在hashMap中寻找,一直到找到最后一对. 3 ...
- 使用Axure设计中,大型的后台系统原型总结
使用Axure设计中,大型的后台系统原型总结 2018年4月16日luodonggan 在产品原型设计中,经常会涉及到后台系统原型的设计,如何设计出更规范标准的后台系统原型,是很多产品同行们都会遇到的 ...
- 优化 ExpressRoute 路由
当你有多个 ExpressRoute 线路时,可以通过多个路径连接到 Azure.结果就是,你所采用的路由可能不是最理想的 - 也就是说,你的流量可能会经历较长的路径才能到达 Azure,而 Azur ...
- 在html的JavaScript部分计算,保留小数点后面的位数
例: f_pbf = ((f_boday_fat/f_weight)*100).toFixed(1); 注:例子中的.toFixed(1)是所用函数,确保在所得结果中保留小数点后面一位数,若 ...
- linux centos6.5 网络配置
1.方法一.修改网络配置文件 ①cd /etc/sysconfig/network-scripts ②cp ifcfg-eth0 ./ifcfg-eth0.bak //修改前先备份 第一个以太网 ...
- lambda 形参:返回值 lambda 匿名函数 格式:
lambda 匿名函数 格式: lambda 形参:返回值 e.g f = lambda n:n**2 print(f(10))
- jQuery实现滚动时动态加载页面内容
有些网站的网页内容不是一次性加载完毕的,而是在鼠标向下滚动时动态加载的,这是怎么做到的呢?看下面代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...
- 1303. [CQOI2009]中位数【前缀和+乱搞】
Description 给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b.中位数是指把所有元素从小到大排列后,位于中间的数. Input 第一行为两个正整数n和b ,第二行为 ...
- luogu P2709 小B的询问
嘟嘟嘟 莫队板子. 记住:删除是先删除再移动,添加是先移动在添加! #include<cstdio> #include<iostream> #include<cmath& ...
- vue2.* 事件 定义方法 执行方法 获取数据 改变数据 执行方法传值 以及事件对象 05
<template> <div id="app"> <button v-on:click="run1()">执行事件的第一种 ...