4.6. メッセージ管理¶
Caution
本バージョンの内容は既に古くなっています。最新のガイドラインはこちらからご参照ください。
4.6.1. Overview¶
Warning
以下の場合において、運用中、あるいは運用前の試験の際、エラーの原因を究明できなくなるリスクが生じる。(開発中は、特に困らないかもしれない。)
- エラーメッセージを、1つのみ定義している
- エラーメッセージを、「重要」と「警告」の2つしか定義していない
その結果、開発メンバが少ない中で、メッセージの定義変更を行い、開発が進むにつれて、修正コストが増えることになる。 そのため、あらかじめメッセージは、細かい粒度で定義しておくことを推奨する。
4.6.1.1. メッセージタイプ¶
メッセージタイプ | カテゴリ | 概要 |
---|---|---|
info | 情報メッセージ | ユーザの操作による処理が正常に実行された後、画面に表示するメッセージ。 |
warn | 警告メッセージ | 処理は継続できるが、注意喚起が必要な状態である場合に表示するメッセージ。(例:パスワード有効期限切れが近い場合の通知メッセージ) |
error | 入力エラーメッセージ | ユーザの入力値が不正な場合に、入力画面に表示するメッセージ。 |
業務エラーメッセージ | 業務ロジックでエラーと判定された場合に表示するメッセージ | |
システムエラーメッセージ | システム起因のエラー(データベースとの接続失敗等)が発生し、ユーザの操作でリカバリできない場合に表示するメッセージ |
4.6.1.2. パターン別メッセージタイプの分類¶
メッセージの出力パターンを、以下に示す。
メッセージパターンとメッセージの表示内容、及びメッセージタイプを、以下に示す。
記号 | パターン | 表示内容 | メッセージタイプ | 例 |
---|---|---|---|---|
(A)
|
タイトル
|
画面のタイトル
|
-
|
|
ラベル
|
画面の項目名
帳票の項目名
コメント
ガイダンス
|
-
|
|
|
(B)
|
ダイアログ
|
確認メッセージ
|
info
|
|
(C)
|
結果メッセージ
|
正常終了
|
info
|
|
(D)
|
警告
|
warn
|
|
|
(E)
|
単項目チェックエラー
|
error
|
|
|
(F)
|
相関チェックエラー
|
error
|
|
|
(G)
|
業務エラー
|
error
|
|
|
(H)
|
システムエラー
|
error
|
|
4.6.1.3. メッセージID体系¶
- メッセージ変更時に、ソースコードを修正することなくメッセージを変更するため
- メッセージの出力箇所を特定しやすくするため
- 国際化に対応できるため
メッセージIDの決め方は、メンテナンス性向上のため、規約を作って統一することを強く推奨する。
4.6.1.3.1. タイトル¶
フォーマット
接頭句 区切り 業務名 区切り 画面名 title.nnn*.nnn*記述内容
項目 位置 内容 備考 接頭句1-5桁目 (5桁)“title” (固定)業務名可変長:任意spring-mvc.xmlで定義したviewResolverのprefixの下のディレクトリ(JSPの上位ディレクトリ)画面名可変長:任意JSP名ファイル名が”aaa.jsp”の場合”aaa”の部分定義例
# "/WEB-INF/views/admin/top.jsp"の場合 title.admin.top=Admin Top # "/WEB-INF/views/staff/createForm.jsp"の場合 title.staff.createForm=Staff Register Input
Tip
本例は、Tilesを利用する場合に有効である。詳細は Tilesによる画面レイアウト を参照されたい。 Tilesを利用しない場合は、次に説明するラベルの規約を利用しても良い。
4.6.1.3.2. ラベル¶
画面のラベル、帳票の固定文言に使用する、メッセージIDの決め方について説明する。
フォーマット
接頭句 区切り プロジェクト区分 区切り 業務名 区切り 項目名 label.xx.nnn*.nnn*記述内容
項目 位置 内容 備考 接頭句1-5桁目 (5桁)“label” (固定)プロジェクト区分7-8桁名 (2桁)プロジェクト名のアルファベット2桁表記業務名可変長:任意項目名可変長:任意ラベル名、説明文名Note
入力チェックエラーのメッセージに項目名(論理名)を含める場合は、
- フォームのモデル名 + “.” + フィールド名
staffForm.staffName = Staff name
- フィールド名
staffName = Staff name
にする必要がある。
使用例
# スタッフ登録画面のフォームの項目名 # プロジェクト区分=em (Event Management System) label.em.staff.staffName=Staff name # ツアー検索画面に表示する説明文の場合 # プロジェクト区分=tr (Tour Reservation System) label.tr.tourSearch.tourSearchMessage=You can search tours with the specified conditions.
Note
プロジェクトが複数存在する場合に、メッセージIDが重複しないようにプロジェクト区分を定義する。 単一プロジェクトの場合でも、将来を見据えてプロジェクト区分を定義することを推奨する。
4.6.1.3.3. 結果メッセージ¶
4.6.1.3.3.1. 業務間で共通して使用するメッセージ¶
同一メッセージを定義しないように、複数の業務間で共有するメッセージについて説明する。
フォーマット
メッセージタイプ 区切り プロジェクト区分 区切り 共通メッセージ区分 区切り エラーレベル 連番 x.xx.fw.9999記述内容
項目 位置 内容 備考 メッセージタイプ1桁目 (1桁)info : iwarn : werror : eプロジェクト区分3-4桁目 (2桁)プロジェクト名のアルファベット2桁表記共通メッセージ区分6-7桁目 (2桁)“fw” (固定)エラーレベル9桁 (1桁)0-1 : 正常メッセージ2-4 : 業務エラー(準正常)5-7 : 入力チェックエラー8 : 業務エラー(エラー)9 : システムエラー連番10-12桁目 (3桁)連番で利用する(000-999)メッセージ削除となっても連番は空き番として、削除しない使用例
# 登録が成功した場合(正常メッセージ) i.ex.fw.0001=Registered successfully. # サーバリソース不足 w.ex.fw.9002=Server busy. Please, try again. # システムエラー発生の場合(システムエラー) e.ex.fw.9001=A system error has occurred.
4.6.1.3.3.2. 各業務で個別に使用するメッセージ¶
業務で個別に使用するメッセージについて説明する。
フォーマット
メッセージタイプ 区切り プロジェクト区分 区切り 業務メッセージ区分 区切り エラーレベル 連番 x.xx.xx.9999記述内容
項目 位置 内容 備考 メッセージタイプ1桁目 (1桁)info : iwarn : werror : eプロジェクト区分3-4桁目 (2桁)プロジェクト名のアルファベット2桁表記業務メッセージ区分6-7桁目 (2桁)業務IDなど業務毎に決める2桁の文字エラーレベル9桁 (1桁)0-1 : 正常メッセージ2-4 : 業務エラー(準正常)5-7 : 入力チェックエラー8 : 業務エラー(エラー)9 : システムエラー連番10-12桁目 (3桁)連番で利用する(000-999)メッセージ削除となっても連番は空き番として、削除しない使用例
# ファイルのアップロードが成功した場合 i.ex.an.0001={0} upload completed. # パスワードの推奨変更期間が過ぎている場合 w.ex.an.2001=The recommended change interval of password has passed. Please change your password. # ファイルサイズが制限を超えている場合 e.ex.an.8001=Cannot upload, Because the file size must be less than {0}MB. # データに不整合がある場合 e.ex.an.9001=There are inconsistencies in the data.
4.6.1.3.4. 入力チェックエラーメッセージ¶
入力チェックでエラーがある場合に出力するメッセージについては、エラーメッセージの定義を参照されたい。
Note
入力チェックエラーの出力場所に関する基本方針を、以下に示す。
単項目入力チェックエラーのメッセージは、対象の項目がわかるように項目の横に表示させる。 相関入力チェックエラーのメッセージは、ページ上部などにまとめて表示させる。 単項目チェックでもメッセージを項目の横に表示させにくい場合は、ページ上部に表示させる。その場合は、メッセージに項目名を含める。
4.6.2. How to use¶
4.6.2.1. プロパティファイルに設定したメッセージの表示¶
4.6.2.1.1. プロパティを使用する際の設定¶
メッセージ管理を行うorg.springframework.context.MessageSource
の実装クラスの定義を行う。
applicationContext.xml
<!-- Message --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <!-- (1) --> <property name="basenames"> <!-- (2) --> <list> <value>i18n/application-messages</value> </list> </property> </bean>
項番 説明 (1)MessageSource
の定義。ここではResourceBundleMessageSource
を使用する。(2)使用するメッセージプロパティの基底名を定義する。クラスパス相対で指定する。この例では”src/main/resources/i18n/application-messages.properties”を読み込む。
4.6.2.1.2. プロパティに設定したメッセージの表示¶
application-messages.properties
ここでは、
application-messages.properties
にメッセージを定義する例を示す。label.aa.bb.year=Year label.aa.bb.month=Month label.aa.bb.day=Day
Note
文字コード「ISO-8859-1」では表現できない文字(日本語など)は
native2ascii
コマンドで ISO-8859-1に変換して使用することが多かった。しかし、JDK 6からは文字コードを指定できるようになったため、 変換する必要はない。文字コードUTF-8にすることで、propertiesファイルに直接日本語等を使用できる。application-messages.properties
label.aa.bb.year=年 label.aa.bb.month=月 label.aa.bb.day=日
この場合、以下のように、
ResourceBundleMessageSource
にも読み込む文字コードを指定する必要がある。applicationContext.xml
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>i18n/application-messages</value> </list> </property> <property name="defaultEncoding" value="UTF-8" /> </bean>
デフォルトではISO-8859-1が使用されるため、日本語等をpropertiesファイルに直接記述したい場合は、 必ず
defaultEncoding
を設定すること。JSP
上記で設定したメッセージをJSPからは、
<spring:message>
タグを用いて表示できる。 インクルード用の共通JSPの作成の設定が必要である。<spring:message code="label.aa.bb.year" /> <spring:message code="label.aa.bb.month" /> <spring:message code="label.aa.bb.day" />
フォームのラベルと使用する場合は、以下のように使用すれば良い。
<form:form modelAttribute="sampleForm"> <form:label path="year"> <spring:message code="label.aa.bb.year" /> </form:label>: <form:input path="year" /> <br> <form:label path="month"> <spring:message code="label.aa.bb.month" /> </form:label>: <form:input path="month" /> <br> <form:label path="day"> <spring:message code="label.aa.bb.day" /> </form:label>: <form:input path="day" /> </form:form>
ブラウザで表示すると以下のように出力される。
Tip
国際化に対応する場合は、
src/main/resources/i18n ├ application-messages.properties (英語メッセージ) ├ application-messages_fr.properties (フランス語メッセージ) ├ ... └ application-messages_ja.properties (日本語メッセージ)
というように各言語用のpropertiesファイルを作成すればよい。 詳細は、国際化を参照されたい。
4.6.2.2. 結果メッセージの表示¶
org.terasoluna.gfw.common.message.ResultMessages
、およびorg.terasoluna.gfw.common.message.ResultMessage
を提供している。クラス名 | 説明 |
---|---|
ResultMessages |
結果メッセージの一覧とメッセージタイプを持つクラス。
結果メッセージの一覧は
List<ResultMessage> 、メッセージタイプはorg.terasoluna.gfw.common.message.ResultMessageType インタフェースで表現される。 |
ResultMessage |
結果メッセージのメッセージID、または、メッセージ本文を持つクラス。
|
<t:messagesPanel>
タグも提供される。4.6.2.2.1. 基本的な結果メッセージの使用方法¶
ControllerでResultMessages
を生成して画面に渡し、JSPで<t:messagesPanel>
タグを使用して、
結果メッセージを表示する方法を説明する。
Controllerクラス
ResultMessages
オブジェクトの生成方法、および画面へメッセージを渡す方法を示す。 application-messages.proertiesには、各業務で個別に使用するメッセージの例が定義されていることとする。package com.example.sample.app.message; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.terasoluna.gfw.common.message.ResultMessages; @Controller @RequestMapping("message") public class MessageController { @RequestMapping(method = RequestMethod.GET) public String hello(Model model) { ResultMessages messages = ResultMessages.error().add("e.ex.an.9001"); // (1) model.addAttribute(messages); // (2) return "message/index"; } }
項番 説明 (1)メッセージタイプが”error”であるResultMessages
を作成し、メッセージIDが”e.ex.an.9001”である結果メッセージを設定する。この処理は次と同義である。ResultMessages.error().add(ResultMessage.fromCode("e.ex.an.9001"));
メッセージIDを指定する場合は、ResultMessage
オブジェクトの生成を省略できるため、省略することを推奨する。(2)ResultMessages
をModelに追加する。属性は指定しなくてよい。(属性名は”resultMessages”になる)JSP
WEB-INF/views/message/index.jspを、以下のように記述する。
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>Result Message Example</title> </head> <body> <h1>Result Message</h1> <t:messagesPanel /><!-- (1) --> </body> </html>
項番 説明 (1)<t:messagesPanel>
タグをデフォルト設定で使用する。デフォルトでは、属性名が”resultMessages”のオブジェクトを表示する。そのため、デフォルトではControllerからModelにResultMessages
を設定する際に、属性名を設定する必要がない。ブラウザで表示すると、以下のように出力される。
<t:messagesPanel>
によって出力されるHTMLを、以下に示す(説明しやすくするために整形している)。<div class="alert alert-error"><!-- (1) --> <ul><!-- (2) --> <li>There are inconsistencies in the data.</li><!-- (3) --> </ul> </div>
項番 説明 (1)メッセージタイプに対応して”alert-error”クラスが付与されている。デフォルトでは<div>
タグのclassに”error error-[メッセージタイプ]”が付与される。(2)結果メッセージのリストが<ul>
タグで出力される。(3)メッセージIDに対応するメッセージがMessageSource
から解決される。<t:messagesPanel>
はclassを付けたHTMLを出力するだけであるため、見栄えは出力されたclassに合わせてCSSでカスタマイズする必要がある(後述する)。Note
ResultMessages.error().add(ResultMessage.fromText("There are inconsistencies in the data."));
というように、 メッセージの本文をハードコードすることもできるが、保守性を高めるため、メッセージキーを使用してResultMessage
オブジェクトを作成し、 メッセージ本文はプロパティファイルから取得することを推奨する。
メッセージのプレースホルダに値を埋める場合は、次のようにadd
メソッドの第二引数以降に設定すればよい。
ResultMessages messages = ResultMessages.error().add("e.ex.an.8001", 1024);
model.addAttribute(messages);
この場合、<t:messagesPanel />
タグにより、以下のようなHTMLが出力される。
<div class="alert alert-error">
<ul>
<li>Cannot upload, Because the file size must be less than 1,024MB.</li>
</ul>
</div>
Warning
terasoluna-gfw-web 1.0.0.RELEASEを使用してプレースホルダに値を埋める場合の注意点
terasoluna-gfw-web 1.0.0.RELEASEを使用している場合、プレースホルダにユーザの入力値を埋め込むとXSS脆弱性の危険がある。ユーザの入力値にXSS対策が必要な文字が含まれる可能性がある場合は、プレースホルダに値を埋め込まないようにすること。
terasoluna-gfw-web 1.0.1.RELEASE以上を使用している場合は、ユーザの入力値をプレースホルダに埋め込んでもXSS脆弱性は発生しない。
Note
ResourceBundleMessageSource
はメッセージを生成する際にjava.text.MessageFormat
を使用するため、1024
は カンマ区切りで1,024
と表示される。カンマが不要な場合は、プロパティファイルには以下のように設定する。e.ex.an.8001=Cannot upload, Because the file size must be less than {0,number,#}MB.詳細は、Javadocを参照されたい。
以下のように、複数の結果メッセージを設定することもできる。
ResultMessages messages = ResultMessages.error()
.add("e.ex.an.9001")
.add("e.ex.an.8001", 1024);
model.addAttribute(messages);
この場合は、次のようなHTMLが出力される(JSPの変更は、不要である)。
<div class="alert alert-error">
<ul>
<li>There are inconsistencies in the data.</li>
<li>Cannot upload, Because the file size must be less than 1,024MB.</li>
</ul>
</div>
infoメッセージを表示したい場合は、次のようにResultMessages.info()
メソッドでResultMessages
オブジェクトを作成すればよい。
ResultMessages messages = ResultMessages.info().add("i.ex.an.0001", "XXXX");
model.addAttribute(messages);
以下のようなHTMLが、出力される。
<div class="alert alert-info"><!-- (1) -->
<ul>
<li>XXXX upload completed.</li>
</ul>
</div>
項番 | 説明 |
---|---|
(1)
|
メッセージタイプに対応して、出力されるclass名が”alert alert-info”に変わっている。
|
標準では、以下のメッセージタイプが用意されている。
メッセージタイプ | ResultMessages オブジェクトの作成 |
デフォルトで出力されるclass名 | 備考 |
---|---|---|---|
success
|
ResultMessages.success() |
alert alert-success
|
-
|
info
|
ResultMessages.info() |
alert alert-info
|
-
|
warn
|
ResultMessages.warn() |
alert alert-warn
|
メッセージタイプ「warning」の追加に伴い、terasoluna-gfw-common 5.0.0.RELEASEから非推奨。
このメッセージタイプは将来削除される可能性がある。
|
warning
|
ResultMessages.warning() |
alert alert-warning
|
CSSフレームワークであるBootstrap のAlertsコンポーネントで用意されているメッセージタイプをデフォルトでサポートするために、terasoluna-gfw-common 5.0.0.RELEASEから追加。
|
error
|
ResultMessages.error() |
alert alert-error
|
-
|
danger
|
ResultMessages.danger() |
alert alert-danger
|
-
|
メッセージタイプに応じてCSSを定義されたい。以下に、CSSを適用した場合の例を示す。
.alert {
margin-bottom: 15px;
padding: 10px;
border: 1px solid;
border-radius: 4px;
text-shadow: 0 1px 0 #ffffff;
}
.alert-info {
background: #ebf7fd;
color: #2d7091;
border-color: rgba(45, 112, 145, 0.3);
}
.alert-warning {
background: #fffceb;
color: #e28327;
border-color: rgba(226, 131, 39, 0.3);
}
.alert-error {
background: #fff1f0;
color: #d85030;
border-color: rgba(216, 80, 48, 0.3);
}
ResultMessages.error().add("e.ex.an.9001")
を<t:messagesPanel />
で出力した例ResultMessages.warning().add("w.ex.an.2001")
を<t:messagesPanel />
で出力した例ResultMessages.info().add("i.ex.an.0001", "XXXX")
を<t:messagesPanel />
で出力した例Note
successとdangerは、スタイルに多様性を持たせるために用意されている。本ガイドラインでは、successとinfo、errorとdangerは同義である。
Tip
CSSフレームワークであるBootstrap のAlertsコンポーネントは、
<t:messagesPanel />
のデフォルト設定で利用できる。Warning
本例では、メッセージキーをハードコードで設定している。しかしながら、保守性を高めるためにも、メッセージキーは、定数クラスにまとめることを推奨する。
メッセージキー定数クラスの自動生成ツールを参照されたい。
4.6.2.2.2. 結果メッセージの属性名指定¶
ResultMessages
をModelに追加する場合、基本的には属性名を省略できる。ResultMessages
は一つのメッセージタイプしか表現できない。ResultMessages
を同時に表示したい場合は、明示的に属性名を指定してModelに設定する必要がある。Controller (MessageControllerに追加)
@RequestMapping(value = "showMessages", method = RequestMethod.GET) public String showMessages(Model model) { model.addAttribute("messages1", ResultMessages.warning().add("w.ex.an.2001")); // (1) model.addAttribute("messages2", ResultMessages.error().add("e.ex.an.9001")); // (2) return "message/showMessages"; }
項番 説明 (1)メッセージタイプが”warning”である、ResultMessages
を属性名”messages1”でModelに追加する。(2)メッセージタイプが”info”である、ResultMessages
を属性名”messages2”でModelに追加する。JSP (WEB-INF/views/message/showMessages.jsp)
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>Result Message Example</title> <style type="text/css"> .alert { margin-bottom: 15px; padding: 10px; border: 1px solid; border-radius: 4px; text-shadow: 0 1px 0 #ffffff; } .alert-info { background: #ebf7fd; color: #2d7091; border-color: rgba(45, 112, 145, 0.3); } .alert-warning { background: #fffceb; color: #e28327; border-color: rgba(226, 131, 39, 0.3); } .alert-error { background: #fff1f0; color: #d85030; border-color: rgba(216, 80, 48, 0.3); } </style> </head> <body> <h1>Result Message</h1> <h2>Messages1</h2> <t:messagesPanel messagesAttributeName="messages1" /><!-- (1) --> <h2>Messages2</h2> <t:messagesPanel messagesAttributeName="messages2" /><!-- (2) --> </body> </html>
項番 説明 (1)属性名が”messages1”であるResultMessages
を表示する。(2)属性名が”messages2”であるResultMessages
を表示する。ブラウザで表示すると、以下のように出力される。
4.6.2.2.3. 業務例外メッセージの表示¶
org.terasoluna.gfw.common.exception.BusinessException
とorg.terasoluna.gfw.common.exception.ResourceNotFoundException
はResultMessages
を保持している。ResultMessages
を設定したBusinessException
をスローすること。BusinessException
をキャッチし、例外中の結果メッセージをModelに追加する。Serviceクラス
@Service @Transactional public class UserServiceImpl implements UserService { // omitted public void create(...) { // omitted... if (...) { // illegal state! ResultMessages messages = ResultMessages.error() .add("e.ex.an.9001"); // (1) throw new BusinessException(messages); } } }
項番 説明 (1)エラーメッセージをResultMessages
で作成し、BusinessException
に設定する。Controllerクラス
@RequestMapping(value = "create", method = RequestMethod.POST) public String create(@Validated UserForm form, BindingResult result, Model model) { // omitted try { userService.create(user); } catch (BusinessException e) { ResultMessages messages = e.getResultMessages(); // (1) model.addAttribute(messages); return "user/createForm"; } // omitted }
項番 説明 (1)BusinessException
が保持するResultMessages
を取得し、Modelに追加する。
通常、エラーメッセージ表示する場合は、ControllerでResultMessages
オブジェクトを作成するのではなく、
こちらの方法を使用する。
4.6.3. How to extend¶
4.6.3.1. 独自メッセージタイプを作成する¶
org.terasoluna.gfw.common.message.ResultMessageType
インタフェースを実装したimport org.terasoluna.gfw.common.message.ResultMessageType;
public enum ResultMessageTypes implements ResultMessageType { // (1)
NOTICE("notice");
private ResultMessageTypes(String type) {
this.type = type;
}
private final String type;
@Override
public String getType() { // (2)
return this.type;
}
@Override
public String toString() {
return this.type;
}
}
項番 | 説明 |
---|---|
(1)
|
ResultMessageType インタフェースを実装したEnumを定義する。定数オブジェクトで作成してもよいが、Enumで作成することを推奨する。 |
(2)
|
getType の返り値が出力されるCSSのclass名に対応する。 |
ResultMessages
を作成する。ResultMessages messages = new ResultMessages(ResultMessageTypes.NOTICE) // (1)
.add("w.ex.an.2001");
model.addAttribute(messages);
項番 | 説明 |
---|---|
(1)
|
ResultMessages のコンストラクタに対象のResultMessageType を指定する。 |
この場合、<t:messagesPanel />
で以下のようなHTMLが出力される。
<div class="alert alert-notice">
<ul>
<li>The recommended change interval has passed password. Please change your password.</li>
</ul>
</div>
Tip
拡張方法は、
org.terasoluna.gfw.common.message.StandardResultMessageType
が参考になる。
4.6.4. Appendix¶
4.6.4.1. <t:messagesPanel>タグの属性変更¶
<t:messagesPanel>
タグには、表示形式を変更する属性がいくつか用意されている。
オプション | 内容 | defaultの設定値 |
---|---|---|
panelElement | 結果メッセージ表示パネルの要素 | div |
panelClassName | 結果メッセージ表示パネルのCSS class名。 | alert |
panelTypeClassPrefix | CSS class名の接頭辞 | alert- |
messagesType | メッセージタイプ。この属性が設定された場合。設定されたメッセージタイプがResultMessages がもつメッセージタイプより優先されて使用される。 |
|
outerElement | 結果メッセージ一覧を構成するHTMLの外側のタグ | ul |
innerElement | 結果メッセージ一覧を構成するHTMLの内側のタグ | li |
disableHtmlEscape | HTMLエスケープ処理を無効化するためのフラグ。
true を指定する事で、出力するメッセージに対してHTMLエスケープ処理が行われなくなる。この属性は、出力するメッセージにHTMLを埋め込むことで、メッセージの装飾などができるようにするために用意している。
trueを指定する場合は、XSS対策が必要な文字がメッセージ内に含まれない事が保証されていること。
terasoluna-gfw-web 1.0.1.RELEASE以上で利用可能な属性である。
|
false |
例えば、CSSフレームワーク”BlueTrip”では以下のようなCSSが用意されている。
.error,.notice,.success {
padding: .8em;
margin-bottom: 1.6em;
border: 2px solid #ddd;
}
.error {
background: #FBE3E4;
color: #8a1f11;
border-color: #FBC2C4;
}
.notice {
background: #FFF6BF;
color: #514721;
border-color: #FFD324;
}
.success {
background: #E6EFC2;
color: #264409;
border-color: #C6D880;
}
<div class="error">...</div>
というようにメッセージが出力されてほしい。<t:messagesPanel>
タグを以下のように使用すればよい(Controllerは修正不要である)。<t:messagesPanel panelClassName="" panelTypeClassPrefix="" />
出力されるHTMLは以下のようになる。
<div class="error">
<ul>
<li>There are inconsistencies in the data.</li>
</ul>
</div>
ブラウザで表示すると、以下のように出力される。
メッセージ一覧を表示するために<ul>
タグを使用したくない場合は、
outerElement
属性とinnerElement
属性を使用することでカスタマイズできる。
以下のように属性を設定した場合は、
<t:messagesPanel outerElement="" innerElement="span" />
次のようにHTMLが出力される。
<div class="alert alert-error">
<span>There are inconsistencies in the data.</span>
<span>Cannot upload, Because the file size must be less than 1,024MB.</span>
</div>
以下のようCSSを設定することで、
.alert > span {
display: block; /* (1) */
}
項番 | 説明 |
---|---|
(1)
|
“alert”クラスの要素の子となる
<span> タグをブロックレベル要素にする。 |
ブラウザで次のように表示される。
true
にした場合、以下のような出力イメージにする事ができる。- jsp
<spring:message var="informationMessage" code="i.ex.od.0001" /> <t:messagesPanel messagesAttributeName="informationMessage" messagesType="alert alert-info" disableHtmlEscape="true" />
- properties
i.ex.od.0001 = Please confirm order content. <font style="color: red; font-size: 16px;">If this orders submitted, cannot cancel.</font>
- 出力イメージ
4.6.4.2. ResultMessagesを使用しない結果メッセージの表示¶
<t:messagesPanel>
タグはResultMessages
オブジェクト以外にも
java.lang.String
java.lang.Exception
java.util.List
オブジェクトも出力できる。
<t:messagesPanel>
タグはResultMessages
オブジェクトの出力用に使用するが、org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
では、認証エラー時に発生した例外オブジェクトをSPRING_SECURITY_LAST_EXCEPTION
という属性名で、リダイレクト時はセッション、フォワード時はリクエストスコープに格納する。<t:messagesPanel>
タグで出力したい場合は、以下のように設定すればよい。<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Login</title>
<style type="text/css">
/* (1) */
.alert {
margin-bottom: 15px;
padding: 10px;
border: 1px solid;
border-radius: 4px;
text-shadow: 0 1px 0 #ffffff;
}
.alert-error {
background: #fff1f0;
color: #d85030;
border-color: rgba(216, 80, 48, 0.3);
}
</style>
</head>
<body>
<c:if test="${param.containsKey('error')}">
<t:messagesPanel messagesType="error"
messagesAttributeName="SPRING_SECURITY_LAST_EXCEPTION" /><!-- (2) -->
</c:if>
<form:form
action="${pageContext.request.contextPath}/authentication"
method="post">
<fieldset>
<legend>Login Form</legend>
<div>
<label for="username">Username: </label><input
type="text" id="username" name="username">
</div>
<div>
<label for="username">Password:</label><input
type="password" id="password" name="password">
</div>
<div>
<input type="submit" value="Login" />
</div>
</fieldset>
</form:form>
</body>
</html>
項番 | 説明 |
---|---|
(1)
|
結果メッセージ表示用のCSSを再掲する。実際はCSSファイルに記述することを強く推奨する。
|
(2)
|
Exception オブジェクトが格納されている属性名をmessagesAttributeName 属性で指定する。また、
ResultMessages オブジェクトとは異なり、メッセージタイプの情報をもたないため、messagesType 属性で、明示的に、メッセージタイプを指定する必要がある。 |
認証エラー時に出力されるHTMLは
<div class="alert alert-error"><ul><li>Bad credentials</li></ul></div>
であり、ブラウザでは以下のように出力される。
Tip
ログイン用のJSPの内容については、認証を参照されたい。
4.6.4.3. メッセージキー定数クラスの自動生成ツール¶
メッセージキー定数クラスの作成
まず空のメッセージキー定数クラスを作成する。ここでは
com.example.common.message.MessageKeys
とする。package com.example.common.message; public class MessageKeys { }
自動生成クラスの作成
次に
MessageKeys
クラスと同じパッケージにMessageKeysGen
クラスを作成し、以下のように記述する。package com.example.common.message; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.regex.Pattern; import org.apache.commons.io.FileUtils; import org.springframework.core.io.ClassPathResource; public class MessageKeysGen { public static void main(String[] args) throws IOException { // message properties file Class<?> targetClazz = MessageKeys.class; File output = new File("src/main/java/" + targetClazz.getName() .replaceAll(Pattern.quote("."), "/") + ".java"); try (InputStream inputStream = new ClassPathResource("i18n/application-messages.properties") .getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); PrintWriter pw = new PrintWriter(FileUtils.openOutputStream( output))) { pw.println("package " + targetClazz.getPackage().getName() + ";"); pw.println("/**"); pw.println(" * Message Id"); pw.println(" */"); pw.println("public class " + targetClazz.getSimpleName() + " {"); String line; while ((line = bufferedReader.readLine()) != null) { String[] vals = line.split("=", 2); if (vals.length > 1) { String key = vals[0].trim(); String value = vals[1].trim(); pw.println(" /** " + key + "=" + value + " */"); pw.println(" public static final String " + key .toUpperCase().replaceAll(Pattern.quote("."), "_") .replaceAll(Pattern.quote("-"), "_") + " = \"" + key + "\";"); } } pw.println("}"); pw.flush(); } } }
メッセージプロパティファイルの用意
src/main/resource/i18m/application-messages.propertiesにメッセージを定義する。ここでは例として、以下のように設定する。
i.ex.an.0001={0} upload completed. w.ex.an.2001=The recommended change interval has passed password. Please change your password. e.ex.an.8001=Cannot upload, Because the file size must be less than {0}MB. e.ex.an.9001=There are inconsistencies in the data.
自動生成クラスの実行
MessageKeys
クラスが、以下のように上書きされる。package com.example.common.message; /** * Message Id */ public class MessageKeys { /** i.ex.an.0001={0} upload completed. */ public static final String I_EX_AN_0001 = "i.ex.an.0001"; /** w.ex.an.2001=The recommended change interval has passed password. Please change your password. */ public static final String W_EX_AN_2001 = "w.ex.an.2001"; /** e.ex.an.8001=Cannot upload, Because the file size must be less than {0}MB. */ public static final String E_EX_AN_8001 = "e.ex.an.8001"; /** e.ex.an.9001=There are inconsistencies in the data. */ public static final String E_EX_AN_9001 = "e.ex.an.9001"; }