详解@EnableWebMvc
最近看了《Spring in Action》的开头,就被Spring注解开发(完全不写web.xml)惊叹了,也第一次知道了@EnableWebMvc是SpringMVC的注解
@EnableWebMvc注解
@EnableWebMvc的javaDoc注释有点长。 从下图得到的几个信息: href="mailto:1.@EnableWebMvc">1.@EnableWebMvc没有任何属性,只是@Import了一个类叫DelegatingWebMvcConfiguration
2. 注释中说明:将@EnableWebMvc添加给@Configuration类来导入SpringMvc的配置;3.自定义MVC配置,实现接口WebMvcConfigurer或更可能继承WebMvcConfigurerAdapter,并且使用@EnableWebMvc;
4.如果还想要自定义配置,移除@EnableWebMvc,并且继承WebMvcConfigurationSupport或DelegatingWebMvcConfiguration。
5.@EnableWebMvc出现自Spring3.1的版本

@EnableWebMvc的注释文档说的很详细,先记录第一点,@Import的类是干啥的!
@Import的多种用法看我这篇文档:Spring @Import . @Import导入了一个类DelegatingWebMvcConfiguration,这个类标注了@Configuration类,这个类下方法上标注了@Bean的都会纳入Spring容器管理。
DelegatingWebMvcConfiguration类如下,但是类里面搜索却没有@Bean标注! 在其父类WebMvcConfigurationSupport里面搜索到了19个@Bean.
这19个@Bean基本上和<mvc:annotation-driven/>实现的功能无差,甚至提供了一种很便捷的方式扩展<mvc:annotation-driven/>

举两个栗子,说明下:1. <mvc:annotation-driven/> @ResponseBody 返回String中文乱码 Spring @ResponseBody String中文乱码

@EnableWebMvc同样存在这个问题,默认字符集为ISO-8859-1,解决方案:继承WebMvcConfigurerAdapter,重写extendMessageConverters方法!

栗子2:比如需要添加拦截器,原先写法可能是<mvc:interceptors></mvc:interceptors>这种形式添加,现在不用XML,方式就是这样:
在继承WebMvcConfigurerAdapter基础上,重写addInterceptor方法。

@EnableWebMvc可扩展的结构
图片可以从processOn拷贝,RequestMappingHandlerMapping地址:https://www.processon.com/view/5c9d8480e4b035b243ba651b
RequestMappingHandlerAdapter地址:https://www.processon.com/view/5c9d86cee4b034408de5663d 红框代表可继承扩展WebMvcConfigurerAdapter等扩展的方法。

想到为什么继承WebMvcConfigurerAdapter或者实现WebMvcConfigurer,就能够在@EnableWebMvc继承上扩展呢?
@EnableWebMvc导入的是DelegatingWebMvcConfiguration类,和WebMvcConfigurer完全没有联系啊?

说明:DelegatingWebMvcConfiguration类,有这样一个属性WebMvcConfigurerComposite,维护着WebMvcConfigurer的集合,有点类似组合模式。
初始化DelegatingWebMvcConfiguration时如果发现了WebMvcConfigurer的实现类,就注入到WebMvcConfigurerComposite中,这样就把我们实现了WebMvcConfigurer的类和@EnableWebMvc联系到一起了,
就可以在<mvc:annotation-driven/>基础上扩展.
这里很神奇,在我理解中Spring没法自动判断两个Bean作为集合注入的啊! 这里起作用的就是required=false 少了这句话就抛出异常!
@EnableWebMvc默认是没有静态资源放行的,比如.css .js文件默认 也会被 dispatchServelt / 形式的拦截到
原来在web.xml文件中可以这样配置,静态资源后缀为.js .css不拦截
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>*.htm</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
在没有web.xml的文件中解决方案:继承WebMvcConfigurerAdapter,并且重写configureDefaultServletHandling方法,即可达到和上面一样的效果,就可以访问 .css .js等文件!

原理解析:如果这篇博客前面看过了,直接看到WebMvcConfigurationSupport,@Bean注册了一个bean defaultServletHandlerMapping,最终configureDefaultServletHandling会制定我们上面的方法。

DefaultServletHandlerConfigurer只是个配置类,Bean实际返回的是hanlderMapping!=null?handlerMapping:new EmptyHandlerMapping(); EmptyHandlerMapping不对请求做任何处理,而configurer的getHandlerMapping方法如下: handler不为空,就会返回一个SimpleUrlHandlerMapping,而configurer.enable()方法等价于configurer.enable(null),就是初始化handler的。总的来说就是,configurer.enable()方法就是注册了一个SimpleUrlHandlerMapping对象,handler就是DefaultServletHttpRequestHandler.


DefaultServletHttpRequestHandler如何处理静态资源请求?
通过获取 服务器默认的servlet进行转发,因为/** 会匹配所有的URI,所以SimpleUrlHandlerMapping必须放在RequestMappingHandlerMapping之后;核心方式就是servletContext.getNamedDispatcher(“default”).forward(request,response);

总结@EnableWebMvc替我们做了什么?
引入了这样一个类DelegatingWebMvcConfiguration,通过@Bean注册了和<mvc:annotation-driven/>一样的组件,RequestMappingHandlerMapping、RequestMappingHandlerAdatper、HandlerExceptionResolver等等,只要有个Spring管理的bean继承WebMvcConfigurer或WebMvcConfigurerAdapter,重写方法即可自定义<mvc:annotation-driven/>.
其实@EnableWebMvc == @Import({DelegatingWebMvcConfiguration.class})
详解@EnableWebMvc的更多相关文章
- Spring MVC 学习总结(二)——控制器定义与@RequestMapping详解
一.控制器定义 控制器提供访问应用程序的行为,通常通过服务接口定义或注解定义两种方法实现. 控制器解析用户的请求并将其转换为一个模型.在Spring MVC中一个控制器可以包含多个Action(动作. ...
- Spring Boot异常处理详解
在Spring MVC异常处理详解中,介绍了Spring MVC的异常处理体系,本文将讲解在此基础上Spring Boot为我们做了哪些工作.下图列出了Spring Boot中跟MVC异常处理相关的类 ...
- Spring MVC测试框架详解——服务端测试
随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的.从Spring 3.2开始Spring了Spring Web测试框架,如果版本低于3.2,请使用sp ...
- SpringMvc测试框架详解----服务端测试
随着RESTful Web Service的流行,测试对外的Service是否满足期望也变的必要的.从Spring 3.2开始Spring了Spring Web测试框架,如果版本低于3.2,请使用sp ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
随机推荐
- HTML第二篇
1>压缩文件格式:使用.zip格式较好 2>charset(字符集) 国内最新字符集格式为:gb18030 国际上通用的字符集是:UTF-8 3>添加图片 <img sr ...
- 借助Algorithmia网站API:用AI给黑白照片上色,复现记忆中的旧时光
先看DEMOhttps://demos.algorithmia.com/colorize-photos/ 了解ColorfulImageColorizationhttps://algorithmia. ...
- Linux - rename 批量替换两种模式
模式一: rename sub raw * 模式二: rename 's/sub/raw/g' * sub raw 这里支持一定程序的正则匹配
- 学习Tensorflow的LSTM的RNN例子
学习Tensorflow的LSTM的RNN例子 基于TensorFlow一次简单的RNN实现 极客学院-递归神经网络 如何使用TensorFlow构建.训练和改进循环神经网络
- 图解HTTP第五章
与 HTTP 协作的 Web 服务器 一台 Web 服务器可搭建多个独立域名的 Web 网站,也可作为通信路径上的中转服务器提升传输效率. 1>用单台虚拟主机实现多个域名 HTTP/1.1 规范 ...
- centos中单进程监控
[root@k8s6 proc]# ps aux|grep -v PID|sort -rn -k +|head - root ? Ssl : : /usr/bin/dockerd root ? Ssl ...
- JSON笔记整理
JSON简介: JSON: JavaScript Object Notation(JavaScript 对象表示法) JSON 是存储和交换文本信息的语法.类似 XML. JSON 比 XML ...
- samba服务配置(二)
需求: 某公司销售部门提出一个文件共享需求,要求部门共享目录有三个,第一个共享目录所有销售部门人员都具有可读可写权限: 第二个共享目录所有销售人员只读权限,经理级别的销售人员具有可读可写权限:第三个共 ...
- 一行代码实现自定义转场动画--iOS自定义转场动画集
WXSTransition 这款非常不错,力推 这是作者源码简书地址: http://www.jianshu.com/p/fd3154946919 这是作者源码github地址 https://git ...
- 736. Parse Lisp Expression
You are given a string expression representing a Lisp-like expression to return the integer value of ...