とある社畜(♀)のダイエット記録~プログラミングもあるよ~

新米SEのレコーディングダイエットの変遷、料理、プログラミング備忘録な雑多ブログです。

Struts_ハマったこと の記事一覧

strutsで文字化け地獄

2013.04.13 (Sat)  Struts_ハマったこと
【文字化け地獄】

もう…こいつには何度泣かされたことでしょう…
jspからサーブレットに日本語を送れば文字化け。DBからとってきた値をjspに表示させれば文字化け。なぜそこまで別の何かに化けたいのか。お前らには自分と言う確固たる芯が無いのかと問いたい。小一時間問い詰めたい。
とりあえず対処法をいくつか書いてみますね。


~画面からサーブレットに日本語を送る場合~


1.jspに文字エンコードの指定をする

jspの頭にこんなのを追加する。

<%@ page contentType="text/html; charset=UTF-8"%>

jsp自体の文字コードをUTF-8にするよ!と言う指定です。
ただこれ、サーブレットを経由しないjspに書くと逆に文字化けしたりとか、訳の分からん動きが時々ありました。
組み合わせによっては不味いことになるのだろうか。
これが書いてあるのに文字化けする!と言うときは逆に取っ払ってみるのも一つの手です。


2.jspに、リクエストを送信する際の文字エンコードの指定をする

jspにこんなのを追加する。

<% request.setCharacterEncoding("UTF-8"); %>

リクエストパラメータに入れる値をUTF-8で送るよ!という指定です。
私の場合はこれだけで上手くいったことはありません。なんでだろう環境の問題?


3.受け取り側で好きなようにエンコードしてしまう

例えばActionFormに入ってきた値が文字化けしてしまうなら、ActionForm内に文字コード変換メソッドを入れてあげます。
↓こんな感じ。



    /**
     * 文字列をUTF-8に変換して返します
     *
     * @param str
     */
    public String toUTF8(String str) {
        String reStr = null;
        try {
            reStr = new String(str.getBytes("ISO-8859-1"), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return reStr;

    }




↓上記メソッドの呼び出し部分はこんな感じ。
ゲッターに設定してあげます。



    /**
     * ユーザー名を取得します。
     *
     * @return String ユーザー名
     */
    public String getUserName(){
        if(this.userName!= null){
            return toUTF8(this.userName);
        }
        return this.userName;
    }



↓もちろん普通にActionに書いて変換しても。



    String name = req.getParameter("name");

    try {
        name = new String(name.getBytes("ISO-8859-1"), "UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }



ただ便利だからと言って必要の無いところ、例えばDBからの値をjspに送るためのbeanなんかに書くと逆に文字化けしました。
DBの文字コードと合ってなかったのかなー?ご利用は計画的に。


4.フィルターを使う

一番楽かもしれません。かつ強力。
ちょっと設定が多いので面倒に感じるかもしれませんが、これ一個設定しておけば同じプロジェクト内で作る限り後なんにも心配しなくて良い気がします。
ちなみに動的アクションフォーム(ダイナアクションフォーム)を使用する場合はformクラスをつくらないので3の方法が使えないため、バリデーションで弾かれた後actionを経由せずに文字コードの設定をしたいとなると、必然的にフィルター機能を使わざるを得ないと思います。

・tomcatをC直下に入れていた場合、
C:\tomcat\6.0\webapps\examples\WEB-INF\classes\filters
というパスが存在するはずです。
filtersフォルダの中にSetCharacterEncodingFilter.javaとSetCharacterEncodingFilter.classがあることを確認してください。

・上記二つのファイルを、ワークスペース内の/WEB-INF/classes以下の同名フォルダにコピーします。
デフォルトでは存在しないはずなので、自分でフォルダを作って放り込みます。
(例)
C:\pleiades\workspace\StrutsSumple\WEB-INF\classes\filters

・web.xmlに追記を行います。



<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">


<web-app>
~中略~
    <filter>
        <!-- ↓フィルターの名前を設定 -->
        <filter-name>EncodeFilter</filter-name>
        <!-- ↓上記で放り込んだフィルタークラスのパス -->
        <filter-class>filters.SetCharacterEncodingFilter</filter-class>
        <!-- ↓フィルタークラスのフィールドの初期化。この場合はUTF-8でエンコーディングさせる設定 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <!-- ↓使いたいフィルターの名前と一致させる -->
        <filter-name>EncodeFilter</filter-name>
        <!-- ↓どのURLを呼んだときに上記フィルタを起動させるか設定。この場合は全てのURLに対してフィルタを使う -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
~中略~
</web-app>



※J2EEが2.3以降でないと、どうやら<filter>タグは使えないようです。

<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
↑ここがちゃんと2.3以降になっているか確認してください。

ちなみに私は
<!DOCTYPE web-app   
  PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"   
  "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">   
この状態で作業してて、<web-app>のコンテンツにフィルターなんてねぇよ!!と怒られてました。ご注意を。


※web.xmlをいじるとこんなエラーが出るかもしれません

The content of element type "web-app" must match "(icon?,display-name?,description?,distributable?,context-param*,filter*,filter-mapping*,listener*,servlet*,servlet-mapping*,session-config?,mime-mapping*,welcome-file-list?,error-page*,taglib*,resource-env-ref*,resource-ref*,security-constraint*,login-config?,security-role*,env-entry*,ejb-ref*,ejb-local-ref*)".

または

要素タイプ "web-app" のコンテンツは "(icon?,display-name?,description?,distributable?,context-param*,filter*,filter-mapping*,listener*,servlet*,servlet-mapping*,session-config?,mime-mapping*,welcome-file-list?,error-page*,taglib*,resource-env-ref*,resource-ref*,security-constraint*,login-config?,security-role*,env-entry*,ejb-ref*,ejb-local-ref*)" と一致しなければなりません。


これは、カッコ内のコンテンツタイプの順番と、実際にweb.xmlに記載されているコンテンツの順番が違うというエラーです。
例えば<servlet>の下に<filter>を置いていたりとか。
エラー文言の通りの記述順に合わせてあげてください。
(ちなみに上記コンテンツタイプを全部記述する必要は無く、あくまで順番どおりに記述すれば良いのです)


これでtomcatを起動させれば、自動的にフィルタがかかってくれる……はず!


スポンサーサイト

jspが表示されない!

2013.03.23 (Sat)  Struts_ハマったこと
【jspが表示されない】
strutsは設定ファイル地獄と言われるほどstruts.configの設定が面倒くさいです。今回はそんな設定に関するエラー。

Actionからjspに遷移するところで、jspがないよーとtomcatに怒られてしまいました。
調べてみたところ、struts.configの記述をミスっていた模様。



 <action-mappings>
  <action
   path="/SumpleAction"
   type="test.question_2.action.SumpleAction"
   name="SumpleForm"
   scope="request"
   validate="false">
   <forward name="Sumple.jsp" path="jsp.question_2.Sumple.jsp">最後にスラッシュが無い!
  </action>
 </action-mappings>



スラッシュが無いだけじゃなく、<action type>の記述に引きずられて、パスの記述を.(ドット)区切りにしていたことも原因でした。
Actionはパッケージに入っているからドット区切り。jspは普通にフォルダの中に入っているからスラッシュ区切りでおk。

↓修正!



 <action-mappings>
  <action
   path="/SumpleAction"
   type="test.question_2.action.SumpleAction"
   name="SumpleForm"
   scope="request"
   validate="false">
   <forward name="BookList.jsp" path="/jsp/question_2/Sumple.jsp" />
  </action>
 </action-mappings>



きちんと認識してくれるようになりましたー!

ActionFormってサーブレットでどう受け取るの?

2013.03.20 (Wed)  Struts_ハマったこと
【jspから返されたActionFormをサーブレットで受け取れない】

まだActionFormの概念がよく分かってなかった頃に躓いたとこです。
引数で持ってきてるのになぜ直に扱えないんだー!となってました。下記の「form」の部分です。




class SumpleAction extends Action{

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse res){

form.getName(); //←コンパイルエラーになる

(~中略)

    }
}




formとして送られてくる想定の型にはちゃんとgetNameメソッドがあるのに、formから直にそのメソッドを呼び出そうとすると上手くいきません。
なぜなら、ここでformは「ActionForm」というabstract(抽象的)なクラスとして定義されているからなのです。
つまり実体が無いので、そのままでは受け取っても処理が出来ません。処理したい独自のActionFormにキャストしてあげる必要があります。

例えば「UserForm」という型として送られてくる想定なら

UserForm userform = (UserForm)form


こうしてあげれば、UserFormとしてサーブレット内で処理が出来るようになります。




class SumpleAction extends Action{

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse res){

UserForm userform = (UserForm)form //←型変更(キャスト)する
userform.getName();

(~中略)

    }
}




これでうまくいきました(´∀`)

Strutsタグが認識されないエラー

2013.03.16 (Sat)  Struts_ハマったこと
【Strutsのタグが認識されない!】

フレームワーク未使用で作成したサーブレットを、Strutsへ移行していた際に起きた現象です。
jspをごりごり直していたのですが、何故かデフォルトのhtml以外のタグが使えない。
Strutsと言えば豊富なタグが魅力ですが、<html:text>とか<logic:enpty>とかを記述しても「不明なタグです」と怒られる。
よくよく見てみれば、jspにタグをインポートしてなかった;



<%@ taglib uri="/tags/struts-html" prefix="html"%>
<%@ taglib uri="/tags/struts-bean" prefix="bean"%>
<%@ taglib uri="/tags/struts-logic" prefix="logic"%>



jspの頭の部分に、このように記述して解決。
ちなみに「prefix="html"」と書かれた部分は、/tags/struts-htmlの内容を「html」という名前で呼び出すよ!と宣言している部分です。
<html:text>とかの頭の「html」を示しているわけですね。

ちなみにこいつらは、web.xmlに記述されている



<taglib>
<taglib-uri>/tags/struts-bean
<taglib-location>/WEB-INF/tld/struts-bean.tld
</taglib>

<taglib>
<taglib-uri>/tags/struts-html
<taglib-location>/WEB-INF/tld/struts-html.tld
</taglib>

<taglib>
<taglib-uri>/tags/struts-logic
<taglib-location>/WEB-INF/tld/struts-logic.tld
</taglib>



これらのことです。<taglib-location>に示されているパス内のtldファイルを見に行ってくれてるんですねー
 | HOME |