首先,我们要了解,web.xml中的各种元素在web容器中的加载顺序:listener(监听器)>filter(过滤器)>servlet.
在web.xml中配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
<filter-name>f</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>f</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
前面我们说到:listener的启动优先级要大于filter,因为spring和struts2结合时,spring作为一个管理和组装对象的角色,就必需优先加载,然后再生产对象后对struts2的action进行注入,所以,这就是我们一般用listener启动spring的原因。其实spring还可以交给struts2来启动,通过修改struts2org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter类的init方法,来产生spring的webApplicationContext对象,但这样spring就依赖于struts2了,这不是我们希望看到的。
对于<context-param>节点:
web容器为每个项目都会对应一个servletConfig对象,这个对象类似与项目中的Applcation对象,都是整个项目的全局对象,看源码会发现,spring通过listener加载时在ContextLoader中,将spring的webApplication对象放置到了servletConfig(实际是放到servletContext中,这里的servletContext代表的是全局的上下文)中,这样就可以在项目的任意能得到servletConfig对象的地方得到spring对象来读取spring的bean了。
而<context-param>节点就是用来为这个全局对象配置参数的,这样就可以在整个项目中都能使用,spring就是通过servletConfig来读取web.xml中的路径参数来过得beans.xml等一些spring的xml文件的。而
<param-value>classpath:beans.xml</param-value>
中,为什么这样写,是spring的规范,spring认为当得到classpath:这样的值时就认为这是一个文件,会在当前项目中寻找此文件并解析,当然,也可以给路径,例如:/WEB-INF/classes/beans.xml。
以上是web.xml的配置,配置完成后,接下来就是配置struts.xml,很简单,首先要在struts.xml中配置一个常量: <constant name="struts.objectFactory" value="spring" />.其实,在你导入了struts-spring-plugin-xx-xx.jar的包后,这个常量已经在这个包中设置好了,所以上面的常量配不配,都没有关系,这里,我们显式配置一下,当你没有导入spring的插件包,上面的常量值是 struts2本身的一个objectFactory的一个类。
配置Action时,很简单,只要将action的class替换为成在spring中的action类的id值就行了,因为,你的struts.objectFactory设置的时spring时,当你访问一个action时,spring会通过action对应的name找到class,再用这个class到spring中找到id为class的值的类,然后生产出action.
spring和struts2零配置整合(在这里,我用spring是xml方式,struts2用零配置方式):
零配置无非是将xml的配置方式,变成注解的方式,首先个人看法是,用注解维护起来没有xml方便,个人比较倾向与xml配置。
我们知道,用注解配置action 是:@Action(value="/action"),但将注解和spring联系起来,我们看文档知道,只需要@Action(value="/action" className="spring中的ID"),这样,当放问这个action时,struts2就向spring要action,spring则会通过这个className来匹配id,然后返回匹配的action类的实例。
经高人指导,还发现另一种配置方式:注解:@Action("/action"),action只需要这样注解就行了,在spring那边用这个action类的全名作为bean的id,我们知道,注解中,是不需要为action指定class这个属性的,其实并不代表这个属性不存在,这个属性的值就是@Action所在的类名,当访问没有设置className属性的action时,struts2找spring要Action,spring就通过这个action类的全名来匹配id的bean,所以,所以我们将这个bean的id设置为action的类名时,spring就能匹配到,这样的配置方式使得spring和struts2解藕度就很高。
例如:
action的代码:
public class MyLoginAction {
private LoginVo lv = new LoginVo();
private MyUserService mus;
@Action(value="/mylogin")
public String login(){
System.out.println(lv.getUpwd()+"====="+lv.getUname());
mus.findUserByUnameUpwd(lv.getUname(), lv.getUpwd());
return null;
}
public MyUserService getMus() {
return mus;
}
public void setMus(MyUserService mus) {
this.mus = mus;
}
public LoginVo getLv() {
return lv;
}
public void setLv(LoginVo lv) {
this.lv = lv;
}
}
spring的xml配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-lazy-init="false">
<bean id="mdao" class="org.xuliang.dao.MyUserDao">
</bean>
<bean id="mservice" class="org.xuliang.services.MyUserService">
<property name="mud" ref="mdao" />
</bean>
<bean id="org.xuliang.web.actions.MyLoginAction" class="org.xuliang.web.actions.MyLoginAction">
</bean>
</beans>