首先是为什么整合strut2和spring?

spring和struts的结合点就在于struts的action不能直接注入service,都是通过自己来进行创建的;

struts2-spring-plugin,版本自由决定,如果因为版本不兼容的问题造成项目无法启动可以考虑使用最新版本的插件包,一般是向下进行兼容的;

  非注解的整合有两种方式:第一种是让spring管理控制器,第二种是自动装配;

1、让spring管理控制器

spring中bean的scope属性默认问sington(单例),必须修改为prototype;

示例:

1、通过maven的方式下载struts、spring以及插件包



<!-- spring所需jar包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- struts2所需jar包 -->
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>2.3.34</version>
        </dependency>
        <!-- struts2和spring整合所需jar包 -->
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-spring-plugin</artifactId>
            <version>2.5.14.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.9.1</version>
        </dependency>



2、在web.xml中配置spring的监听器和struts的过滤器



<!-- 指定spring配置文件的位置 -->
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:spring/applicationContext.xml</param-value>
  </context-param>
  <!-- spring启动 -->
  <listener>
      <listener-class>
          org.springframework.web.context.ContextLoaderListener
      </listener-class>
  </listener>
  <!-- 配置struts2过滤器 -->
  <filter>
      <filter-name>struts</filter-name>
      <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>



3、创建action



public class LoginAction {
    private LoginService loginService;
    public LoginService getLoginService() {
        return loginService;
    }
    public void setLoginService(LoginService loginService) {
        this.loginService = loginService;
    }
    public String execute(){
        loginService.sys();
        return "success";
    }
}



4、在applicationContext.xml中配置bean的创建



<!-- 创建一个service实例 -->
     <bean id="loginService" class="com.lcg.service.LoginService"></bean>
     <!-- 
         创建一个action实例,因为scope默认的为sington,此处需要修改为prototype
         为其注入service实例对象
     -->
     <bean id="loginAction" class="com.lcg.action.LoginAction"  scope="prototype">
         <property name="loginService" ref="loginService"></property>
     </bean>



5、在struts.xml中配置action的信息



<package name="basepkg" extends="struts-default" namespace="/">
    <!--class为spring创建的bean的ID属性的值-->
        <action name="login" class="loginAction" method="execute">
            <result name="success">/index.jsp</result>
            <result name="error">/login.jsp</result>
        </action>
    </package>



缺点:这种方式的缺点是必须把action配置在spring当中,而且在struts.xml中还要生成一个伪action,这样子会导致配置文件比较臃肿;

2、自动装配

  这种方式的基本流程是这样的,这种情况的整合,action的创建还是由struts2来进行创建,创建后对象会去spring容器中寻找它成员变量对应的bean,默认的自动装配的粗略是按照名称来进行匹配;

优缺点:

   优点:

    struts.xml文件是和未整合前是一致的,主要的变化是业务逻辑层的bean交由spring来进行管理;相对于第一种方式这种方式的好处就是简化配置文件;

   缺点:

    如果采用默认的自动装配策略,action中的成员变量名要和spring中的bean的id名保持一致,且,代码的可读性较差;

配置自动装配策略:

    spring插件的自动装配可以通过struts.objectFactory.spring.autoWire  该常量可以接收如下值:

         name:根据属性名自动装配

         type:根据类型进行自动装配,如果有多个类型相同的bean就会抛出一个致命的异常,如果没有匹配的bean则什么都不会发生,属性不会被设置;

         auto:spring插件会自动检测根据什么方式进行自动装配

         constructor:同type类似,区别是根据constructor使用构造器来构造注入所需的值;

示例:

struts.xml文件保持不变,增加装配类型,默认根据名称进行装配



<!-- 设置service的自动装配方式,默认为name,根据bean的id来进行装配 -->
    <constant name="struts.objectFactory.spring.autoWire" value="type"></constant>
    <package name="basepkg" extends="struts-default" namespace="/">
        <action name="login" class="com.lcg.action.LoginAction" method="execute" >
            <result name="success">/index.jsp</result>
            <result name="error">/login.jsp</result>
        </action>
    </package>



applicationContext.xml



<!-- 创建一个service实例 -->
     <bean id="loginService" class="com.lcg.service.LoginService"></bean>



action



private LoginService loginServices;
    public LoginService getLoginServices() {
        return loginServices;
    }
    public void setLoginServices(LoginService loginServices) {
        this.loginServices = loginServices;
    }
    public String execute(){
        loginServices.sys();
        return "success";
    }



3、使用注解的方式整合spring+struts2

第一步,开启spring注解扫描

spring 整合 struts2 spring+struts_web.xml

第二步,定义action,并通过注解进行配置

@Controller:定义一个控制器类

@parentPackage:定义action的父包,一般为struts-default

@NameSpace:定义命名空间

@Scope:定义作用域

@Action:定义action的访问路径,和结果

@Autowired:自动装配

spring 整合 struts2 spring+struts_struts_02