→SAStruts関連

→[[JSP関連]]

→[[Java関連]]

→JavaのWebアプリ開発

→JBoss Seam関連

→DI(依存性注入)

→Webアプリ開発

→トランザクショントークン

→Webサーバ

#contents

----
*Webサイト [#t1934283]
-http://struts.apache.org/
-http://struts.apache.org/release/2.3.x/docs/struts-2-maven-archetypes.html


**環境構築 [#n8ff53b9]
大雑把な流れは以下の通り
-JDKをインストール
-Tomcatをインストール
-Eclipseをインストール
-TomcatプラグインをEclipseに追加
--http://www.eclipsetotale.com/tomcatPlugin.html

-[[Struts環境構築>http://tech.1-east.net/201004/225.html]]


**Tomcat [#p6704e5a]
-http://tomcat.apache.org/
-[[【はじめての方向け】Apache Tomcatのインストール方法を簡単に!>https://eng-entrance.com/java-servlet-tomcat-install]] 2019.8


**ドキュメント [#td181fde]
-http://struts.apache.org/release/2.3.x/index.html
-http://struts.apache.org/release/2.3.x/docs/tutorials.html



*入門記事、リファレンス [#n810abe3]
-[[Strutsについて>https://qiita.com/adevalue/items/1b4dea67cf1c96f937c3]] 2016.9

-[[Strutsの常識を知り、EclipseとTomcatの環境構築 (1/4)>http://www.atmarkit.co.jp/ait/articles/0807/31/news129.html]]

-[[@いう間にWebアプリを作れる「Struts 2」入門>http://www.atmarkit.co.jp/fjava/special/struts2/struts2_1.html]]
--いまいち使えない記事…

-[[Webアプリの常識をJSPとStrutsで身に付ける>http://www.atmarkit.co.jp/fjava/index/index_webjousiki.html]]

-[[Apache TomcatとJakarta TaglibsとApache Strutsとその他の部屋>http://kamakura.cool.ne.jp/oppama/ssja/index.html]]

-[[Strutsを使うWebアプリケーション構築術>http://www.atmarkit.co.jp/fjava/index/index_struts.html]]

-[[忘れっぽいエンジニアのための jakarta Strutsリファレンス>http://struts.wasureppoi.com/]]
-[[Struts>http://www.ne.jp/asahi/hishidama/home/tech/struts/index.html]]

-[[ケーピーの技術ノート Struts関連>http://kpnote.cocolog-nifty.com/blog/2008/11/struts-5710.html]]

-[[struts「設計パターン」についてまとめてみる>http://ledsun.hatenablog.com/entry/20120202/1328200624]] 2012.2.2


*Tips [#ec437f51]
-[[LookupDispatchActionクラス>http://www.javaroad.jp/opensource/js_struts14.htm]]
--1フォームに複数のsubmitボタンがあり、どれを押すかによって違う動きをさせたいときに使う。

-[[ForwardActionクラス>http://www.javaroad.jp/opensource/js_struts13.htm]]
--単純に画面遷移だけを行いたいときに使うActionクラス

-[[DynaActionForm>http://www.atmarkit.co.jp/fjava/rensai3/struts04/struts04_2.html]]
--フォームの項目をstruts-config.xmlに設定して自動生成できる
--<form-property>タグで指定した内容に合わせてformクラスを生成してくれる
--但し使用できるプロパティの型に制限がある。
--値取得の例
 DynaActionForm dForm = (DynaActionForm)form;
 int n = ((Integer)dForm.get("xxx")).intValue();

-[[エラーメッセージにヘッダーとフッターをつける>http://struts.wasureppoi.com/taglib/04_headder.html]]
--エラーメッセージのプロパティファイルに以下の値を作成する
--errors.header : エラーメッセージ出力前に1回出力される。
--errors.footer : エラーメッセージが全て出力後に1回出力される。
--errors.prefix : 各エラーメッセージの最初に出力される
--errors.suffix : 各エラーメッセージの最後に出力される


-[[validate()メソッドによる入力値検証>http://www.stackasterisk.jp/tech/java/strutsSec02_01.jsp]]

-http://strutstestcase.sourceforge.net/
-[[StrutsTestCase>http://634.ayumu-baby.com/strutstestcase/index.html]]
--Actionクラスの単体テストをするためのフレームワーク
--Actionによる画面遷移と定義されたActionErrorのチェックを行うことができ
--JUnitと組み合わせて動作するように設計されている
--Struts1.3.5から単体テスト機能がStrutsに追加されたのでそれを使うならStrutsTestCaseは不要


-リクエストヘッダの参照
 HttpServletRequest req = RequestUtil.getRequest();
 Enumeration<String> e = req.getHeaderNames();
 while(  e.hasMoreElements() ) {
   String s = e.nextElement();
   System.out.println(s + "=" +req.getHeader(s) );
 }

-セッション情報のバインドとアンバインドのタイミングで何かするには
--HttpSessionBindingListener を実装すればよい

-セッションのロケールを変更する
 HttpServletRequest req = RequestUtil.getRequest();
 HttpSession session = req.getSession();
 session.setAttribute(Globals.LOCALE_KEY, Locale.ENGLISH); 

-[[例外発生時のカスタムエラーページの設定>http://charie99.egloos.com/page/6]]
--やり方はいろいろあるが、struts-config内におけるエラーハンドリングの記述がま
ず考えられる手段だといえるだろう。
 <global-exceptions>
 <exception key="error.global" type="java.lang.Exception" path="/error.html"/>
 </global-exceptions>
 
 (struts-config.xml)

-[[メッセージリソースファイルの日本語処理>http://www.javaroad.jp/opensource/js_struts16.htm]]

-[[Struts でフォームに配列を使う>http://www.res-system.com/weblog/item/242]]

-[[配列のデータを取得したい。>http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=9471&forum=12&1]]

-[[StrutsでHTMLの表示や入力に配列を使用したい>http://www.whitemark.co.jp/tec/struts/strutsarray.html]]

-[[バリデータの自作>http://kamakura.cool.ne.jp/oppama/ssja/index.html]]

-[[Strutsでテキストをダウンロードする>http://kamakura.cool.ne.jp/oppama/ssja/struts-download.html]]

-[[Strutsでのプルダウンの作り方>http://www.masatom.in/pukiwiki/Struts/%A5%D7%A5%EB%A5%C0%A5%A6%A5%F3%A4%CE%BA%EE%A4%EA%CA%FD/]]

-[[URLの取得>http://www.memorycraft.jp/2009/02/sastrutsurl.html]]
 @Resource
 protected Map requestScope;
 
 @Execute(validator = false)
 public String test(){
 
        String requestUri = (String)requestScope.get("javax.servlet.forward.request_uri");
        String contextPath =(String)requestScope.get("javax.servlet.forward.context_path");
        String servletPath =(String)requestScope.get("javax.servlet.forward.servlet_path");
        String pathInfo =(String)requestScope.get("javax.servlet.forward.path_info");
        String queryString =(String)requestScope.get("javax.servlet.forward.query_string");
 
        System.out.println(requestUri);
        System.out.println(contextPath);
        System.out.println(servletPath);
        System.out.println(pathInfo);
        System.out.println(queryString);
                
        return "test.html";     
 }
--もしくは request.getURI()
--関連:[[サーブレットパスの構成要素を取得する>http://www.atmarkit.co.jp/fjava/javatips/067jspservlet030.html]]
 getContextPath  	コンテキストパス
 getServletPath 	サーブレットパス
 getPathInfo 	拡張パス
 getPathTranslated 	拡張パス(物理パス)
 getRequestURL 	リクエスト時のURL
 getRequestURI 	コンテキストパスから拡張パスまで

-[[サーブレット仕様の認証を使わずにgetRemoteUserやisUserInRoleを使う>http://d.hatena.ne.jp/paulownia/20080918/1221751667]]
--独自の認証機構を使うと自由にログイン処理を記述できる代わりにHttpServletRequestのgetRemoteUserやisUserInRoleは使えない。
--しかし独自の認証でもHttpServletRequestWrapperとFilterを組み合わせれば、getRemoteUserやisUserInRoleを有効にできる。

-[[画面遷移とアクセス制御の方法>http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=8447&forum=12&3]]

-[[「どのスコープにもBean org.apache.struts.taglib.html.BEAN がありません」というエラー>http://maebashi.cool.ne.jp/kuruchi/memo1.shtml]]
--どっかタグが抜けてたり閉じ忘れてたり。
--formでないのにproperty設定してるタグを使っている。formのネスト内のみ有効のタグは、html:textareaやhtml:textやhtml:passwordなど


*入門記事、リファレンス [#n810abe3]
-[[Struts/基礎>http://f13.aaa.livedoor.jp/~itiit/wiki/pukiwiki.php?%5B%5BStruts%2F%B4%F0%C1%C3%5D%5D]]
--ActionServletのカスタマイズ方法など

-[[Webアプリの常識をJSPとStrutsで身に付ける>http://www.atmarkit.co.jp/fjava/index/index_webjousiki.html]]

-[[Apache TomcatとJakarta TaglibsとApache Strutsとその他の部屋>http://kamakura.cool.ne.jp/oppama/ssja/index.html]]

-[[Strutsを使うWebアプリケーション構築術>http://www.atmarkit.co.jp/fjava/index/index_struts.html]]

-[[忘れっぽいエンジニアのための jakarta Strutsリファレンス>http://struts.wasureppoi.com/]]
-[[Struts>http://www.ne.jp/asahi/hishidama/home/tech/struts/index.html]]

-[[ケーピーの技術ノート Struts関連>http://kpnote.cocolog-nifty.com/blog/2008/11/struts-5710.html]]


*SAStruts [#b4785db7]
-テーブルの一部の列を入力欄にして、各行につけたボタンでsubmitしたいとき
--JSP側。html:text のindexedをfalseにするのがポイント
 <c:forEach var="m" items="${mapItems}" begin="0"
 	end="${dispMax - 1}" step="1">
 	<s:form target="_blank" >
 	<tr>
 		<td class="data01">${f:h(m.referenceId)}</td>
 		<td class="data01">${f:h(m.orderNo)}</td>
 		<td class="data01">${f:h(m.orderDateYmd)}</td>
 		<td class="data01">
 		<html:text name="m" property="passengerName" indexed="false" value="${m.passengerName}" />
 		</td>
 		<td class="data01">
 		<html:text name="m" property="messageBox" indexed="false" value="${m.messageBox}" />
 		</td>
 		<td class="data01">${f:h(m.issuedStatus)}</td>
 		<td class="data01">${f:h(m.childCd)}</td>
 		<td class="data01">
 			<html:hidden property="id" value="${m.referenceId}"/>
 			<input type="submit" name="detail" value="詳細表示"/>
 		</td>
 	</tr>
 	</s:form>
 </c:forEach>
--フォームクラス側
 public String issued_status; //発行ステータス
 public String ken_syubetsu;
 public String child_code;
--Action側はdetailメソッドが呼ばれたときにフォームの変数にアクセスできる

-validateでエラーになったときに遷移する先(input属性で指定するjsp)を場合にによって切り替えたいとき
--inputにはjspだけでなくurlを指定しても良いので、Actionに切替用の実行メソッドを用意し、それをinputに指定する。その上でそのメソッドの中で遷移先を切り替えればよい

-[[SAStrutsの入力チェックの順序>http://d.hatena.ne.jp/koroharo/20090514/1242269946]]

-セッションのDtoでIllegalArgumentExceptionになる場合、serializableを実装して
ないクラスをメンバに持っていないかチェック
 2009-05-18 19:04:05,156 [http-8080-2]
 org.apache.struts.action.RequestProcessor
 ERROR - パス /index に対するアクションのインスタンスがありません
 Caused by: java.lang.IllegalArgumentException:

-サーバの処理結果をポップアップメッセージで出すには
--jsp側でこのようにしておく
 <body onload="${f:h(onLoadScript)}">
--Action側でonLoadScriptのプロパティを用意し、そこにjavascriptを書く。
--(例)
 this.onLoadSctipt = "alert('更新処理が正常に終了しました')";
--onLoadScriptプロパティは必要ならセッションスコープにする。
--jspをリロードする
--ただしこの方法だと戻るボタンなどでそのページに戻ってきたときもalert()が動いてしまうのだが

-リクエストのヘッダ情報を参照
 HttpServletRequest req = RequestUtil.getRequest();
 Enumeration<String> e = req.getHeaderNames();
 while(  e.hasMoreElements() ) {
    String s = e.nextElement();
    System.out.println(s + "=" +req.getHeader(s) );
 }

-画像のバイナリイメージをHTTPレスポンスとして出力
 package test.action;
*struts-config.xmlのタグ [#fc59d962]
-<global-exceptions> 例外処理の設定
--[[例外発生時のカスタムエラーページの設定>http://charie99.egloos.com/page/6]]
--やり方はいろいろあるが、struts-config内におけるエラーハンドリングの記述がま
ず考えられる手段だといえるだろう。
 <global-exceptions>
 <exception key="error.global" type="java.lang.Exception" path="/error.html"/>
 </global-exceptions>
 
 import java.awt.Color;
 import java.awt.Graphics2D;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.net.URL;
 
 import javax.imageio.ImageIO;
 import javax.imageio.ImageWriter;
 import javax.imageio.stream.ImageOutputStream;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
 import org.seasar.struts.annotation.Execute;
 import org.seasar.struts.util.ResponseUtil;
 
 public class OutImgAction {
 
   public String id;
 
   //
   // 画像をhttpレスポンスのボディとして出力してみるテスト
   //
   // 呼ぶときは↓こんなふうにします
   // http://localhost:8080/test/outImg/output/1
   //
   @Execute(validator=false, urlPattern = "output/{id}")
   public String output() {
     try {
       URL url = getClass().getResource("../../data/sample.png");
       BufferedImage im = ImageIO.read(url.openStream());
 
       HttpServletResponse response = ResponseUtil.getResponse();
       response.setContentType("image/jpeg");
       ServletOutputStream sos = response.getOutputStream();
       ImageOutputStream ios = ImageIO.createImageOutputStream(sos);
       ImageWriter iw = (ImageWriter)ImageIO.
                       getImageWritersByFormatName("jpeg").next();
       iw.setOutput(ios);
 
           //IDを表示してみる
       Graphics2D g = im.createGraphics();
       g.setColor(Color.BLACK);
       g.drawString("id="+id, 20, 20);
       g.dispose();
 
       iw.write(im);
 
      ios.close();
      sos.close();
 
     } catch (IOException e) {
       e.printStackTrace();
     }
 
     return null;
   }
 
   @Execute(validator = false)
     public String index() {
     return "/";
     }
 }
--注意点:ServletOutputStreamを明示的にclose()してやらないと以下のような例外になるので注意
 java.lang.IllegalStateException: レスポンスをコミットした後でフォワードできません
 (struts-config.xml)

-<global-forwards> 共通の遷移
-<action-mappings> Actitonクラスと画面遷移(forward)の設定
--forwardはmapping.findforward()の引数に渡す文字列
-<message-resources> メッセージリソース
--(ベース名).properties 日本語を使うときはnative2asciiを使う
-<plug-in> プラグインの設定
-<form-beans> フォームクラスの設定
-<data-sources> データソースの設定


-[[AJAXでXMLを取得>http://code.nanigac.com/source/wiki/view_title/597/Ajax%E3%81%A7XML%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%8F%96%E5%BE%97%E3%81%97%E3%81%BE%E3%81%97%E3%82%87%E3%81%86]]

-[[SAStruts関連@codeなにがし>http://code.nanigac.com/source/wiki/view/597]]

--[[SAStrutsに関して読んでおきたい資料集>http://code.nanigac.com/source/wiki/view_title/597/SAStruts%E3%81%AB%E9%96%A2%E3%81%97%E3%81%A6%E8%AA%AD%E3%82%93%E3%81%A7%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84%E8%B3%87%E6%96%99%E9%9B%86]]

--[[DoltengでHello project>http://code.nanigac.com/source/wiki/view_title/597/Dolteng%E3%81%A7%E3%80%8CHello%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%80%8D%E3%82%92%E4%BD%9C%E6%88%90%E3%81%97%E3%81%BE%E3%81%97%E3%82%87%E3%81%86]]
---Apache+Tomcat連携設定の説明アリ

--[[開発時に気をつけること>http://code.nanigac.com/source/wiki/view_title/597/%E9%96%8B%E7%99%BA%E6%99%82%E3%81%AB%E6%B0%97%E3%82%92%E3%81%A4%E3%81%91%E3%82%8B%E3%81%93%E3%81%A8%E9%9B%86]]
---プロパティ以外でgetXXXXというメソッド名にしない
---セッションスコープにした変数にSerializableをimplementsしてない変数があるとSIllegalArgumentException


-[[サーバ再起動不要のSMART deployとバリデーション>http://www.atmarkit.co.jp/fjava/rensai4/saweb03/saweb03_1.html]]
--SMART deployはDIコンテナである「Seasar」のバージョン2.4から実装されたデプロイ機能で、DI(依存性の注入)の技術が生かされています。
--デプロイ方法には「HOT」「COOL」「WARM」の3種類があります。
--開発時には便利なHOT deployですが、若干パフォーマンスが悪くなります。本番運用のときはソースコードを変える必要はないので、要らない機能となってしまいます。そこでリリース時には、COOL deployで動作させます。
--WARM deployは必要なとき必要なクラスを読み込むもので、HOT deployとCOOL deployの中間のような機能です。例えば、JUnitなどのテスティングフレームワークでテストをするときにはソースコードの変更はありません。しかし、単体テストではすべての機能を動作させるわけではないので、COOL Deployのときのようにプロジェクト全体のすべてのDI設定を行う必要はないはずです。
--すべての設定を行うと、当然それだけ起動が遅くなるので、必要ない部分を読み込みたくないときは、単体テストで必要な最小限の設定を読み込み、オブジェクトが生成できればいいわけです。そうしたときに使用するのがWARM deployです。

-[[JSPでActionに指定したrolesを使う>http://d.hatena.ne.jp/cypher256/20080429/p2]]

-[[SAStrutsでログイン確認インターセプタを使う>http://d.hatena.ne.jp/idesaku/20081226/1230263190]]

-[[SAStrutsタグ>http://www.atmarkit.co.jp/fjava/rensai4/saweb04/saweb04_1.html]]
--<s:form>タグ
--<s:form>タグは、Strutsのカスタムタグの1つ<html:form>タグに代わるものです。<html:form>タグでは、Actionパスの再計算が行われないため、相対パスなどで記述すると同じページにアクセスするたびに、URLがずれてしまう問題がありました。
--SAStrutsで用意されている<s:form>タグではaction属性を設定したリンクのURLを
基準として、パスが「/」で始まっている場合、コンテキストルートから見た絶対パスになります。パスが「/」で始まっていない場合、JSPファイルから見た相対パスが計算されて設定されます。
--この自動計算により、リクエストのパスが「/dept」であっても「/dept/list」で
あっても、相対パスで入力してあっても出力URLがずれたりすることがなくなります。
-- <s:link>タグ
--<s:link>タグは先ほど紹介した<s:form>タグのリンク版です。Strutsの<html:link>タグに代わるものです。href属性を設定するときに<s:form>と同様のパスの計算が行われ同様に出力URLがずれることがなくなります。
-- <s:submit>タグ
--<s:submit>タグはStrutsの<html:submit>タグに代わるものです。
--<s:submit>タグを使用すると、簡単にクライアントバリデーションが設定できます。clientValidate属性にtrueを設定するとクライアントバリデーションができます。

-[[StrutsのXML地獄から開発者を解放するSAStruts@IT>http://www.atmarkit.co.jp/fjava/rensai4/saweb02/saweb02_1.html]]

-[[SAStruts>http://sastruts.seasar.org/]]
-http://wiki.paulownia.jp/java/sastruts
-[[SAStruts入門>http://snowhiro.web.fc2.com/sastruts/]]
-[[SAStrutsPlugin>http://sastruts.seasar.org/sastrutsplugin.html]]

-[[SASTruts チートシート>http://seasar-users.jp/cheatsheet/sastruts]]


*トランザクショントークン [#sf533000]
-[[Strutsトランザクショントークン>http://www.ne.jp/asahi/hishidama/home/tech/struts/ttoken.html]]
--表示する画面の中にhiddenでランダムなID(トークン)を埋め込んでおき、そのトークンをサーバー側でもセッション内に保持しておく。
--その画面でサブミットされると、hiddenに埋められていたトークンがリクエストに入れられてサーバーに届く。
--サーバーでは、届いたhiddenのトークンとセッション内に保持していたトークンを比較する。一致していれば正しい遷移と判断する。
--別の画面のhiddenには別のトークンが埋められている為、意図しない画面から来た場合はセッション内のトークンとは一致しないので 誤った遷移であると判断できる。
--比較直後にセッション内からトークンを削除しておけば、重複サブミットの二度目の処理を防止できる。
--つまり、連続してサブミットボタンが押されたような場合には同一のトークンが再び届くが、セッションのトークンは既に存在しないので一致しない。すなわち不正なサブミットだと判断できる。

-org.apache.struts.util.TokenProcessor というシングルトンなクラスを使う

-実装手順(SAStrutsの場合)
--アクションクラスでリクエストを触れるようにしておく
 @Resource
 protected HttpServletRequest request;

--ページのindex()などでセッションにトークンをセーブします。
 TokenProcessor.getInstance().saveToken(request);

--jspは修正する必要がありません(※)

--チェックしたいタイミングでこのようにチェックする
 if( TokenProcessor.getInstance().isTokenValid(request, true) ==false){
    //戻るボタンによる二度押しされたときのエラー処理
   addGlobalMessage(MessageId.W_TRANSACTION_TOKEN_ERROR);
   ...(適切な画面に遷移など)
  }
--チェックとは、セッションに保存したトークンとjspからリクエストに渡されたトークンがマッチするかをチェックしています。これがfalseで帰ってきたら、戻るボタンで戻って二度目のsubmitで来たということです。チェックしたあとトークンをsessionから消すなら第二引数をtrueにします。通常はtrue。


-※本来ならばjspファイルのほうで、
 <form id="form">
 <input type="hidden" id="token" name="org.apache.struts.taglib.html.TOKEN" .../>
 ...
 </form>
としておく必要がありますが、セッションにトランザクショントークンがセーブしてあるとStrutsが自動的にinputタグを差し込んでくれます。

-[[参考ページ1>http://f13.aaa.livedoor.jp/~itiit/wiki/pukiwiki.php?%5B%5BStruts%2F%B4%F0%C1%C3%5D%5D]]
-[[参考ページ2>http://www.masatom.in/pukiwiki/Struts/%C6%B1%B4%FC%A5%C8%A1%BC%A5%AF%A5%F3%A4%C7%C6%F3%C5%D9%B2%A1%A4%B7%A4%CA%A4%C9%A4%F2%A5%C1%A5%A7%A5%C3%A5%AF%A4%B9%A4%EB/]]


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS