• struts2学习笔记之spring整合


    一、整合步骤:
    1 配置classpath,将struts-spring-plugin.jar和spring.jar添加进去
       如果少了spring.jar将报错,提示找不到相关类定义。

    2 在web.xml中配置spring

    <context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>classpath*:META-INF/spring/**/*-context.xml</param-value>
      </context-param>
      使用ContextLoaderListener
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListenre</listener-class>
      </listener>

       
    3  配置application-Context.xml 
      如:

        <bean id="userService" class="service.impl.UserServiceImpl">
           ...
        </bean>


    4 在struts的action类中使用service

      private UserService userService;
      public void setUserService(UserService userService){
         this.userService = userService;
      }


      通过以上方式,便可以直接在action中直接使用service进行逻辑处理。
      
    二、原理分析:
    1  spring的ApplicationContext的加载:
           加载方式通常有两种:
           A  通过ContextLoaderListener,如前面例子所示;但要求Web服务器支持servlet2.3以上的规范
           B  通过ContextLoaderServlet,不需要服务器支持servlet2.3以上规范:

              <context-param>... 配置spring配置文件位置,如上示例
              <servlet>
                 <servlet-name>context</servlet-name>
                 <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
                 <load-on-startup>1</load-on-startup>    
                <!--load-on-startup大于等于0时表示服务器启动时将实例化该servlet并调用init方法,数字表示优先级,越小则初始化的时机越先 -->
              </servlet>

              然而spring的加载时机在listener方式中是更靠前的。

        ContextLoaderListener与ContextLoaderServlet的实现原理是一样的,其都是通过ContextLoader来加载ApplicationContext:

           this.contextLoader = createContextLoader();
           this.contextLoader.initWebApplicationContext(event.getServletContext());


           而ContextLoader中加载spring配置的代码如下:

           this.context = createWebApplicationContext(servletContext, parent);
           servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);

           可以看到,loader对象将加载后的WebAppApplication对象放入了servletContext中(application级别的内存对象),以WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE为key来访问。

    2  struts2中如何与spring协作:
           struts2加载配置文件的顺序为 struts-default.xml/struts-plugin.xml/struts.xml,因此插件中的配置文件优先级比默认配置文件中要高;
           struts中的Action、Result、拦截器实例均通过以struts.objectFactory常量指定的实现类来创建,该类需要继承于com.opensymphony.xwork2.ObjectFactory
           查看struts-default.xml可以找到:

     <bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" />

          而struts.objectFactory的默认值便是struts,因此默认情况下struts使用org.apache.struts2.impl.StrutsObjectFactory来创建Action、拦截器等实例

          再看看struts-spring-plugin.jar中的xml配置:

          <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
            <!--  Make the Spring object factory the automatic default -->
            <constant name="struts.objectFactory" value="spring" />

           于是,在加载了spring插件之后,struts.objectFactory将采用org.apache.struts2.spring.StrutsSpringObjectFactory
           查看StrutsSpringObjectFactory的构造方法:  

    //获得原先加载的spring的context
               Object rootWebApplicationContext =  servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); 
                 ...
               ApplicationContext appContext = (ApplicationContext) rootWebApplicationContext;
               this.setApplicationContext(appContext);   //注入到当前实例

           该类继承了SpringObjectFactory,查看源码发现其创建bean的时候都使用了属于spring的名为autoWiringFactory的对象向bean注入了属性,正如上面看到的
           action中的setUserService被用于注入service;

          此外还需要考虑一个autowireStrategy参数,其指定了自动装配的策略(属于spring的范畴),默认是name即按名称注入。

         可以通过修改struts.objectFactory.spring.autoWire的常量值来改变autowireStrategy,可选的值包括:name/type(按类型)/auto(由spring自动检测)/constructor(构造器注入)


    三、 另一种整合方式
         此处介绍一下另外一种整合的方式:
         1  action类与开头例子一致;
         2  struts.xml中配置action的class属性值为spring配置文件中的bean名;
         3  spring配置对应名称的bean,class指向真实的action类,此时action更加直观的由spring管理,获得了更高的可配置性。

         查看SpringObjectFactory中的buildBean方法:

     //当spring的context中存在bean名的定义时,直接使用spring管理的方式来构造对象,否则走混合注入的方式(开头例子所采用,也是推荐使用的)
          if (appContext.containsBeanDefinition(beanName)) {
                o = appContext.getBean(beanName);
            } else {
                Class beanClazz = getClassInstance(beanName);
                o = buildBean(beanClazz, extraContext);
            }

       怎么样,一目了然了吧

      然而这样的方式在大多数情况下显得很臃肿:action需要配置多处;另外spring部分的配置稍显繁杂。因此一般不推荐该整合方式,这里仅仅是介绍罢了。
         
           
      
           




         


          

     
     

  • 相关阅读:
    oracle多个单引号的处理
    oracle 存储过程 动态sql语句
    Python内置方法的时间复杂度
    链表和数组的区别
    python enumerate用法总结
    Python 特殊语法:filter、map、reduce、lambda
    Pandas中DateFrame修改列名
    机器学习通用框架
    Python文件处理之文件写入方式与写缓存(三)
    转载: scikit-learn学习之回归分析
  • 原文地址:https://www.cnblogs.com/littleatp/p/4354498.html
Copyright © 2020-2023  润新知