注解ControllerAdvice配合ExceptionHandler實(shí)現(xiàn)全局異常處理蚕甥。當(dāng)將異常拋出時(shí),可以對(duì)異常進(jìn)行統(tǒng)一處理,規(guī)定返回的json格式或是跳轉(zhuǎn)到一個(gè)錯(cuò)誤頁(yè)面象踊。
- 第一步测蹲,定義一個(gè)全局異常處理Hanlder
@ControllerAdvice
public class GlobalExceptionHanlder {
//
// @Autowired
// private Tracer tracer;
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHanlder.class);
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(value = Throwable.class)
@ResponseBody
public RestResponse<Object> handler(HttpServletRequest req, Throwable throwable){
LOGGER.error(throwable.getMessage(),throwable);
// tracer.addTag(Span.SPAN_ERROR_TAG_NAME, ExceptionUtils.getExceptionMessage(throwable));
// System.out.println(tracer.getCurrentSpan().getTraceId());
RestCode restCode = Exception2CodeRepo.getCode(throwable);
RestResponse<Object> response = new RestResponse<Object>(restCode.code,restCode.msg);
return response;
}
}
- 第二步肤舞,定義異常類(lèi)型轉(zhuǎn)換返回代碼類(lèi)
public class Exception2CodeRepo {
private static final ImmutableMap<Object, RestCode> MAP = ImmutableMap.<Object, RestCode>builder()
.put(IllegalParamsException.Type.WRONG_PAGE_NUM,RestCode.WRONG_PAGE)
.put(IllegalStateException.class,RestCode.UNKNOWN_ERROR)
.put(UserException.Type.USER_NOT_LOGIN,RestCode.TOKEN_INVALID)
.put(UserException.Type.USER_NOT_FOUND,RestCode.USER_NOT_EXIST)
.put(UserException.Type.USER_AUTH_FAIL,RestCode.USER_NOT_EXIST).build();
private static Object getType(Throwable throwable){
try {
return FieldUtils.readDeclaredField(throwable, "type", true);
} catch (Exception e) {
return null;
}
}
public static RestCode getCode(Throwable throwable) {
if (throwable == null) {
return RestCode.UNKNOWN_ERROR;
}
Object target = throwable;
if (throwable instanceof WithTypeException) {
Object type = getType(throwable);
if (type != null ) {
target = type;
}
}
RestCode restCode = MAP.get(target);
if (restCode != null) {
return restCode;
}
Throwable rootCause = ExceptionUtils.getRootCause(throwable);
if (rootCause != null) {
return getCode(rootCause);
}
return restCode.UNKNOWN_ERROR;
}
}
- 第三步图仓,自定義異常類(lèi),繼承RuntimeException
public class IllegalParamsException extends RuntimeException implements WithTypeException{
private static final long serialVersionUID = 1L;
private Type type;
public IllegalParamsException(){
}
public IllegalParamsException(Type type,String msg){
super(msg);
this.type = type;
}
public Type type(){
return type;
}
public enum Type{
WRONG_PAGE_NUM,WRONG_TYPE
}
}
public class UserException extends RuntimeException implements WithTypeException{
private static final long serialVersionUID = 1L;
private Type type;
public UserException(String message) {
super(message);
this.type = Type.LACK_PARAMTER;
}
public UserException(Type type, String message) {
super(message);
this.type = type;
}
public Type type(){
return type;
}
public enum Type{
WRONG_PAGE_NUM,LACK_PARAMTER,USER_NOT_LOGIN,USER_NOT_FOUND,USER_AUTH_FAIL;
}
}
/**
* 包含類(lèi)型的異常
*/
public interface WithTypeException {
}
- 第四步揭厚,定義返回值枚舉類(lèi)
public enum RestCode {
OK(0,"ok"),
UNKNOWN_ERROR(1,"未知異常"),
TOKEN_INVALID(2,"TOKEN失效"),
USER_NOT_EXIST(3,"用戶(hù)不存在"),
WRONG_PAGE(10100,"頁(yè)碼不合法"),
LACK_PARAMS(10101,"缺少參數(shù)");
public final int code;
public final String msg;
private RestCode(int code,String msg){
this.code = code;
this.msg = msg;
}
}
- 第五步却特,業(yè)務(wù)代碼中異常拋出
public User getLoginedUserByToken(String token) {
Map<String, String> map = null;
try {
map = JwtHelper.verifyToken(token);
} catch (Exception e) {
throw new UserException(Type.USER_NOT_LOGIN,"User not login");
}
String email = map.get("email");
Long expired = redisTemplate.getExpire(email);
if (expired > 0L) {
renewToken(token, email);
User user = getUserByEmail(email);
user.setToken(token);
return user;
}
throw new UserException(Type.USER_NOT_LOGIN,"user not login");
}
結(jié)果:{"code":2,"msg":"TOKEN失效","result":null}