上篇博客中说到了Spring的核心实现,这篇博客就是根据这些来说一下Spring对Struts1的集成。
来看一下Struts1的实现流程图:
在这没有Spring介入时,常见的Struts1的Action代码如下:
LoginActionForm laf=(LoginActionForm)form; String username=laf.getUsername(); String password=laf.getPassword(); UserManager userManager=new UserManager(); try { userManager.login(username, password); }和上篇说到的一样,这种通过new的方式,写的很“死”,Spring如何解决这个问题?
使用查找方式在Action中获取UserManager:
代码为:
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); UserManager userManager = (UserManager)factory.getBean("userManager");这种方法虽然解决了new的问题,也使用了查找的方式,但是很明显,Spring配置文件的读取与逻辑本身没有太大关联,需要分离出来。
将factory的生成放到容器启动时,web.xml配置文件:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>注意contextConfigLocation不能更改,获取所有Spring的配置文件,然后通过listener的方式,在容器启动时,即加载Spring配置文件,按照配置进行对象的依赖注入。
然后通过以下代码得到factory。
BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getSession().getServletContext());
但是仍然存在问题,无论如何都不能避免BeanFactory factory……,因为是主动查找,而非注入,即Struts仍然依赖Spring的API,如何解决?
以上问题出现的原因是Action并没有纳入Ioc容器,无法对其进行注入,所以想解决以上问题,务必要将Action纳入Spring管理中,新方案如下:
为此,需要将struts的配置文件修改为:
<action-mappings> <action path="/login" type="org.springframework.web.struts.DelegatingActionProxy" name="loginForm" scope="request" > <forward name="success" path="/login_success.jsp"/> </action> </action-mappings>
同时在Spring配置文件中添加:
<bean name="/login" class="com.tgb.usermgr.web.actions.LoginAction" scope="prototype"> <property name="userManager" ref="userManager"/> </bean> <bean id="userManager" class="com.tgb.usermgr.manager.UserManagerImpl"/>
此时流程变为:
说一下DelegatingActionProxy,这个类为代理类,它的作用是将请求转发给Spring下管理的Action,此时在LoginAction中,即可完成UserManagerImpl的注入。
Spring与Struts的集成,主要体现在代理类上面,通过代理类,将真正的Action纳入到IoC容器的管理,进而进行对象注入。