目录
一、枚举类定义错误码和错误描述
package com.sumperman.resuratant.common;
public enum ErrorCodeEnum {
/*
* 重复提交数据库端异常
* */
REP_COMMIT_ERROR("ORDER001","重复提交"),
/*
* 数据库链接失败
* */
LINKED_DATABASE_FAIL("SYS001","系统错误"),
/*
* 数据库中没有相关的信息
* */
NO_QUERY_DATA("DATABASE001","没有查到相关信息")
;
ErrorCodeEnum(String typeCode, String type) {
this.typeCode = typeCode;
this.type = type;
}
private String typeCode;
private String type;
public String getTypeCode() {
return typeCode;
}
public void setTypeCode(String typeCode) {
this.typeCode = typeCode;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
然后在异常的地方将错误码和错误描述返回:
@Service
public class BookService {
@Autowired
private BookMapper booM;
//根据id查找数据的全部信息
public HashMap<String,Object> findOneBookById(Long id) {
HashMap<String,Object> map = new HashMap<>(1);
Book book = booM.selectByPrimaryKey(id);
if(book == null) {
map.put(ErrorCodeEnum.NO_QUERY_DATA.getTypeCode(), ErrorCodeEnum.NO_QUERY_DATA.getType());
}else {
map.put(book.hashCode()+ "",book);
}
map.put(book.hashCode()+ "",book);
return map;
}
}这是项目中经常使用的一种简单的手段,定义好枚举的错误码和错误描述直接返回给前端即可。优点:简单;缺点:增加或者修改均需要编译、打包、重新部署等。
二、枚举类只定义错误码,错误描述放在配置文件中
public enum ErrorCodeCenter {
NO_DATA_IN_DATABASE("dining001")
;
private String code = "0000";
ErrorCodeCenter(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
使用枚举的错误码
@Service
public class BookService {
@Autowired
private BookMapper booM;
//根据id查找数据的全部信息
public HashMap<String,Object> findOneBookById(Long id) {
HashMap<String,Object> map = new HashMap<>(1);
Book book = booM.selectByPrimaryKey(id);
if(book == null) {
map.put("failCode", ErrorCodeCenter.NO_DATA_IN_DATABASE.getCode());
}else {
map.put(book.hashCode()+ "",book);
}
map.put(book.hashCode()+ "",book);
return map;
}
}定义配置文件:errorCodeConfig.properties
dining001=查询的数据不存在读取配合文件的工具类:
public class PropertiesUtil {
public static Properties parsePro(String filePath) {
Properties prop = new Properties();
//设置格式,否则解析的汉字是乱码
InputStream in = PropertiesUtil.class.getResourceAsStream(filePath);
try {
prop.load(new InputStreamReader(in, "UTF-8"));
//prop.load(in);
} catch (IOException e) {
e.printStackTrace();
}
return prop;
}
}自定义返回值拦截器:
@ControllerAdvice
public class InterceptResponse implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Nullable
@Override
public Object beforeBodyWrite(@Nullable Object body, MethodParameter methodParameter, MediaType mediaType,
Class<? extends HttpMessageConverter<?>> aClass,
ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
ServletServerHttpResponse responseTemp = (ServletServerHttpResponse) serverHttpResponse;
HttpServletResponse resp = responseTemp.getServletResponse();
ServletServerHttpRequest sshr = (ServletServerHttpRequest) serverHttpRequest;
HttpServletRequest req = sshr.getServletRequest();
//此处的 Result 对象是我自定义的返回值类型,具体根据自己需求修改即可
HashMap<String,Object> ret = new HashMap<>(2);
HashMap result = (HashMap) body;
if(body instanceof HashMap && result.get("failCode")!=null) {
String s = result.get("failCode").toString();
/*!=null?result.get("failCode").toString():null;*/
System.out.println("获取的错误码"+s);
//替换failCode成用户描述
Properties pro = PropertiesUtil.parsePro("/config/errorCodeConfig.properties");
System.out.println("获取的pro"+pro);
System.out.println("获取的结果" + s);
ret.put("failCode",pro.getProperty(s));
return ret;
}
System.out.println("返回的结果" +result);
return result;
}
}当发生异常时便可以将错误码转成错误描述返回给前端。该办法有一个好处是可以修改配置文件,然后重新启动程序就可以实现错误描述的修改,免去了编译代码和重新发版的麻烦。但是拦截器是基于切面的,底层是动态代理,性能上有所损失。如果不是经常需要修改错误码对应的描述,其实没多优势,就是看起来高大上,实际上比较鸡肋的一种设计。
三、使用@RestControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.io.IOException;
import java.util.HashMap;
/**
* @ControllerAdvice: 表示当前类是异常处理类,给Controller控制器类增强功能的
* 位置: 在类的上面
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 定义处理异常的方法,当异常发生后,执行这个方法
* 处理IOException异常
*
* @ExceptionHandler: 表示此方法处理相应的异常
* 属性: value 表示异常的类型
* 位置: 在方法的上面
*/
@ExceptionHandler(value = IOException.class)
public HashMap<String,Object> doNameException(Exception e) {
System.out.println("doNameException===" + e);
HashMap<String,Object> ret = new HashMap<>(2);
ret.put("code","10001");
ret.put("message","请求失败");
return ret;
}
/**
* 定义处理异常的方法,当异常发生后,执行这个方法
* 处理RuntimeException异常
*
* @ExceptionHandler: 表示此方法处理相应的异常
* 属性: value 表示异常的类型
* 位置: 在方法的上面
*/
@ExceptionHandler(value = RuntimeException.class)
public HashMap<String,Object> doAgeException(Exception e) {
System.out.println("doAgeException" + e);
HashMap<String,Object> ret = new HashMap<>(2);
ret.put("code","10002");
ret.put("message","请求失败");
return ret;
}
//处理其他异常 Error
@ExceptionHandler
public HashMap<String,Object> doOtherException(Exception e) {
System.out.println("doOtherException" + e);
HashMap<String,Object> ret = new HashMap<>(2);
ret.put("code","10003");
ret.put("message","请求失败");
return ret;
}
}该办法是一种粗放式的处理方式,异常很难精细化。但是省去了维护错误和错误描述的麻烦,后台存好日志,也可以查找具体原因,前端展示给用户的是一些可接受的错误描述,适合做应急的处理,个人不推荐这种方式。
四、将错误码和错误描述放在配置中心
微服务框架可以考虑,将错误码和错误描述发布在配置中心,这样可以实现热更新。该方案需要另外搭建环境,暂时不实践。
版权声明:本文为weixin_41670928原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。