|
@@ -1,16 +1,19 @@
|
|
package cn.com.qmth.examcloud.web.support;
|
|
package cn.com.qmth.examcloud.web.support;
|
|
|
|
|
|
-import java.util.HashSet;
|
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
+import javax.validation.ConstraintViolation;
|
|
|
|
+import javax.validation.ConstraintViolationException;
|
|
|
|
|
|
-import org.apache.commons.collections4.CollectionUtils;
|
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
|
-import org.springframework.dao.DataIntegrityViolationException;
|
|
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.http.ResponseEntity;
|
|
|
|
+import org.springframework.http.converter.HttpMessageNotReadableException;
|
|
|
|
+import org.springframework.validation.BindingResult;
|
|
|
|
+import org.springframework.validation.ObjectError;
|
|
|
|
+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.ControllerAdvice;
|
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
@@ -19,8 +22,7 @@ import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
|
|
import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
|
|
import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
|
|
import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
|
|
import cn.com.qmth.examcloud.commons.util.JsonUtil;
|
|
import cn.com.qmth.examcloud.commons.util.JsonUtil;
|
|
-import cn.com.qmth.examcloud.commons.util.PropertiesUtil;
|
|
|
|
-import cn.com.qmth.examcloud.commons.util.RegExpUtil;
|
|
|
|
|
|
+import cn.com.qmth.examcloud.web.enums.HttpServletRequestAttribute;
|
|
|
|
|
|
/**
|
|
/**
|
|
* 类注释
|
|
* 类注释
|
|
@@ -39,22 +41,6 @@ public class CustomExceptionHandler {
|
|
private static final ExamCloudLog INTERFACE_LOG = ExamCloudLogFactory
|
|
private static final ExamCloudLog INTERFACE_LOG = ExamCloudLogFactory
|
|
.getLog("INTERFACE_LOGGER");
|
|
.getLog("INTERFACE_LOGGER");
|
|
|
|
|
|
- private static ExamCloudLog LOG = ExamCloudLogFactory.getLog(CustomExceptionHandler.class);
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * 不输出堆栈的状态码
|
|
|
|
- */
|
|
|
|
- private static Set<String> nonStackTraceStatusCodes = new HashSet<>();
|
|
|
|
-
|
|
|
|
- static {
|
|
|
|
- String str = PropertiesUtil.getString("$log.nonStackTraceStatusCodes");
|
|
|
|
- if (StringUtils.isNotBlank(str)) {
|
|
|
|
- List<String> list = RegExpUtil.findAll(str, "[\\w\\-]+");
|
|
|
|
- CollectionUtils.addAll(nonStackTraceStatusCodes, list);
|
|
|
|
- LOG.info("nonStackTraceStatusCodes: " + JsonUtil.toJson(nonStackTraceStatusCodes));
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* 异常处理
|
|
* 异常处理
|
|
*
|
|
*
|
|
@@ -70,39 +56,96 @@ public class CustomExceptionHandler {
|
|
Throwable cause = e.getCause();
|
|
Throwable cause = e.getCause();
|
|
StatusResponse body = null;
|
|
StatusResponse body = null;
|
|
|
|
|
|
- if (null != cause && cause instanceof StatusException) {
|
|
|
|
|
|
+ if (null == cause) {
|
|
|
|
+ body = new StatusResponse("500", "系统异常");
|
|
|
|
+ cause = e;
|
|
|
|
+ } else if (cause instanceof StatusException) {
|
|
StatusException se = (StatusException) cause;
|
|
StatusException se = (StatusException) cause;
|
|
body = new StatusResponse(se.getCode(), se.getDesc());
|
|
body = new StatusResponse(se.getCode(), se.getDesc());
|
|
- } else if (null != cause && cause instanceof DataIntegrityViolationException) {
|
|
|
|
- body = new StatusResponse(ResponseStatus.DATA_INTEGRITY_VIOLATION.getCode(),
|
|
|
|
- ResponseStatus.DATA_INTEGRITY_VIOLATION.getDesc());
|
|
|
|
- } else if (null != cause && cause instanceof IllegalStateException) {
|
|
|
|
- IllegalStateException se = (IllegalStateException) cause;
|
|
|
|
- body = new StatusResponse(ResponseStatus.FATAL_ERROR.getCode(), se.getMessage());
|
|
|
|
|
|
+ } else if (cause instanceof IllegalStateException) {
|
|
|
|
+ body = new StatusResponse("500", cause.getMessage());
|
|
|
|
+ } else if (cause instanceof javax.validation.ConstraintViolationException) {
|
|
|
|
+ javax.validation.ConstraintViolationException cvExcp = (ConstraintViolationException) cause;
|
|
|
|
+ Set<ConstraintViolation<?>> constraintViolations = cvExcp.getConstraintViolations();
|
|
|
|
+
|
|
|
|
+ StringBuffer errorMsg = new StringBuffer();
|
|
|
|
+ boolean isFirst = true;
|
|
|
|
+ for (ConstraintViolation<?> cv : constraintViolations) {
|
|
|
|
+ if (isFirst) {
|
|
|
|
+ errorMsg.append(cv.getMessage());
|
|
|
|
+ isFirst = false;
|
|
|
|
+ } else {
|
|
|
|
+ errorMsg.append("; ").append(cv.getMessage());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ body = new StatusResponse("500", errorMsg.toString());
|
|
|
|
+ } else if (cause instanceof org.springframework.jdbc.CannotGetJdbcConnectionException) {
|
|
|
|
+ body = new StatusResponse("500", "网络拥堵,请稍后重试");
|
|
} else {
|
|
} else {
|
|
- body = new StatusResponse(ResponseStatus.FATAL_ERROR.getCode(),
|
|
|
|
- ResponseStatus.FATAL_ERROR.getDesc());
|
|
|
|
|
|
+ body = new StatusResponse("500", "系统异常");
|
|
cause = e;
|
|
cause = e;
|
|
}
|
|
}
|
|
|
|
|
|
- boolean alwaysOK = alwaysOK(request);
|
|
|
|
- if (alwaysOK) {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. StatusCode=" + HttpStatus.OK);
|
|
|
|
- if (nonStackTraceStatusCodes.contains(body.getCode())) {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body));
|
|
|
|
- } else {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body), cause);
|
|
|
|
- }
|
|
|
|
- return new ResponseEntity<StatusResponse>(body, HttpStatus.OK);
|
|
|
|
- } else {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. StatusCode=" + HttpStatus.INTERNAL_SERVER_ERROR);
|
|
|
|
- if (nonStackTraceStatusCodes.contains(body.getCode())) {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body));
|
|
|
|
|
|
+ return asResult(cause, body, request);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 异常处理
|
|
|
|
+ *
|
|
|
|
+ * @author WANGWEI
|
|
|
|
+ * @param e
|
|
|
|
+ * @param request
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ @ExceptionHandler(MethodArgumentNotValidException.class)
|
|
|
|
+ public ResponseEntity<StatusResponse> handleException(MethodArgumentNotValidException e,
|
|
|
|
+ HttpServletRequest request) {
|
|
|
|
+ BindingResult result = e.getBindingResult();
|
|
|
|
+ List<ObjectError> allErrors = result.getAllErrors();
|
|
|
|
+ StringBuffer errorMsg = new StringBuffer();
|
|
|
|
+ boolean isFirst = true;
|
|
|
|
+ for (ObjectError err : allErrors) {
|
|
|
|
+ if (isFirst) {
|
|
|
|
+ errorMsg.append(err.getDefaultMessage());
|
|
|
|
+ isFirst = false;
|
|
} else {
|
|
} else {
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body), cause);
|
|
|
|
|
|
+ errorMsg.append("; ").append(err.getDefaultMessage());
|
|
}
|
|
}
|
|
- return new ResponseEntity<StatusResponse>(body, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
|
|
}
|
|
}
|
|
|
|
+ StatusResponse body = new StatusResponse("500", errorMsg.toString());
|
|
|
|
+ return asResult(e, body, request);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 异常处理
|
|
|
|
+ *
|
|
|
|
+ * @author WANGWEI
|
|
|
|
+ * @param e
|
|
|
|
+ * @param request
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ @ExceptionHandler(MissingServletRequestParameterException.class)
|
|
|
|
+ public ResponseEntity<StatusResponse> handleException(MissingServletRequestParameterException e,
|
|
|
|
+ HttpServletRequest request) {
|
|
|
|
+
|
|
|
|
+ StatusResponse body = new StatusResponse("500", e.getMessage());
|
|
|
|
+ return asResult(e, body, request);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 异常处理
|
|
|
|
+ *
|
|
|
|
+ * @author WANGWEI
|
|
|
|
+ * @param e
|
|
|
|
+ * @param request
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ @ExceptionHandler(HttpMessageNotReadableException.class)
|
|
|
|
+ public ResponseEntity<StatusResponse> handleException(HttpMessageNotReadableException e,
|
|
|
|
+ HttpServletRequest request) {
|
|
|
|
+
|
|
|
|
+ StatusResponse body = new StatusResponse("500", "Required request body is missing");
|
|
|
|
+ return asResult(e, body, request);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -116,26 +159,30 @@ public class CustomExceptionHandler {
|
|
@ExceptionHandler(Exception.class)
|
|
@ExceptionHandler(Exception.class)
|
|
public ResponseEntity<StatusResponse> handleException(Exception e, HttpServletRequest request) {
|
|
public ResponseEntity<StatusResponse> handleException(Exception e, HttpServletRequest request) {
|
|
|
|
|
|
- StatusResponse body = new StatusResponse(
|
|
|
|
- cn.com.qmth.examcloud.web.support.ResponseStatus.FATAL_ERROR.getCode(),
|
|
|
|
- cn.com.qmth.examcloud.web.support.ResponseStatus.FATAL_ERROR.getDesc());
|
|
|
|
|
|
+ StatusResponse body = new StatusResponse("500", "致命错误");
|
|
|
|
+
|
|
|
|
+ return asResult(e, body, request);
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * 构建响应结果
|
|
|
|
+ *
|
|
|
|
+ * @author WANGWEI
|
|
|
|
+ * @param t
|
|
|
|
+ * @param body
|
|
|
|
+ * @param request
|
|
|
|
+ * @return
|
|
|
|
+ */
|
|
|
|
+ private ResponseEntity<StatusResponse> asResult(Throwable t, StatusResponse body,
|
|
|
|
+ HttpServletRequest request) {
|
|
boolean alwaysOK = alwaysOK(request);
|
|
boolean alwaysOK = alwaysOK(request);
|
|
if (alwaysOK) {
|
|
if (alwaysOK) {
|
|
- INTERFACE_LOG.info("[HTTP-RESP]. StatusCode=" + HttpStatus.OK);
|
|
|
|
- if (nonStackTraceStatusCodes.contains(body.getCode())) {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body));
|
|
|
|
- } else {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body), e);
|
|
|
|
- }
|
|
|
|
|
|
+ INTERFACE_LOG.error("[HTTP-RESP]. status=" + HttpStatus.OK.value());
|
|
|
|
+ INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body), t);
|
|
return new ResponseEntity<StatusResponse>(body, HttpStatus.OK);
|
|
return new ResponseEntity<StatusResponse>(body, HttpStatus.OK);
|
|
} else {
|
|
} else {
|
|
- INTERFACE_LOG.info("[HTTP-RESP]. StatusCode=" + HttpStatus.INTERNAL_SERVER_ERROR);
|
|
|
|
- if (nonStackTraceStatusCodes.contains(body.getCode())) {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body));
|
|
|
|
- } else {
|
|
|
|
- INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body), e);
|
|
|
|
- }
|
|
|
|
|
|
+ INTERFACE_LOG.error("[HTTP-RESP]. status=" + HttpStatus.INTERNAL_SERVER_ERROR.value());
|
|
|
|
+ INTERFACE_LOG.error("[HTTP-RESP]. response=" + JsonUtil.toJson(body), t);
|
|
return new ResponseEntity<StatusResponse>(body, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
return new ResponseEntity<StatusResponse>(body, HttpStatus.INTERNAL_SERVER_ERROR);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -149,7 +196,7 @@ public class CustomExceptionHandler {
|
|
*/
|
|
*/
|
|
private boolean alwaysOK(HttpServletRequest request) {
|
|
private boolean alwaysOK(HttpServletRequest request) {
|
|
boolean alwaysOK = false;
|
|
boolean alwaysOK = false;
|
|
- Object attribute = request.getAttribute("$ALWAYS_OK");
|
|
|
|
|
|
+ Object attribute = request.getAttribute(HttpServletRequestAttribute.$_ALWAYS_OK.name());
|
|
if (null != attribute) {
|
|
if (null != attribute) {
|
|
try {
|
|
try {
|
|
alwaysOK = (boolean) attribute;
|
|
alwaysOK = (boolean) attribute;
|