/** * Copyright 2013-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.iflytek.edu.cloud.frame.spring; import java.io.IOException; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.iflytek.edu.cloud.frame.error.support.CycoreErrorException; import org.springframework.beans.TypeMismatchException; import org.springframework.core.NestedExceptionUtils; import org.springframework.core.Ordered; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver; import com.iflytek.edu.cloud.frame.Constants; import com.iflytek.edu.cloud.frame.error.MainError; import com.iflytek.edu.cloud.frame.error.MainErrorType; import com.iflytek.edu.cloud.frame.error.MainErrors; import com.iflytek.edu.cloud.frame.error.SubError; import com.iflytek.edu.cloud.frame.error.SubErrorType; import com.iflytek.edu.cloud.frame.error.SubErrors; import com.iflytek.edu.cloud.frame.error.support.ErrorRequestMessageConverter; import com.iflytek.edu.cloud.frame.error.support.InvalidParamException; import com.iflytek.edu.cloud.frame.error.support.MissingParamException; /** * * @author libinsong1204@gmail.com * */ public class DefaultHandlerExceptionResolver extends AbstractHandlerExceptionResolver { private static final Map<String, SubErrorType> INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS = new LinkedHashMap<String, SubErrorType>(); private static final ModelAndView ERROR_MODEL_AND_VIEW = new ModelAndView(); static { INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("typeMismatch", SubErrorType.ISV_PARAMETERS_MISMATCH); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("NotNull", SubErrorType.ISV_MISSING_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("NotEmpty", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("Size", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("Range", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("Pattern", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("Min", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("Max", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("DecimalMin", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("DecimalMax", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("Digits", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("Past", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("Future", SubErrorType.ISV_INVALID_PARAMETER); INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.put("AssertFalse", SubErrorType.ISV_INVALID_PARAMETER); } private ErrorRequestMessageConverter messageConverter; public DefaultHandlerExceptionResolver() { setOrder(Ordered.LOWEST_PRECEDENCE); } @Override protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); MainError mainError = null; Locale locale = (Locale)request.getAttribute(Constants.SYS_PARAM_KEY_LOCALE); try { if (ex instanceof BindException) { mainError = handleBindException((BindException) ex, request, response, handler); } else if (ex instanceof MissingParamException) { MissingParamException _exception = (MissingParamException)ex; mainError = SubErrors.getMainError(SubErrorType.ISV_MISSING_PARAMETER, locale); SubError subError = SubErrors.getSubError(SubErrorType.ISV_MISSING_PARAMETER.value(), locale, _exception.getParamName(), _exception.getMessage()); mainError.addSubError(subError); } else if (ex instanceof InvalidParamException) { InvalidParamException _exception = (InvalidParamException)ex; mainError = SubErrors.getMainError(SubErrorType.ISV_INVALID_PARAMETER, locale); SubError subError = SubErrors.getSubError(SubErrorType.ISV_INVALID_PARAMETER.value(), locale, _exception.getParamName(), _exception.getValue(), _exception.getMessage()); mainError.addSubError(subError); } else if (ex instanceof CycoreErrorException) { CycoreErrorException _exception = (CycoreErrorException)ex; mainError = SubErrors.getMainError(SubErrorType.ISV_CYCORE_ERROR, locale); SubError subError = SubErrors.getSubError(SubErrorType.ISV_CYCORE_ERROR.value(), locale, _exception.getErrorMessage(), _exception.getMessage()); mainError.addSubError(subError); } else if (ex instanceof TypeMismatchException) { TypeMismatchException _exception = (TypeMismatchException)ex; mainError = SubErrors.getMainError(SubErrorType.ISV_PARAMETERS_MISMATCH, locale); SubErrorType tempSubErrorType = SubErrorType.ISV_PARAMETERS_MISMATCH; SubError subError = SubErrors.getSubError(tempSubErrorType.value(), locale, _exception.getValue(), _exception.getRequiredType().getSimpleName()); mainError.addSubError(subError); } else { SubError subError = SubErrors.getSubError(SubErrorType.ISP_SERVICE_UNAVAILABLE.value(), (Locale)request.getAttribute(Constants.SYS_PARAM_KEY_LOCALE), request.getParameter(Constants.SYS_PARAM_KEY_METHOD), NestedExceptionUtils.buildMessage(ex.getMessage(), ex)); mainError = MainErrors.getError(MainErrorType.SERVICE_CURRENTLY_UNAVAILABLE, (Locale)request.getAttribute(Constants.SYS_PARAM_KEY_LOCALE)); mainError.addSubError(subError); } request.setAttribute(Constants.MAIN_ERROR_CODE, mainError.getCode()); messageConverter.convertData(request, response, mainError); logger.warn(ex.getMessage(), ex); } catch (Exception handlerException) { logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException); } return ERROR_MODEL_AND_VIEW; } protected MainError handleBindException(BindException ex, HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); List<ObjectError> errorList = ex.getBindingResult().getAllErrors(); //将Bean数据绑定时产生的错误转换为Rop的错误 MainError mainError = null; if (errorList != null && errorList.size() > 0) { mainError = toMainErrorOfSpringValidateErrors(errorList, (Locale)request.getAttribute(Constants.SYS_PARAM_KEY_LOCALE)); } return mainError; } /** * 将通过JSR 303框架校验的错误转换为服务框架的错误体系 * * @param allErrors * @param locale * @return */ private MainError toMainErrorOfSpringValidateErrors(List<ObjectError> allErrors, Locale locale) { if (hastSubErrorType(allErrors, SubErrorType.ISV_MISSING_PARAMETER)) { return getBusinessParameterMainError(allErrors, locale, SubErrorType.ISV_MISSING_PARAMETER); } else if (hastSubErrorType(allErrors, SubErrorType.ISV_PARAMETERS_MISMATCH)) { return getBusinessParameterMainError(allErrors, locale, SubErrorType.ISV_PARAMETERS_MISMATCH); } else { return getBusinessParameterMainError(allErrors, locale, SubErrorType.ISV_INVALID_PARAMETER); } } /** * 判断错误列表中是否包括指定的子错误 * * @param allErrors * @param subErrorType1 * @return */ private boolean hastSubErrorType(List<ObjectError> allErrors, SubErrorType subErrorType1) { for (ObjectError objectError : allErrors) { if (objectError instanceof FieldError) { FieldError fieldError = (FieldError) objectError; if (INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.containsKey(fieldError.getCode())) { SubErrorType tempSubErrorType = INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.get(fieldError.getCode()); if (tempSubErrorType == subErrorType1) { return true; } } } } return false; } /** * 生成对应子错误的错误类 * * @param allErrors * @param locale * @param subErrorType * @return */ private MainError getBusinessParameterMainError(List<ObjectError> allErrors, Locale locale, SubErrorType subErrorType) { MainError mainError = SubErrors.getMainError(subErrorType, locale); for (ObjectError objectError : allErrors) { if (objectError instanceof FieldError) { FieldError fieldError = (FieldError) objectError; SubErrorType tempSubErrorType = INVALIDE_CONSTRAINT_SUBERROR_MAPPINGS.get(fieldError.getCode()); if (tempSubErrorType == subErrorType) { SubError subError = SubErrors.getSubError(tempSubErrorType.value(), locale, fieldError.getField(), fieldError.getRejectedValue(), fieldError.getDefaultMessage()); mainError.addSubError(subError); } } } return mainError; } public ErrorRequestMessageConverter getMessageConverter() { return messageConverter; } public void setMessageConverter(ErrorRequestMessageConverter messageConverter) { this.messageConverter = messageConverter; } }