目前正在学习spring mvc
,遇到两个问题,在此请教各位大神:
1、异常处理部分一般通过实现 org.springframework.web.servlet.HandlerExceptionResolver
来统一处理,但是:
NoSuchRequestHandlingMethodException
HttpRequestMethodNotSupportedException
HttpMediaTypeNotSupportedException
HttpMediaTypeNotAcceptableException
MissingServletRequestParameterException
ServletRequestBindingException
ConversionNotSupportedException
TypeMismatchException
HttpMessageNotReadableException
HttpMessageNotWritableException
MethodArgumentNotValidException
MissingServletRequestPartException
BindException
NoHandlerFoundException
以上类型的异常会被 org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
处理掉,但是返回了我不希望的结果。
如图:由于 order 不够优先,提前弹出结果了!
请教下各位,这类问题是如何统一所有类型的异常的?目前我的理解是
覆盖
org.springframework.web.servlet.DispatcherServlet
的processHandlerException
@Override
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
int statusCode = 0;
boolean found = true;
try {
if (ex instanceof NoSuchRequestHandlingMethodException) {
statusCode = HttpServletResponse.SC_NOT_FOUND;
} else if (ex instanceof HttpRequestMethodNotSupportedException) {
statusCode = HttpServletResponse.SC_METHOD_NOT_ALLOWED;
} else if (ex instanceof HttpMediaTypeNotSupportedException) {
statusCode = HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
} else if (ex instanceof HttpMediaTypeNotAcceptableException) {
statusCode = HttpServletResponse.SC_NOT_ACCEPTABLE;
} else if (ex instanceof MissingServletRequestParameterException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof ServletRequestBindingException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof ConversionNotSupportedException) {
statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
} else if (ex instanceof TypeMismatchException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof HttpMessageNotReadableException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof HttpMessageNotWritableException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof MethodArgumentNotValidException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof MissingServletRequestPartException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof BindException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof NoHandlerFoundException) {
statusCode = HttpServletResponse.SC_NOT_FOUND;
} else {
found = false;
}
if (found) {
ServiceException error = new ServiceException(statusCode, "Forbidden");
error.setException(ex);
ex = error;
}
} catch (Exception e) {
}
return super.processHandlerException(request, response, handler, ex);
}
另一种方案是想办法提高自定义
HandlerExceptionResolver
的优先级,但是目前没有找到办法!
求助!
2、第二个问题,我希望对 JSON 请求返回JSON错误,例如:
{
"status": 500,
"statusInfo": "Internal Server Error",
"data": {
"type": "Exception",
"message": "UserException"
}
}
但是异常处理方法 resolveException(HttpServletRequest request, HttpServletResponse response, Object obj, Exception ex)
中无法确定该请求到底该由哪个 View
渲染啊
我的理解:
通过
拦截器
的preHandle(HttpServletRequest, HttpServletResponse, Object)
将应该由哪个View渲染页面的实例,注入给request
中,不知道各位大神觉得这个方法是否靠谱?
PS:Java初学者,大神勿喷
第一个问题找到方法了:
servlet-spring.xml
文件配置如下:
<bean class="org.springframework.web.servlet.handler.HandlerExceptionResolverComposite">
<property name="order" value="0" />
<property name="exceptionResolvers">
<list>
<bean class="io.conf.DefaultExceptionResolver">
<property name="errorView" value="/common/error" />
<property name="showErrorState" value="false" />
</bean>
</list>
</property>
</bean>
实现类核心代码如下
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if (ex == null) {
return null;
}
ModelAndView mv;
try {
// 判断是不是异步请求
if (WebUtils.hasResponseAnnotation(handler)) {
mv = new ModelAndView(new JsonView());
if (showErrorState) {
response.sendError(500);
}
} else {
mv = new ModelAndView(errorView);
}
int statusCode = 500;
try {
if (ex instanceof NoSuchRequestHandlingMethodException) {
statusCode = HttpServletResponse.SC_NOT_FOUND;
} else if (ex instanceof HttpRequestMethodNotSupportedException) {
statusCode = HttpServletResponse.SC_METHOD_NOT_ALLOWED;
} else if (ex instanceof HttpMediaTypeNotSupportedException) {
statusCode = HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE;
} else if (ex instanceof HttpMediaTypeNotAcceptableException) {
statusCode = HttpServletResponse.SC_NOT_ACCEPTABLE;
} else if (ex instanceof MissingServletRequestParameterException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof ServletRequestBindingException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof ConversionNotSupportedException) {
statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
} else if (ex instanceof TypeMismatchException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof HttpMessageNotReadableException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof HttpMessageNotWritableException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof MethodArgumentNotValidException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof MissingServletRequestPartException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof BindException) {
statusCode = HttpServletResponse.SC_BAD_REQUEST;
} else if (ex instanceof NoHandlerFoundException) {
statusCode = HttpServletResponse.SC_NOT_FOUND;
}
} catch (Exception e) {
}
Map<String, Object> data = new HashMap<String, Object>();
data.put("message", ex.getMessage());
data.put("type", ex.getClass().getSimpleName());
mv.addObject("status", statusCode);
mv.addObject("data", data);
mv.addObject("statusInfo", ex.getLocalizedMessage());
return mv;
} catch (Exception e) {
}
return null;
}
@ControllerAdvice+@ExceptionHandler 解决你的第二个问题,第一个问题是代码设计上的问题,跟spring关系不大。