Seasar DI Container with AOP

S2Struts概要

使用S2Struts,可以容易地实现S2和Struts的连动。 因为在Action类中,service组件是自动地被设定的,所以Action类的作用仅仅是调用适当的service组件。 Action类自始自终被用作控制器,从而使得表现层和服务层(service)的角色分担也变得明确。 而且,对于Action可以实现AOP的应用。

安装

与S2同样,S2Struts也需要JDK1.4 或者 JDK1.5的系统环境。使用Eclipse3.1环境进行动作确认。

把S2StrutsVx.x.x.zip解压缩,将得到的s2struts目录作为一个完整的Java项目引入(import)Eclipse。 当Eclipse提示是否要覆写(overwrite).classpath时,选择 '全部「Yes」' ,引入所有的内容。 这样将生成一个与本资料中提示的完全相同的开发环境。

本案例以使用 TomcatTomcat Plugin为前提条件。 请预先安装好。

案例是用S2StrutsExampleVx.x.x.zip另外提供的,请下载并解压缩。使用Eclipse,以s2struts-example为名作成一个Java项目。 请注意这不是一个Tomcat项目。将解压缩得到的s2struts-example目录完全引入这个项目中。 当Eclipse提示是否要覆写.classpath时,选择 '全部「Yes」' ,引入所有的内容。 选中s2struts-example项目,单击右键,选择属性->Tomcat。选中Tomcat项目, 应用程序URI设定为/s2struts-example。然后重新启动Tomcat,从浏览器访问 http://localhost:8080/s2struts-example/ 可以看到使用S2Struts的案例。 不过如果要想看Employee Management案例的场合,请使用WEB-INF/bin目录下的runHsqldb.bat启动HSQLDB。

在S2StrutsBlankVx.x.x.zip里,含有为了使用S2Struts的所有必要的文件。 进一步而言,包括了在Mayaa,S2Dao等Web应用程序开发中用到的便利的文件。 作为开发Web应用程序的雏形利用的场合,请参照以下的文件一览表,删掉不需要的文件。

・使用S2Struts时的必要文件。
WEB-INF/
        struts-config.xml             
        tiles-defs.xml                
        validation.xml                
        validator-rules.xml           
        web.xml                       

WEB-INF/lib
        javassist-3.0.jar                 
        commons-logging-1.0.4.jar           
        log4j-1.2.8.jar               
        ognl-2.6.5.jar                
        aopalliance-1.0.jar               
        s2-framework-2.x.x.jar        
        
        commons-beanutils-1.7.0.jar         
        commons-digester-1.6.jar          
        commons-fileupload-1.0.jar        
        commons-validator-1.0.4.jar         
        oro-2.0.8.jar               
        struts-1.2.8.jar                    
        
        s2-struts-x.x.x.jar           

WEB-INF/src
        log4j.properties              
        application.properties        
        app.dicon                     
        s2struts.dicon                


・为使用S2扩张功能追加的文件。
WEB-INF/lib
        jta.jar                       
        junit-3.8.1.jar               
        poi-2.5-final-20040804.jar    
        s2-extension-2.x.x.jar

WEB-INF/src
        j2ee.dicon                    
        aop.dicon                     


・为使用Mayaa追加的文件。不用的话请删除。
WEB-INF/lib
        jaxen-1.1-beta-8.jar          
        nekohtml-0.9.5.jar            
        rhino-1.6r2.jar               
        xercesImpl-2.7.1.jar          
        xml-apis-1.3.jar              
        mayaa-x.x.x.jar                


・为使用S2Dao追加的文件。不用的话请删除。
WEB-INF/lib
        s2-dao-x.x.x.jar              

WEB-INF/src
        dao.dicon                     


・为使用HSQLDB追加的文件。不用的话请删除。
WEB-INF/lib
        hsqldb.jar                    

如果想用Tiger注释(annotation)的话,请把S2StrutsTigerVx.x.x.zip解压缩,得到s2struts-tiger目录。将此目录下的

  • lib/s2-struts-tiger-x.x.x.jar

复制到WEB-INF/lib目录下,并且在CLASSPATH中设定该路经。

如果想用backport175注释的话,请把S2StrutsBackport175Vx.x.x.zip解压缩,得到s2struts-backport175目录,将此目录下的

  • lib/s2-struts-backport175-x.x.x.jar
  • lib/backport175-1.0.jar

复制到WEB-INF/lib目录下,并且在CLASSPATH中设定该路经。

快速上手

让我们快点来试试看吧。

快速上手,以使用 TomcatTomcat Plugin为前提。 请预先安装好。

为了简单的利用S2Struts,我们使用S2StrutsBlankVx.x.x.zip。 把S2StrutsBlankVx.x.x.zip解压缩,得到s2struts-blank目录,作为Eclipse的一个Java项目而引入所有内容。 当Eclipse提示是否要覆写.classpath时,选择 '全部「Yes」' ,引入所有的内容。 选择s2struts-blank项目,点击右键,选择プロパティ->Tomcat。到此为止准备工作完毕。

首先做一个用于演示画面的HTML。在s2struts-blank目录下作成greetingInput.html、greeting.html。

greetingInput.html

指定时间带的画面。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=Windows-31j">
  <title>Greeting Demo</title>
</head>
<body>
  <form method="GET" action="greeting.html">
    <table>
      <tr>
        <th>time</th>
        <td>
          <select name="time">
            <option value="" selected>Please select</option>
            <option value="a.m.">a.m.</option>
            <option value="p.m.">p.m.</option>
          </select>
        </td>
      </tr>
    </table>
    <input type="submit" value="greeting">
  </form>
</body>
</html>

greeting.html

根据时间带显示不同问候语的画面。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=Windows-31j">
  <title>Greeting Demo</title>
</head>
<body>
  <table>
    <tr>
      <th>time</th>
      <td>a.m.</td>
    </tr>
    <tr>
      <th>greeting</th>
      <td>Good morning</td>
    </tr>
  </table>
  <a href="greetingInput.html">back</a>
</body>
</html>

浏览器上如果显示出greetingInput.html的话,就可以开始看应用程序的演出了。

你是否已想象得出要制作的是什么吗?

那么就开始制作吧。制作流程如下所示。

  • 作一个接口(interface)
  • 实装(implement)接口,作成组件
  • 连接组件

这次,我们用POJO作一个Action,并使用Mayaa生成view。 在S2Struts中,用POJO生成Action的场合,必须将接口(interface)和实装(implement)分开。 详细情况请参阅「POJO作为Action时的用法」

首先,定义GreetingInputInitAction、GreetingAction、GreetingService接口。 作为与画面的接口,还要生成一个作为ActionForm(DTO)的GreetingDto。

GreetingDto

我们将使用POJO的DTO作为ActionForm,。这一DTO将保持来自画面的项目信息内容。

package examples.dto;

public class GreetingDto {
    private String time = "";

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }
}

GreetingInputInitAction

这是为了显示greetingInput.html画面,提供必要信息的Action接口。

package examples.action;

public interface GreetingInputInitAction {
    String initialize();
}

GreetingAction

这是进行问候处理的的Action接口。

package examples.action;

public interface GreetingAction {
    String SUCCESS = "success";
    
    String goGreeting();
}

GreetingService

这个接口提供不依存于Struts等表现层framework的服务(service)

package examples.service;

import java.util.List;
import examples.dto.GreetingDto;

public interface GreetingService {
    List getTimeList();

    String getGreeting(GreetingDto dto);
}

到此为止,一系列的接口就作好了。下面,生成实装接口的组件。

GreetingInputInitActionImpl

setGreetingService是为了注入GreetingService的setter方法。 getTimeList是为了将信息传递给画面的getter方法。

package examples.action.impl;

import java.util.List;
import examples.action.GreetingInputInitAction;
import examples.service.GreetingService;

public class GreetingInputInitActionImpl implements GreetingInputInitAction {
    private GreetingService service;
    private List timeList;

    public String initialize() {
        timeList = service.getTimeList();
        return null;
    }
    
    public void setGreetingService(GreetingService service) {
        this.service = service;
    }

    public List getTimeList() {
        return timeList;
    }
}

GreetingActionImpl

setGreetingService是为了注入GreetingService的setter方法。 setGreetingDto是为了从画面接收ActionForm的setter方法,getGreetingDto是为了把ActionForm传递给画面的getter方法。 getGreeting是把信息传递给画面的fetter方法。

package examples.action.impl;

import examples.action.GreetingAction;
import examples.dto.GreetingDto;
import examples.service.GreetingService;

public class GreetingActionImpl implements GreetingAction {
    private GreetingService service;
    private GreetingDto greetingDto;
    private String greeting;

    public String goGreeting() {
        greeting = service.getGreeting(greetingDto);
        return SUCCESS;
    }

    public void setGreetingService(GreetingService service) {
        this.service = service;
    }

    public GreetingDto getGreetingDto() {
        return greetingDto;
    }

    public void setGreetingDto(GreetingDto greetingDto) {
        this.greetingDto = greetingDto;
    }

    public String getGreeting() {
        return greeting;
    }
}

GreetingServiceImpl

package examples.service.impl;

import java.util.ArrayList;
import java.util.List;
import examples.dto.GreetingDto;
import examples.service.GreetingService;

public class GreetingServiceImpl implements GreetingService {
    private static final String AM = "a.m.";
    private static final String PM = "p.m.";

    public List getTimeList() {
        List result = new ArrayList();
        result.add(AM);
        result.add(PM);
        return result;
    }

    public String getGreeting(GreetingDto dto) {
        if (AM.equals(dto.getTime())) {
            return "Good morning";
        }
        if (PM.equals(dto.getTime())) {
            return "Good evening";
        }
        return "";
    }
}

到此为止,所有的实装已完成,全部组件都准备好了。下一步是将所有的组件连起来。

greeting.dicon

为了把Action和Service连起来,在examples/dicon的目录下生成greeting.dicon。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
  "http://www.seasar.org/dtd/components21.dtd">
<components>
  <include path="aop.dicon"/>

  <component name="actionInterceptorChain"
      class="org.seasar.framework.aop.interceptors.InterceptorChain">
    <initMethod name="add"><arg>aop.traceInterceptor</arg></initMethod>
  </component>

  <component
    class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    <property name="autoNaming">
      <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    </property>
    <initMethod name="addClassPattern">
      <arg>"examples.service.impl"</arg>
      <arg>".*ServiceImpl"</arg>
    </initMethod>
  </component>
  
  <component
    class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    <property name="instanceDef">
      @org.seasar.framework.container.deployer.InstanceDefFactory@REQUEST
    </property>
    <property name="autoNaming">
      <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    </property>
    <initMethod name="addClassPattern">
      <arg>"examples.action.impl"</arg>
      <arg>".*ActionImpl"</arg>
    </initMethod>
  </component>
  <component class="org.seasar.framework.container.autoregister.AspectAutoRegister">
    <property name="interceptor">actionInterceptorChain</property>
    <initMethod name="addClassPattern">
      <arg>"examples.action.impl"</arg>
      <arg>".*ActionImpl"</arg>
    </initMethod>
  </component>

</components>

在app.dicon里追加include以便读取greeting.dicon。

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
  "http://www.seasar.org/dtd/components21.dtd">
<components>
  <include path="s2struts.dicon"/>
  <include path="examples/dicon/greeting.dicon"/>
</components>

今后,即使要追加新的Action,也无需修改greeting.dicon。因为可以利用由S2提供的组件自动登录功能。

最后,为了把画面和Action,ActionForm连接起来,我们将修改greetingInput.html、greeting.html,生成相应的mayaa文件。 关于Mayaa的详细情况,请参照「JavaServer Templates "Mayaa"」的章节。

greetingInput.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=Windows-31j">
  <title>Greeting Demo</title>
</head>
<body>
<div id="appBody">
  <form method="GET" action="greeting.html" id="appForm">
    <table>
      <tr>
        <th>time</th>
        <td>
          <select name="time" id="time">
            <option value="" selected>Please select</option>
            <option value="a.m.">a.m.</option>
            <option value="p.m.">p.m.</option>
          </select>
        </td>
      </tr>
    </table>
    <input type="submit" value="greeting" id="goGreeting">
  </form>
</div>
</body>
</html>

greetingInput.mayaa

我们使用S2Struts提供的init标签,调用GreetingInputInitAction#initialize()。 通过执行initialize(),得到显示画面所必需的timeList。

<?xml version="1.0" encoding="UTF-8"?>
<m:mayaa xmlns:m="http://mayaa.seasar.org"
        xmlns:html="http://struts.apache.org/tags-html"
        xmlns:bean="http://struts.apache.org/tags-bean"
        xmlns:s2struts="http://www.seasar.org/tags-s2struts"
        m:noCache="true">

    <m:with id="appBody" replace="false">
        <s2struts:init action="#{greetingInputInitAction.initialize}"/>
        <m:doBody />
    </m:with>

    <html:form m:id="appForm" action="/greeting" method="POST" />
    <html:select m:id="time" property="time">
        <html:option value="">Please select</html:option>
        <html:options name="timeList" />
    </html:select>
    <html:submit m:id="goGreeting" >greeting</html:submit>

</m:mayaa>

greeting.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=Windows-31j">
  <title>Greeting Demo</title>
</head>
<body>
<div id="appBody">
  <table>
    <tr>
      <th>time</th>
      <td><span id="time">a.m.</span></td>
    </tr>
    <tr>
      <th>greeting</th>
      <td><span id="greeting">Good morning</span></td>
    </tr>
  </table>
  <a href="greetingInput.html" id="goBack">back</a>
</div>
</body>
</html>

greeting.mayaa

<?xml version="1.0" encoding="UTF-8"?>
<m:mayaa xmlns:m="http://mayaa.seasar.org"
        xmlns:html="http://struts.apache.org/tags-html"
        xmlns:bean="http://struts.apache.org/tags-bean"
        xmlns:s2struts="http://www.seasar.org/tags-s2struts"
        m:noCache="true">

    <m:ignore id="appBody" />

    <bean:write m:id="time" name="greetingDto" property="time" />
    <bean:write m:id="greeting" name="greeting" />
    <html:link m:id="goBack" page="/greetingInput.html">back</html:link>

</m:mayaa>

到此为止,处理流程就结束了。

重新启动Tomcat, 请从浏览器访问http://localhost:8080/s2struts-blank/greetingInput.html确认动作是否正常。

虽然没有编辑struts-config.xml,但是系统动作是正常的。 之所以如此是因为,执行时S2Struts遵循规约,生成了struts-config信息。 在生成GreetingDto和GreetingAction的同时,也就等于完成了以下的struts-config配置。

...
<form-beans>
    ...
    <form-bean
        name="greetingDto"
        type="examples.dto.GreetingDto" />
    ...
</form-beans>
...
<action-mappings>
    ...
    <action
        path="/greeting"
        type="examples.action.GreetingAction"
        name="greetingDto"
        scope="request"
        validate="true">
        <forward name="success" path="/greeting.html" />
    </action>
    ...
</action-mappings>
...

这次因为遵循规约所以不需要设定,不过也有不遵守规约的场合。 这种场合,可以使用注释直接指定。 关于规约和注释请参照「无设定S2Struts」的章节。

S2Struts的世界如何? POJO的Action看起来是不是很容易测试呢? 从此我们不用再为随着应用规模的增大而不断增大的struts-config.xml文件而烦恼了。 如果想更详细地了解S2Struts的场合,请参照以下的指南。

S2Struts指南

基本用法

首先,为了起动S2Container,在web.xml里要对S2ContainerServlet进行登录。 并请像下面这样设定S2ContainerFilter和S2StrutsFilter。

其次,如果是代替org.apache.struts.action.ActionServlet,请对org.seasar.struts.servlet.S2ActionServlet进行登录, 如果是代替org.apache.struts.actions.RedeployableActionServlet,请对org.seasar.struts.servlet.S2RedeployableActionServlet进行登录。

web.xml

<web-app>
  <display-name>Struts Application</display-name>

  <filter>
    <filter-name>s2filter</filter-name>
    <filter-class>
      org.seasar.framework.container.filter.S2ContainerFilter
    </filter-class>
  </filter>

  <filter>
    <filter-name>s2strutsfilter</filter-name>
    <filter-class>org.seasar.struts.filter.S2StrutsFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>s2filter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <filter-mapping>
    <filter-name>s2strutsfilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <servlet>
    <servlet-name>s2container</servlet-name>
    <servlet-class>
      org.seasar.framework.container.servlet.S2ContainerServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <!-- Standard Action Servlet Configuration (with debugging) -->
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.seasar.struts.servlet.S2ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>debug</param-name>
      <param-value>2</param-value>
    </init-param>
    <init-param>
      <param-name>detail</param-name>
      <param-value>2</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>s2container</servlet-name>
    <url-pattern>/s2container</url-pattern>
  </servlet-mapping>

  <!-- Standard Action Servlet Mapping -->
  <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <!-- The Usual Welcome File List -->
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>

为了使S2和Struts连动,必须在struts-config.xml里,对S2用的RequestProcessor进行登录。 我们提供了S2RequestProcessor和S2TilesRequestProcessor。 它们分别对应于Struts的RequestProcessor和TilesRequestProcessor。

struts-config.xml

<struts-config>
  ...
  <controller processorClass="org.seasar.struts.processor.S2RequestProcessor"/>
  ...
</struts-config>

希望连动的Action类必须在组件定义中登录。 Action类也可以个别的进行登录,不过个别登录的话,在追加Action类的时候,必须修改组件定义文件。 为了回避这一问题,推荐使用组件的自动登录功能。

Multiply.dicon

<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
  "http://www.seasar.org/dtd/components21.dtd">
<components>
  <component name="traceInterceptor"
      class="org.seasar.framework.aop.interceptors.TraceInterceptor"/>

  <component
      class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    <property name="autoNaming">
      <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    </property>
    <initMethod name="addClassPattern">
      <arg>"org.seasar.struts.examples.multiply"</arg>
      <arg>".*ServiceImpl"</arg>
    </initMethod>
  </component>
  
  <component
      class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    <property name="instanceDef">
      @org.seasar.framework.container.deployer.InstanceDefFactory@REQUEST
    </property>
    <property name="autoNaming">
      <component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    </property>
    <initMethod name="addClassPattern">
      <arg>"org.seasar.struts.examples.multiply"</arg>
      <arg>".*Action"</arg>
    </initMethod>
  </component>
  <component class="org.seasar.framework.container.autoregister.AspectAutoRegister">
    <property name="interceptor">traceInterceptor</property>
    <initMethod name="addClassPattern">
      <arg>"org.seasar.struts.examples.multiply"</arg>
      <arg>".*Action"</arg>
    </initMethod>
  </component>
</components>

并且这一组件定义文件必须在全体应用程序的定义app.dicon中进行登录。

app.dicon

<components>
  ...
  <include path="org/seasar/struts/examples/dicon/Multiply.dicon"/>
  ...
</components>

到此为止,由RequestProcessor生成的所有Action类才和S2形成了连动。

如果事先对接口定义setter方法, 将会自动地进行settert・注入。 还有,只有接口定义了有参数的Constructor的场合,会自动进行 Constructor・注入

为了取得service组件,Action类要事先定义Constructor或者是setter方法。 execute()方法,由于只是将处理委托给service,所以源程序看起来非常简洁。

MultiplyAction

package org.seasar.struts.examples.multiply;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.seasar.struts.examples.form.CalculationForm;

public class MultiplyAction extends Action {

    private MultiplyService multiplyService_;

    public MultiplyAction(MultiplyService multiplyService) {
        multiplyService_ = multiplyService;
    }

    public ActionForward execute(
            ActionMapping mapping,
            ActionForm form,
            HttpServletRequest request,
            HttpServletResponse response) {

        CalculationForm calForm = (CalculationForm) form;
        int result = multiplyService_.multiply(calForm.getArg1(), calForm.getArg2());
        calForm.setResult(result);
        return (mapping.findForward("success"));
    }
}

POJO作为Action时的用法

我们可以把没有继承org.apache.struts.action.Action的POJO作为Action使用。

向下面这样,生成接口和实装类,在组件定义文件中定义实装类。 Action方法返回一个String类型的forward名。 并且在struts-config里,在action标签的type属性中指定接口名。

EchoAction

public interface EchoAction {
	String echo();
}

EchoActionImpl

public class EchoActionImpl implements EchoAction {
    private StringForm strForm;
    
    public EchoActionImpl() {
    }

    public String echo() {
        strForm.setResult(strForm.getInput());
        
        return FowardNameConstants.SUCCESS;
    }

    public StringForm getStrForm() {
        return strForm;
    }
    public void setStrForm(StringForm strForm) {
        this.strForm = strForm;
    }
}

POJO的Action类中,如果是有setter方法的场合,HttpServletRequest或者HttpSession的值会被自动绑定。
参照时的优先顺序如下所示。
(1)HttpServletRequest#getParameter(属性名)
(2)HttpServletRequest#getAttribute(属性名)
(3)HttpSession#getAttribute(属性名)

1.3.0-RC3以后,优先顺序发生了变化,如下所示(第一和第二的优先顺序互换)。
(1)HttpServletRequest#getAttribute(属性名)
(2)HttpServletRequest#getParameter(属性名)
(3)HttpSession#getAttribute(属性名)

还有,如果接收的参数带有[],类似于foo[0]=fooVal0,foo[1]=fooVal1的参数的场合, 第一参数类型为int,第二参数为含有index值的setter方法会成为自动绑定的对象。如下所示。

setFoo(int index, Object value);

getter方法的场合也是同样的,HttpServletRequest或者HttpSession会自动地被绑定到一个值。
(1)缺省时执行HttpServletRequest#setAttribute(属性名,属性值)。
(2)如果想执行HttpSession#setAttribute(属性名,属性值)的场合,必须在Action类中声明常量注释,如下所示。

public final static String 属性名_EXPORT = org.seasar.struts.Constants.SESSION;

我们也可以使用注释。如果使用注释的话,如下所示,对getter方法指定注释。

@ExportToSession()
public String getFoo() {
    return foo;
}
也可以象下面这样,使用backport175注释。
/**
 * @org.seasar.struts.annotation.backport175.ExportToSession()
 */
public String getFoo() {
    return foo;
}

Echo.dicon

<components>
	<component class="org.seasar.struts.examples.echo.EchoActionImpl" instance="request"/>
</components>

struts-config.xml

<struts-config>
  ...
  <action-mappings>
    ...
    <action
      path="/echo"
      type="org.seasar.struts.examples.echo.EchoAction"
      name="strForm"
      scope="request"
      validate="false"
      input="/pages/echoInput.jsp">
      <forward name="success" path="/pages/strResult.jsp" />
    </action>
    ...
  <action-mappings>
  ...
</struts-config>

通过在web.xml中事先登录S2ContainerFilter,实装类的属性会自动地被绑定到request或session以及Action。 至于request和session之中的哪一个会被绑定,将根据组件定义文件中的instance属性决定的。关于ActionForm,则是由 struts-config.xml中定义的scope属性决定的。

还有,接口中有复数方法存在的场合,则与使用org.apache.struts.actions.DispatchAction的场合同样, 在struts-config.xml的action标签里,追加parameter属性,对于JSP的submit按钮,通过name属性和value属性这2个属性指定方法。

ChangeCaseAction

public interface ChangeCaseAction {
    String toLowerCase();

    String toUpperCase();
}

struts-config.xml

<struts-config>
  ...
  <action-mappings>
    ...
    <action
      path="/changeCase"
      type="org.seasar.struts.examples.changecase.ChangeCaseAction"
      name="strForm"
      scope="request"
      validate="true"
      parameter="command"
      input="/pages/changeCaseInput.jsp">
      <forward name="success" path="/pages/strResult.jsp" />
    </action>
    ...
  <action-mappings>
  ...
</struts-config>

changeCaseInput.jsp

...
<html:submit property="command"><bean:message key="toLowerCase"/></html:submit>
<p>
<html:submit property="command"><bean:message key="toUpperCase"/></html:submit>
...

变换成HTML,如下所示。

<input type="submit" name="command" value="toLowerCase">
<p>
<input type="submit" name="command" value="toUpperCase">

ProxyAction类的用法

使用ProxyAction类,可以调用在组件定义文件中的Action,也可以进行委托处理。 这种情况下,struts-config和组件定义文件无需对同一类名进行定义/同期。 在struts-config的action的path属性和组件定义文件中定义的component的name属性必须一致。 详细情况请参照「关于path属性和Action类的映射」的章节。

如果只有ProxyAction类,那么在struts-config里,即使不登录S2用的RequestProcessor,也可以和S2连动。 但是,如果希望其他的Action类也和S2连动的场合,则如前所述,必须在struts-config.xml里登录S2用的RequestProcessor。 也即,为了和S2连动,只有特定的Action类是有效的。

struts-config.xml

<struts-config>
  ...
  <action-mappings>
    ...
    <action
      path="/subtract"
      type="org.seasar.struts.action.ProxyAction"
      name="calcForm"
      scope="request"
      validate="false"
      input="/pages/subtractInput.jsp">
      <forward name="success" path="/pages/result.jsp" />
    </action>
    ...
  <action-mappings>
  ...
</struts-config>

Subtract.dicon

<components>
  <component name="/subtract" class="org.seasar.struts.examples.SubtractAction"/>
  <component class="org.seasar.struts.examples.SubtractServiceImpl"/>
</components>

在struts-config的action中,不使用type属性指定一个Action类

和ProxyAction类的用法同样,只要struts-config的action的path属性和 组件定义文件中定义的component的name属性相一致,那么不使用type属性,也可以调用Action类。 详细情况请参照「关于path属性和Action类的映射」的章节。 利用这一手法是有条件的。也即,调用时不存在type属性,forward属性,include属性这3个属性。 这种情况下,struts-config和组件定义文件无需对同一个类名进行定义/同期。

struts-config.xml

<struts-config>
  ...
  <action-mappings>
    ...
    <action
      path="/divide"
      name="calcForm"
      scope="request"
      validate="false"
      input="/pages/divideInput.jsp">
      <forward name="success" path="/pages/result.jsp" />
    </action>
    ...
  <action-mappings>
  ...
</struts-config>

Divide.dicon

<components>
  <component name="/divide" class="org.seasar.struts.examples.DivideAction"/>
  <component class="org.seasar.struts.examples.DivideServiceImpl"/>
</components>

关于path属性和Action类的映射

在此,我们对前面提到的,「ProxyAction类的用法」「在struts-config的action中,不使用type属性指定一个Action类」里, 关于path属性和Action类的映射关系,做一详细介绍。

假定存在以下的web.xml,struts-config,还有组件定义文件。

web.xml

<web-app>
  ...
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
      <param-name>config</param-name>
      <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
      <param-name>config/foo</param-name>
      <param-value>/WEB-INF/struts-config-foo.xml</param-value>
    </init-param>
    ...
  </servlet>
  ...
</web-app>

struts-config.xml

<struts-config>
  ...
  <action-mappings>
    ...
    <action path="/bar"
      ...
    </action>
    ...
  <action-mappings>
  ...
</struts-config>

struts-config-foo.xml

<struts-config>
  ...
  <action-mappings>
    ...
    <action path="/baz"
      ...
    </action>
    ...
  <action-mappings>
  ...
</struts-config>

组件定义文件

<components>
  <component name="/bar" class="BarAction"/>
  <component name="/foo/baz" class="BazAction"/>
</components>

如果是缺省的模块module(用struts-config.xml动作的模块),将在struts-config的action标签的path属性和 组件定义文件中定义的component标签的name属性之间进行映射。映射方式为下记的子模块(subModule)中的(2)的模式(pattern)。

如果是子模块(此例中,用struts-config-foo.xml动作的模块),映射方式则有2种。

    (1)模块(prefix)名(/foo)+path属性(/baz)=name属性(/foo/baz
    (2)path属性(/baz)=name属性(/baz
取得组件的优先顺序为(1)、(2)的顺序。也即,如果没有找到名字为/foo/baz的组件,那么就取得名字为/baz的组件。

还有,作成org.seasar.struts.ComponentNameCreator的实装类,经由app.dicon登录,可以替换上述的缺省映射方式。

用法提示

优点・缺点


优点 缺点
POJOAction(推荐) 提高了可测试性
Action类的模块切换很容易
向S2JSF等的移植很容易
接口定义文件有可能增加 (不过,The Seasar Foundation认为,对外接口越明确,说明可维护性越好)
Multiply的例子 现有的Action,struts-config的action-mapping无需修改即可使用

Subtract(ProxyAction)的例子 为了从ActionMapping的信息(缺省为路径名)检索组件, 无需对struts-config和组件定义文件里记载的Action的类名进行同期
有着继承关系的Action类可以登录到container中
必须对ActionMapping的信息和组件名进行同期
Divide的例子 同上。在struts-config里,不必使用type属性(Action的类名),减少了设定内容 同上。但是,从Struts而言,由于是非正规的struts-config的定义方法,有可能无法取得与定义struts-config的工具之间的协调关系

如果没有特别的理由,推荐使用POJOAction。

从组件得到RequestProcessor

正如可以对Action类实施共通的aspect一样,可以从组件取得RequestProcessor。 并且,除了实施aspect之外,也可以实施与其他的组件同样的用法。

首先,必须在web.xml里登录S2ActionServlet。 在web.xml里定义的servlet并非是org.apache.struts.action.ActionServlet,而是 org.seasar.struts.action.S2ActionServlet或者是org.seasar.struts.action.S2RedeployableActionServlet。 (S2ActionServlet继承的是ActionServlet,S2RedeployableActionServlet继承的是RedeployableActionServlet。)

web.xml

<web-app>
  ...
  <!-- Standard Action Servlet Configuration (with debugging) -->
  <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.seasar.struts.action.S2ActionServlet</servlet-class>
    ...
  </servlet>
  ...
</web-app>

这次的案例,是对S2RequestProcessor实施被称为MeasureTimeInterceptor的aspect, 能够测出各请求(request)的处理时间,并输出到stdout。

RequestProcessor.dicon

<components>
  <include path="s2struts.dicon"/>
  <component class="org.seasar.struts.S2RequestProcessor">
    <aspect pointcut="process">
      <component class="org.seasar.struts.examples.MeasureTimeInterceptor">
    </aspect>
  </component>
</components>

从任意的组件管理错误信息的显示

使用org.seasar.struts.action.MessageManager类,可以从任意的组件管理错误信息的显示。

MessageActionImpl.java

public class MessageActionImpl implements MessageAction {

    public String execute() {
        MessageManager.addGlobalError("examplemessage");
        MessageManager.addGlobalError("examplemessage", "foo");
        MessageManager.addGlobalError("examplemessage", "bar", "baz", "qux");
        MessageManager.addError("property", "examplemessage");
        MessageManager.addError("property", "examplemessage", "foo");
        MessageManager.addError("property", "examplemessage", "bar", "baz", "qux");
        MessageManager.saveErrors();

        return FowardNameConstants.SUCCESS;
    }

}

这与Struts的Action类实装的代码几乎完全相同。

  ActionMessages errors = new ActionMessages();
  errors.add(ActionErrors.GLOBAL_MESSAGE,new ActionMessage("examplemessage"));
  errors.add(ActionErrors.GLOBAL_MESSAGE,new ActionMessage("examplemessage", "foo"));
  errors.add(ActionErrors.GLOBAL_MESSAGE,new ActionMessage("examplemessage", "bar", "baz", "qux"));
  errors.add("property",new ActionMessage("examplemessage"));
  errors.add("property",new ActionMessage("examplemessage", "foo"));
  errors.add("property",new ActionMessage("examplemessage", "bar", "baz", "qux"));
  if(!errors.isEmpty()) {
      saveErrors(request,errors);
  }

说二者"几乎"相同,是因为上述利用资源(resource)中的关键字examplemessage里,在包含{4}的场合,其删除功能,在MessageManager里也具备。

并且,MessageManager还具有管理信息用的addGlobalMessage(),addMessage()方法和saveMessages()方法。其参数与处理错误信息的场合相同。

无设定S2Struts指南

一旦使用S2Struts,只要遵循规约就可以对struts-config实现自动补齐功能(无设定S2Struts)。 使用注释指定struts-config,也有可能实现补齐功能。 由此,通过struts-config而省略设定成为可能。

无设定S2Struts

为了利用无设定S2Struts的功能,必须在struts-config里登录AutoStrutsConfigRegisterPlugIn。 在PlugIn里因为有读取的先后顺序,所以请在ValidatorPlugIn之后再进行登录。

struts-config.xml

<struts-config>
  ...
  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    ...
  </plug-in>
    
  <plug-in className="org.seasar.struts.plugin.AutoStrutsConfigRegisterPlugIn">
    <set-property property="enableJar" value="false"/>
    <set-property property="jarFilePattern" value="^My.*\.jar$"/>
    <set-property property="actionClassPattern" value="foo.bar.action.*Action"/>
    <set-property property="formClassPattern" value="foo.bar.form.*Form"/>
    <set-property property="docRoot" value="/WEB-INF/jsp"/>
    <set-property property="viewExtension" value="jsp,html,view"/>
  </plug-in>
  ...
</struts-config>

插件(plugin)的属性里可以进行值的设定。各属性的说明如下所示。各属性的定义省略时将使用缺省值。

属性 说明 缺省值
enableJar 在检索无设定S2Struts里包含的类时,指定是否要检索classpath中包含的jar文件。检索的话,值为true。 false
jarFilePattern enableJar的值为true时,指定检索对象jar文件的文件名类型。
(什么样的jar文件都是非检索对象)
referenceClass 检索指定的类所在的目录或者是以jar文件为基点的自动登录类。
actionClassPattern 在无设定S2Struts中,指定Action类名的类型以便特定action标签的值。 .*Action$
formClassPattern 在无设定S2Struts中,指定ActionForm类名的类型以便特定form-bean标签的值。 (.*Form$)|(.*Dto$)
docRoot 指定View模板文件的储存位置的首目录。
viewExtension 指定View模板文件的扩张子。 jsp,html

在无设定S2Struts中,省略可能的值将成为form-bean标签的属性,或者是action标签和该action标签内的forward标签的属性。 缺省时遵循提供的规约的场合,各属性值如下所示。

form-bean标签的属性值

以"Form"或者是"Dto"结尾的类为基准补齐设定。

属性 缺省值规约定义的值
type 类名
name 从类名检索在S2中的登录的组件,使用组件名。
restricted false

action标签的属性值

以"Action"结尾的类为基准补齐设定。

属性 缺省值规约定义的值
type 类名
path 从类名检索在S2中登录的组件。
如果组件名以"/"开始的话使用该组件名。
不是以"/"开始的话在先头加上"/", 结尾如果是以下的值就将其删除。这些值是,"ActionImpl","Impl","Action"共3个。
没找到组件名的话,将类名的开头设定为小写文字得到的值作为组件名做如上设定。
name 删除path属性的先头的"/"的值。
scope request
validate true
input 无设定(null)
parameter 无设定(null)
attribute 无设定(null)
forward 无设定(null)
include 无设定(null)
prefix 无设定(null)
suffix 无设定(null)
unknown 无设定(false)
roles 无设定(null)
cancellable false

action标签内的forward标签的属性値

以"Action"结尾的类为基准补齐设定。
属性 缺省值规约定义的值
name success(不可变更)
path 请按以下说明的顺序设定path。
1.把包(package)名的"."更改为"/",,用该值与类名相连结(Action名的连结)。
2.类名的最后如果是以下的值删除。这些值是,"ActionImpl","Impl","Action"共3个。连结时类名的先头设为小写文字。
3.在AutoStrutsConfigRegisterPlugIn的docRoot里指定的值附加在path的先头。
4.检索以".html"和".jsp"为扩张子的文件,如果文件存在设定到path中。
5.没找到文件的场合,将package中直到第2个"/"之前的文字列全部删掉,再返回步骤"4"进行操作。
6.如果到最后还没有找到的话,不再进行设定而是输出到log。


类:aaa.bbb.ccc.HogeAction
AutoStrutsConfigRegisterPlugIn的docRoot:/jsp
的场合,在path里设定的文字检索顺序为
1)/jsp/aaa/bbb/ccc/hoge.jsp
2)/jsp/bbb/ccc/hoge.jsp
3)/jsp/ccc/hoge.jsp
4)/jsp/hoge.jsp
如上述步骤操作。
redirect 不设定(false)

使用注释的struts-configの設定

使用Tiger注释的定义方法和使用backport175注释的定义方法都可以使用。但是不能同时使用这2种注释。 使用这两种注释时,分别需要有下表中的jar文件。

Annotation必要的jar文件(x.x.x表示版本)
Tigers2-struts-tiger-x.x.x.jar
backport175s2-struts-backport175-x.x.x.jar

如下所示,在Action里通过定义注释可以对struts-config进行设定。

package org.seasar.struts.examples.employee.action;

import org.seasar.struts.annotation.tiger.StrutsAction;
import org.seasar.struts.annotation.tiger.StrutsActionForward;

@StrutsAction(name="employeeForm", validate=false)
public interface EmployeeEditAction {

	@StrutsActionForward(path="/pages/employee/employeeEdit.jsp")
	public String SUCCESS = "success";

	public String execute();

}
使用backport175注释时的定义如下所示。
package org.seasar.struts.examples.employee.action;

/**
 * @org.seasar.struts.annotation.backport175.StrutsAction(
 *   name="employeeForm", validate=false)
 */
public interface EmployeeEditAction {

	/**
	 * @org.seasar.struts.annotation.backport175.StrutsActionForward(
	 *         path="/pages/employee/employeeEdit.jsp")
	 */
	public String SUCCESS = "success";

	public String execute();

}
使用常量注释时的定义如下所示。
package org.seasar.struts.examples.employee.action;

public interface EmployeeEditAction {

	public static final String ACTION = "name=employeeForm, validate=false";

	public static final String SUCCESS_FORWARD = "path=/pages/employee/employeeEdit.jsp";

	public String SUCCESS = "success";

	public String execute();

}
这与以下的定义具有相同的效果。
...
<action-mappings>
    ...
    <action
        path="/employeeEdit"
        type="org.seasar.struts.examples.employee.action.EmployeeEditAction"
        name="employeeForm"
        scope="request"
        validate="true">
        <forward name="success" path="/pages/employee/employeeEdit.jsp" />
    </action>
    ...

用StrutsAction(ACTION)可能指定的属性

属性必须
path
×
name
×
scope
×
validate
×
input
×
parameter
×
attribute
×
forward
×
include
×
prefix
×
suffix
×
unknown
×
roles
×
cancellable
×
注释与struts-config的action标签的属性为1对。并且,各属性的缺省值,为无设定S2Struts中定义的值。

用StrutsActionForward(FORWARD)可能指定的属性

属性必须缺省值
path
-
redirect
×
false
注释与struts-config的forward标签的属性为1对。用常量值指定name属性。

并且如下所示,在Form(DTO)里通过定义注释可以对struts-config进行设定。

package org.seasar.struts.examples.employee.dto;

import org.seasar.struts.annotation.tiger.StrutsActionForm;

@StrutsActionForm(name="employeeForm")
public class EmployeeDto extends Employee {
	...
}
使用backport175注释的定义如下所示。
package org.seasar.struts.examples.employee.dto;

/**
 * @org.seasar.struts.annotation.backport175.StrutsActionForm(name="employeeForm")
 */
public class EmployeeDto extends Employee {
	...
}
常量注释的定义如下所示。
package org.seasar.struts.examples.employee.dto;

public class EmployeeDto extends Employee {

	public static final String FORM = "name=employeeForm";
	...
}
这些和以下的定义具有相同效果。
...
<form-beans>
    ...
    <form-bean
        name="employeeForm"
        type="org.seasar.struts.examples.employee.dto.EmployeeDto" />
    ...

用StrutsActionForm(FORM)可能指定的属性

属性必须
name
×
restricted
×
注释与struts-config的form-bean标签的属性为1对。并且,各属性的缺省值,是无设定S2Struts中定义的值。

使用注释的validationの設定

如下所示,在ActionForm的setter方法中,通过定义注释可以对validation进行设定。

public class ValidateDto implements Serializable {

    private String value;

    @ValidateOrder(1)
    @Required
    @Minlength(10)
    @Maxlength(15)
    @Mask(pattern="com$",messageKey="mustendcom")
    @EmailType
    @Args(keys="mixValue",resource=false)
    public void setValue(String value) {
        this.value = value;
    }
使用backport175注释的定义,如下所示。
public class ValidateDto implements Serializable {

    private String value;

    /**
     * @org.seasar.struts.validator.annotation.backport175.ValidateOrder(1)
     * @org.seasar.struts.validator.annotation.backport175.Required
     * @org.seasar.struts.validator.annotation.backport175.Minlength(value=10)
     * @org.seasar.struts.validator.annotation.backport175.Maxlength(value=15)
     * @org.seasar.struts.validator.annotation.backport175.Mask(
     *    pattern="com$",messageKey="mustendcom")
     * @org.seasar.struts.validator.annotation.backport175.Email
     * @org.seasar.struts.validator.annotation.backport175.Args(
     *    keys="mixValue",resource=false)
     */
    public void setValue(String value) {
        this.value = value;
    }
}
使用常量注释的定义如下所示。
public class ValidateDto implements Serializable {

    private String value;

    public static final int value_VALIDATOR_ORDER = 1;
    public static final String value_VALIDATOR = "required";
    public static final String value_VALIDATOR_0 = "minlength, value=10";
    public static final String value_VALIDATOR_1 = "maxlength, value=15";
    public static final String value_VALIDATOR_2 = "mask, pattern=com$, messageKey=mustendcom";
    public static final String value_VALIDATOR_3 = "email";
    public static final String value_VALIDATOR_ARGS = "keys=mixValue, resource=false";

    public void setValue(String value) {
        this.value = value;
    }
}

S2Struts中,为了设定validation提供了各种注释。 除了ValidateOrder、Args、Message以外,其余的注释在基本校验时都会用到。

ValidateOrder

用于控制验证顺序。按指定顺序显示错误信息。

属性必须缺省值说明
value
×
999
指定验证顺序。

Args

指定信息中用到的置换参数。

属性必须缺省值说明
keys
×
-
指定信息中用到的置换参数。
用","分隔符可以进行复数个参数的指定。
常量注释中关于用","进行分隔的方法请参照「常量注释的补充」
bundle
×
-
使用缺省值以外的信息资源的场合, 指定所用到的信息资源的key。
resource
×
true
指定是否利用由keys指定的值作为资源key。
true的场合,作为资源key使用,该值被作为置换参数。
false的场合,用keys指定的值直接被当作置换参数。
value
×
-
用Arg注释个别指定置换参数的场合使用。
个别指定置换参数的场合,请不要指定keys,bundle,resource。

Arg

个别指定信息中用到的置换参数。

属性必须缺省值说明
key
-
指定信息中用到的置换参数。
name
×
-
指定使用置换参数的校验名。
bundle
×
-
使用缺省值以外的信息资源的场合, 指定使用信息资源的key。
resource
×
true
指定是否把key指定的值作为资源key使用。
true的场合作为资源key使用,使用该值作为信息。
false的场合用key指定的值直接作为信息。
position
×
-
指定置换参数的位置。

常量注释如下所示,用属性名_VALIDATOR_ARG进行指定。 复数指定的场合,常量名的最后附上以0开头的INDEX。

    public static final String value_VALIDATOR_0 = "required";
    public static final String value_VALIDATOR_1 = "integer";
    public static final String value_VALIDATOR_ARG_0 = "form.value";
    public static final String value_VALIDATOR_ARG_1 = "form.value.def";
    public static final String value_VALIDATOR_ARG_2 = "form.value.req, name = required, position = 1";

    public void setValue(String value) {
        this.value = value;
    }

Messages

想指定复数个Message注释的场合使用。

属性必须缺省值说明
value
-
指定复数个Message注释。

Message

想显示个别信息以代替缺省信息的场合指定。

属性必须缺省值说明
key
-
指定信息key或者信息。
name
-
指定一个指定信息的校验名。
bundle
×
-
使用缺省值以外的信息资源的场合, 指定使用信息资源的key。
resource
×
true
指定是否把key指定的值作为资源key使用。
true的场合作为资源key使用,使用该值作为信息。
false的场合使用key指定的值直接作为信息。

Required

确认该值是否含有空白以外的文字。 无参数。

Mask

确认该值是否与pattern指定的正规表现一致。

属性必须缺省值说明
pattern
-
指定正规表现。
messageKey
×
-
指定取得信息用的key。
resource
×
true
指定是否把key指定的值作为资源key使用。
true的场合作为资源key使用,使用该值作为置换参数。
false的场合使用key指定的值直接作为置换参数。

IntRange, LongRange, FloatRange, DoubleRange

确认值是否处于min和max指定的范围内。

属性必须缺省值说明
min
-
指定值范围内的最小值。
max
-
指定值范围内的最大值。

Maxlength

确认值的文字数是否在value以下。

属性必须缺省值说明
value
-
指定值的长度的上限值。

Minlength

确认值的文字数是否在value以上。

属性必须缺省值说明
value
-
指定值的长度的下限值。

Maxbytelength

确认值的字节数是否在value以下。

属性必须缺省值说明
value
-
指定值的长度的上限值。
charset
×
-
指定用字节数验证时的文字set。
不指定的场合,使用platform的缺省文字set。

Minbytelength

确认值的字节数是否在value以上。

属性必须缺省值说明
value
-
指定值的长度的下限值。
charset
×
-
指定用字节数验证时的文字set。
不指定的场合,使用platform的缺省文字set。

ByteType, ShortType, IntegerType, LongType, FloatType, DoubleType

确认值是否能够变换成指定的型。 无属性。

DateType

确认值是否可表示有效的日期。

属性必须缺省值说明
pattern
×
s2struts.dion的dateConfigRegister组件定义时指定的类型(pattern)
指定日期的类型(pattern)。

CreditCardType

确认值是否为有效的信用卡号码。 无属性。

EmailType

确认值是否为有效的邮件地址。 无属性。

UrlType

确认值是否为有效的URL。

属性必须缺省值说明
allowallschemes
×
false
指定是否允许scheme。
如果设定为true,全部的scheme都得到允许。
allow2slashes
×
false
指定是否允许双斜线(//)。
如果为true,允许。
nofragments
×
false
指定是否允许URL的分割。
如果为false,允许。
schemes
×
http,https,ftp
指定用,(逗号)分隔允许的scheme。

NoValidate

指定不要自动校验。 无属性。

常量注释的补充

常量注释,利用「,」(逗号)作为属性的分割文字。 在值里,指定「,」的场合,像下面这样,把値用「'」(单引号)或者「"」(双引号)括起来。

 public static final String value_VALIDATOR = "mask, pattern='(^[0-9]{1,2}$)', messageKey=comma";

 public static final String value_VALIDATOR = "mask, pattern=\"(^[0-9]{1,2}$)\", messageKey=comma";

S2Struts标签库(tag library)指南

S2Struts中,提供了ButtonTag和SubmitTag。 二者均为Struts的标签的扩张形式。

button标签

org.seasar.struts.taglib.html.ButtonTag(标签名:button)

http://struts.apache.org//struts-doc-1.2.8/userGuide/struts-html.html#button
在上述基础上追加的属性,如下所示。

属性名必须rtexprvalue说明
type
×
false
以下的值,指定按钮的种类。
"button":一般按钮。
"submit":执行按钮。
"reset":复位按钮。
在HTML4.01 中 submit是作为规定值被定义的,
在IE6.0 或 Netscape 的实装中,规定值是 button 。
indexId
×
false
用logic:iterate标签的id属性等指定变量名。
在button的value属性的值里,设定为这一变量值。
(变量值为32位的Integer的话,变换后的html例子:<button ... value="32" ...>)

submit标签

org.seasar.struts.taglib.html.SubmitTag(标签名:submit)

http://struts.apache.org//struts-doc-1.2.8/userGuide/struts-html.html#submit
在上述基础上追加的属性,如下所示。

属性名必须rtexprvalue说明
action
×
-
根据action="#{component.method}"的定义,submit时可以指定执行的组件和方法。 组件必须用这一属性指定的名字在S2Container中登录。
没有指定indexId属性的场合,调用无参数的指定method。
例如,定义为<s2struts:submit action="{hogeAction.create}"> 的按钮被按下的场合, 会调用String create() 方法
指定indexId属性的场合,调用int型的index为参数的方法。
例如,定义为<s2struts:submit action="{hogeAction.create}" indexId="index"> 的按钮被按下的场合, 会调用String create(int index) 方法。

S2Struts1.3.0-RC3以后,将使用与指定组件对应的ActionMapping。 ActionMapping指的是,缺省时从ActionPathNamingRule组件得到path作为keye而被决定。 明确指定的场合在调用方法(method)中,请指定BINDING_METHOD注释
indexId
×
false
用logic:iterate标签的id属性指定已定义了的变量名。
将被变换成propertyName[变量值]那样。
(变量值是32位的Integer的场合,变换后的html例子:<... foo[32]="bar"...>)
cancel
×
false
指定为true的场合,将无视与form相关的ActionForm的validate, 调用Action。

cancel标签

org.seasar.struts.taglib.html.CancelTag(标签名:cancel)

http://struts.apache.org//struts-doc-1.2.8/userGuide/struts-html.html#cancel
对上述cancel进行扩张,不利用Request参数实现Cancel功能的标签。 没有追加的属性。

image标签

org.seasar.struts.taglib.html.ImageTag(标签名:image)

http://struts.apache.org//struts-doc-1.2.8/userGuide/struts-html.html#image
在上述基础上追加的属性,如下所示。

属性名必须rtexprvalue说明
action
×
-
根据action="#{component.method}"的定义,提交(submit)时可以指定执行组件和方法。 组件必须用这一属性指定的名字在S2Container中进行登录。

S2Struts1.3.0-RC3以后,使用与指定的组件相对应的ActionMapping。 ActionMapping指的是,缺省时从ActionPathNamingRule组件得到path作为key而决定。 明确指定的场合在调用方法(method)中,请指定BINDING_METHOD注释
cancel
×
false
指定为true的场合,将无视与form相关的ActionForm的validate, 调用Action。

checkbox标签

org.seasar.struts.taglib.html.CheckboxTag(标签名:checkbox)

http://struts.apache.org//struts-doc-1.2.8/userGuide/struts-html.html#checkbox
对上述checkbox进行扩张,即使没有check的场合,与form相关连的ActionForm的属性里也可以设定为false。 没有追加的属性。

page标签

org.seasar.struts.taglib.html.PageTag(标签名:page)

根据这个标签在JSP里的定义,可以对struts-config的input属性进行无设定化处理(错误时重新显示自身画面)。 需要在form标签中进行定义。如果有复数个form存在的场合,必须分别定义。

属性名必须rtexprvalue说明
-
-
-
无属性。

init标签

org.seasar.struts.taglib.InitializeTag(标签名:init)

使用这一标签,可以进行画面的初始化处理。在显示JSP的时候,执行action属性中定义的MethodBinding。

属性名必须rtexprvalue说明
action
×
-
根据action="#{component.method}"里的定义,显示JSP时,可以指定执行组件和方法。 组件必须用这一属性指定的名字在S2Container中进行登录。

BINDING_METHOD注释

S2Struts1.3.0-RC3以后可以利用。

BINDING_METHOD注释,对于用submit标签或者image标签指定的action,为了显示指定ActionMapping而被使用。

常量注释

在Action里,以下列形式作为static字段定义。

public static final String 方法名_BINDING_METHOD = "path=ActionMapping的path"

标签和Java的定义例子如下所示。
<s2struts:submit action="#{modAction.mod}" property="submit" value="提交(submit)"/>
public static final String mod_BINDING_METHOD = "path=/hoge";

public String mod() {
  ...
}

Tiger注释

在Action方法中以下列形式指定注释。

@BindingMethod(path = "ActionMapping的路径")

标签和Java的定义例子如下所示。
<s2struts:submit action="#{modAction.mod}" property="submit" value="提交(submit)"/>
@BindingMethod(path = "/hoge")
public String mod() {
  ...
}