package com.nis.restful; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.TypeMismatchException; import org.springframework.beans.factory.InitializingBean; import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.stereotype.Component; import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MissingServletRequestParameterException; import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException; @Component public class DefaultRestErrorResolver implements RestErrorResolver,InitializingBean{ /** * 预先定义的所有异常类型 */ private Map exceptionMappings = Collections.emptyMap(); /** * 配置文件中自定义扩展错误 */ private Map exceptionMappingDefinitions = Collections.emptyMap(); @Override public RestResult resolveError(HttpServletRequest request, Object handler, Exception ex) { RestResult error = this.buildError(ex, request); return error; } private RestResult buildError(Exception ex, HttpServletRequest request) { RestResult error = new RestResult(); error.setStatus(this.getHttpStatusByEx(ex));// 设置http状态 //获取日志源[只有日志需要返回日志源和ActiveSys] String logSource = ((RestServiceException) ex).getLogSource(); String activeSys = ((RestServiceException) ex).getActiveSys(); if(logSource != null ){ error.setLogSource(logSource); } if(activeSys != null ){ error.setActiveSys(activeSys); } //RestServiceException 包含有错误code if(ex instanceof RestServiceException){ int errorCode = ((RestServiceException) ex).getErrorCode(); error.setBusinessCode(RestBusinessCode.valueOf(errorCode)); } else { error.setBusinessCode(RestBusinessCode.valueOf(998)); } error.setMsg(ex.getMessage()); if(null != request){ error.setFromUri(request.getRequestURI()); }else { error.setFromUri("unknow url"); } return error; } private HttpStatus getHttpStatusByEx(Exception ex){ if(this.exceptionMappingDefinitions.containsKey(ex.getClass().getName())){ return HttpStatus.valueOf(Integer.parseInt(this.exceptionMappingDefinitions.get(ex.getClass() .getName()))); } else return HttpStatus.INTERNAL_SERVER_ERROR; } @Override public void afterPropertiesSet() throws Exception { //初始化所有预先定义的错误 this.exceptionMappings = createDefaultExceptionMappingDefinitions(); //如果存在自定义的错误,添加到预定义错误中 if (this.exceptionMappingDefinitions != null && !this.exceptionMappingDefinitions.isEmpty()) { this.exceptionMappings.putAll(this.exceptionMappingDefinitions); } } /** * 将spring中的http状态和异常互相对应 参考 spring的defaultExceptionHandler实现类似 * * @return */ private final Map createDefaultExceptionMappingDefinitions() { Map m = new LinkedHashMap(); // 400 applyDef(m, HttpMessageNotReadableException.class, HttpStatus.BAD_REQUEST); applyDef(m, MissingServletRequestParameterException.class, HttpStatus.BAD_REQUEST); applyDef(m, TypeMismatchException.class, HttpStatus.BAD_REQUEST); applyDef(m, "javax.validation.ValidationException", HttpStatus.BAD_REQUEST); // 404 applyDef(m, NoSuchRequestHandlingMethodException.class, HttpStatus.NOT_FOUND); applyDef(m, "org.hibernate.ObjectNotFoundException", HttpStatus.NOT_FOUND); // 405 applyDef(m, HttpRequestMethodNotSupportedException.class, HttpStatus.METHOD_NOT_ALLOWED); // 406 applyDef(m, HttpMediaTypeNotAcceptableException.class, HttpStatus.NOT_ACCEPTABLE); // 409 applyDef(m, "org.springframework.dao.DataIntegrityViolationException", HttpStatus.CONFLICT); // 415 applyDef(m, HttpMediaTypeNotSupportedException.class, HttpStatus.UNSUPPORTED_MEDIA_TYPE); return m; } private void applyDef(Map m, Class clazz, HttpStatus status) { applyDef(m, clazz.getName(), status); } private void applyDef(Map m, String key, HttpStatus status) { m.put(key, status.value() + ""); } public Map getExceptionMappings() { return exceptionMappings; } public void setExceptionMappings(Map exceptionMappings) { this.exceptionMappings = exceptionMappings; } public Map getExceptionMappingDefinitions() { return exceptionMappingDefinitions; } public void setExceptionMappingDefinitions( Map exceptionMappingDefinitions) { this.exceptionMappingDefinitions = exceptionMappingDefinitions; } }