https://www.cnblogs.com/xuwujing/p/10933082.html
这个是网上找的异常处理方案,有几个问题:
-
http状态码是三位数的,自定义状态码应该跟他们分开,应该类似于10001这样
-
/** * 处理其他异常 * @param req * @param e * @return */ @ExceptionHandler(value =Exception.class) @ResponseBody public ResultBody exceptionHandler(HttpServletRequest req, Exception e){ logger.error("未知异常!原因是:",e); return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR); }
这个地方的http状态码不应该是200 了,需要去改变http的状态码
-
返回信息中应该包含请求的方式和请求的对应请求路径
-
缺少自定义异常的http状态码的动态处理
借鉴了一下它的方案,总结了以下几步,测试代码就不贴出来了。
Step1、自定义错误码配置文件
exception-codes-demo.properties
sell.codes[1]=SUCCESS
#参数错误
sell.codes[10001]=参数为空
sell.codes[10002]=参数不全
sell.codes[10003]=参数类型错误
sell.codes[10004]=参数无效
#用户错误
sell.codes[20001]=永久不存在
sell.codes[20002]=用户未登录
sell.codes[20003]=用户名或者密码错误
sell.codes[20004]=用户账户已被禁用
sell.codes[20005]=用户已经存在
#业务错误
sell.codes[30001]=系统业务出现问题
#系统错误
sell.codes[40001]=系统内部错误
#数据错误
sell.codes[50001]=数据未找到
sell.codes[50002]=数据有误
sell.codes[50003]=数据已存在
#接口错误
sell.codes[60001]=系统业务出现问题
sell.codes[60002]=系统外部接口调用异常
sell.codes[60003]=接口禁止访问
sell.codes[60004]=接口地址无效
sell.codes[60005]=接口请求超时
sell.codes[60006]=接口负载过高
#权限错误
sell.codes[70001]=没有访问权限
Step2、编写自定义错误码的处理类,与配置文件绑定
package com.immoc.sell.core.configuration;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author allen
*/
@Component
@PropertySource(value = "classpath:config/exception-codes-demo.properties",encoding = "utf-8")
@ConfigurationProperties(prefix = "sell")
@Getter
@Setter
public class ExceptionCodeConfiguration {
private Map<Integer, String> codes = new HashMap<>();
public String getMessage(int code){
return codes.get(code);
}
}
Step3、编写通用返回消息类 也就是ResultBody
package com.immoc.sell.core;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.StringTokenizer;
/**
* @author allen
*/
@Data
@AllArgsConstructor
public class UnifyResponse {
private int code;
private String message;
private String request;
}
Step4、自定义异常父类和它的子类
package com.immoc.sell.exception.http;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
/**
* @author allen
*/
@Data
public class HttpException extends RuntimeException {
protected Integer code;
protected Integer httpStatusCode = 500;
}
package com.immoc.sell.exception.http;
/**
* @author allen
*/
public class ForbiddenException extends HttpException {
public ForbiddenException(int code) {
this.code = code;
this.httpStatusCode = 403;
}
}
package com.immoc.sell.exception.http;
/**
* @author allen
*/
public class NotFoundException extends HttpException{
public NotFoundException(int code) {
this.httpStatusCode = 404;
this.code = code;
}
}
Step5、编写全局异常处理通知类
package com.immoc.sell.core;
import com.immoc.sell.core.configuration.ExceptionCodeConfiguration;
import com.immoc.sell.exception.http.HttpException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import javax.servlet.http.HttpServletRequest;
/**
* @author allen
*/
@ControllerAdvice
public class GlobalExceptionAdvice {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionAdvice.class);
@Autowired
private ExceptionCodeConfiguration exceptionCodeConfiguration;
/**
* 处理自定义的业务异常
* http类型的
*
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = HttpException.class)
@ResponseBody
public ResponseEntity<UnifyResponse> httpExceptionHandler(HttpServletRequest req, HttpException e) {
logger.error("发生http类型的异常!原因是:{}", e.getMessage());
UnifyResponse response = new UnifyResponse(e.getCode(), exceptionCodeConfiguration.getMessage(e.getCode()), req.getMethod() + " " + req.getRequestURI());
return ResponseEntity.status(e.getHttpStatusCode()).body(response);
}
/**
* 处理其他异常
*
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public UnifyResponse exceptionHandler(HttpServletRequest req, Exception e) {
logger.error("未知异常!原因是:", e);
return new UnifyResponse(99999, "服务器异常", req.getMethod() + " " + req.getRequestURI());
}
}
总结:
- 自定义已知异常其实是用把异常当做通知表达出来,传递到前端和日志系统
- httpStatus和自定义的错误码是两个维度的东西
- 在全局异常类里面我们要做的:
1、捕获未知的异常,拦截出来定义出500 的系统异常
2、已知的异常主动抛出,分门别类的用自定义异常类来抛出,通知给前端 - 作为使用异常框架的同学只需要
1、维护自定义异常码的配置文件
2、在业务代码中抛出异常并传入错误码