package org.onetwo.boot.core.web.mvc.exception; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.onetwo.boot.core.config.BootJFishConfig; import org.onetwo.boot.core.web.controller.AbstractBaseController; import org.onetwo.boot.core.web.service.impl.ExceptionMessageAccessor; import org.onetwo.boot.core.web.utils.BootWebUtils; import org.onetwo.common.data.DataResult; import org.onetwo.common.log.JFishLoggerFactory; import org.onetwo.common.spring.mvc.utils.DataResults; import org.onetwo.common.utils.LangUtils; import org.onetwo.common.utils.StringUtils; import org.onetwo.common.web.utils.RequestUtils; import org.onetwo.common.web.utils.ResponseType; import org.slf4j.Logger; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.ui.ModelMap; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.WebRequest; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; /************ * 异常处理 * instead of BasicErrorController * @author wayshall * */ public class BootWebExceptionResolver extends SimpleMappingExceptionResolver implements InitializingBean, ExceptionMessageFinder { // public static final String MAX_UPLOAD_SIZE_ERROR = "MVC_MAX_UPLOAD_SIZE_ERROR"; public static final String ERROR_MESSAGE_OBJECT_KEY = "__ERROR_MESSAGE_OBJECT__"; private static final String EXCEPTION_STATCK_KEY = "__exceptionStack__"; private static final String ERROR_CODE_KEY = "__errorCode__"; private static final String PRE_URL = "preurl"; private static final String AJAX_RESULT_PLACEHOLDER = "result"; public static final int RESOLVER_ORDER = -9999; protected final Logger logger = JFishLoggerFactory.getLogger(this.getClass()); // private Map<String, WhenExceptionMap> whenExceptionCaches = new WeakHashMap<String, WhenExceptionMap>(); protected final Logger mailLogger = JFishLoggerFactory.findMailLogger(); // resouce: exception-messages /*@Qualifier(BootContextConfig.BEAN_EXCEPTION_MESSAGE) @Autowired private MessageSource exceptionMessage;*/ // private List<String> notifyThrowables;// = BaseSiteConfig.getInstance().getErrorNotifyThrowabbles(); // @Autowired // private BootSiteConfig bootSiteConfig; @Autowired private BootJFishConfig bootJFishConfig; @Autowired(required=false) private ExceptionMessageAccessor exceptionMessageAccessor; private ResponseEntityExceptionHandler responseEntityExceptionHandler = new ResponseEntityExceptionHandler(){}; /*** * WebRequest inject by WebApplicationContextUtils#registerWebApplicationScopes WebRequestObjectFactory */ @Autowired(required=false) private WebRequest webRequest; // protected String defaultRedirect; public BootWebExceptionResolver(){ setOrder(RESOLVER_ORDER); } @Override public void afterPropertiesSet() throws Exception { initResolver(); // this.notifyThrowables = bootSiteConfig.getNotifyThrowables(); } protected void initResolver(){ // defaultRedirect = BaseSiteConfig.getInstance().getLoginUrl(); } protected void beforeReturnModelAndView(HttpServletRequest request, Object handlerMethod, ModelAndView mv, ErrorMessage errorMessage){ RequestContextHolder.getRequestAttributes().setAttribute(ERROR_MESSAGE_OBJECT_KEY, errorMessage, RequestAttributes.SCOPE_REQUEST); if(mv!=null){ this.doLog(request, errorMessage); } } @Override protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handlerMethod, Exception ex) { ModelMap model = new ModelMap(); ErrorMessage errorMessage = this.getErrorMessage(ex); String viewName = determineViewName(ex, request); errorMessage.setViewName(viewName); // Object req = RequestContextHolder.getRequestAttributes().getAttribute(WebHelper.WEB_HELPER_KEY, RequestAttributes.SCOPE_REQUEST); if(BootWebUtils.isAjaxRequest(request) || BootWebUtils.isAjaxHandlerMethod(handlerMethod)){ DataResult<?> result = DataResults.error(errorMessage.getMesage()).build(); model.put(AJAX_RESULT_PLACEHOLDER, result); ModelAndView mv = new ModelAndView("error", model); beforeReturnModelAndView(request, handlerMethod, mv, errorMessage); return mv; // BootWebUtils.webHelper(request).setAjaxErrorResult(result);// for BootWebExceptionHandler //return null for post exceptionHandler to process // return null; } String msg = errorMessage.getMesage(); if(!model.containsKey(AbstractBaseController.ERROR)){ model.put(AbstractBaseController.ERROR, msg); model.put(AbstractBaseController.MESSAGE_TYPE, AbstractBaseController.MESSAGE_TYPE_ERROR); } if(BootWebUtils.isRedirect(errorMessage.getViewName())){ ModelAndView mv = this.createModelAndView(errorMessage.getViewName(), model, request, response, ex); beforeReturnModelAndView(request, handlerMethod, mv, errorMessage); return mv; } String eInfo = ""; if(!errorMessage.isDetail()){ eInfo = LangUtils.toString(ex, true); // WebContextUtils.attr(request, EXCEPTION_STATCK_KEY, eInfo); // WebContextUtils.attr(request, EXCEPTION_STATCK_KEY2, eInfo); }else{ // WebContextUtils.attr(request, EXCEPTION_STATCK_KEY, ""); // WebContextUtils.attr(request, EXCEPTION_STATCK_KEY2, ""); } // eInfo = errorMessage.toString()+" "+ eInfo; model.put(EXCEPTION_STATCK_KEY, eInfo); model.put(ERROR_CODE_KEY, errorMessage.getCode()); ModelAndView mv = createModelAndView(errorMessage.getViewName(), model, request, response, ex); beforeReturnModelAndView(request, handlerMethod, mv, errorMessage); return mv; } /*protected String getUnknowError(){ return SystemErrorCode.DEFAULT_SYSTEM_ERROR_CODE; }*/ protected String getPreurl(HttpServletRequest request){ String preurl = StringUtils.isBlank(request.getParameter(PRE_URL))?BootWebUtils.requestUri():request.getParameter(PRE_URL); // return encode(preurl); return preurl; } protected ModelAndView createModelAndView(String viewName, ModelMap model, HttpServletRequest request, HttpServletResponse response, Exception ex){ // return new ModelAndView(viewName, model); // Apply HTTP status code for error views, if specified. // Only apply it if we're processing a top-level request. Integer statusCode = determineStatusCode(ex, request, viewName); if (statusCode != null) { applyStatusCodeIfPossible(request, response, statusCode); } ModelAndView mv = null; if (viewName != null) { mv = getModelAndView(viewName, ex, request); mv.addObject("statusCode", statusCode); } else if (StringUtils.isNotBlank(bootJFishConfig.getErrorView()) && isResponsePage(request)){ mv = getModelAndView(bootJFishConfig.getErrorView(), ex, request); mv.addObject("statusCode", statusCode); } else { //will forward next HandlerExceptionResolver, see DispatcherServlet#processHandlerException mv = null; } return mv; } protected boolean isResponsePage(HttpServletRequest request){ ResponseType responseType = RequestUtils.getResponseType(request); return responseType==ResponseType.PAGE; } protected Integer determineStatusCode(Exception ex, HttpServletRequest request, String viewName) { Integer statusCode = super.determineStatusCode(request, viewName); if(statusCode==null){ ResponseEntity<Object> reponse = responseEntityExceptionHandler.handleException(ex, webRequest); statusCode = reponse.getStatusCodeValue(); } return statusCode; } protected void doLog(HttpServletRequest request, ErrorMessage errorMessage){ errorMessage.setNotifyThrowables(bootJFishConfig.getNotifyThrowables()); logError(request, errorMessage); } @Override public ExceptionMessageAccessor getExceptionMessageAccessor() { return this.exceptionMessageAccessor; } public Logger getErrorLogger() { return JFishLoggerFactory.findErrorLogger(logger); } public ExceptionMessageFinderConfig getExceptionMessageFinderConfig() { return this.bootJFishConfig; } }