当前位置:网站首页>Coding skills - Global exception capture & unified return body & Business exception
Coding skills - Global exception capture & unified return body & Business exception
2022-07-27 16:11:00 【Qihai Jianren】
In development , Exception capture used to be a headache ; This article introduces several methods , How to capture and handle business exceptions gracefully ;
Checked exception and not checked exception ?
Let me introduce you first , abnormal Exception Divided into runtime exceptions (RuntimeException) And non runtime exceptions , Also known as not checking exceptions (Unchecked Exception) And check for abnormalities (Checked Exception).
(1) We can find out the abnormality checkedException( Exceptions that the compiler requires to handle ): The right program is running , It's easy to see 、 An abnormal condition that can be tolerated by reason . No matter whether it will happen or not , The compiler will force you to Throws Or use try/catch; except RuntimeException And its subclasses , Other Exception Class and its subclasses are queryable exceptions .
(2) No exceptions can be found ( Compiler does not require mandatory exceptions ): Including runtime exceptions (RuntimeException And its subclasses ) And mistakes (Error), You need to throw it yourself / Capture / Handle , Or try to avoid .( It is recommended to predict exceptions and handle exceptions )
If you use throw Throw a queryable exception in the method body , You need to declare in the method header that the method may throw throws Type of exception . The program will in throw Terminate immediately after statement , The statement after it can't be executed , And then in all of it try In block ( Maybe in the upper level call function ) Look inside out for something that matches catch Clause try block .
Runtime and non runtime exceptions ?
(1) The runtime exceptions are RuntimeException Class and its subclass exception , Such as NullPointerException、IndexOutOfBoundsException etc. , These exceptions are not checked , The program can choose to capture the processing , Or not . These exceptions are usually caused by program logic errors , Programs should try to avoid such exceptions from a logical point of view . When there is a RuntimeException When , We don't have to deal with . When such an exception occurs , It's always taken over by the virtual machine . such as : We've never had anyone deal with NullPointerException abnormal , It's a runtime exception , And it's one of the most common exceptions .
If you don't want to terminate , All runtime exceptions must be caught , Never let this processing thread exit . There is abnormal data in the queue , Normal processing should be to discard abnormal data , Then keep a log . The following normal data processing should not be affected due to abnormal data .
(2) The non runtime exception is RuntimeException An exception , They all belong to Exception Classes and subclasses . Such as IOException、SQLException And user-defined Exception abnormal . For this kind of abnormality ,JAVA The compiler forces us to catch And deal with , Otherwise, the program cannot be compiled . therefore , In the face of this kind of abnormality, whether we like it or not , I can only write a lot by myself catch Block to handle possible exceptions .
therefore —— Whether or not an exception should be thrown , Or capture / Handling exceptions ?
One of the principles of exception handling : Delay capture , intend , When an exception occurs , Should not be captured immediately , Instead, consider whether the current scope has the ability to handle this exception , without , Then the exception should continue to be thrown upward , Leave it to the higher-level scope .
for example : A method String readFile(Stringfilename), Will try to read the contents of the specified file and return , Its use FileInputStream To read the specified file , and FileInputStream The constructor of will throw FileNotFoundException, This is a CheckedException. that readFile The method is to catch this exception , Or throw this exception ? Obviously, it should be thrown . because readFile This method may be used in different scenarios , Called by different code , In these scenarios , appear “ File not found ” The processing logic may be different , For example, an alarm message should be sent in a certain scene , In another scenario, you may try to read from another file , In the third scenario, you may need to prompt the user with an error message . under these circumstances , stay readFile Within the scope of the method , Can't handle this exception , Need to throw , Handed over to the upper , The scope with the ability to handle this exception ;
Sum up , Attention should be paid to exception capture 3 A little bit :
1. Never throw abnormal information to users ! Make friendly user prompts for users , Some tips can be given to front-end developers to facilitate interaction and processing , It can also be used for log and buried point reporting ;
2. Exception capture should consider whether the current scope has the ability to handle this exception , without , Then the exception should continue to be thrown upward , Leave it to the higher-level scope ;
3. Business exceptions should be runtime exceptions , It should be bound with a business status code enumeration , There can be different treatments for different status codes 、 prompt ;
Here are two common business exception capture and processing schemes , Can be used for DUBBO perhaps HTTP Interface return processing :
Definition of business exception
Be careful : If it is C End , Business exceptions except message attribute , You can add toast attribute
import AA.common.enums.ResultCodeEnum;
import lombok.Getter;
/**
* @author AA
* @description Custom business exception , Encapsulatable system status code 、 Business error message 、 Abnormal reasons and other information
*/
@Getter
public class BusinessException extends RuntimeException {
/**
* Store the system return code corresponding to the business error
*/
private ResultCodeEnum code;
/**
* Store business error messages , And only print in the log
*/
private String busErrMsg;
/**
* Business exceptions returned without business error messages
*
* @param code
*/
public BusinessException(ResultCodeEnum code) {
super(code.getDesc());
this.code = code;
}
/**
* There are business exceptions that return business error messages
*
* @param code
* @param busErrMsg
*/
public BusinessException(ResultCodeEnum code, String busErrMsg) {
super(code.getDesc());
this.code = code;
this.busErrMsg = busErrMsg;
}
/**
* Encapsulate the business exception of the specified exception class
*
* @param code
* @param cause
*/
public BusinessException(ResultCodeEnum code, Throwable cause) {
super(code.getDesc(), cause);
this.code = code;
}
}
Status code enumeration :
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @author AA
* @description The status code enumeration of the return status requested by the interface
* First level return code : System level
* Secondary return code : Business level
* @date 2019/11/27
*/
@Getter
@AllArgsConstructor
public enum ResultCodeEnum {
/**
* First level return code , Successful operation
*/
SUCCESS(0, " Return to success "),
/**
* First level return code , System internal exception
*/
SERVER_ERROR(10000, " Server internal error ( Unknown error )"),
/**
* First level return code , The system requests a third-party system ( Such as dubbo service ) abnormal
*/
REQUEST_THIRD_SYSTEM_EXCEPTION(10001, " The system requests an exception from the third-party system "),
/**
* First level return code , Server busy
*/
SERVER_BUSYNESS(10002, " Server busy "),
/**
* First level return code , Request method Request.Method I won't support it
*/
REQUEST_METHOD_NOT_SUPPORT(10003, " The request method does not support "),
/**
* First level return code , Protocol not supported
*/
PROTOCOL_NOT_SUPPORT(10004, " Protocol not supported "),
/**
* First level return code , Unknown system error
*/
UNKNOWN(10010, " Unknown system error "),
/**
* Secondary return code , The user is not logged in
*/
UN_LOGIN(20000, " The user is not logged in !"),
/**
* Secondary return code , bad parameter
*/
BAD_PARAMS(20001, " Request parameter error "),
/**
* Secondary return code ,HttpClient request was aborted
*/
HTTPCLIENT_REQUEST_FAILED(20002, "HttpClient request was aborted !"),
/**
* Secondary return code , Fuse failure
*/
CIRCUIT_BREAKERS(20003, " Fuse failure "),
/**
* Business return code , Gift certificate sending failed
*/
SENT_TICKET_FAIL(30001, " Gift certificate sending failed "),
/**
* Business return code , Failed to collect
*/
RECEIVE_FAIL(30004, " Failed to collect "),
/**
* Business return code , Failed to issue points
*/
SENT_POINT_FAIL(30005, " Failed to issue points "),
/**
* Business return code , Query data is empty
*/
QUERY_DATA_EMPTY(30007, " Query data is empty "),
;
/**
* Status code
*/
private int code;
/**
* describe
*/
private String desc;
/**
* Find the enumeration type according to the status code
*
* @param code
* @return
*/
public static ResultCodeEnum byCode(int code) {
for (ResultCodeEnum resultEnum : ResultCodeEnum.values()) {
if (resultEnum.getCode() == code) {
return resultEnum;
}
}
throw new IllegalArgumentException("cannot find resultCode by error code : " + code);
}
}Definition of return result
dubbo:FacadeResult
import XXcommon.enums.FacadeResultCodeEnum;
import lombok.Data;
import java.io.Serializable;
/**
* @author AA
* @description default dubbo Interface return DTO
* @date 2019/11/27
*/
@Data
public class FacadeDefaultDTO<T> implements Serializable {
private static final long serialVersionUID = 6804764310822280735L;
/**
* System return code
*/
private Integer code;
/**
* Return code information
*/
private String msg;
/**
* Return the data
*/
private T data;
public FacadeDefaultDTO() {
}
private FacadeDefaultDTO(ResponseBuilder<T> builder) {
this.code = builder.code;
this.msg = builder.msg;
this.data = builder.data;
}
public static ResponseBuilder builder() {
return new ResponseBuilder();
}
public static class ResponseBuilder<T> {
private int code = FacadeResultCodeEnum.SUCCESS.getCode();
private String msg = FacadeResultCodeEnum.SUCCESS.getDesc();
private T data;
public ResponseBuilder code(int code) {
this.code = code;
return this;
}
public ResponseBuilder msg(String msg) {
this.msg = msg;
return this;
}
public ResponseBuilder data(T data) {
this.data = data;
return this;
}
public FacadeDefaultDTO<T> build() {
return new FacadeDefaultDTO<>(this);
}
}
/**
* Return to success , encapsulation Data, The compiler checks generics
*
* @param data
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> FacadeDefaultDTO<T> success(T data) {
return FacadeDefaultDTO.builder().code(FacadeResultCodeEnum.SUCCESS.getCode()).msg(FacadeResultCodeEnum.SUCCESS.getDesc()).data(data).build();
}
/**
* Return failed , Return code of encapsulation failure ,data by null
*
* @param facadeResultCodeEnum
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> FacadeDefaultDTO<T> fail(FacadeResultCodeEnum facadeResultCodeEnum) {
return FacadeDefaultDTO.builder().code(facadeResultCodeEnum.getCode()).msg(facadeResultCodeEnum.getDesc()).data(null).build();
}
/**
* Return failed , Customize the return code of failure code and msg,data by null( Used for the conversion of business exception code and service exception code )
*
* @param errCode
* @param errMsg
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> FacadeDefaultDTO<T> fail(int errCode, String errMsg) {
return FacadeDefaultDTO.builder().code(errCode).msg(errMsg).data(null).build();
}
public boolean isSuccess() {
return FacadeResultCodeEnum.SUCCESS.getCode() == this.getCode();
}
}http:BaseResponse
import xx.common.enums.ResultCodeEnum;
import lombok.Data;
/**
* @author AA
* @description default controller The return class of
* @date 2019/11/27
*/
@Data
public class DefaultResponseDTO<T> {
/**
* System return code
*/
private Integer code;
/**
* Return code information
*/
private String msg;
/**
* Return the data
*/
private T data;
public DefaultResponseDTO() {
}
private DefaultResponseDTO(ResponseBuilder<T> builder) {
this.code = builder.code;
this.msg = builder.msg;
this.data = builder.data;
}
public static ResponseBuilder builder() {
return new ResponseBuilder();
}
public static class ResponseBuilder<T> {
private int code = ResultCodeEnum.SUCCESS.getCode();
private String msg = ResultCodeEnum.SUCCESS.getDesc();
private T data;
public ResponseBuilder code(int code) {
this.code = code;
return this;
}
public ResponseBuilder msg(String msg) {
this.msg = msg;
return this;
}
public ResponseBuilder data(T data) {
this.data = data;
return this;
}
public DefaultResponseDTO<T> build() {
return new DefaultResponseDTO<>(this);
}
}
/**
* Return to success , encapsulation Data, The compiler checks generics
*
* @param data
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> DefaultResponseDTO<T> success(T data) {
return DefaultResponseDTO.builder().code(ResultCodeEnum.SUCCESS.getCode()).msg(ResultCodeEnum.SUCCESS.getDesc()).data(data).build();
}
/**
* Return failed , Return code of encapsulation failure
*
* @param resultCodeEnum
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> DefaultResponseDTO<T> fail(ResultCodeEnum resultCodeEnum) {
return DefaultResponseDTO.builder().code(resultCodeEnum.getCode()).msg(resultCodeEnum.getDesc()).build();
}
/**
* Return failed , use errMsg Replace the error code desc
*
* @param resultCodeEnum
* @param errMsg
* @return
*/
@SuppressWarnings("unchecked")
public static DefaultResponseDTO fail(ResultCodeEnum resultCodeEnum, String errMsg) {
return DefaultResponseDTO.builder().code(resultCodeEnum.getCode()).msg(errMsg).data(null).build();
}
/**
* Return failed , Encapsulate the failed return code and exception err_data
*
* @param resultCodeEnum
* @param err_data
* @param <T>
* @return
*/
@SuppressWarnings("unchecked")
public static <T> DefaultResponseDTO<T> fail(ResultCodeEnum resultCodeEnum, T err_data) {
return DefaultResponseDTO.builder().code(resultCodeEnum.getCode()).msg(resultCodeEnum.getDesc()).data(err_data).build();
}
public boolean isSuccess() {
return ResultCodeEnum.SUCCESS.getCode() == this.getCode();
}
}Mode one :Controller Global exception catcher
import com.alibaba.csp.sentinel.slots.block.BlockException;
import XXcommon.enums.ResultCodeEnum;
import XXcommon.exception.BusinessException;
import XXcommon.model.DefaultResponseDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
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.validation.ConstraintViolationException;
import java.util.Optional;
/**
* @author AA
* @description Application layer global exception handling class
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
private static String CLIENT_ABORT_EXCEPTION_PACKAGE_NAME = "org.apache.catalina.connector.ClientAbortException";
@ExceptionHandler(Exception.class)
@ResponseBody
public DefaultResponseDTO handleException(Exception e) {
// Interface current limiting exception handling
if (e != null && e.getCause() instanceof BlockException) {
log.warn("[exception handler]BlockException occur! cause:{}", e.getCause() != null ? e.getCause() : "");
return DefaultResponseDTO.fail(ResultCodeEnum.RATE_LIMIT);
}
// Exception capture is too complete , When the user actively disconnects, the server will generate ClientAbortException, This exception needs to be ignored
if (e != null && CLIENT_ABORT_EXCEPTION_PACKAGE_NAME.equals(e.getClass().getName())) {
log.error("[exception handler]ClientAbortException occur! ignore this exception.");
return null;
}
log.error("[exception handler]controllerAdvice handleException, e:{}", e);
return DefaultResponseDTO.fail(ResultCodeEnum.SERVER_BUSYNESS);
}
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(BusinessException.class)
@ResponseBody
public DefaultResponseDTO handleBusinessException(BusinessException e) {
String busErrMsg = e.getBusErrMsg();
Throwable cause = e.getCause();
if (null != cause) {
log.error("[exception handler]handle BusinessException with Throwable=[{}]", cause);
} else {
String errorMessage = String.format("%s %s", e.getCode(), e.getMessage());
log.error("[exception handler]handle BusinessException advice, errorMessage=[{}]", errorMessage);
}
return DefaultResponseDTO.fail(e.getCode(), StringUtils.isNotBlank(busErrMsg) ? busErrMsg : e.getMessage());
}
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(BindException.class)
@ResponseBody
public DefaultResponseDTO handleValidException(BindException e) {
StringBuilder builder = new StringBuilder();
builder.append("bad params: ");
Optional.ofNullable(e.getFieldErrors()).ifPresent(
fieldErrors -> fieldErrors.forEach(
f -> {
builder.append(f.getField());
builder.append(f.getDefaultMessage());
builder.append("|");
}
)
);
String message = removeLastSeparation(builder);
log.error("[exception handler]handle ValidException, bad param=[{}]", message);
return DefaultResponseDTO.fail(ResultCodeEnum.BAD_PARAMS, message);
}
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public DefaultResponseDTO handleConstraintViolationException(ConstraintViolationException e) {
StringBuilder builder = new StringBuilder();
builder.append("bad params: ");
Optional.ofNullable(e.getConstraintViolations()).ifPresent(
constraintViolationSet -> constraintViolationSet.forEach(
c -> {
builder.append(c.getPropertyPath().toString());
builder.append(StringUtils.isNotEmpty(c.getMessage()) ? " " + c.getMessage() : null);
builder.append("|");
}
)
);
String message = removeLastSeparation(builder);
log.error("[exception handler]handle ConstraintViolationException, param=[{}]", message);
return DefaultResponseDTO.fail(ResultCodeEnum.BAD_PARAMS, message);
}
private String removeLastSeparation(StringBuilder builder) {
String message;
if (null != builder && builder.length() > 0) {
message = builder.substring(0, builder.length() - 1);
} else {
message = "";
}
return message;
}
}
Mode two :DubboFilter
SPI The way :

dubboBizExceptionFilter=com.xx.filter.DubboBizExceptionFilterpackage com.AA.service.helper.filter;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.xx.common.exception.BusinessException;
import com.xx.facade.common.enums.FacadeResultCodeEnum;
import com.xx.facade.common.model.FacadeDefaultDTO;
import org.apache.dubbo.rpc.service.GenericService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.springframework.validation.BindException;
import javax.validation.ConstraintViolationException;
import java.util.Optional;
/**
* @author AA
* @description dubbo Exception interceptor
*/
@Slf4j
@Activate(group = CommonConstants.PROVIDER)
public class DubboBizExceptionFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
try {
org.apache.dubbo.rpc.Result result = invoker.invoke(invocation);
if (result.hasException() && GenericService.class != invoker.getInterface()) {
try {
Throwable exception = result.getException();
// Abnormal current limiting
if (exception.getCause() != null && exception.getCause() instanceof BlockException) {
log.warn("[DubboFilter]BlockException_occurred. [serviceName={} methodName={} args={}]", invocation.getServiceName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()));
AsyncRpcResult rpcResult = AsyncRpcResult.newDefaultAsyncResult(invocation);
rpcResult.setValue(FacadeDefaultDTO.builder().code(FacadeResultCodeEnum.RATE_LIMITED.getCode()).msg(FacadeResultCodeEnum.RATE_LIMITED.getDesc()).build());
return rpcResult;
}
// Business exceptions Attention should be paid to : Not meeting the conditions By RuntimeException When wrapping Require special treatment
if (exception instanceof BusinessException) {
log.warn("[DubboFilter]BusinessException_occurred. [serviceName={} methodName={} args={}]", invocation.getServiceName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()));
BusinessException busException = (BusinessException) exception;
AsyncRpcResult rpcResult = AsyncRpcResult.newDefaultAsyncResult(invocation);
rpcResult.setValue(FacadeDefaultDTO.builder().code(busException.getCode().getCode()).msg(busException.getMessage()).build());
return rpcResult;
}
// Parameters validate
if (exception instanceof ConstraintViolationException) {
ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception;
StringBuilder builder = new StringBuilder();
Optional.ofNullable(constraintViolationException.getConstraintViolations()).ifPresent(constraintViolationSet -> {
constraintViolationSet.forEach(c -> {
log.warn(String.format("Call %s bad param: %s", c.getPropertyPath(), c.getMessage()));
builder.append(c.getMessage());
builder.append(" | ");
});
});
String errorMessage = removeLastSeparation(builder);
log.warn("[DubboFilter]ConstraintViolationException_occurred. [serviceName={} methodName={} args={} errorMessage={}]", invocation.getServiceName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()), errorMessage);
AsyncRpcResult rpcResult = AsyncRpcResult.newDefaultAsyncResult(invocation);
rpcResult.setValue(FacadeDefaultDTO.builder().code(FacadeResultCodeEnum.BAD_PARAMS.getCode()).msg(errorMessage).build());
return rpcResult;
}
// spring validation Parameter exception
if (exception instanceof BindException) {
BindException bindException = (BindException) exception;
StringBuilder builder = new StringBuilder();
Optional.ofNullable(bindException.getFieldErrors()).ifPresent(fieldErrors -> {
fieldErrors.forEach(f -> builder.append(f.getField()).append("|"));
builder.deleteCharAt(builder.length() - 1);
});
String errorMessage = removeLastSeparation(builder);
log.warn("[DubboFilter]BindException_occurred. [serviceName={} methodName={} args={} errorMessage={}]", invocation.getServiceName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()), errorMessage);
AsyncRpcResult rpcResult = AsyncRpcResult.newDefaultAsyncResult(invocation);
rpcResult.setValue(FacadeDefaultDTO.builder().code(FacadeResultCodeEnum.BAD_PARAMS.getCode()).msg(errorMessage).build());
return rpcResult;
}
// otherwise ,RPC Abnormal packaging into local BizException Throw to client
if (!(exception instanceof org.apache.dubbo.rpc.RpcException)) {
log.error("[DubboFilter]OtherException_occurred. [serviceName={} methodName={} args={}] e:{}", invocation.getServiceName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()), exception);
AsyncRpcResult rpcResult = AsyncRpcResult.newDefaultAsyncResult(invocation);
rpcResult.setValue(FacadeDefaultDTO.builder().code(FacadeResultCodeEnum.SERVER_ERROR.getCode()).build());
return rpcResult;
} else {
// yes Dubbo The anomaly of itself , Direct selling
log.error("[DubboFilter]RPCException_occurred. [serviceName={} methodName={} args={} e:{}]", invocation.getServiceName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()), exception);
return result;
}
} catch (Throwable e) {
log.error("[DubboFilter]Fail_to_ExceptionFilter_when_called_by: [serviceName={} methodName={} args={} exception={}] e:{}", invocation.getServiceName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()), e.getClass().getName(), e);
return result;
}
}
return result;
} catch (RuntimeException e) {
log.error("[DubboFilter]Got_exception_which_called_by: [serviceName={} methodName={} args={} exception={}] e:{}", invocation.getServiceName(), invocation.getMethodName(), JSON.toJSONString(invocation.getArguments()), e.getClass().getName(), e);
AsyncRpcResult rpcResult = AsyncRpcResult.newDefaultAsyncResult(invocation);
rpcResult.setValue(FacadeDefaultDTO.builder().code(FacadeResultCodeEnum.SERVER_ERROR.getCode()).build());
return rpcResult;
}
}
private String removeLastSeparation(StringBuilder builder) {
String message;
if (null != builder && builder.length() > 0) {
message = builder.toString().substring(0, builder.length() - 2);
} else {
message = "";
}
return message;
}
}
Be careful , There may be :" Project introduction dubboFilter when , Custom business exceptions found cannot be filter Capture , Wrapped in runtime exceptions "
Analysis of the source code :org.apache.dubbo.rpc.filter.ExceptionFilter

practice : take Dubbo Business exceptions are placed on both sides jar In bag ( This is also the common practice of middleware two-party package );
Mode three : Slice capture
This method is more flexible , The accuracy can reach the method , But we should pay attention to some cases of section failure , Like class call ;
annotation :
package com.AA.web.helper.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author AA
* @description API General processing annotations
* @date 2022/3/10
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResultHandler {
}section :
package com.AA.web.helper;
import com.AA.dto.BaseResponse;
import com.AA.enums.ResultCodeEnum;
import com.AA.exception.BusinessException;
import com.AA.ConfigManager;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* @author AA
* @description API General treatment
* @date 2022/3/10
*/
@Aspect
@Component
public class ResultHandlerAspect {
private final static Logger LOGGER = LoggerFactory.getLogger(ResultHandlerAspect.class);
private static final String GLOBAL_ERROR_LOG_SWITCH = "global.error.log.switch";
@Around("@annotation(com.AA.helper.annotation.ResultHandler)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed;
try {
proceed = joinPoint.proceed();
}
// Parameter exception
catch (IllegalArgumentException ie) {
return BaseResponse.buildResult(ResultCodeEnum.PARAMS_ERROR);
}
// Business exceptions
catch (BusinessException e) {
final ResultCodeEnum code = e.getCode();
final String busErrMsg = e.getBusErrMsg();
final String toast = e.getToast();
if (code != null) {
if (StringUtils.isNotBlank(busErrMsg)) {
return BaseResponse.buildResult(code, String.join(" detail: ", code.getMessage(), busErrMsg), null);
}
return BaseResponse.buildResult(code);
}
// If there is no status code, the default system exception will be returned
return BaseResponse.buildResult(ResultCodeEnum.SYSTEM_ERROR);
}
// Other exception encapsulation " System exception "
catch (Throwable e) {
if (ConfigManager.getBoolean(GLOBAL_ERROR_LOG_SWITCH, true)) {
LOGGER.error("unhandled_exception:", e);
}
return BaseResponse.buildResult(ResultCodeEnum.SYSTEM_ERROR);
}
return proceed;
}
}边栏推荐
- Delete node quickly and efficiently_ modules
- [tensorboard] oserror: [errno 22] invalid argument processing
- C: On function
- [sword finger offer] interview question 45: arrange the array into the smallest number
- MySQL表数据的增删查改
- JSP基础
- centos上mysql5.7主从热备设置
- 43亿欧元现金收购欧司朗宣告失败!ams表示将继续收购
- busybox login: can't execute '/bin/bash': No such file or directory 解决方法
- Openwrt adds RTC (mcp7940 I2C bus) drive details
猜你喜欢

centos上mysql5.7主从热备设置

Pycharm导入已有的本地安装包

Pychart imports the existing local installation package

DRF学习笔记(二):数据反序列化

Mlx90640 infrared thermal imager temperature sensor module development notes (VII)

Mapreduce实例(三):数据去重

2.2 JMeter基本元件

DRF学习笔记(一):数据序列化
![[sword finger offer] interview question 49: ugly number](/img/7a/2bc9306578530fbb5ac3b32254676d.png)
[sword finger offer] interview question 49: ugly number

渗透测试-干货 | 80篇+网络安全面试经验帖(面试篇)
随机推荐
Solve the compilation warning of multiple folders with duplicate names under the openwrt package directory (call subdir function)
Common tool classes under JUC package
flume增量采集mysql数据到kafka
[sword finger offer] interview question 39: numbers that appear more than half of the time in the array
[sword finger offer] interview question 46: translating numbers into strings - dynamic programming
juc包下常用工具类
编码技巧——全局日志开关
无线网络分析有关的安全软件(aircrack-ng)
Openwrt new platform compilation
Hematemesis finishing c some commonly used help classes
[regular expression] matches multiple characters
台积电的反击:指控格芯侵犯25项专利,并要求禁售!
减小程序rom ram,gcc -ffunction-sections -fdata-sections -Wl,–gc-sections 参数详解
A powerful web vulnerability scanning and verification tool (vulmap)
测试新手学习宝典(有思路有想法)
Leetcode 226 翻转二叉树(递归)
Paper_ Book
Six capabilities of test and development
[regular expression] matching grouping
flink打包程序提交任务示例