Problem description
Tips: Describe the problems encountered in the project here:
Exceptions thrown by custom filters do not use custom global exceptions
Cause analysis:
The exception thrown when customizing the filter cannot go to the controller, so it will not go to the custom global exception.
{<!-- --> "timestamp": "2023-09-06 16:29:30", "status": 500, "error": "Internal Server Error", "path": "/openapi/openApi/test" }
Solution:
1. Customize a filter to capture filter exceptions
public class ExceptionFilter implements Filter {<!-- --> public static final String ERROR_CONTROLLER_PATH = "/error/throw"; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {<!-- --> try {<!-- --> filterChain.doFilter(request, response); } catch (BizException e) {<!-- --> e.printStackTrace(); // Pass exception information request.setAttribute("filterError", e); //Specify the processor to handle the request request.getRequestDispatcher(ERROR_CONTROLLER_PATH).forward(request, response); } } @Override public void init(FilterConfig filterConfig) throws ServletException {<!-- --> } @Override public void destroy() {<!-- --> } }
Register filter:
@Configuration public class OpenApiFilterConfig {<!-- --> // Filter code class @Bean public ExceptionFilter ExceptionFilter() {<!-- --> return new ExceptionFilter(); } @Bean public FilterRegistrationBean exceptionFilter(ExceptionFilter exceptionFilter) {<!-- --> FilterRegistrationBean registrationBean = new FilterRegistrationBean(); registrationBean.setFilter(exceptionFilter); registrationBean.setName("exceptionFilter"); registrationBean.setOrder(-1); return registrationBean; } }
Define exception handling controller:
@RestController public class ExceptionController {<!-- --> public static final String ERROR_CONTROLLER_PATH = "/error/throw"; @RequestMapping(ERROR_CONTROLLER_PATH) public void handleException(HttpServletRequest request) {<!-- --> throw (BizException) request.getAttribute("filterError"); } }
Custom global exception
@ControllerAdvice public class GlobalExceptionHandler {<!-- --> private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /** * Handle customized business exceptions * * @param req * @param e * @return */ @ExceptionHandler(value = BizException.class) @ResponseBody public ResultBody bizExceptionHandler(HttpServletRequest req, BizException e) {<!-- --> logger.error("A business exception occurred! The reason is: {}", e.getErrorMsg()); return ResultBody.error(e.getErrorCode(), e.getErrorMsg(),e.getMessage()); } /** * Handle null pointer exceptions * * @param req * @param e * @return */ @ExceptionHandler(value = NullPointerException.class) @ResponseBody public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e) {<!-- --> logger.error("A null pointer exception occurred! The reason is:", e); return ResultBody.error(CommonEnum.BODY_NOT_MATCH); } /** * Handle other exceptions * * @param req * @param e * @return */ @ExceptionHandler(value = Exception.class) @ResponseBody public ResultBody exceptionHandler(HttpServletRequest req, Exception e) {<!-- --> logger.error("Unknown exception! The reason is:", e); return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR); }
Related encapsulation classes and interfaces
public class BizException extends RuntimeException {<!-- --> private static final long serialVersionUID = 1L; /** * error code */ protected String errorCode; /** * error message */ protected String errorMsg; /** * Error message code */ protected String message; public BizException() {<!-- --> super(); } public BizException(BaseErrorInfoInterface errorInfoInterface) {<!-- --> super(errorInfoInterface.getResultCode()); this.errorCode = errorInfoInterface.getResultCode(); this.errorMsg = errorInfoInterface.getResultMsg(); this.message = errorInfoInterface.getMessage(); } public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {<!-- --> super(errorInfoInterface.getResultCode(), cause); this.errorCode = errorInfoInterface.getResultCode(); this.errorMsg = errorInfoInterface.getResultMsg(); this.message = errorInfoInterface.getMessage(); } public BizException(String errorMsg) {<!-- --> super(errorMsg); this.message = errorMsg; } public BizException(String errorCode, String errorMsg) {<!-- --> super(errorCode); this.errorCode = errorCode; this.errorMsg = errorMsg; } public BizException(String errorCode, String errorMsg, String message) {<!-- --> super(errorCode); this.errorCode = errorCode; this.errorMsg = errorMsg; this.message = message; } public BizException(String errorCode, String errorMsg, Throwable cause) {<!-- --> super(errorCode, cause); this.errorCode = errorCode; this.errorMsg = errorMsg; } public BizException(String errorCode, String errorMsg, String message, Throwable cause) {<!-- --> super(errorCode, cause); this.errorCode = errorCode; this.errorMsg = errorMsg; this.message = message; } public String getErrorCode() {<!-- --> return errorCode; } public void setErrorCode(String errorCode) {<!-- --> this.errorCode = errorCode; } public String getErrorMsg() {<!-- --> return errorMsg; } public void setErrorMsg(String errorMsg) {<!-- --> this.errorMsg = errorMsg; } public String getMessage() {<!-- --> return message; } public void setMessage(String message) {<!-- --> this.message = message; } @Override public Throwable fillInStackTrace() {<!-- --> return this; } }
public interface BaseErrorInfoInterface {<!-- --> /** * error code */ String getResultCode(); /** * wrong description */ String getResultMsg(); /** * Error message code */ String getMessage(); }
public enum CommonEnum implements BaseErrorInfoInterface {<!-- --> //Data operation error definition SUCCESS("200", "Success!", "SUCCESS"), BODY_NOT_MATCH("400", "The requested data format does not match!", "BODY_NOT_MATCH"), INTERNAL_SERVER_ERROR("500", "Server internal error!", "INTERNAL_SERVER_ERROR"), INVALID_ACCOUNTID("406", "Invalid Happy Office ID", "INVALID_ACCOUNTID"), NOT_FOUND_ACCOUNTID("407", "The Happy Office ID must be sent but was not sent", "NOT_FOUND_ACCOUNTID"), NOT_FOUND_PROCINSID_FORMID_FORMTITLE("402", "Process definition id form id work order title priority process type must be passed but not passed", "NOT_FOUND_PROCINSID_FORMID_FORMTITLE"), NOT_FOUND_PROCINSID_DEPLOYID("408", "Process id deployment id must be passed but was not passed", "NOT_FOUND_PROCINSID_DEPLOYID"), BODY_NOT_TIMESTAMP("400", "The request header does not carry a timestamp", "BODY_NOT_TIMESTAMP"), BODY_NOT_SIGN("400", "The request header sign is empty", "BODY_NOT_SIGN"), BODY_NOT_APPID("400", "The request header appId is empty and the signature verification failed", "BODY_NOT_APPID"), TIMEOUT("406", "Signature verification failed, more than three minutes", "TIMEOUT"), NOT_APPINFO("406", "No corresponding information found, signature verification failed.", "NOT_APPINFO"), NOT_APP_SECRET("406", "app_secret, the query is empty, the signature verification failed", "NOT_APP_SECRET"), DIFFERENT_SIGN("406", "sign encryption is different, signature verification failed", "DIFFERENT_SIGN"), SERVER_BUSY("503", "The server is busy, please try again later!", "SERVER_BUSY"); /** * error code */ private String resultCode; /** * wrong description */ private String resultMsg; /** * Error message code */ private String message; CommonEnum(String resultCode, String resultMsg, String message) {<!-- --> this.resultCode = resultCode; this.resultMsg = resultMsg; this.message = message; } @Override public String getResultCode() {<!-- --> return resultCode; } @Override public String getResultMsg() {<!-- --> return resultMsg; } @Override public String getMessage() {<!-- --> return message; } }
public class ResultBody {<!-- --> /** * response code */ private String code; /** * response message */ private String message; /** *Response message code */ private String msg; /** *Response results */ private Object result; public ResultBody() {<!-- --> } public ResultBody(BaseErrorInfoInterface errorInfo) {<!-- --> this.code = errorInfo.getResultCode(); this.message = errorInfo.getResultMsg(); this.msg = errorInfo.getMessage(); } public String getCode() {<!-- --> return code; } public void setCode(String code) {<!-- --> this.code = code; } public String getMessage() {<!-- --> return message; } public void setMessage(String message) {<!-- --> this.message = message; } public Object getResult() {<!-- --> return result; } public void setResult(Object result) {<!-- --> this.result = result; } public String getMsg() {<!-- --> return msg; } public void setMsg(String msg) {<!-- --> this.msg = msg; } /** * success * * @return */ public static ResultBody success() {<!-- --> return success(null); } /** * success * * @param data * @return */ public static ResultBody success(Object data) {<!-- --> ResultBody rb = new ResultBody(); rb.setCode(CommonEnum.SUCCESS.getResultCode()); rb.setMessage(CommonEnum.SUCCESS.getResultMsg()); rb.setMsg(CommonEnum.SUCCESS.getMessage()); rb.setResult(data); return rb; } /** * fail */ public static ResultBody error(BaseErrorInfoInterface errorInfo) {<!-- --> ResultBody rb = new ResultBody(); rb.setCode(errorInfo.getResultCode()); rb.setMessage(errorInfo.getResultMsg()); rb.setMsg(errorInfo.getMessage()); rb.setResult(null); return rb; } /** * fail */ public static ResultBody error(String code, String message, String msg) {<!-- --> ResultBody rb = new ResultBody(); rb.setCode(code); rb.setMessage(message); rb.setMsg(msg); rb.setResult(null); return rb; } /** * fail */ public static ResultBody error(String message) {<!-- --> ResultBody rb = new ResultBody(); rb.setCode("-1"); rb.setMessage(message); rb.setResult(null); return rb; } @Override public String toString() {<!-- --> return JSONObject.toJSONString(this); } }
perfect solution
{<!-- --> "code": "400", "message": "The request header does not carry a timestamp", "msg": "BODY_NOT_TIMESTAMP", "result": null }