Spring之webMvc异常处理
异常处理可以前端处理,也可以后端处理。
从稳妥的角度出发,两边都应该进行处理。
本文专门阐述如何在服务端进行http请求异常处理。
一、常见的异常类型
当我们做http请求的时候,会有各种各样的可能错误,比较常见的例如:
1.服务类异常
2.接口异常,而接口异常有各种各样的情况
究极就是接口的异常。
异常可以发生在请求的各个步骤之中,这里主要阐述网络通讯正常的情况。
这些通讯异常在方法 org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.doResolveException(HttpServletRequest, HttpServletResponse, Object, Exception)中
有详细的描述:
if (ex instanceof HttpRequestMethodNotSupportedException) {
return handleHttpRequestMethodNotSupported(
(HttpRequestMethodNotSupportedException) ex, request, response, handler);
}
else if (ex instanceof HttpMediaTypeNotSupportedException) {
return handleHttpMediaTypeNotSupported(
(HttpMediaTypeNotSupportedException) ex, request, response, handler);
}
else if (ex instanceof HttpMediaTypeNotAcceptableException) {
return handleHttpMediaTypeNotAcceptable(
(HttpMediaTypeNotAcceptableException) ex, request, response, handler);
}
else if (ex instanceof MissingPathVariableException) {
return handleMissingPathVariable(
(MissingPathVariableException) ex, request, response, handler);
}
else if (ex instanceof MissingServletRequestParameterException) {
return handleMissingServletRequestParameter(
(MissingServletRequestParameterException) ex, request, response, handler);
}
else if (ex instanceof ServletRequestBindingException) {
return handleServletRequestBindingException(
(ServletRequestBindingException) ex, request, response, handler);
}
else if (ex instanceof ConversionNotSupportedException) {
return handleConversionNotSupported(
(ConversionNotSupportedException) ex, request, response, handler);
}
else if (ex instanceof TypeMismatchException) {
return handleTypeMismatch(
(TypeMismatchException) ex, request, response, handler);
}
else if (ex instanceof HttpMessageNotReadableException) {
return handleHttpMessageNotReadable(
(HttpMessageNotReadableException) ex, request, response, handler);
}
else if (ex instanceof HttpMessageNotWritableException) {
return handleHttpMessageNotWritable(
(HttpMessageNotWritableException) ex, request, response, handler);
}
else if (ex instanceof MethodArgumentNotValidException) {
return handleMethodArgumentNotValidException(
(MethodArgumentNotValidException) ex, request, response, handler);
}
else if (ex instanceof MissingServletRequestPartException) {
return handleMissingServletRequestPartException(
(MissingServletRequestPartException) ex, request, response, handler);
}
else if (ex instanceof BindException) {
return handleBindException((BindException) ex, request, response, handler);
}
else if (ex instanceof NoHandlerFoundException) {
return handleNoHandlerFoundException(
(NoHandlerFoundException) ex, request, response, handler);
}
else if (ex instanceof AsyncRequestTimeoutException) {
return handleAsyncRequestTimeoutException(
(AsyncRequestTimeoutException) ex, request, response, handler);
}
我们整理为表格:
编码 | 名称 | 备注 |
handleHttpRequestMethodNotSupported | 请求方法不支持 | 例如RequestMapping只指定了post,但用get请求 |
HttpMediaTypeNotSupportedException | 媒体类型不支持 | 例如消息转换器可能只处理JSON,但请求头确设置为xml之类的 |
HttpMediaTypeNotAcceptableException | 媒体类型不可接受 | 请求处理器无法生成客户端可以支持的响应内容 |
MissingPathVariableException | 缺失路径变量 |
请求url缺乏路径变量。例如 @RequestMapping("/show/{name}") public Object show(@PathVariable String name){} 工程师可能少写了{name} |
MissingServletRequestParameterException | 缺失Servlet请求参数 | 例如使用了@RequstParam,但是url并没有提供对应的参数 |
ServletRequestBindingException | Servlet请求绑定异常 | 在执行绑定的时候发生的异常 |
ConversionNotSupportedException | 不支持的转换异常 | 无法为bean找到匹配的编辑器或者转换器 |
TypeMismatchException | 类型不匹配异常 | 给bean复制的时候,发现类型不匹配 |
HttpMessageNotReadableException | http消息无法读取 | 当HttpMessageConverter#read方法发生错误的时候 |
HttpMessageNotWritableException | http消息无法写异常 | 当HttpMessageConverter#write方法发生错误的时候 |
MethodArgumentNotValidException | 方法参数不可用异常 | 验证 @Valid过的参数时候所发生的异常 |
MissingServletRequestPartException | 缺失Servlet请求part异常 | 请求的媒体类型是文件类型(或者是附件),但内容没有 |
BindException | 绑定异常 | |
NoHandlerFoundException | 没有找到处理器 |
By default when the DispatcherServlet can't find a handler for a request it sends a 404 response. However if its property "throwExceptionIfNoHandlerFound" is set to 默认情况下,分发器处理器程序无法找到请求的处理器的时候(例如静态资源或者请求控制器方法的时候),会发送一个404响应。此外会设置属性throwExceptionIfNoHandlerFound=true,并引发没有处理器异常。用户可以考虑配置一个HandlerExceptionResolver来处理 |
AsyncRequestTimeoutException | 异步请求超时异常。即503 错误。 |
spring和springboot中和异常/错误有关的类远不止上表那么多。
出于代码的严谨性要求,几乎所有的函数/过程都会有异常处理(try catch throw),限于篇幅,不会讨论所有的代码,也没有必要。
二、WMS中的异常配置
关于wms的介绍,可以参考: wms配置简介
wms可以处理异常的地方有几个,但我们专门考虑exception字眼的部分。
@Bean
public HandlerExceptionResolver handlerExceptionResolver(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
configureHandlerExceptionResolvers(exceptionResolvers);
if (exceptionResolvers.isEmpty()) {
addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);
}
extendHandlerExceptionResolvers(exceptionResolvers);
HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();
composite.setOrder(0);
composite.setExceptionResolvers(exceptionResolvers);
return composite;
} /**
* Override this method to configure the list of
* {@link HandlerExceptionResolver HandlerExceptionResolvers} to use.
* <p>Adding resolvers to the list turns off the default resolvers that would otherwise
* be registered by default. Also see {@link #addDefaultHandlerExceptionResolvers}
* that can be used to add the default exception resolvers.
* @param exceptionResolvers a list to add exception resolvers to (initially an empty list)
*/
protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
} /**
* A method available to subclasses for adding default
* {@link HandlerExceptionResolver HandlerExceptionResolvers}.
* <p>Adds the following exception resolvers:
* <ul>
* <li>{@link ExceptionHandlerExceptionResolver} for handling exceptions through
* {@link org.springframework.web.bind.annotation.ExceptionHandler} methods.
* <li>{@link ResponseStatusExceptionResolver} for exceptions annotated with
* {@link org.springframework.web.bind.annotation.ResponseStatus}.
* <li>{@link DefaultHandlerExceptionResolver} for resolving known Spring exception types
* </ul>
*/
protected final void addDefaultHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers,
ContentNegotiationManager mvcContentNegotiationManager) { ExceptionHandlerExceptionResolver exceptionHandlerResolver = createExceptionHandlerExceptionResolver();
exceptionHandlerResolver.setContentNegotiationManager(mvcContentNegotiationManager);
exceptionHandlerResolver.setMessageConverters(getMessageConverters());
exceptionHandlerResolver.setCustomArgumentResolvers(getArgumentResolvers());
exceptionHandlerResolver.setCustomReturnValueHandlers(getReturnValueHandlers());
if (jackson2Present) {
exceptionHandlerResolver.setResponseBodyAdvice(
Collections.singletonList(new JsonViewResponseBodyAdvice()));
}
if (this.applicationContext != null) {
exceptionHandlerResolver.setApplicationContext(this.applicationContext);
}
exceptionHandlerResolver.afterPropertiesSet();
exceptionResolvers.add(exceptionHandlerResolver); ResponseStatusExceptionResolver responseStatusResolver = new ResponseStatusExceptionResolver();
responseStatusResolver.setMessageSource(this.applicationContext);
exceptionResolvers.add(responseStatusResolver); exceptionResolvers.add(new DefaultHandlerExceptionResolver());
}
通过wms机制,可以覆盖bean(handlerExceptionResolver),或者覆盖方法 configureHandlerExceptionResolvers添加异常处理解析器。
不过一般情况下,我们都没有那个必要。
一般情况下,使用DefaultHandlerExceptionResolver进行处理即可,即前文介绍的内容。
三、springboot的http请求异常
如果使用springboot开发,那么springboot会通过自动配置引入一个 org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController
这类控制器类实现了接口 org.springframework.boot.web.servlet.error.ErrorController。
根据springboot的有关描述,我们可以实现它接口org.springframework.boot.web.servlet.error.ErrorController,以便覆盖默认的实现。
例如:
@Controller
public class ErrController implements ErrorController { @RequestMapping("/error")
public String handleError(HttpServletRequest request,HttpServletResponse response) {
int statusCode=response.getStatus();
if (statusCode == 404) {
return "/main/err.html";
}
else if (statusCode == 444) {
return "/main/login.html";
}
return "";
}
}
需要注意的是,ErrorController 的代码是在wms的异常处理之后执行的。
此外,也可以只用控制器advice注解处理, 例如:SpringBoot系列——自定义统一异常处理 - huanzi-qch - 博客园 (cnblogs.com)
四、小结
spring为了少让我们的代码出现问题,还引入了一个机制:验证。例如可以验证参数验证。不过验证仅仅只是解决了少数的异常情形,虽然参数不合法的发生的数量还是比较多的。
但这个验证一般情况下,也不需要,因为一般在客户端就先处理了!
Spring之webMvc异常处理的更多相关文章
- spring mvc4:异常处理
前面学习过struts2的异常处理,今天来看下spring mvc4的异常处理: 一.Servlet配置文件修改 <bean id="exceptionResolver" c ...
- 使用Spring MVC统一异常处理实战
1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦合 ...
- Spring MVC 统一异常处理
Spring MVC 统一异常处理 看到 Exception 这个单词都心慌 如果有一天你发现好久没有看到Exception这个单词了,那你会不会想念她?我是不会的.她如女孩一样的令人心动又心慌,又或 ...
- 【Spring学习笔记-MVC-15.1】Spring MVC之异常处理=404界面
作者:ssslinppp 异常处理请参考前篇博客:<[Spring学习笔记-MVC-15]Spring MVC之异常处理>http://www.cnblogs.com/sssl ...
- 使用Spring MVC统一异常处理实战<转>
1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦合 ...
- Spring 中的异常处理
工作中遇到这样的同事,问他活干完吗,他说开发好了,结果测试时发现各种异常情况未处理,联调测试时各种未知错误,最后联调完成比他预期的两倍工作量还多.这样的开发如果是新人还可以原谅,如果有工作经验且出现多 ...
- 编程小白入门分享三:Spring AOP统一异常处理
Spring AOP统一异常处理 简介 在Controller层,Service层,可能会有很多的try catch代码块.这将会严重影响代码的可读性."美观性".怎样才可以把更多 ...
- Spring Boot全局异常处理
本文为大家分享了Spring Boot全局异常处理,供大家参考,具体内容如下 1.后台处理异常 a.引入thymeleaf依赖 <!-- thymeleaf模板插件 --> <dep ...
- Spring MVC 全局异常处理&文件上传
Spring MVC 全局异常处理 使用SimpleMappingExceptionResolver实现异常处理 在welcome-servlet.xml进行如下配置: <bean class= ...
- 使用Spring MVC统一异常处理实战(转载)
原文地址:http://blog.csdn.net/ufo2910628/article/details/40399539 种方式: (1)使用Spring MVC提供的简单异常处理器SimpleMa ...
随机推荐
- dotnet6 C# 一个国内还能用的 NTP 时间校准客户端的实现
本文来记录一个我自己在使用的 NTP 时间校准客户端的实现 核心方法是在国内使用 腾讯 和 阿里 提供的 NTP 时间服务器来获取网络时间,如果连接不上,再依次换成 国家服务器 和 中国授时 服务,如 ...
- C语言实验1
#include<stdio.h> #include<stdlib.h> int main() { printf(" o\n"); printf(" ...
- 服务端向客户端发送消息Server-Sent Events
今天听说了服务端向客户端发消息的一种方式:Server-Sent Events SSE使用的是HTTP协议,本质上是服务端向客户端发送流式数据. HTTP不支持服务端向客户端发送请求,但是如果客户端向 ...
- python性能分析line_profiler
在编程世界中,效率是王道.对于Python开发者来说,line_profiler 是一把锐利的剑,能够深入代码的每一行,找出性能瓶颈.今天,就让我们一起深入探索 line_profiler,学习如何用 ...
- LLaMA 3 源码解读-大语言模型5
本来不是很想写这一篇,因为网上的文章真的烂大街了,我写的真的很有可能没别人写得好.但是想了想,创建这个博客就是想通过对外输出知识的方式来提高自身水平,而不是说我每篇都能写得有多好多好然后吸引别人来看. ...
- gorm 关系一对一,一对多,多对多查询
gorm 关系一对一,一对多,多对多查询 gorm v2版本 Belongs To mysql表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_IN ...
- Splashtop 教育行业用户增加700%
由于新冠肺炎大流行继续限制对大学.学院和K-12学校的计算机实验室的物理访问,Splashtop的销售数据表明,越来越多的学校开始使用远程访问软件作为使用计算机实验室资源的替代方法. 在6月到8月 ...
- WPF自定义控件,如何使得xaml涉及器中的修改能立即反应到预览
这是我无意中发现的,xaml中设置的是依赖属性而不是包装器,所以我们可以直接在注册依赖属性那里设置回调,触发某个控件重绘,比如本身或父控件重绘. xaml设计器就会实时更新 1 // !!!由于xam ...
- RestTemplate 介绍和用法
RestTemplate 简介 RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求.POST 请求.PUT ...
- golang的 CGO 是什么
CGO是Go(Golang)语言中的一个工具,全称为 "C-Go" 或者 "C for Go". 它是Go标准库的一部分,允许Go代码与C语言代码进行交互. C ...