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

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

スポンサーサイト

--.--.-- (--)  スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

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を起動させれば、自動的にフィルタがかかってくれる……はず!


スポンサーサイト

コメント

No title
コンテンツの順番をいれかえれば上手くいくと...参考になりました!thanks(^◇^)‼
Re: No title
>shuさん
コメントありがとうございます!
プログラム系の記事でお役にたてたの初めてだったので超嬉しいです;;
ヘボSEゆえ色々とおかしなとこあったらすみませんです><
助かりました!
よそのサイトを見ながら同じ文字化け対応してたのですが、エラー(filtersの配置場所のこと言ってたみたいでした)が出てずっと悩んでいたところ、こちらのサイトでようやく解決しました。
よそのサイトの説明に惑わされて、コンパイルできない場所にファイルを配置してました。お恥ずかしい。。。

とっても説明が、明快で分かりやすいです。
自分の思い込みを解消することができました。

本当にありがとうございました。
No title
>>みけねこさん

コメントありがとうございます!

配置場所って結構引っかかりやすいところなんですよね…バージョンによっても変わってきたりしますし、調べても正解が掴みづらいエラーだと思います…
この記事が少しでもみけねこさんのお役に立てたようでなによりです!
割と取っ散らかした書き方になってしまうなぁと反省することが多いのですが、説明がわかりやすいと言って頂いて本当に嬉しいです( ;∀;)

こちらこそ、ありがとうございました!

管理者のみに表示

トラックバック

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。