デジタルチャイルド日記

コンピュータ関連のいろいろメモを残していく子供部屋です。

Strutsの入力制御込みのタグ

Strutsの入力制御に関するメモ。

 

別にStrutsのってことではないのですが、Strutsを使った画面の入力要素の制御でいろいろ考えてみてるとこれが一番落ち着きそうってことで。

 

基本的にな考え方は、入力不可要素には、disabledを使って入力不可とする。

ただ、disabledは、POSTされなくなる為、disabledになった要素については、hidden要素を作成して、そちらでPOSTするようにするという方法です。

readonlyも考えたのですが、なんかいろいろ気になる部分があって、こちらほうがいい気してます。

ほんとはこれをTaglibとして作成してそれを使うほうがいいでしょうね。

 

では、ソース

<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<%@taglib uri="/tags/struts-html" prefix="html" %>
<%@taglib uri="/tags/struts-tiles" prefix="tiles" %>
<%@taglib uri="/tags/struts-bean" prefix="bean" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html:html>
<head>
<title>入力要素、TAGLIBテスト</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<html:form enctype="multipart/form-data">
<p>■入力制御</p>
入力不可の場合のhiddenを追加で出力する方法<br/>
<%
  boolean enabled = false;  // enabledに有効無効の値をセットする。
%>
1.TEXTBOX<br />
<html:text name="helloworld" property="helloWorldText" disabled='<%=!enabled %>'></html:text><br/>
<% if(!enabled) { %>
<html:hidden name="helloworld" property="helloWorldText"></html:hidden>
<% } %>
<br/>
2.TEXTAREA<br />
<html:textarea name="helloworld" property="helloWorldTextarea" disabled='<%=!enabled %>'></html:textarea><br/>
<% if(!enabled) { %>
<html:hidden name="helloworld" property="helloWorldTextarea"></html:hidden>
<% } %>
<br/>
3.CHECKBOX<br />
<html:checkbox name="helloworld" property="helloWorldCheckbox1" value="1" disabled='<%=!enabled %>'></html:checkbox><br />
<% if(!enabled) { %>
<html:hidden name="helloworld" property="helloWorldCheckbox1"></html:hidden>
<% } %>
<html:hidden name="helloworld" property="helloWorldCheckbox1" value="0"></html:hidden>
<br/>
4.RADIO<br />
<html:select name="helloworld" property="helloWorldSelect" disabled='<%=!enabled %>'>
<html:option value="00">値1</html:option>
<html:option value="01">値2</html:option>
</html:select><br/>
<% if(!enabled) { %>
<html:hidden name="helloworld" property="helloWorldSelect"></html:hidden>
<% } %>
<br/>
5.FILE<br />
ファイルは選択できないんだから、この項目からのPOSTを意識する必要がない為、hiddenもなし<br />
<html:file name="helloworld" tabindex="-1" property="helloWorldFile" disabled='<%=!enabled %>'></html:file><br/>
<br /> <html:submit>送信</html:submit> </html:form> </body> </html:html>

アプリによっては若干のアレンジが必要ですが基本的にはこれがいいのかなと思います。

以下はちょっと他とは違う入力項目の説明

1.チェックボックスは、入力可能な状態でも未選択だった場合、パラメータが送られないので、未選択を表すhiddenタグを用意しています。また、入力不可の状態になった場合は未選択状態のタグよりも上に選択状態を表すhiddenを用意しています。

2.ファイルの場合は、選択できない状態であるということは、そもそも送られないので、hiddenも用意していません。実アプリでは、ファイルパスなどをhiddenで保持しておいて、無効になっている場合(つまり、FileFormが送られてこない場合)は、そちらを使うようにAction側で記述するようにしたほうがいいでしょう。

 

ただ、この方式の場合、変更不可な要素なのですがPOSTされてしまうということになるので、DB更新などが発生する場合は、考慮が必要かもしれません。

 

 昨日、半日以上、会社で悩んだのに、土曜日の朝2時間ぐらいで「はっ!」と解決した・・・どれだけ会社で集中できてないんだ(笑)

 

Strutsの独自taglib

Strutsの独自のtaglibを作る方法について、検証したのでメモメモ。

 

Strutsでtaglibを作成する場合、すでにある既存クラスを継承して作成するほうが楽ですね。一から作るとめんどくさいし、バグも生み出しそうですし。

 

作ってみた感想としては、うまく利用すれば、かなり使えるものができあがりそう・・でした。

 

taglib用のクラスを作成

taglibの基本的な動きは、JavaでHTMLを成形して出力する!ということになりますので、HTML出力用のクラスを作成します。

Strutsにはもともと、いろいろなtaglibクラスがあるのでそれを継承して、クラスを作成します。今回元にしたのは、html:textのクラス(TextTagクラス)になります。

【DateTextTag.java

package jp.co.test.taglib;
import javax.servlet.jsp.JspException;
import org.apache.struts.taglib.TagUtils;
import org.apache.struts.taglib.html.TextTag;

public class DateTextTag extends TextTag {

  @Override
  public int doStartTag() throws JspException {

    // セッションの状態により有効無効の切り替え
    if("30".equals(pageContext.getSession().getAttribute("roleid"))) {
      this.setDisabled(true);
    } else {
      this.setDisabled(false);
    }
    // 元のテキストボックス表示
    super.doStartTag();
    // テキストボックスのblur用のJavaScriptを出力
    if (pageContext.getAttribute(TextTag.class.getName()) == null){
      TagUtils.getInstance().write(this.pageContext,
          "\n"
          + "<script type=\"text/javascript\">\n"
          + "function _toSlash(obj) {\n"
          + "  if(new RegExp(/^[0-9]{8}$/).test(obj.value)) {"
          + "    var str = obj.value.trim();\n"
          + "    var y = str.substr(0,4);\n"
          + "    var m = str.substr(4,2);\n"
          + "    var d = str.substr(6,2);\n"
          + "    obj.value = y + \"/\" + m + \"/\" + d; } }\n"
          + "</script>\n");
          
      pageContext.setAttribute(TextTag.class.getName(), Boolean.TRUE);
    }
    
    return SKIP_BODY;
  }
    
  @Override
  public String getOnblur() {
    String org = super.getOnblur();
    return "_toSlash(this);" + (org == null ? "" : org);
  }
}

taglibの設定ファイルを作成

今回は、struts-html.tldの中から、textの設定だけをコピーして、sample.tldを作成しました。変更箇所は以下

属性名 設定値
name tag名を指定。今回は、datetextにしました。
tag-class 先の手順で作成したクラスを指定。

 

【sample.tld

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib 
    PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
    "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
     
  <taglib>
    <tlib-version>1.0</tlib-version>
    <jsp-version>1.2</jsp-version>
    <short-name>sample</short-name>
    <tag>
      <name>datetext</name>
      <tag-class>jp.co.test.taglib.DateTextTag</tag-class>
      <description>
      <![CDATA[ 

JSPにtaglibの設定を追加

最後にJSPに新規に作成したtldJSPを追加して完成です。

 

追加分 設定値
taglib設定追加 @taglibに上記で作成したtldファイルを追加
tagを追加 sample:datetextとして、新規作成したtaglibを追加

【input.jsp

<%@ taglib uri="WEB-INF/tld/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="WEB-INF/tld/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="WEB-INF/tld/struts-html.tld" prefix="html" %>
<%@ taglib uri="WEB-INF/tld/struts-html.tld" prefix="tiles" %>
<%@ taglib uri="WEB-INF/tld/sample.tld" prefix="sample" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>INPU WORLD サンプル</title>
  </head>
  <body>
    <html:errors/>
    <html:form action="inputworld.html?action_id=regist" method="POST">
      ■入力チェック用<br />
      <sample:datetext name="inputworld" property="inputValue" errorStyle="background-color:#ff0000"></sample:datetext><br />
      <br />
      <html:submit></html:submit>
    </html:form>
  </body>
</html>

 

 上記以外にも、テキストボックスのエラースタイルが決まっているなら、要素ごとにJSPで指定するよりも、taglibで一気に変更するほうが手っ取り早いですし、いろいろと加工することも可能です。

 

結構使えそうなので、今後は使っていきたいと思います。(使う機会があればですがw

 

以上。メモメモでした。

都道府県マスタの必要性

システムを構築しているとよく出てくる都道府県マスタ・・・

 

ふと、これ必要か?と思うことがある。

 

データベース上に都道府県コードと都道府県名、場合によっては略称をもっているという例のあれである。

 

そもそも、都道府県名称と都道府県コードなって、法律によって縛られていて、おいそれと変わるものではない。要件次第だと思うが、なぜかかかわっているシステムにはすべて都道府県マスタが存在する。

 

しかも最近開発に携わっているシステムの多くが、顧客の住所はそのまま、「東京都大田区・・」などのように特に都道府県コードを意識しないケースが多い。

あえて、都道府県だけ別枠の保持する意味がないのかもしれない。

 

都道府県名が変わったら!なんてことを心配するのかもしれないが、そんなもの、市区町村名が変わるほうがよっぽど多いし><;

 

古い基幹システムなどからデータを連携する場合に必要ということもあるかもしれないが、そもそも同一のマスタをみてないなら、そんなマスタに意味がにない。

※連携時に一緒にマスタも連携するなら話は別だが、そんなことするなら、変換してから連携してくれ(笑)

 

昔はなにも考えずに、必要って思ってたが、最近はいらんのじゃね?と思うこの頃です。

 

以上。メモじゃなくて、思ってることでした

Strutsの独自Validator

先日の続きでvalidatorについて。

 

Strtusから提供されているValidatorもいろいろありますが、それだけではすべてのチェックを行うことはできません。

その為、どうしても独自のValidatorを作成する必要に迫られることがあります。

 

独自のvalidtorを追加するのは、意外と簡単で、以下の手順で作成が可能です。

 

チェック(検証)を行うクラス作成

まずは、チェックを行う処理を追加します。

今回のサンプルは同一名の項目が複数ある場合に、いずれが必須という処理になります。たとえば、都道府県のうち1つは必須など。

 

詳細は説明はソースのコメントを参照してください。

package jp.co.test.validator;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.validator.Field;
import org.apache.commons.validator.Validator;
import org.apache.commons.validator.ValidatorAction;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.validator.Resources;

public class AreaCheckValidator {

  /**
   * チェックのうち1つ以上必須
   * ・同名の項目のうち1つ以上が選択されている場合に使用します。
   *
   * @param bean Beanクラス
   * @param va バリデータアクション
   * @param field フィールド
   * @param errors エラーメッセージ
   * @param v バリデータ
   * @param request リクエスト
   * @return チェック結果
   */
  public static boolean validateSelectOne(Object bean,
      ValidatorAction va,
      Field field,
      ActionMessages errors,
      Validator v,
      HttpServletRequest request) {
    
    String[] values = {};
    // varで指定されたcheckonの値を取得
    String onvalue = Resources.getVarValue("checkon", field, v, request, true);
    
    try {
      // プロパティの値を取得(配列の為、PropertyUtils使用)
      values = (String[])PropertyUtils.getProperty(bean, field.getProperty());
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
    
    // 取得したプロパティがない場合は、TRUEを返す。
    if(null == values || values.length == 0) {
      return Boolean.TRUE;
    }
  
    // チェック本体
    for(int i=0;i<values.length;i++) {
      // 値がnullか未入力の場合、値比較しない
      if ( values[i] != null && values[i].length() != 0 ){
        // varで指定された値かどうかチェックする。
        if( values[i].equals(onvalue) ){
// チェックOKで終了 return Boolean.TRUE; } } } // 1つも値が一致しない場合、フィールドにエラーメッセージをセット errors.add(field.getKey(), Resources.getActionMessage(v, request, va, field)); // チェックNGで終了 return Boolean.FALSE; } }

【補足】

ちなみに、上のロジックは実用性には欠けますので、そのままでは使えませんので、悪しからず・・・(笑)

 クラスを設定(validator-rules.xml)を追加

 作成したクラスをvalidator-rules.xmlに追加します。

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE form-validation PUBLIC
    "-//Apache Software Foundation//
    DTD Commons Validator Rules Configuration 1.1.3//EN"
    "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
<form-validation>
  <global>

    <validator name="selectOne"
        classname="jp.co.test.validator.AreaCheckValidator"
        method="validateSelectOne"
        methodParams="java.lang.Object,
          org.apache.commons.validator.ValidatorAction,
          org.apache.commons.validator.Field,
          org.apache.struts.action.ActionMessages,
          org.apache.commons.validator.Validator,
          javax.servlet.http.HttpServletRequest"
        msg="errors.selectOne"/>
      
  </global>
</form-validation>

validatorの詳細な内容は以下を参照。

属性名 説明
name チェックの名称。
validation.xmlとの紐づけに使う。
classname チェックロジックのクラス。
method チェックロジックのメソッド名
methodParams チェックロジックのパラメータ。
※パラメータは一緒なのになぜ指定しているのかが不明。パラメータの方が取れないからか?
msg チェックでNGになった場合のデフォルトメッセージ。
※validation.xmlの設定で上書きされる???

  ※他にもありますが、今回は省略。

validation.xmlに設定を追加

最後に、 validation.xmlにチェックを追加します。

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE form-validation PUBLIC
    "-//Apache Software Foundation//
    DTD Commons Validator Rules Configuration 1.1.3//EN"
    "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">

  <form-validation>
    <formset>
      <field property="checkValue" depends="selectOne">
        <var>
          <var-name>checkon</var-name>
          <var-value>1</var-value>
        </var>
        <msg name="sample" key="errors.selectOne" />
      </field>
    </form>
  </formset>
</form-validation>

 これはいつもと同じです。

  • checkValueがString[]型で定義すること。
  • dependsはvalidator-rules.xmlと合わせて、selectOneとすること
  • varで、checkonとして、ON状態の値を設定すること。

ぐらいですかね。

 個人的には

 個人的にですが、開発時にはドメインやエンティティが確定した段階で、検証ロジックは作成するほうがいいかなと思っています。そのほうが、開発(実装)への着手が早くなり、問題点の洗い出しや実装イメージが早く固まることが予想されるからです。

また、単体のテストとしても早く取り掛かることができる為、時間的にもゆとりがでるようになると思います。

実際のチェックロジックの実装は、validator内には置かず、別途チェッククラスを作成して、validatorからはそのロジックを呼ぶようにするほうがいいでしょう。こうすることで、どのレイヤ(Strutsのvalidatorはプレゼンテーション層)からでも、チェックロジックを呼ぶことができますからね。

 

以上。メモメモでした。

Strutsのvalidator

StrutsのValidatorについて、調べてみたので、メモメモ。

 

Validator

Strutsには入力チェックの仕組みとしてValidatorがあります。

簡単にいえば、ActionFormの中身をチェックする仕組みです。入力値のチェックや場合によっては、ログイン状態のチェックや、メンテナンス時間のチェックなど、考えればいろいろできそうです。

実際に、validatorを使うためには、以下の設定が必要です。 

プラグイン設定

Strutsのvalidator機能は、プラグインとして提供されている為、struts-config.xmlプラグインの設定を追加します。

<!-- Validator Plugin Setting -->
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validation.xml,/WEB-INF/validator-rules.xml" />
</plug-in>

 上記設定を追加することで、/WEB-INF/validation.xmlと/WEB-INF/validator-rules.xmlの2つのファイルを設定として読み込むようになります。

validation.xmlの追加

 /WEB-INF/validation.xmlのファイルを作成して、チェックする項目などを定義します。

【validation.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//
    DTD Commons Validator Rules Configuration 1.1.3//EN"
    "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
<form-validation>
  <formset>
  <!-- 適用するアクション・フォームBeanを論理名で指定 -->
    <form name="formName">
      <field property="inputValue" depends="required">
      </field>
    </form>
  </formset>
</form-validation> 

 上記の場合、Struts-config.xmlでformNameと定義されたフォームクラスについて、入力時チェックをするということになります。

対象は、inputValueプロパティで、チェックは必須チェック(required)となります。

Strutsには、いくつかのチェックがデフォルトで提供されている為、単項目チェックなどは非常に簡単に実装することができます。

また業務チェックなどの複合チェックも独自にチェックロジック(validator)を実装することも可能です。※方法については、後程の記事で。

validator-rules.xmlの追加

 /WEB-INF/validator-rules.xmlを作成して、チェックのルールを定義します。

上のvalidation.xmlで定義しているのが、必須(required)なので、今回は以下のように設定します。

【validator-rules.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation// 
    DTD Commons Validator Rules Configuration 1.1.3//EN"
    "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
<form-validation>
<global>
<validator name="required"
classname="org.apache.struts.validator.FieldChecks"
method="validateRequired"
methodParams="java.lang.Object,
       org.apache.commons.validator.ValidatorAction,
       org.apache.commons.validator.Field,
       org.apache.struts.action.ActionMessages,
       org.apache.commons.validator.Validator,
       javax.servlet.http.HttpServletRequest"
     msg="errors.required"/>
</global>
</form-validation>

なお、Strutsが提供する必須チェックは、String型のプロパティに適応される為、例えば、配列型の必須には使えません。ご注意を。

struts-config.xmlへの追加

今回はInputWorldForm.javaとInputWorldAction.java、input.jspを作成して、struts-config.xmlに設定しています。 

【form-beanの設定】

InputWorldForm.javaには、プロパティとして、「inputValue」を作成しています。getter/setterも作成済みです。

また、Formクラスは、validateFormを継承して作成するようにしてください。

<form-beans>
  <form-bean name="inputworld" type="jp.co.test.form.InputWorldForm">
</form-bean>

【actionの設定】

Actionクラスの設定としては、InputWorldActionを作成して、initを返すようにしています。また、設定としてvalidate="true"として、チェックを行うような指定をしています。

<!-- INPUT TEST -->
<action path="/inputworld" type="jp.co.test.actions.InputWorldAction"
    name="inputworld" validate="true" scope="session" input="/input.jsp">
<forward name="init" path="/input.jsp" />
</action>

 【メッセージファイルの設定】

エラー発生時に表示するエラーメッセージの設定を以下のように行います。

<message-resources parameter="MessageResources" />

MessageResources.propertiesの作成

struts-config.xmlで指定したメッセージファイルを作成します。メッセージファイルはソースと同じフォルダに配置します。

たとえば、今回のstruts-config.xmlの設定の場合で、ソースファイルをsrc/java/配下に作成している場合、src/java/MessageResources.propertiesというファイルを作成することになります。

errors.required = それは必須です。

ノウハウメモ

  • strutsの標準のチェックは基本的にString型のプロパティが対象である。
    つまり、String[]型の必須チェックなどを行いたい場合は、requiredではチェックできないので、別途専用のチェッククラスを作成する必要がある。
    その記事はまた、後程。

 以上。

Struts + Tiles

現場でStrutsを使い始めて、はや半年!あまりに昔のことすぎていろいろ忘れているので、Tilesメモ(笑)

 

Tilesって

Tilesとは、簡単にいえば、画面をタイルのようにブロック分けして作成していくためのものってことになります。

 

Tilesを使うためには

Tilesを使うためには、いろいろ設定が必要になります。

今は「設定よりもルール!」の時代なのですが、なにせ古いものですから。

 

■tilesの設定

  1. struts-tiles.tldの配置

    struts-tiles.tldを/WEB-INF/tld/配下に配置します。(場所は他のtldと同じでよいので、適時読み替えてください)

    WEB-INF/lib配下にstruts-tiles-x.x.x.jarがあることが前提です。

  2. web.xmlにtilesの設定を追加

    web.xmlに以下のようなtilesの設定を追加します。

    【web.xml
    <taglib>
    <taglib-uri>/tags/struts-tiles</taglib-uri>
    <taglib-location>/WEB-INF/tld/struts-tiles.tld</taglib-location>
    </taglib>
    

    上記設定の場合、tilesを使いたい場合は、以下のようにjspに記述します。
    <%@taglib uri="/tags/struts-tiles" prefix="tiles" %>
    


    ※以下のパラメータを<servlet>タグ内に記入しないとあとでエラーが発生したので、ここでメモ。

    <init-param>
    <param-name>chainConfig</param-name>
    <param-value>org/apache/struts/tiles/chain-config.xml</param-value>
    </init-param>
    
  3. struts-config.xmlにtilesの設定を追加 

    struts-config.xmlにtilesを使うための設定を追加します。

    struts-config.xml

    <plug-in className="org.apache.struts.tiles.TilesPlugin" >
    <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />
    <set-property property="moduleAware" value="true" />
    </plug-in>
  4. tilesの設定ファイルを作成

    /WEB-INF/tiles-defs.xmlを作成します。

    【tiles-defs.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration//EN"
    "http://jakarta.apache.org/struts/dtds/tiles-config_1_3.dtd">
    

    ※このファイルはあとで、設定を追加しますので、新規作成としてはここまで。

■tilesを使ってみよう

  1. tiles-defs.xmlに画面構成を追加
    設定手順で作成した、tiles-defs.xmlにtilesの画面設定を追加します。
    【tiles-defs.xml
    <tiles-definitions>
      <definition name="tilesworld" path="/tilesworld.jsp">
        <put name="title" value="ようこそTilesへ"/>
        <put name="header" value="/layout/header.jsp"/>
        <put name="footer" value="/layout/footer.jsp"/>
      </definition>
    </tiles-definitions>
    

    上記は、tilesworld.jspをtilesworldとして登録していることになります。

    さらにその設定値(値)として、title、menu、contentsと3つ用意して、それぞれに値を設定しています。

  2. JSPの作成
    今回、作成するのは、tilesworld.jsp、/layout/header.jsp、/layout/footer.jspの3つ。
    【tilesworld.jsp
    <%@ page language="java" contentType="text/html; 
        charset=UTF-8" pageEncoding="UTF-8"%> 
    <%@taglib uri="/tags/struts-html" prefix="html" %> 
    <%@taglib uri="/tags/struts-tiles" prefix="tiles" %> 
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
       "http://www.w3.org/TR/html4/loose.dtd"> 
    <html:html> 
      <head> 
        <title><tiles:getAsString name="title"/></title> 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
      </head> 
      <body> 
        <table border="1" width="100%"> 
          <tr> 
            <td valign="top"> 
              <tiles:insert attribute="header"/> 
            </td> 
          </tr> 
          <tr> 
            <td valign="top"> 
              ここにコンテンツが記述されます。 
            </td> 
          </tr> 
          <tr> 
            <td valign="top"> 
              <tiles:insert attribute="footer"/> 
            </td> 
          </tr> 
        </table> 
      </body> 
    </html:html>
    

    【header.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8"%>
    これがヘッダー!!
    

    【footer.jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    これがフッター!!
    
  3. Strutsなので、Actionなどを作成
    Strutsなので、ActionクラスやFormクラスを作る必要がありますが、今回はtilesのメモなのでそこらへんはスルーで、設定のみ。

    struts-config.xml
    <action path="/tilesworld" type="jp.co.test.actions.HelloWorldAction"
      className="jp.co.test.mapping.HelloWorldMapping"
      name="helloworld" validate="false" scope="session" input="/error.jsp">
    <forward name="init" path="tilesworld" />
    </action>
    

    ※前に作ったHelloWorldを参照してます。

    違いは、forward内のpathがtiles-defs.xmlのnameと一致していることぐらいです。

 

以上、簡単ですが、Struts+Tilesのメモでした。

 

Ajaxでファイルアップロード、そして・・・

Strutsを使ってファイルアップロードするという話があって、ちょいと調べたのでメモ。

 

Strutsのファイルアップロード

Strutsからファイルアップロードをする場合、ActionFormにFormFileクラスのプロパティを用意するのが一番手っ取り早そうだ。

 

■ActionForm側

public class FileUploadForm extends ActionForm{

  private FormFile file;

  /**
   * @return file
   */
  public FormFile getFile() {
    return file;
  }

  /**
   * @param file セットする file
   */
  public void setFile(FormFile file) {
    this.file = file;
  }
}

こんな感じ。これで、基本的にはファイルが受け取れる。

ただ、今回は画面Aで画像を選択して、確認ボタンを押下すると、モーダルダイアログを起動して、画像を表示するという仕様らしく(えらく古い仕様だ・・)

この調査中にshowModalDialogがすでに廃止された仕様であることが発覚して、どうしたものか思っているところでもある・・・w

 

さて、そんな仕様のため、単純にフォームからPOSTするとうわけにもいかず。

※showModalDialogにはPOSTできないらしい。

 

そこで思いついたのが、確認ボタン時にAjaxで画像だけ先行してアップロードしちゃって、そのあとJavaScriptで画像ファイル名なんかを引数にモーダルを開くって方法。

 

調べてみたら、JQueryAjaxで画像がアップロードできるらしいじゃないか。

 

で、以下がそのコード。

JavaScript
$(function() {
  $("input[name='upload']").click(function(){
    // ファイルアップロードのデータ生成
    var formData = new FormData();
    if ($("input[name='file']").val()!== '') {
      formData.append( "file", $("input[name='file']").prop("files")[0] );
    }
    // AJAX通信
    $.ajax({
      url : "/StrutsSample/fileUpload.do",
      type : "POST",
      data : formData,
      processData : false,
      contentType : false,
      dataType: "json",
      success : function(result) {
        // ここに、showModalDialogを記述して、画像パスを渡せば、いけんじゃね?
        alert(result.linkString);
      },
      error : function(xml,status,etc) {
      }
    });
  });
});

■HTML

<form action="" method="post">
  <input type="file" name="file">
  <input id="text" type="hidden" value="hoge">
  <input type="button" name="upload" value="アップロード">
</form>

 肝になるのは、contentType:false と processData: falseらしい。

 

なお、以下のようにすれば、ファイル以外も同時にあげれるらしい。

  // 追加データ
  formData.append("text",$("#text").val());

 しかし、いまさらshowModalDialogを使うのも、悩みどころ。

 

【後日談:2018/04/30】

最終的にはshowModalDialogでなくてもいいということになった。ほかの機能でできないと判断されたらしく、普通にJavaScriptでpostすることになった。

その際にIEだけうまくいかないという風に言われたが、特に問題なく稼働している・・謎w