package com.artfess.base.handler; import com.artfess.base.aop.AopCacheHelper; import com.artfess.base.constants.JmsConstant; import com.artfess.base.constants.TenantConstant; import com.artfess.base.enums.ResponseErrorEnums; import com.artfess.base.exception.BaseException; import com.artfess.base.jms.JmsProducer; import com.artfess.base.model.CommonResult; import com.artfess.base.util.*; import com.artfess.base.util.time.DateUtil; import com.fasterxml.jackson.databind.node.ObjectNode; import com.netflix.hystrix.exception.HystrixRuntimeException; import feign.RetryableException; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.ibatis.binding.BindingException; import org.mybatis.spring.MyBatisSystemException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.dao.DataAccessException; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.validation.BindException; import org.springframework.validation.BindingResult; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.NoHandlerFoundException; import javax.servlet.http.HttpServletRequest; import java.io.Serializable; import java.net.ConnectException; import java.sql.SQLException; import java.util.concurrent.TimeoutException; /** * 全局的异常处理类 * * @company 阿特菲斯信息技术有限公司 * @author heyifan * @email heyf@jee-soft.cn * @date 2020年4月4日 */ @RestControllerAdvice(annotations = { RestController.class, Controller.class }) public class BaseExceptionHandler { private final Logger log = LoggerFactory.getLogger(getClass()); private static String moduleType = "base" ; @Value("${spring.profiles.title:base}") public void setModuleType(String param){ moduleType = param; } /** * 请求参数类型错误异常的捕获 * * @param e * @return */ @ExceptionHandler(value = { BindException.class }) @ResponseBody @ResponseStatus(value = HttpStatus.BAD_REQUEST) public CommonResult badRequest(BindException e) { String opeContent = ExceptionUtil.getFullStackTrace(e); log.error("occurs error when execute method ,message {}", opeContent); saveExceptionLogs(opeContent); return new CommonResult<>(ResponseErrorEnums.BAD_REQUEST); } /** * 404错误异常的捕获 * * @param e * @return */ @ExceptionHandler(value = { NoHandlerFoundException.class }) @ResponseBody @ResponseStatus(value = HttpStatus.NOT_FOUND) public CommonResult badRequestNotFound(BindException e) { String opeContent = ExceptionUtil.getFullStackTrace(e); log.error("occurs error when execute method ,message {}", opeContent); saveExceptionLogs(opeContent); return new CommonResult<>(ResponseErrorEnums.NOT_FOUND); } /** * mybatis未绑定异常 * * @param e * @return */ @ExceptionHandler(BindingException.class) @ResponseBody @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public CommonResult mybatis(Exception e) { String opeContent = ExceptionUtil.getFullStackTrace(e); log.error("occurs error when execute method ,message {}", opeContent); saveExceptionLogs(opeContent); return new CommonResult<>(ResponseErrorEnums.BOUND_STATEMENT_NOT_FOUNT); } /** * 自定义异常的捕获 自定义抛出异常。统一的在这里捕获返回JSON格式的友好提示。 * * @param exception * @param request * @return */ @ExceptionHandler(value = { BaseException.class }) @ResponseBody @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public CommonResult sendError(BaseException exception, HttpServletRequest request) { String requestURI = request.getRequestURI(); String opContent = getErrorDetail(exception); log.error("occurs error when execute url ={} ,message {}", requestURI, opContent); String errorId = saveExceptionLogs(opContent); CommonResult commonResult = new CommonResult<>(exception.getCode(), exception.getMessage()); commonResult.setLogId(errorId); return commonResult; } /** * 数据库操作出现异常 * * @param e * @return */ @ExceptionHandler(value = { SQLException.class, DataAccessException.class }) @ResponseBody @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public CommonResult systemError(Exception e) { String opeContent = ExceptionUtil.getFullStackTrace(e); log.error("occurs error when execute method ,message {}", opeContent); String errorId = saveExceptionLogs(opeContent); if(e instanceof MyBatisSystemException){ return new CommonResult<>(((MyBatisSystemException) e).getRootCause().getMessage()); }else{ CommonResult commonResult = new CommonResult<>(ResponseErrorEnums.DATABASE_ERROR); commonResult.setMessage( "数据库操作失败,请联系管理员或查看日志!"); commonResult.setLogId(errorId); return commonResult; } } /** * 网络连接失败! * * @param e * @return */ @ExceptionHandler(value = { ConnectException.class }) @ResponseBody @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public CommonResult connect(Exception e) { String opeContent = ExceptionUtil.getFullStackTrace(e); log.error("occurs error when execute method ,message {}", opeContent); saveExceptionLogs(opeContent); return new CommonResult<>(ResponseErrorEnums.CONNECTION_ERROR); } @ExceptionHandler(value = { HystrixRuntimeException.class }) @ResponseBody @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public CommonResult hystrixRuntimeError(HystrixRuntimeException e) { log.error("occurs error when execute method ,message {}", ExceptionUtils.getFullStackTrace(e)); CommonResult result = null; if (e.getCause() instanceof TimeoutException || e.getCause() instanceof RetryableException) { result = new CommonResult<>(ResponseErrorEnums.SERVICE_INVOKE_ERROR, "服务调用超时:" + e.getLocalizedMessage()); } else { result = new CommonResult<>(false, "服务调用失败:" + ExceptionUtils.getRootCauseMessage(e)); } String opeContent = ExceptionUtil.getFullStackTrace(e); saveExceptionLogs(opeContent); return result; } private String getErrorDetail(BaseException e) { String opeContent = ""; if (BeanUtils.isNotEmpty(ExceptionUtil.getRootCauseMessage(e))){ opeContent = ExceptionUtil.getFullStackTrace(ExceptionUtil.getRootCause(e)); }else{ opeContent = ExceptionUtil.getFullStackTrace(e); } return opeContent; } @ExceptionHandler(value = { RuntimeException.class }) @ResponseBody @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public CommonResult runTimeError(Exception e) { String opeContent = ExceptionUtil.getFullStackTrace(e); log.error("occurs error when execute method ,message {}", opeContent); String errorMsg = ExceptionUtil.getRootCauseMessage(e); String flowErrorMsg = ThreadMsgUtil.getMapMsg(ThreadMsgUtil.MSG_FLOW_ERROR, true); if (StringUtil.isNotEmpty(errorMsg) && errorMsg.indexOf("流程异常") > -1 && StringUtil.isNotEmpty(flowErrorMsg)) { errorMsg = flowErrorMsg; }else if (StringUtil.isNotEmpty(errorMsg)) { String[] msgs = errorMsg.split("Exception:"); if(msgs.length==2){ errorMsg = msgs[1]; } } String errorId = saveExceptionLogs(opeContent); CommonResult commonResult = new CommonResult<>(false, errorMsg); commonResult.setLogId(errorId); return commonResult; } @ExceptionHandler(value = { Exception.class }) @ResponseBody @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public CommonResult notAllowed(Exception e) { String opeContent = ExceptionUtil.getFullStackTrace(e); String errorMsg = ""; if(BeanUtils.isNotEmpty(ExceptionUtil.extractMessageFromXML(e.getMessage()))){ errorMsg = ExceptionUtil.extractMessageFromXML(e.getMessage()); }else{ errorMsg = e.getMessage(); } log.error("occurs error when execute method ,message {}", opeContent); String errorId = saveExceptionLogs(opeContent); CommonResult commonResult = new CommonResult<>(false,errorMsg); commonResult.setLogId(errorId); return commonResult; } /** * 校验错误信息收集 * @param e * @return */ @ExceptionHandler(value = { MethodArgumentNotValidException.class }) @ResponseBody @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public CommonResult methodArgumentNotValidException(MethodArgumentNotValidException e) { StringBuffer stringBuffer = new StringBuffer(); BindingResult bindingResult = e.getBindingResult(); bindingResult.getAllErrors().forEach(error-> stringBuffer.append(error.getDefaultMessage()+" ")); log.error("occurs error when execute method ,message {}", stringBuffer.toString()); return new CommonResult(ResponseErrorEnums.ILLEGAL_ARGUMENT.getCode(),stringBuffer.toString()); } private String addErrorIdForMsg(String errorId, String errorMsg) { return "【日志ID:"+errorId+"】" + errorMsg; } private String saveExceptionLogs(String opeContent) { AopCacheHelper aopCacheHelper = AppUtil.getBean(AopCacheHelper.class); JmsProducer jmsProducer = AppUtil.getBean(JmsProducer.class); String errorId = ""; try { /* Map cacheSettings = aopCacheHelper.getSysLogsSettingStatusMap(); if(BeanUtils.isEmpty(cacheSettings) || !cacheSettings.containsKey(moduleType)) { log.error("未获取到日志配置中关于模块:{}的日志配置,跳过该模块的日志记录。", moduleType); } */ String executor = "系统[无用户登录系统]"; if(StringUtil.isNotEmpty(AuthenticationUtil.getCurrentUserFullname())){ executor = String.format("%s[%s]",AuthenticationUtil.getCurrentUserFullname(),AuthenticationUtil.getCurrentUsername()); } HttpServletRequest request = HttpUtil.getRequest(); String reqUrl = HttpUtil.getRequest().getRequestURI(); ObjectNode objectNode = JsonUtil.getMapper().createObjectNode(); errorId = UniqueIdUtil.getSuid(); objectNode.put("id", errorId); objectNode.put("opeName", "系统异常"); objectNode.put("moduleType", moduleType); objectNode.put("reqUrl", reqUrl); objectNode.put("opeContent", opeContent); objectNode.put("type", "sysLog"); objectNode.putPOJO("executionTime", DateUtil.getCurrentDate()); String tenantId = HttpUtil.getTenantId(); if(BeanUtils.isEmpty(tenantId)) { tenantId = TenantConstant.PLATFORM_TENANT_ID; } objectNode.put("tenantId", tenantId); objectNode.put("logType", "异常日志"); /* // 是否开始配置日志 if(BeanUtils.isNotEmpty(cacheSettings) && cacheSettings.containsKey(moduleType) && "1".equals(cacheSettings.get(moduleType))){ objectNode.put("executor", executor); objectNode.put("ip", WebUtil.getIpAddr(request)); //发送错误日志信息 jmsProducer.sendToQueue(JsonUtil.toJson(objectNode), JmsConstant.SYS_ERR_LOG_QUEUE); } */ objectNode.put("executor", executor); objectNode.put("ip", WebUtil.getIpAddr(request)); //发送错误日志信息 jmsProducer.sendToQueue(JsonUtil.toJson(objectNode), JmsConstant.SYS_ERR_LOG_QUEUE); } catch (Exception err) { log.error("保存异常日志失败。" + ExceptionUtils.getFullStackTrace(err)); } return errorId; } }