@ -1,321 +0,0 @@
package com.chinaunicom.mall.ebtp.common.exception.service ;
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
import java.util.Objects ;
import javax.servlet.http.HttpServletRequest ;
import org.apache.commons.lang3.StringUtils ;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty ;
import org.springframework.context.annotation.Profile ;
import org.springframework.dao.DataAccessException ;
import org.springframework.dao.DuplicateKeyException ;
import org.springframework.dao.EmptyResultDataAccessException ;
import org.springframework.http.HttpStatus ;
import org.springframework.transaction.TransactionSystemException ;
import org.springframework.validation.BindException ;
import org.springframework.validation.BindingResult ;
import org.springframework.validation.FieldError ;
import org.springframework.web.HttpRequestMethodNotSupportedException ;
import org.springframework.web.bind.MethodArgumentNotValidException ;
import org.springframework.web.bind.MissingServletRequestParameterException ;
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 org.springframework.web.method.annotation.MethodArgumentTypeMismatchException ;
import com.chinaunicom.mall.ebtp.common.base.entity.BaseResponse ;
import com.chinaunicom.mall.ebtp.common.exception.entity.BusinessException ;
import com.chinaunicom.mall.ebtp.common.exception.entity.AuthFailureException ;
import com.chinaunicom.mall.ebtp.common.util.JsonUtils ;
import cn.hutool.core.convert.Convert ;
import cn.hutool.core.exceptions.ExceptionUtil ;
import io.seata.core.context.RootContext ;
import io.seata.core.exception.RmTransactionException ;
import lombok.Getter ;
import lombok.Setter ;
import lombok.extern.slf4j.Slf4j ;
/**
* 异常处理 拦截BindException异常, 返回HttpStatus是400的绑定错误信息
* 拦截FrameException异常, 返回HttpStatus是406的业务处理错误信息(支持自定义状态码)
* 拦截Exception异常, 返回HttpStatus是500服务器内部异常
*
* @author fqj
* @date 2020年9月3日 11:42:25
*/
@Slf4j
@ControllerAdvice
@ResponseBody
@ConditionalOnProperty ( name = " mconfig.exception-handle-enabled " , matchIfMissing = true )
@Profile ( { " test " , " local " , " uat " } )
public class BusinessExceptionHandlerAdviceDefault {
/**
* 业务异常处理
*
* @param request 请求
* @param exception ServiceErrorException异常对象
* @return 响应
*/
@ExceptionHandler ( value = BusinessException . class )
@ResponseStatus ( HttpStatus . OK )
public BaseResponse < String > serviceErrorException ( HttpServletRequest request , BusinessException exception ) {
// 堆栈信息转为字符串
log . info ( ExceptionUtil . stacktraceToString ( exception ) ) ;
Map < String , Object > body = new HashMap < > ( ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( exception . getCode ( ) , exception . getMessage ( ) , Convert . toStr ( body ) ) ;
}
/**
* hibernate valid 验证异常拦截
*
* @param request 请求
* @param exception ServiceErrorException异常对象
* @return 响应
*/
@ExceptionHandler ( value = MethodArgumentNotValidException . class )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > handleInvalidMethodArgException ( HttpServletRequest request ,
MethodArgumentNotValidException exception ) {
// 堆栈信息转为字符串
log . info ( ExceptionUtil . stacktraceToString ( exception ) ) ;
// 按需重新封装需要返回的错误信息
List < ArgumentInvalidResult > invalidArguments = new ArrayList < > ( ) ;
// 解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
BindingResult bindingResult = exception . getBindingResult ( ) ;
for ( FieldError error : bindingResult . getFieldErrors ( ) ) {
ArgumentInvalidResult invalidArgument = new ArgumentInvalidResult ( ) ;
invalidArgument . setDefaultMessage ( error . getDefaultMessage ( ) ) ;
invalidArgument . setField ( error . getField ( ) ) ;
invalidArgument . setRejectedValue ( error . getRejectedValue ( ) ) ;
invalidArguments . add ( invalidArgument ) ;
}
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , JsonUtils . objectToJson ( invalidArguments ) ) ;
body . put ( " error " , HttpStatus . BAD_REQUEST . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . BAD_REQUEST . value ( ) , " 参数验证错误 " , Convert . toStr ( body ) ) ;
}
/**
* 参数绑定异常
*
* @param request 请求
* @param exception BindException异常对象
* @return 响应
*/
@ExceptionHandler ( value = BindException . class )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > methodArgumentNotValidHandler ( HttpServletRequest request , BindException exception ) {
// 按需重新封装需要返回的错误信息
List < ArgumentInvalidResult > invalidArguments = new ArrayList < > ( ) ;
// 解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
for ( FieldError error : exception . getBindingResult ( ) . getFieldErrors ( ) ) {
ArgumentInvalidResult invalidArgument = new ArgumentInvalidResult ( ) ;
invalidArgument . setDefaultMessage ( error . getDefaultMessage ( ) ) ;
invalidArgument . setField ( error . getField ( ) ) ;
invalidArgument . setRejectedValue ( error . getRejectedValue ( ) ) ;
invalidArguments . add ( invalidArgument ) ;
}
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , JsonUtils . objectToJson ( invalidArguments ) ) ;
body . put ( " error " , HttpStatus . BAD_REQUEST . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . BAD_REQUEST . value ( ) , " 参数错误 " , Convert . toStr ( body ) ) ;
}
/**
* 用户验证失败, 无效的token
*
* @param request 请求
* @param exception InvalidTokenException异常对象
* @return 响应
*/
@ExceptionHandler ( AuthFailureException . class )
@ResponseStatus ( HttpStatus . METHOD_NOT_ALLOWED )
public BaseResponse < String > handleInvalidTokenException ( HttpServletRequest request ,
AuthFailureException exception ) {
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , exception . getMessage ( ) ) ;
body . put ( " error " , HttpStatus . UNAUTHORIZED . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . UNAUTHORIZED . value ( ) , " 登陆已超期 " , Convert . toStr ( body ) ) ;
}
/**
* 请求方式异常
*
* @param request 请求
* @param exception HttpRequestMethodNotSupportedException异常对象
* @return 响应
*/
@ExceptionHandler ( HttpRequestMethodNotSupportedException . class )
@ResponseStatus ( HttpStatus . METHOD_NOT_ALLOWED )
public BaseResponse < String > handleMethodNotSupportedException ( HttpServletRequest request ,
HttpRequestMethodNotSupportedException exception ) {
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , exception . getMessage ( ) ) ;
body . put ( " error " , HttpStatus . METHOD_NOT_ALLOWED . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . METHOD_NOT_ALLOWED . value ( ) , " 错误的请求方式 " , Convert . toStr ( body ) ) ;
}
/**
* 参数缺失
*
* @param request 请求
* @param exception MissingServletRequestParameterException异常对象
* @return 响应
*/
@ExceptionHandler ( MissingServletRequestParameterException . class )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > handleMissingParameterException ( HttpServletRequest request ,
MissingServletRequestParameterException exception ) {
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , exception . getMessage ( ) ) ;
body . put ( " error " , HttpStatus . BAD_REQUEST . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . BAD_REQUEST . value ( ) , " 参数缺失 " , Convert . toStr ( body ) ) ;
}
// ----------------------------data--------------------------------------
/**
* 数据库异常
*
* @param request 请求
* @param exception DataAccessException异常对象
* @return 响应
*/
@ExceptionHandler ( DataAccessException . class )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > handlerDataAccessException ( HttpServletRequest request , DataAccessException exception ) {
log . error ( ExceptionUtil . stacktraceToString ( exception ) ) ;
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , exception . getMessage ( ) ) ;
body . put ( " error " , HttpStatus . BAD_REQUEST . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . BAD_REQUEST . value ( ) , " 数据库异常 " , Convert . toStr ( body ) ) ;
}
/**
* 数据不存在
*
* @param request 请求
* @param exception EmptyResultDataAccessException异常对象
* @return 响应
*/
@ExceptionHandler ( EmptyResultDataAccessException . class )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > handleDataEmptyException ( HttpServletRequest request ,
EmptyResultDataAccessException exception ) {
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , exception . getMessage ( ) ) ;
body . put ( " error " , HttpStatus . BAD_REQUEST . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . BAD_REQUEST . value ( ) , " 数据不存在 " , Convert . toStr ( body ) ) ;
}
/**
* 请求方式异常
*
* @param request 请求
* @param exception DuplicateKeyException异常对象
* @return 响应
*/
@ExceptionHandler ( DuplicateKeyException . class )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > handleDataDualException ( HttpServletRequest request , DuplicateKeyException exception ) {
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , exception . getMessage ( ) ) ;
body . put ( " error " , HttpStatus . BAD_REQUEST . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . BAD_REQUEST . value ( ) , " 数据重复插入 " , Convert . toStr ( body ) ) ;
}
/**
* 方法参数类型不匹配异常
*
* @param request 请求
* @param exception MethodArgumentTypeMismatchException异常对象
* @return 响应
*/
@ExceptionHandler ( MethodArgumentTypeMismatchException . class )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > handleMethodArgumentTypeException ( HttpServletRequest request ,
MethodArgumentTypeMismatchException exception ) {
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , exception . getMessage ( ) ) ;
body . put ( " error " , HttpStatus . BAD_REQUEST . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . BAD_REQUEST . value ( ) , " 参数类型不匹配 " , Convert . toStr ( body ) ) ;
}
/**
* 全局异常处理
*
* @param request 请求
* @param exception Exception异常对象
* @return 响应
*/
@ExceptionHandler ( value = Exception . class )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > handleException ( HttpServletRequest request , Exception exception ) {
// 堆栈信息转为字符串
log . info ( ExceptionUtil . stacktraceToString ( exception ) ) ;
Map < String , Object > body = new HashMap < > ( ) ;
body . put ( " errors " , exception . getMessage ( ) ) ;
body . put ( " error " , HttpStatus . INTERNAL_SERVER_ERROR . getReasonPhrase ( ) ) ;
// body.put("path", request.getRequestURI());
return BaseResponse . fail ( HttpStatus . INTERNAL_SERVER_ERROR . value ( ) , " 系统异常 " , Convert . toStr ( body ) ) ;
}
/**
* @param request
* @param exception
* @return
*/
@ExceptionHandler ( { TransactionSystemException . class , RmTransactionException . class } )
@ResponseStatus ( HttpStatus . BAD_REQUEST )
public BaseResponse < String > handleTransactionSystemException ( HttpServletRequest request ,
TransactionSystemException exception ) {
log . info ( ExceptionUtil . stacktraceToString ( exception ) ) ;
if ( ( ( String ) Objects . requireNonNull ( exception . getMessage ( ) ) ) . contains ( " may be has finished " ) ) {
String xid = RootContext . getXID ( ) ;
if ( StringUtils . isNotEmpty ( xid ) ) {
RootContext . unbind ( ) ;
log . info ( " TransactionSystemException ----- suspending current transaction,xid = {} " , xid ) ;
return BaseResponse . fail ( " 系统繁忙,请重试 " , null ) ;
}
}
return BaseResponse . fail ( " 系统异常 " , exception . getMessage ( ) ) ;
}
/**
* 参数异常
*/
@Getter
@Setter
class ArgumentInvalidResult {
/**
* 字段名
*/
private String field ;
/**
* 输入的错误值
*/
private Object rejectedValue ;
/**
* 错误信息
*/
private String defaultMessage ;
}
}