diff --git a/src/main/java/com/darkness/common/PublicConst.java b/src/main/java/com/darkness/common/PublicConst.java index a31b93e..68922cb 100644 --- a/src/main/java/com/darkness/common/PublicConst.java +++ b/src/main/java/com/darkness/common/PublicConst.java @@ -5,6 +5,9 @@ package com.darkness.common; */ public class PublicConst { + public static final String SCOPE_GENERAL = "general"; + public static final Integer ERROR_GENERAL_EXCEPTION = 500; + // 索引名称 // 索引类型 diff --git a/src/main/java/com/darkness/common/base/ControllerBase.java b/src/main/java/com/darkness/common/base/ControllerBase.java new file mode 100644 index 0000000..9eb65d9 --- /dev/null +++ b/src/main/java/com/darkness/common/base/ControllerBase.java @@ -0,0 +1,71 @@ +package com.darkness.common.base; + +import com.darkness.common.PublicConst; +import com.darkness.common.util.response.RestResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class ControllerBase { + + @ExceptionHandler(Exception.class) + public ResponseEntity handleException(Exception ex) { + RestResponse restResponse; + if (ex instanceof RuntimeErrorException) { + RuntimeErrorException errorException = (RuntimeErrorException) ex; + + String errorDetail = getErrorDetail(ex); + log.error(String.format("Exception in processStat request [%s]: %s",WebRequestSequence.current().getRequestSequence(),errorDetail)); + restResponse = new RestResponse( + errorException.getErrorScope(), errorException.getErrorCode(), errorDetail); + restResponse.setErrorDetails(errorDetail); + + } else if(ex instanceof BindException){ + log.error(String.format("Exception in processStat request [%s]: %s", WebRequestSequence.current().getRequestSequence(), ex.getMessage() != null ? ex.getMessage() : ""), ex); + BindException bindException = (BindException)ex; + FieldError fieldError = bindException.getFieldError(); + String exMessage = null; + if (fieldError != null) { + exMessage = fieldError.getDefaultMessage(); + } + restResponse = new RestResponse( + PublicConst.SCOPE_GENERAL, PublicConst.ERROR_GENERAL_EXCEPTION, exMessage); + restResponse.setErrorDetails(exMessage); + }else { + log.error(String.format("Exception in processStat request [%s]: %s", WebRequestSequence.current().getRequestSequence(), ex.getMessage() != null ? ex.getMessage() : ""), ex); + String exMessage = ex.toString(); + restResponse = new RestResponse( + PublicConst.SCOPE_GENERAL, PublicConst.ERROR_GENERAL_EXCEPTION, exMessage); + restResponse.setErrorDetails(exMessage); + } + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.set("Content-Type", "application/json; charset=utf-8"); + + return new ResponseEntity<>(restResponse, responseHeaders, HttpStatus.OK); + } + + private String getErrorDetail(Exception ex) { + String errorDetail; + if (ex.getCause() != null) { + errorDetail = ex.getCause().toString(); + } else { + errorDetail = ex.toString(); + } + return errorDetail; + } + + @InitBinder + public void initListBinder(WebDataBinder binder) { + binder.setAutoGrowCollectionLimit(Integer.MAX_VALUE); + } +} diff --git a/src/main/java/com/darkness/common/base/RuntimeErrorException.java b/src/main/java/com/darkness/common/base/RuntimeErrorException.java new file mode 100644 index 0000000..8d91c7c --- /dev/null +++ b/src/main/java/com/darkness/common/base/RuntimeErrorException.java @@ -0,0 +1,137 @@ +package com.darkness.common.base; + +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class RuntimeErrorException extends RuntimeException { + private static final long serialVersionUID = 2326809448876379756L; + private Severity severity; + private String errorScope; + private int errorCode; + private Map errorMap; + + public RuntimeErrorException() { + this.severity = Severity.Error; + this.errorCode = -1; + this.errorMap = new HashMap(); + } + + public RuntimeErrorException(String message) { + super(message); + this.severity = Severity.Error; + this.errorCode = -1; + this.errorMap = new HashMap(); + } + + public RuntimeErrorException(String message, Throwable cause) { + super(message, cause); + this.severity = Severity.Error; + this.errorCode = -1; + this.errorMap = new HashMap(); + } + + public RuntimeErrorException(Throwable cause) { + super(cause); + this.severity = Severity.Error; + this.errorCode = -1; + this.errorMap = new HashMap(); + } + + public Throwable fillInStackTrace() { + return this; + } + + public RuntimeErrorException setSeverity(Severity severity) { + this.severity = severity; + return this; + } + + public Severity getSeverity() { + return this.severity; + } + + public RuntimeErrorException setErrorScope(String errorScope) { + this.errorScope = errorScope; + return this; + } + + public String getErrorScope() { + return this.errorScope; + } + + public RuntimeErrorException setErrorCode(int errorCode) { + this.errorCode = errorCode; + return this; + } + + public int getErrorCode() { + return this.errorCode; + } + + public RuntimeErrorException setErrorObject(int index, Object obj) { + this.errorMap.put(String.valueOf(index), obj); + return this; + } + + public Object getErrorObject(int index) { + return this.errorMap.get(String.valueOf(index)); + } + + public RuntimeErrorException setErrorObject(String name, Object obj) { + this.errorMap.put(name, obj); + return this; + } + + public Object getErrorObject(String name) { + return this.errorMap.get(name); + } + + public static RuntimeErrorException errorWith(String errorScope, int errorCode, String description, Object... errorObjects) { + String errorMessage = String.format(description, errorObjects); + RuntimeErrorException e = new RuntimeErrorException(errorMessage); + e.setErrorScope(errorScope).setErrorCode(errorCode); + if (errorObjects != null) { + int i = 0; + Object[] var7 = errorObjects; + int var8 = errorObjects.length; + + for(int var9 = 0; var9 < var8; ++var9) { + Object obj = var7[var9]; + e.setErrorObject(i, obj); + ++i; + } + } + + return e; + } + + public static RuntimeErrorException errorWith(Throwable cause, String errorScope, int errorCode, String description, Object... errorObjects) { + String errorMessage = String.format(description, errorObjects); + RuntimeErrorException e = new RuntimeErrorException(errorMessage, cause); + e.setErrorScope(errorScope).setErrorCode(errorCode); + if (errorObjects != null) { + int i = 0; + Object[] var8 = errorObjects; + int var9 = errorObjects.length; + + for(int var10 = 0; var10 < var9; ++var10) { + Object obj = var8[var10]; + e.setErrorObject(i, obj); + ++i; + } + } + + return e; + } + + public static enum Severity { + Error, + Fatal; + + private Severity() { + } + } +} diff --git a/src/main/java/com/darkness/common/base/WebRequestSequence.java b/src/main/java/com/darkness/common/base/WebRequestSequence.java new file mode 100644 index 0000000..a853e7c --- /dev/null +++ b/src/main/java/com/darkness/common/base/WebRequestSequence.java @@ -0,0 +1,98 @@ +package com.darkness.common.base; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.concurrent.atomic.AtomicLong; + +public class WebRequestSequence { + + private static final Logger LOGGER = LoggerFactory.getLogger(WebRequestSequence.class); + private static final String IGNORED_TRACE = "Ignored_Trace"; + + private static ThreadLocal s_sequences = new ThreadLocal<>(); + + private static final AtomicLong s_nextId = new AtomicLong(System.currentTimeMillis()); + + private static final boolean TRACE_ENABLED = initTrace(); + + private static String prefix = ""; + + private String requestSequence = ""; + private static String traceIdDefault = ""; + + static { + InetAddress addr; + try { + addr = InetAddress.getLocalHost(); + } catch (UnknownHostException var1) { + addr = InetAddress.getLoopbackAddress(); + } + if (addr != null) { + byte[] address = addr.getAddress(); + int lastByte = ((int) address[address.length - 1] & 0xff); + prefix = lastByte + "-"; + } + } + + private static boolean initTrace() { + boolean traceAgent = false; + try { + Class.forName("org.apache.skywalking.apm.agent.SkyWalkingAgent"); + traceAgent = true; + } catch (ClassNotFoundException e) { + LOGGER.info("Trace agent org.apache.skywalking.apm.agent.SkyWalkingAgent not found."); + } + + boolean traceContext = false; + try { + Class.forName("org.apache.skywalking.apm.toolkit.trace.TraceContext"); + traceContext = true; + } catch (ClassNotFoundException e) { + LOGGER.info("Trace context org.apache.skywalking.apm.toolkit.trace.TraceContext not found."); + } + + if (traceAgent && traceContext) { + LOGGER.info("Distribute traceId enabled."); + return true; + } + LOGGER.info("Local request sequence enabled."); + return false; + } + + private WebRequestSequence() { + // + } + + public static WebRequestSequence current() { + WebRequestSequence seq = s_sequences.get(); + if (seq == null) { + seq = new WebRequestSequence(); + s_sequences.set(seq); + } + return seq; + } + + public String getRequestSequence() { + return this.requestSequence; + } + + public void setupRequestSequence() { + if (TRACE_ENABLED) { + String traceId = traceIdDefault; + if (!IGNORED_TRACE.equals(traceId)) { + this.requestSequence = traceId; + return; + } + } + + long id = s_nextId.addAndGet(1); + this.requestSequence = prefix + String.valueOf(id); + } + + public void clearRequestSequence() { + s_sequences.remove(); + } +} \ No newline at end of file diff --git a/src/main/java/com/darkness/common/util/response/RestResponse.java b/src/main/java/com/darkness/common/util/response/RestResponse.java new file mode 100644 index 0000000..50eb930 --- /dev/null +++ b/src/main/java/com/darkness/common/util/response/RestResponse.java @@ -0,0 +1,31 @@ +package com.darkness.common.util.response; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@Data +public class RestResponse { + @JsonProperty("response") + private Object responseObject; + private String errorScope; + private Integer code; + private String errorDescription; + private String errorDetails; + + public RestResponse() { + this.code = 200; + } + + public RestResponse(String errorScope, int errorCode, String errorDescription) { + this.errorScope = errorScope; + this.code = errorCode; + this.errorDescription = errorDescription; + } + + public RestResponse(Object responseObject) { + this.responseObject = responseObject; + this.code = 200; + } +}