Struts2整合Spring从xml到注解

strutsspring整合首先要在Web容器启动的时候自动装配ApplicationContext的配置信息,可想而知应该在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>

配置了org.springframework.web.context.ContextLoaderListener后我们就不惜要编写代码显示地实例化ApplicationContext对象了。至于为什么要使用监听是因为web.xml 的加载顺序是:context-param -> listener -> filter -> servlet 。如果你是在不想使用监听,或许你可以尝试下继承struts2org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter重写这个它的init方法在StrutsPrepareAndExecuteFilter过滤器init中实例化ApplicationContext对象加载配置信息,虽然这种方法也可行,但是当拦截每个action都会加载一次配置信息,重新实例化了一个新的web容器,不仅浪费了资源也让spring更加依赖了struts

1、使用xml方式:

struts2配置:

<package name="user" extends="struts-default">
    <action name="login" class="userAction">
        <result name="success">/success.jsp</result>
        <result name="input" type="redirect">/index.jsp</result>
    </action>
</package>

spring配置:

<bean id="userDao" class="org.han.dao.impl.UserDaoImpl" />
<bean id="biz" class="org.han.service.impl.LoginBizImpl">
    <property name="userdao" ref="userDao"/>
</bean>
<bean id="userAction" class="org.han.action.LoginAction" scope="prototype" >
    <property name="biz" ref="biz" />
</bean>

注意,struts2action class与对应的action bean必须相同,这样才能由spring管理action;

2struts2使用零配置方式:

当你导入了零配置插件包的时候千万要注意约定大于配置,还是上面的spring配置,只是不需要struts2配置了。

第一种方式

只需要将ActionclassName对应到spring配置中的bean id就行了:

@Action(value = "/login", results = { @Result(name = "success", location = "/success.jsp"),@Result(name="input",location="/index.jsp")},className="userAction")
    public String login() throws Exception {
        User u=biz.login(this.getUser());
        if(u!=null){
            return SUCCESS;
        }
    return INPUT;
}
第二种方式:
Action注解不需要className了,将spring配置稍作修改
<bean id="org.han.action.LoginAction" class="org.han.action.LoginAction" scope="prototype" >
<property name="biz" ref="biz" />
</bean>

这样可以是因为当你使用零配置的时候,actionclass默认是当前类的全类名,所以和spring整合的时候刚好使用全类名在spring配置中查找以全类名为idbean

3struts2spring都使用注解方式:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:context="http://www.springframework.org/schema/context" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
         http://www.springframework.org/schema/context 
         http://www.springframework.org/schema/context/spring-context-3.0.xsd"> 
   <context:component-scan base-package="org.han.dao.impl,org.han.service.impl,org.han.action"/> 
</beans>

<context:component-scan base-package="***"/>用此种方式,不需要在配置文件中再配置bean,也不需要再导入上面对应的处理bean

也就是说可以不需要在配置文件中使用<context:annotation-config/>了,因为此种方式会自动导入

@Namespace("/") 
@Component(value="userLogin") 
@Scope(value="prototype") 
public class LoginAction extends ActionSupport { 
     public LoginAction() { 
        super(); 
        System.out.println("action:"+this.hashCode()); 
    } 
    @Autowired 
    private ILoginBiz biz; 
    private User user; 
 
    public User getUser() { 
        return user; 
    } 
 
    public void setUser(User user) { 
        this.user = user; 
    } 
    @Autowired 
    public void setBiz(ILoginBiz biz) { 
        this.biz = biz; 
    } 
 
    @Override 
    @Action(value = "hello", results = { @Result(name = "success", location = "/success.jsp"),@Result(name="input",location="/index.jsp")}) 
    public String execute() throws Exception { 
        System.out.println("biz:"+this.biz.hashCode()); 
        User u=biz.login(this.getUser()); 
        if(u!=null){ 
            return SUCCESS; 
        } 
        return INPUT; 
    } 
}
@Component   有一个可选的入参,用于指定 Bean 的名称。一般情况下, Bean 都是 singleton  的,需要注入  Bean  的地方仅需要通过  byType  策略就可以自动注入了,所以大可不必指定  Bean  的名称。

除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository@Service 和 @Controller

在目前的 Spring 版本中,这 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 个注释分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository@Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。@Scope用于定义Bean的作用范围。

@Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有 @Autowired 注释时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。所以对成员变量使用 @Autowired 后,您大可将它们的 setter 方法删除。

@Qualifier(name中的 name是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量、方法入参、构造函数入参。

@PostConstruct 和 @PreDestroy:JSR-250 为初始化之后/销毁之前方法的指定定义了两个注释类,这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。
通过 <bean> 元素的 init-method/destroy-method 属性进行配置,都只能为 Bean 指定一个初始化 销毁的方法。但是使用 @PostConstruct 和 @PreDestroy 注释却可以指定多个初始化 销毁方法,那些被标注 @PostConstruct @PreDestroy 注释的方法都会在初始化 销毁时被执行。
更多的关于注解使用:请看官方文档

4、总结:
1、注释配置不一定在先天上优于 XML 配置。如果 Bean 的依赖关系是固定的,(如 Service 使用了哪几个 DAO 类),这种配置信息不会在部署时发生调整,那么注释配置优于 XML 配置;反之如果这种依赖关系会在部署时发生调整,XML 配置显然又优于注释配置,因为注释是对 Java 源代码的调整,您需要重新改写源代码并重新编译才可以实施调整。
2、如果 Bean 不是自己编写的类(如 JdbcTemplateSessionFactoryBean 等),注释配置将无法实施,此时 XML 配置是唯一可用的方式。
3、注释配置往往是类级别的,而 XML 配置则可以表现得更加灵活。比如相比于 @Transaction 事务注释,使用 aop/tx 命名空间的事务配置更加灵活和简单。
所以在实现应用中,我们往往需要同时使用注释配置和 XML 配置,对于类级别且不会发生变动的配置可以优先考虑注释配置;而对于那些第三方类以及容易发生调整的配置则应优先考虑使用 XML 配置。Spring 会在具体实施 Bean 创建和 Bean 注入之前将这两种配置方式的元信息融合在一起。

你可能感兴趣的:(spring,xml,bean,struts,action,Autowired)