首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

struts2 详细配备

2012-08-21 
struts2 详细配置Struts2的配置文件是以XML的形式出现的。不过它的XML的语义比较简单,下面是我抽取了位于st

struts2 详细配置
Struts2的配置文件是以XML的形式出现的。不过它的XML的语义比较简单,下面是我抽取了位于struts2-core-2.0.14.jar内部的struts-default.xml的片段:

  Xml代码   

<struts>
    <bean name="xwork" />
    <bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" />

    <bean type="com.opensymphony.xwork2.ActionProxyFactory" name="xwork" name="struts" static="true" />
    <bean static="true" />
   
     <!-- 省略了其他的静态注入的定义 -->
 
    <package name="struts-default" abstract="true">
        <result-types>
            <result-type name="chain" default="true"/>
            <result-type name="redirect" name="xwork" /> <bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" />

这点没什么好说的,在struts.xml中,你可以为某个接口声明它所对应的实现类。

  name属性

  你可以声明多个实现类,使用name属性进行区分。在注入的时候,将使用这个属性的值作为接口实现类的选择。

  required属性

  你还可以通过required属性,来指定是否在运行时必不可少的注入。如果reqired被设置成false,那么当不存在相应的接口定义时,注入将被忽略。

  static属性

  在XML的定义中,还可以使用static属性。如果static属性被设置成true,那么注入将针对bean中的static方法和static属性进行。

  2. 在代码中使用Annotation进行注入

  Java代码 

@Inject("xwork")
protected ObjectFactory objectFactory;

public LightURLUnknownHandler(@Inject ObjectFactory objectFactory) {
    this.objectFactory = objectFactory;
}

@Inject
public void setObjectFactory(ObjectFactory factory) {
    this.objectFactory = factory;
}

@Inject(required=false)
public void setUnknownHandler(UnknownHandler handler) {
    this.unknownHandler = handler;
}  在代码中,使用@Inject这样一个Annotation进行对象依赖注入。在上面的例子中,我们可以看到,@Inject这个Annotation,可以作用在属性上,也可以作用在方法上,甚至可以作用在方法的参数上。

  在默认情况下,如果@Inject不指定value,那么XML配置定义中的name="default"或者name=""的实现类定义将被注入。

  那么,在struts-default.xml中,Struts2到底选择了那些实现类,作为Struts2或者XWork内部接口的默认实现类呢?默认情况下,struts-default.xml中定义的bean的name="struts"的将被作为默认的接口实现类被注入。这些默认行为,是由org.apache.struts2.config.BeanSelectionProvider所决定的,有兴趣的读者可以参阅这个类的源码。


3. 内部的Container机制完成一切背后工作

  上面看到的,是现象。在内部,Struts2通过一个Container来实现所有的注入机制。

  Java代码   

public interface Container extends Serializable {

  /**
   * Default dependency name.
   */
  String DEFAULT_NAME = "default";

  /**
   * Injects dependencies into the fields and methods of an existing object.
   */
  void inject(Object o);

  /**
   * Creates and injects a new instance of type {@code implementation}.
   */
  <T> T inject(Class<T> implementation);

  /**
   * Gets an instance of the given dependency which was declared in
   * {@link com.opensymphony.xwork2.inject.ContainerBuilder}.
   */
  <T> T getInstance(Class<T> type, String name);

  /**
   * Convenience method.&nbsp;Equivalent to {@code getInstance(type,
   * DEFAULT_NAME)}.
   */
  <T> T getInstance(Class<T> type);
 
  /**
   * Gets a set of all registered names for the given type
   * @param type The instance type
   * @return A set of registered names
   */
  Set<String> getInstanceNames(Class<?> type);

  /**
   * Sets the scope strategy for the current thread.
   */
  void setScopeStrategy(Scope.Strategy scopeStrategy);

  /**
   * Removes the scope strategy for the current thread.
   */
  void removeScopeStrategy();
}

在系统启动的时候,这个Container的实现类就会工作,把XML中定义的内容进行注入。有兴趣的读者可以继续探寻这个接口的实现类:com.opensymphony.xwork2.inject.ContainerImpl。

  静态变量(Constant)的注入

  @Inject这个Annotation不仅能够对接口的实现类进行注入,也能够对静态变量进行注入。

  有关静态变量的声明和注入,在我的另外一篇专栏文章中已经详细阐述:《深入plugin》 ——  http://www.iteye.com/wiki/struts2/1333-deep-into-plugin。在这里,我也就不详细介绍了。

  package节点详解

  package节点是整个配置的核心部分。每个package,从语义上讲,其实代表了每一个独立的模块。在这个模块中,你可以定义隶属于这个模块的行为方式,而与其他的模块没有关系。所以,每个package都有独立的interceptor、result-type和action的定义,绝大多数的Runtime配置定义都是通过package节点实现的。接下来我们就来详细讨论一下package中的属性和子节点。

  基本属性

  1. name

  name属性为每个package设置一个唯一的标识,这个标识在所有的package定义中不能重复。

  2. abstract

  标识这个package的定义是一个抽象定义,也就是允许他仅包含声明式的定义,而不需要在package定义中包含action的定义。

  3. extends

  通过使用extends,你可以指定本package继承另外一个package的所有的配置。当某个package继承了另外一个package的所有配置,那么你就无需对父package中已经声明过的配置定义做再次的定义。

  同时,如果重复定义父package中已声明过的配置定义,那么这些重复定义声明将覆盖父package中的相关定义。



4. namespace

  Struts2 Reference 写道

  The namespace attribute subdivides action configurations into logical modules, each with its own identifying prefix. Namespaces avoid conflicts between action names. Each namespace can have its own "menu" or "help" action, each with its own implementation.

  这段来自Struts2的Reference的引用,基本上阐明了namespace的作用:对于action配置进行逻辑划分。

  如果我们不为package节点指定namespace,Struts2默认使用一个空字符串作为默认的namespace。当然,也可以使用"/"等字符串来表示namespace。

  Struts2在根据URL进行寻址的时候,使用以下的步骤:

  1) 根据URL进行Namespace和ActionName的计算

  2) 根据计算的得到的Namespace和ActionName查找package节点中相应配置

  3) 如果查找失败,则查找Namespace为空,ActionName为整个URL的配置

  有关上述3点的详细信息,请参考Struts2的Reference:http://struts.apache.org/2.0.14/docs/namespace-configuration.html

  result-types节点

  在result-types节点中,我们可以声明在本package中所支持的Result类型。这些Result类型,将在action节点中被引用到。

  interceptors节点

  在interceptors节点中有两类节点:<interceptor>和<interceptor-stack>。这两个节点都用于声明拦截器。前者的作用,是真正定义一个拦截器。而后者则通过引用已经定义的拦截器,指定他们的执行顺序。

  当我们在试图在Action中引用拦截器时,我们实际上是为某个Action指定需要执行哪些拦截器,并且为这些拦截器指定执行顺序。所以Action所引用的,是某个<interceptor-stack>中的定义。

  缺省配置指向

  为了简化配置,我们可以在package节点中指定本package内的缺省配置指向。这可以通过<default-interceptor-ref>、<default-action-ref>、<global-results>等子节点来完成。

  action节点

  action节点是所有的Runtime配置的核心内容。它的主要作用就是指定URL与Action之间的映射关系。同时,在action节点中你也可以指定action执行时的相关配置,例如action所引用的interceptor等。

  参考文档

  上面所有的内容,实际上我只是做了一些简单的概括和归纳,至于每个节点语义和每个节点中具体属性的使用,我认为还是需要参考Struts2的Reference,因为Reference的讲解比任何教程都来的详细和正确,所以希望大家在了解了这些配置的基本分类之后,重新阅读Struts2的Reference的相关章节,从而更加深刻的理解Struts2配置文件的方方面面:http://struts.apache.org/2.0.14/docs/configuration-elements.html

热点排行