1.异常处理作用
统一的异常处理可以让前台隔离那些对他们无需的信息,但是又让后台可以很好的规避泛滥的异常.
2.代码示例:
- 建立业务异常
/**
* 服务(业务)异常如"账号或密码错误",该异常只做INFO级别的日志记录
*
* @see com.ley.springboot.seed.config.WebConfig
*/
public class ServiceException extends RuntimeException {
public ServiceException() {
}
public ServiceException(String message) {
super(message);
}
public ServiceException(String message, Throwable cause) {
super(message, cause);
}
}
2.建立web相应封装
/**
* 统一API响应结果封装
*/
public class Result<T> {
/**
* response code
**/
private int code;
/**
* response message
**/
private String message;
/**
* response data
**/
private T data;
public Result setCode(ResultCode resultCode) {
this.code = resultCode.code();
return this;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
public Result setMessage(String message) {
this.message = message;
return this;
}
public T getData() {
return data;
}
public Result setData(T data) {
this.data = data;
return this;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}
/**
* 响应码枚举,参考HTTP状态码的语义
*
* @see org.springframework.http.HttpStatus
*/
public enum ResultCode {
SUCCESS(200),//成功
FAIL(400),//失败
UNAUTHORIZED(401),//未认证(签名错误)
NOT_FOUND(404),//接口不存在
INTERNAL_SERVER_ERROR(500);//服务器内部错误
private final int code;
ResultCode(int code) {
this.code = code;
}
public int code() {
return code;
}
}
3.统一异常处理
/**
* web config
**/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
private final Logger logger = LoggerFactory.getLogger(WebConfig.class);
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullNumberAsZero);
// 按需配置,更多参考FastJson文档
converter.setFastJsonConfig(config);
converter.setDefaultCharset(Charset.forName("UTF-8"));
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
converters.add(converter);
}
//统一异常处理
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
exceptionResolvers.add(new HandlerExceptionResolver() {
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
Result result = new Result();
if (e instanceof ServiceException) {//业务失败的异常,如"账号或密码错误"
result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
logger.info(e.getMessage());
} else if (e instanceof NoHandlerFoundException) {
result.setCode(ResultCode.NOT_FOUND).setMessage("接口 [" + request.getRequestURI() + "] 不存在");
} else if (e instanceof ServletException) {
result.setCode(ResultCode.FAIL).setMessage(e.getMessage());
} else {
result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");
String message;
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
message = String.format("接口 [%s] 出现异常,方法:[%s.%s],异常摘要:%s",
request.getRequestURI(),
handlerMethod.getBean().getClass().getName(),
handlerMethod.getMethod().getName(),
e.getMessage());
} else {
message = e.getMessage();
}
// result.setMessage(message);
logger.error(message, e);
}
responseResult(response, result);
return new ModelAndView();
}
});
}
private void responseResult(HttpServletResponse response, Result result) {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.setStatus(HttpStatus.OK.value());
try {
response.getWriter().write(JSON.toJSONString(result));
} catch (IOException ex) {
logger.error(ex.getMessage());
}
}
}