• 新手指南


    新手指南

    Seasar2能够进行热部署,对程序进行的修改,不需要重启服务器。 并且,基本上不需要写配置文件。

    参照新手指南工程的安转, 请启动应用服务器,并对JAVA代码和*.properties等属性文件进行修改,感受热部署的威力。

    index

    访问http://localhost:8080/sa-struts-tutorial, 进入一系列演示应用的一览画面。

    请查看webapp(Web应用的根目录)目录,并没有index.jsp(index.html)。 因此,哪个页面被显示呢。それでは、どのページが表示されているのでしょうか。

    对于SAStruts来说,访问应用程序根的时候, 如果存在包名.action.IndexAction类的话,自动跳转到这个类。 根包名的详细信息,请参照这里

    IndexAction.java的代码如下。

    IndexAction.java
    package tutorial.action;
    
    import org.seasar.struts.annotation.Execute;
    
    public class IndexAction {
    
        @Execute(validator = false)
        public String index() {
            return "index.jsp";
        }
    }
    

    跳转到这个Action类之后,调用有@Execute注解的执行方法。当存在多个执行方法的时候, 应该调用哪个执行方法,请参照这里。 这回的情况只有1个执行方法,无条件调用index()。

    然后将跳转到方法的返回值。IndexAction#index()执行之后将跳转到index.jsp。web.xml里定义了VIEW_PREFIX为/WEB-INF/view,所以具体的路径 为/WEB-INF/view/index.jsp。

    然后请看webapp/WEB-INF/struts-config.xml, 并没有多少Action和ActionForm的定义。SAStrut能更具URL找到适当的Action,然后根据Action类的信息, 组合成struts-config.xml里定义的类似的信息。

    再看一下webapp/WEB-INF/validation.xml。 也没有多少文件。SAStruts对每个属性可以增加验证用的注解,可以组合成validation.xml类似的信息。

    加法运算

    从首页跳转到加法运算页面。 或者直接访问加法运算页面http://localhost:8080/sa-struts-tutorial/add/。

    /add对应的Action为tutorial.action.AddAction。Action的详细情报请参照这里

    AddAction.java的代码如下。

    AddAction.java
    package tutorial.action;
    
    import org.seasar.struts.annotation.Execute;
    import org.seasar.struts.annotation.IntegerType;
    import org.seasar.struts.annotation.Required;
    
    public class AddAction {
    
        @Required
        @IntegerType
        public String arg1;
    
        @Required
        @IntegerType
        public String arg2;
    
        public Integer result;
    
        @Execute(validator = false)
        public String index() {
            return "index.jsp";
        }
    
        @Execute(input = "index.jsp")
        public String submit() {
            result = Integer.valueOf(arg1) + Integer.valueOf(arg2);
            return "index.jsp";
        }
    }
    

    Action是POJO,Action的状态也能在Action里定义。相关的信息都在同一类里定义比较好理解。

    Seasar2将public变量视为属性。不需要定义getter,setter方法。public变量,EL和Struts也能够识别。 如果有兴趣的话,请参看org.seasar.struts.action的代码。

    对于请求的处理,请参考执行方法。 执行方法,有@Execute注解,返回值为跳转路径。

    如果有多个执行方法的时候,通过URL指定调用哪个执行方法。

    下例调用AddAction#index()が呼び出されます。/add/后面指定了需要调用的执行方法名index。

    http://localhost:8080/sa-struts-tutorial/add/index
    

    执行方法没有定义的时候,默认调用index。下面的URL和上面的一样都是调用AddAction的index方法。

    http://localhost:8080/sa-struts-tutorial/add/
    

    表单提交时,按纽的名字就是需要调用执行方法的名字。 下例就是,调用Action的submit()方法。

    <input type="submit" name="submit" value="サブミット"/>
    

    @Execute的详细,请参照这里

    通过声明式验证,对变量添加验证用的注解,@Execute的valiator属性设为true(默认)。validator=true时,如果验证结果为NG的时候,跳转的页面必须通过input属性来指定。 验证的详细,请参照这里

    /add/index.jsp如下所示。

    /add/index.jsp
    <html>
    <head>
    <title>Add</title>
    </head>
    <body>
    <html:errors/>
    <s:form>
    <html:text property="arg1"/> + <html:text property="arg2"/>
    = ${f:h(result)}<br />
    <input type="submit" name="submit" value="サブミット"/>
    </s:form>
    </body>
    </html>
    

    所有JSP需要的共通的taglib的声明在webapp/WEB-INF/view/common/common.jsp中定义。common.jsp的详细信息请参照JSP

    为了显示验证结果为NG时的错误信息,定义了标签html:errors。

    为了接收被提交的值,定义了s:form。action属性,能够自动计算出来,所以通常不需要指定。

    为了接收输入值,定义了html:text标签。property属性定义了Action的属性名。

    提交时为了调用AddAction#submit(),submit的name属性的值设为submit。

    提交后,根据注解将验证输入的arg1,arg2的值是不是必须输入,是不是整数。

    如果为NG时,跳转回input属性制定的index.jsp。 如果OK,则掉哟国内submit()方法。

    submit()的返回值为index.jsp,所以还将跳转到index.jsp。

    Action的result属性,和请求的属性同名所以可以调用${f:h(result)}来显示。f:h对HTML进行Escape操作。详细信息请参照这里

    文件上传

    从首页访问文件上传页面。 或者通过URL http://localhost:8080/sa-struts-tutorial/upload直接访问文件上传页面。

    /upload对应的Action类为tutorial.action.UploadAction。Action的详细信息,请参照这里

    UploadAction.javaのソースコードは次のようになります。

    UploadAction.java
    package tutorial.action;
    
    import java.io.BufferedOutputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    
    import javax.servlet.ServletContext;
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
    import org.apache.struts.action.ActionMessage;
    import org.apache.struts.action.ActionMessages;
    import org.apache.struts.upload.FormFile;
    import org.seasar.framework.container.annotation.tiger.Binding;
    import org.seasar.framework.container.annotation.tiger.BindingType;
    import org.seasar.framework.exception.IORuntimeException;
    import org.seasar.struts.annotation.Execute;
    import org.seasar.struts.annotation.Required;
    import org.seasar.struts.upload.S2MultipartRequestHandler;
    import org.seasar.struts.util.ActionMessagesUtil;
    
    public class UploadAction {
    
        @Required
        @Binding(bindingType = BindingType.NONE)
        public FormFile formFile;
    
        @Binding(bindingType = BindingType.NONE)
        public FormFile[] formFiles;
    
        public HttpServletRequest request;
    
        public ServletContext application;
    
        @Execute(validator = false)
        public String index() {
            SizeLimitExceededException e = (SizeLimitExceededException) request
                .getAttribute(S2MultipartRequestHandler.SIZE_EXCEPTION_KEY);
            if (e != null) {
                ActionMessages errors = new ActionMessages();
                errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
                    "errors.upload.size",
                    new Object[] { e.getPermittedSize(), e.getActualSize() }));
                ActionMessagesUtil.addErrors(request, errors);
            }
            return "index.jsp";
        }
    
        @Execute(input = "index.jsp")
        public String upload() {
            ActionMessages messages = new ActionMessages();
            upload(formFile, messages);
            for (FormFile file : formFiles) {
                upload(file, messages);
            }
            ActionMessagesUtil.addMessages(request, messages);
            return "index.jsp";
        }
    
        protected void upload(FormFile file, ActionMessages messages) {
            if (file.getFileSize() == 0) {
                return;
            }
            String path = application.getRealPath("/WEB-INF/work/"
                + file.getFileName());
            try {
                OutputStream out = new BufferedOutputStream(new FileOutputStream(
                    path));
                try {
                    out.write(file.getFileData(), 0, file.getFileSize());
                } finally {
                    out.close();
                }
            } catch (IOException e) {
                throw new IORuntimeException(e);
            }
            messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(
                "messages.upload.complete",
                new Object[] { path }));
        }
    }
    

    文件上传,在Action或者ActionForm里定义FormFile类型的属性。 通过FormFile来取得上传得文件。

    因为FormFile是借口,Seasar2默认为自动绑定的对象,会抛出执行时没有DI的警告。为了防止出现警告,需要在属性上增加@Binding(bindingType = BindingType.NONE)的注解。

    属性的类型也可以指定为数组FormFile[],这样可以接受多个FormFile。

    如果是FormFile数组时,不能指定注解式验证。 实际上传了没有,可以通过FormFile#getFileSize()返回0来进行判断。

    上传文件的刀削,超过定义的上限(在struts-config.xml的标签controller的maxFileSize属性的值)时,抛出SizeLimitExceededException异常。

    发生这种异常的时候,将跳转到index方法。 所以在index方法中,检测是否存在SizeLimitExceededException异常,来检测上传文件是否超过上限。

    /upload/index.jsp如下所示。

    /upload/index.jsp
    <html>
    <head>
    <title>Upload</title>
    </head>
    <body>
    <html:errors/>
    <html:messages id="m" message="true">
    ${f:h(m)}<br />
    </html:messages>
    
    <s:form action="/upload" enctype="multipart/form-data">
    <input type="file" name="formFile" /><br />
    <c:forEach varStatus="s" begin="0" end="1">
    <input type="file" name="formFiles[${s.index}]" /><br />
    </c:forEach>
    
    <input type="submit" name="upload" value="アップロード"/>
    </s:form>
    </body>
    </html>
    

    文件上传的时候,form的enctype属性设为"multipart/form-data"。 上传用的tag(<input type="file" ... />)的name,和Action或者ActionForm的属性值一致。FormFile数组时,name属性的值为属性名[数组的序号]。

    客户端验证

    从首页访问客户端验证。或者通过URL http://localhost:8080/sa-struts-tutorial/clientValidator/进行访问。

    什么都没有输入的时候点击「aaaが必須」。JavaScript进行验证,并显示「aaaは必須です。」的信息。

    然后点击「bbbが必須」。JavaScript进行验证,并显示「aaaは必須です。」的信息。 我们可以了解到每个按钮进行了不同的验证。

    /clientValidator对应的Action类为tutorial.action.ClientValidatorAction。Action的详细信息请参照这里

    ClientValidatorAction.java的代码如下。

    ClientValidatorAction.java
    package tutorial.action;
    
    import org.seasar.struts.annotation.Execute;
    import org.seasar.struts.annotation.Required;
    
    public class ClientValidatorAction {
    
        @Required(target = "submit")
        public String aaa;
    
        @Required(target = "submit2")
        public String bbb;
    
        @Execute(validator = false)
        public String index() {
            return "index.jsp";
        }
    
        @Execute(validator = true, input = "index.jsp")
        public String submit() {
            return "index.jsp";
        }
    
        @Execute(validator = true, input = "index.jsp")
        public String submit2() {
            return "clientValidator.jsp";
        }
    }
    

    按钮(方法)不同调用的验证不同。 验证的注解taget属性可以指定方法名。多个方法的时候,可以用逗号分开。

    /clientValidator/index.jspは次のようになります。

    /clientValidator/index.jsp
    <html>
    <head>
    <title>Client Validator</title>
    <html:javascript formName="clientValidatorActionForm_submit"/>
    <html:javascript formName="clientValidatorActionForm_submit2"/>
    </head>
    <body>
    <html:errors/>
    <s:form action="/clientValidator">
    aaa:<html:text property="aaa"/><br />
    bbb:<html:text property="bbb"/><br />
    <input type="submit" name="submit" value="aaaが必須"
        onclick="forms[0].name='clientValidatorActionForm_submit';
            return validateClientValidatorActionForm_submit(forms[0]);"/>
    <input type="submit" name="submit2" value="bbbが必須"
        onclick="forms[0].name='clientValidatorActionForm_submit2';
            return validateClientValidatorActionForm_submit2(forms[0]);"/>
    </s:form>
    </body>
    </html>
    

    为了输出验证用的JavaScript,使用标签html:javascript。formName属性指定为「Action名 + Form + _ + 方法名」。

    为了调用验证的JavaScript按钮的onclick属性里,form的name属性设为formName属性的值,然后调用 「validate + formName属性的值」方法。

  • 相关阅读:
    【数论】 快速幂
    【时间复杂度】你还在担心时间复杂度太高吗?
    【数据结构】 最小生成树(三)——prim算法
    【数据结构】 最小生成树(二)——kruskal算法
    node.js初识11
    node.js初识10
    node.js初识09
    node.js初识08
    node.js初识07
    node.js初识06
  • 原文地址:https://www.cnblogs.com/aggavara/p/2716393.html
Copyright © 2020-2023  润新知