探 Spring 3.1之无web.xml式 基于代码配置的servlet3.0应用

[size=medium][align=left] 前些天,spring framework 有了新版本3.1的 release。应该是在11年12月13日,由于springframework 的资源下载都得输入些个人信息,系统应该有纪录哪些用户对哪些资源感兴趣,所以我的邮箱有3.1版的release 信息,顺着邮箱点去的网页,有Juergen发的新版本的概述。扫了一眼,对The servlet 3.0 webapplicationInitializer mechanism很感兴趣,故而今天对此特别research了一番。[/align][/size]
[size=medium][align=left] 穿越:之前在eclipse 里新建servlet3.0的webapp时,就会有创建 web.xml文件与否的选项,很明显这是表明servlet3.0有着不用创建web.xml的机制,自然也就想到了注解式的配置,于是很容易在eclipse的editor里利用代码辅助找到了@WebServlet,@WebFilter , @WebInitParam, @WebListener等注解。它在javax.servlet.annotation下,一般是存于服务器的lib中。如我的用vFabric tc server , 的lib下的serverlt-api.jar中。注解不用看源码,就在eclipse里看它的名字与方法就会用了。也就是说在所写的Servlet, Listener, Filter代码中直接注解,服务器就可以找到它们,如此一来也就省去了web.xml。 当时的问题在于:所见web程序的大部分web.xml配置,全是第三方框架的类。下载框架的源码再更改后再编译,是一件很烦琐的事情,多人开发时,管理这个重新编译的框架,也是件令人头疼的事。这个不便让我没有去尝鲜.[/align][/size]
[size=medium][align=left] 也许有人纳闷,我们已经熟于web.xml配置,为什么要弄一个新的配置方法,还得去与之磨合,而且xml文件的易理解与通用性,方便了程序的部署用户修改参数。不试不知道,这个原因你试试后就自然明白了。[/align][/size]
[size=medium][align=left] 个人观点:首先,节省时间,提高效率。想想hibernate的hbm文件全部融合到实体类中时,我们不再需要时而看看.java文件,时而看看hbm文件。切换editor中的文件本来就是会浪费时间,有时大脑被别的东西打断时,还需要重新点回另一个文件去确保每一个mapping都正确;为了mapping正确,还需要从一个文件反复地切换到另一个文件来进行复制/粘贴,大大降低了开发效率。Spring framework的component-scan也做了同样的合二为一的效果。 那些@Component,@Controller, @Service, @Repository真的是大快人心。 再有就是方便用户的事情,我们完全可以做一个页面的安装程序,让部署用户去看xml文件本来就是一个没有很好UE的做法。[/align][/size]
[size=medium][align=left] 回到当前:这回spring 3.1的基于代码的web程序初始化,让我假想到了spring将那些@WebXXXXX注解加到了已有的类中,迫不及待地看了一下。结果假想是错误的。[/align][/size]
[size=medium][align=left] Well, 首先简要扫盲一下它的用法:[/align][/size]
[size=medium][align=left] 一句话:实现接口org.springframework.web.WebApplicationInitializer, 覆写public void onStartUp(ServletContext container)throw ServletException方法。
如下:[/align][/size]
public class MyWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
/*add self-defined servlet*/
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}

}

[size=medium][align=left] 这个只是简单替代了web.xml文件,并附加了一个简单的添加了servlet配置的示例。ServletContext还可以addFilter, addListener的 这两个方法的参数就是某个Filter,Listener的一个实例。
对比一下同样的代码在原来的web.xml中:[/align][/size]
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

[size=medium][align=left] 总之, web.xml里的配置全部都可以在这个onStartup方法里。你不用写任何配置,附有servlet3.0支持的服务器会自动找到这个MyWebAppInitializer的onStartup方法从而启动应用。Spring 将applicationContext.xml的spring配置也注解化了,就是说上面代码段的dispatcher-config.xml可以换为:[/align][/size]
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
container.addListener(new ContextLoaderListener(rootContext));



[size=medium][align=left]AppConfig是自定义的类,用@Configuration注解即可。[/align][/size]

[size=medium][align=left] 不过问题来了:这样的设置并没有做到合二为一,只不过是把web.xml文件换成是自定义类,我们还是需要确保所写的Listener/Servlet/Filter是否mapping正确到onStartup方法中。[/align][/size]

[size=medium][align=left] 其实充斥我脑海的疑问是,服务器到底是怎么找到onStartup方法的。没有任何注解。 Spring在玩儿魔术?再深度research一下,其实很简单。放在下一文章中吧。[/align][/size]

[size=medium][align=left] 经过research,合二为一的事情也很好解决:不用特意写WebApplicationInitialize的实现类,直接在你写的每个Listener/Filter/Servlet中实现该接口并覆写onStartup方法,每个onStartup方法中只向container中添加自身。[/align][/size]
[size=medium][align=left] 这是我想到的方法,没有尝试。读者们可以试一下,我确定行地通。因为我发现了spring的这个魔术,他们用了30行左右的有效代码,做了一个循环。并且这个短短30行说明这个魔术是我们都可以在10分钟内做到的,其实关键是servlet3.0的强大。我们没有去认真读过文档而已。[/align][/size]

[size=medium][align=left] 对于实用性,这篇文章足以解决了。代码均复制自spring api: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/中对WebApplicationInitializer的示例. 另外如果期望web.xml与基于代码的配置共存的话,需要将web.xml中版本配置到3.0以上,以下的web.xml都会被ignore掉.[/align][/size]

[size=small][align=left] 附:[color=blue]XmlWebApplicationContext[/color]和[color=blue]AnnotationConfigWebApplicationContext[/color]在包[color=indigo]org.springframework.web.support[/color]中
[color=blue]ContextLoaderListener[/color] 在[color=indigo]org.springframework.web[/color]中
其它未提及包名的类均是[color=indigo]javax.servlet[/color]中的[/align][/size]

[size=x-small][align=left]有兴趣的朋友可以读一下下一篇<< 究 Spring 3.1之无web.xml式 基于代码配置的servlet3.0应用>>[/align][/size]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值