4.9. コードリスト¶
4.9.1. Overview¶
コードリストとは、「コード値(value)とその表示名(label)」の集合である。
画面のセレクトボックスなどコード値を画面で表示する際のラベルへのマッピング表として利用される。
共通ライブラリでは、
xmlファイルやDBに定義されたコードリストをアプリケーション起動時に読み込みキャッシュする機能
JSPやThymeleafのテンプレートHTML、Javaクラスからコードリストを参照する機能
コードリストを用いて入力チェックする機能
を提供している。
また、応用的な使い方として、
コードリストの国際化対応
キャッシュされたコードリストのリロード
もサポートしている。
Note
標準でリロードが可能なのは、DBに定義されたコードリストを使用する場合のみである。
共通ライブラリでは、以下のコードリスト実装クラスを提供している。
種類 |
内容 |
Reloadable |
---|---|---|
|
xmlファイルに直接記述した内容を使用する。 |
NO |
|
数値の範囲のリストを作成する際に使用する。 |
NO |
|
DBから対象のコードをSQLで取得して使用する。 |
YES |
|
|
NO |
|
国際化に対応し、java.util.Localeに応じたコードリストを使用する。 |
NO |
|
国際化に対応し、java.util.Localeに応じた更新可能なコードリストを使用する。(5.4.2から追加) |
YES |
org.terasoluna.gfw.common.codelist.CodeList
を提供している。org.terasoluna.gfw.common.codelist.i18n.I18nCodeList
を提供している。共通ライブラリで提供しているコードリストのクラス図構成を以下に示す。
4.9.2. How to use¶
本項では、各種コードリストを使用する上での設定や実装方法を記述する。
4.9.2.1. SimpleMapCodeListの使用方法¶
org.terasoluna.gfw.common.codelist.SimpleMapCodeList
とは、
xmlファイルに定義したコード値をアプリケーション起動時に読み込み、そのまま使用するコードリストである。
SimpleMapCodeListのイメージ
4.9.2.1.1. コードリスト設定例¶
bean定義ファイルの定義
bean定義ファイルは、コードリスト用に作成することを推奨する。
XxxCodelistConfig.java
@Bean("CL_ORDERSTATUS") // (1) public SimpleMapCodeList clOrderstatus() { Map<String, String> codeMap = new LinkedHashMap<>(); codeMap.put("1", "Received"); // (2) codeMap.put("2", "Sent"); // (2) codeMap.put("3", "Cancelled"); // (2) SimpleMapCodeList bean = new SimpleMapCodeList(); bean.setMap(codeMap); return bean; }
項番
説明
(1)SimpleMapCodeListクラスをbean定義する。beanIDは、後述するorg.terasoluna.gfw.web.codelist.CodeListInterceptor
のIDパターンに合致する名称にすること。(2)Mapの Key、Valueを定義する。上記例ではjava.util.LinkedHashMap
で登録しているため、「名前と値」が登録順にMapへ保持される。
コードリスト用bean定義ファイルを作成後、既存bean定義ファイルにimportを行う必要がある。
XxxDomainConfig.java
@Configuration @ComponentScan(basePackages = { "com.example.domain" }) @Import({ XxxCodelistConfig.class }) // (3) public class XxxDomainConfig {
項番
説明
(3)コードリスト用bean定義ファイルをimportする。
xxx-codelist.xml
<bean id="CL_ORDERSTATUS" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList"> <!-- (1) --> <property name="map"> <util:map> <entry key="1" value="Received" /> <!-- (2) --> <entry key="2" value="Sent" /> <!-- (2) --> <entry key="3" value="Cancelled" /> <!-- (2) --> </util:map> </property> </bean>
項番
説明
(1)SimpleMapCodeListクラスをbean定義する。beanIDは、後述するorg.terasoluna.gfw.web.codelist.CodeListInterceptor
のIDパターンに合致する名称にすること。(2)Mapの Key、Valueを定義する。map-class属性を省略した場合java.util.LinkedHashMap
で登録されるため、上記例では「名前と値」が登録順にMapへ保持される。
コードリスト用bean定義ファイルを作成後、既存bean定義ファイルにimportを行う必要がある。
xxx-domain.xml
<import resource="classpath:META-INF/spring/projectName-codelist.xml" /> <!-- (3) --> <context:component-scan base-package="com.example.domain" />
項番
説明
(3)コードリスト用bean定義ファイルをimportする。component-scanしている間にimport先の情報が必要な場合があるため、importは<context:component-scan base-package="com.example.domain" />
より上で設定する必要がある。
4.9.2.1.2. 共通ライブラリから提供しているインタセプターの使用¶
共通ライブラリから提供しているインタセプターを用いることで、リクエストスコープに自動的に設定し、JSP/テンプレートHTMLからコードリストを容易に参照できる。
bean定義ファイルの定義
SpringMvc.java
@EnableAspectJAutoProxy @EnableWebMvc @Configuration public class SpringMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(codeListInterceptor()) .addPathPatterns("/**"); // (1) } // (2) @Bean public CodeListInterceptor codeListInterceptor() { CodeListInterceptor codeListInterceptor = new CodeListInterceptor(); codeListInterceptor.setCodeListIdPattern(Pattern.compile("CL_.+")); // (3) return codeListInterceptor; }
項番
説明
(1)適用対象のパスを設定する。(2)CodeListInterceptor クラスをbean定義する。(3)自動でリクエストスコープに設定する、コードリストのbeanIDのパターンを設定する。パターンにはjava.util.regex.Pattern
で使用する正規表現を設定すること。上記例では、idが”CL_XXX”形式で定義されているデータのみを対象とする。その場合、idが”CL_”で始まらないbean定義は取り込まれない。“CL_”で定義したbeanIDは、リクエストスコープに設定されるため、JSPで容易に参照できる。codeListIdPattern
プロパティは省略可能である。codeListIdPattern
を省略した場合は、すべてのコードリスト(org.terasoluna.gfw.common.codelist.CodeList
インタフェースを実装しているbean)がリクエストスコープに設定される。
spring-mvc.xml
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /> <!-- (1) --> <bean class="org.terasoluna.gfw.web.codelist.CodeListInterceptor"> <!-- (2) --> <property name="codeListIdPattern" value="CL_.+" /> <!-- (3) --> </bean> </mvc:interceptor> <!-- omitted --> </mvc:interceptors>
項番
説明
(1)適用対象のパスを設定する。(2)CodeListInterceptor クラスをbean定義する。(3)自動でリクエストスコープに設定する、コードリストのbeanIDのパターンを設定する。パターンにはjava.util.regex.Pattern
で使用する正規表現を設定すること。上記例では、idが”CL_XXX”形式で定義されているデータのみを対象とする。その場合、idが”CL_”で始まらないbean定義は取り込まれない。“CL_”で定義したbeanIDは、リクエストスコープに設定されるため、JSPで容易に参照できる。codeListIdPattern
プロパティは省略可能である。codeListIdPattern
を省略した場合は、すべてのコードリスト(org.terasoluna.gfw.common.codelist.CodeList
インタフェースを実装しているbean)がリクエストスコープに設定される。
Warning
例外発生時のコードリスト利用について
terasoluna-gfw-common 5.4.2.RELEASEより、Controllerのハンドラメソッドで例外が発生し @ExceptionHandler
や SystemExceptionResolver
で例外ハンドリングを行なった場合は、コードリストがリクエストスコープに登録されなくなった。
これは、 CodeListInterceptor
が HandlerInterceptor#postHandle
メソッドでコードリストの登録を行うように変更されたためである。
例外時に遷移する画面でコードリストを利用したい場合は、ハンドラメソッドで例外を捕捉(try-catch)するか、JSP/テンプレートHTMLから直接コードリストBeanを参照するを利用してコードリストを取得することを検討されたい。
例外ハンドリングの方法については、例外のハンドリング方法を参照されたい。
jspの実装例
<form:select path="orderStatus">
<form:option value="" label="--Select--" /> <!-- (4) -->
<form:options items="${CL_ORDERSTATUS}" /> <!-- (5) -->
</form:select>
項番 |
説明 |
---|---|
(4)
|
セレクトボックスの先頭にダミーの値を設定する場合、valueに空文字を指定すること。
|
(5)
|
コードリストを定義したbeanIDを指定する。
|
テンプレートHTML実装例
<select th:field="*{orderStatus}">
<option value="">--Select--</option> <!--/* (4) */-->
<option th:each="order : ${CL_ORDERSTATUS}" th:value="${order.key}" th:text="${order.value}"></option> <!--/* (5) */-->
</select>
項番 |
説明 |
---|---|
(4)
|
セレクトボックスの先頭にダミーの値を設定する場合、valueに空文字を指定すること。
|
(5)
|
コードリストを定義したbeanIDを指定する。
|
出力HTML
<select id="orderStatus" name="orderStatus">
<option value="">--Select--</option>
<option value="1">Received</option>
<option value="2">Sent</option>
<option value="3">Cancelled</option>
</select>
出力画面
4.9.2.1.3. Javaクラスでのコードリスト使用¶
jakarta.inject.Inject
アノテーションと、jakarta.inject.Named
アノテーションを設定してコードリストをインジェクションする。@Named
にコードリスト名を指定する。import org.springframework.stereotype.Service;
import org.terasoluna.gfw.common.codelist.CodeList;
import jakarta.inject.Inject;
import jakarta.inject.Named;
@Service
public class OrderServiceImpl implements OrderService {
@Inject
@Named("CL_ORDERSTATUS")
CodeList orderStatusCodeList; // (1)
public boolean existOrderStatus(String target) {
return orderStatusCodeList.asMap().containsKey(target); // (2)
}
}
項番 |
説明 |
---|---|
(1)
|
beanIDが、”CL_ORDERSTATUS”であるコードリストをインジェクションする。
|
(2)
|
CodeList#asMapメソッドでコードリストを
java.util.Map 形式で取得する。 |
4.9.2.2. NumberRangeCodeListの使用方法¶
org.terasoluna.gfw.common.codelist.NumberRangeCodeList
とは、アプリケーション起動時に、指定した数値の範囲をリストにするコードリストである。NumberRangeCodeListのイメージ
Tip
NumberRangeCodeListはアラビア数字のみ対応しており、漢数字やローマ数字には対応していない。
漢数字やローマ数字を表示したい場合はJdbcCodeList、SimpleMapCodeListに定義することで対応可能である。
NumberRangeCodeListには、以下の特徴がある。
Fromの値をToの値より小さくする場合、昇順にinterval分増加した値をFrom~Toの範囲分リストにする。
Toの値をFromの値より小さくする場合、降順にinterval分減少した値をTo~Fromの範囲分リストにする。
増加分(減少分)はintervalを設定することで変更できる。
ここでは、昇順のNumberRangeCodeList
について説明をする。
降順のNumberRangeCodeList
とインターバルの変更方法については、「NumberRangeCodeListのバリエーション」を参照されたい。
4.9.2.2.1. コードリスト設定例¶
Fromの値をToの値より小さくする(From < To)場合の実装例を、以下に示す。
bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_MONTH") public NumberRangeCodeList clMonthAsc() { NumberRangeCodeList bean = new NumberRangeCodeList(); // (1) bean.setFrom(1); // (2) bean.setTo(12); // (3) bean.setValueFormat("%d"); // (4) bean.setLabelFormat("%02d"); // (5) bean.setInterval(1); // (6) return bean; }
項番
説明
(1)NumberRangeCodeListをbean定義する。(2)範囲開始の値を指定する。省略した場合、”0”が設定される。(3)範囲終了の値を設定する。指定必須。(4)コード値のフォーマット形式を設定する。フォーマット形式はjava.lang.String.format
の形式が使用される。省略した場合、”%s”が設定される。(5)コード名のフォーマット形式を設定する。フォーマット形式はjava.lang.String.format
の形式が使用される。省略した場合、”%s”が設定される。(6)増加する値を設定する。省略した場合、”1”が設定される。
xxx-codelist.xml
<bean id="CL_MONTH" class="org.terasoluna.gfw.common.codelist.NumberRangeCodeList"> <!-- (1) --> <property name="from" value="1" /> <!-- (2) --> <property name="to" value="12" /> <!-- (3) --> <property name="valueFormat" value="%d" /> <!-- (4) --> <property name="labelFormat" value="%02d" /> <!-- (5) --> <property name="interval" value="1" /> <!-- (6) --> </bean>
項番
説明
(1)NumberRangeCodeListをbean定義する。(2)範囲開始の値を指定する。省略した場合、”0”が設定される。(3)範囲終了の値を設定する。指定必須。(4)コード値のフォーマット形式を設定する。フォーマット形式はjava.lang.String.format
の形式が使用される。省略した場合、”%s”が設定される。(5)コード名のフォーマット形式を設定する。フォーマット形式はjava.lang.String.format
の形式が使用される。省略した場合、”%s”が設定される。(6)増加する値を設定する。省略した場合、”1”が設定される。
4.9.2.2.2. コードリストの使用¶
設定例の詳細は、前述した共通ライブラリから提供しているインタセプターの使用を参照されたい。
jspの実装例
<form:select path="depMonth" items="${CL_MONTH}" />
テンプレートHTML実装例
<select th:field="*{depMonth}">
<option th:each="month : ${CL_MONTH}" th:value="${month.key}" th:text="${month.value}"></option>
</select>
出力HTML
<select id="depMonth" name="depMonth">
<option value="1">01</option>
<option value="2">02</option>
<option value="3">03</option>
<option value="4">04</option>
<option value="5">05</option>
<option value="6">06</option>
<option value="7">07</option>
<option value="8">08</option>
<option value="9">09</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
</select>
出力画面
4.9.2.2.3. Javaクラスでのコードリスト使用¶
設定例の詳細は、前述したJavaクラスでのコードリスト使用を参照されたい。
4.9.2.3. JdbcCodeListの使用方法¶
org.terasoluna.gfw.common.codelist.JdbcCodeList
とは、アプリケーション起動時にDBから値を取得し、コードリストを作成するクラスである。JdbcCodeList
はアプリケーション起動時にキャッシュを作るので、リスト表示時はDBアクセスによる遅延がない。JdbcCodeList
にはorg.springframework.jdbc.core.JdbcTemplate
を設定するフィールドがある。JdbcTemplate
のfetchSize
に上限を設定すれば、その分だけのレコードが起動時に読み込まれる。JdbcCodeListのイメージ
4.9.2.3.1. コードリスト設定例¶
テーブル(authority)の定義
authority_id |
authority_name |
---|---|
01
|
STAFF_MANAGEMENT
|
02
|
MASTER_MANAGEMENT
|
03
|
STOCK_MANAGEMENT
|
04
|
ORDER_MANAGEMENT
|
05
|
SHOW_SHOPPING_CENTER
|
bean定義ファイルの定義
XxxCodelistConfig.java
@Value("${codelist.jdbc.fetchSize:1000}") private Integer fetchSize; @Bean("jdbcTemplateForCodeList") public JdbcTemplate jdbcTemplateForCodeList() { JdbcTemplate bean = new JdbcTemplate(); // (1) bean.setDataSource(dataSource); bean.setFetchSize(fetchSize); // (2) return bean; } // (3) private JdbcCodeList abstractJdbcCodeList() { JdbcCodeList bean = new JdbcCodeList(); bean.setJdbcTemplate(jdbcTemplateForCodeList()); // (4) return bean; } @Bean("CL_AUTHORITIES") public JdbcCodeList clAuthorities() { JdbcCodeList jdbcCodeList = abstractJdbcCodeList(); // (5) jdbcCodeList.setQuerySql("SELECT authority_id, authority_name FROM t_authority ORDER BY authority_id"); // (6) jdbcCodeList.setValueColumn("authority_id"); // (7) jdbcCodeList.setLabelColumn("authority_name"); // (8) return jdbcCodeList; }
項番
説明
(1)org.springframework.jdbc.core.JdbcTemplate
クラスをbean定義する。独自にfetchSize
を設定するために必要となる。(2)fetchSize
を設定する。fetchSize
のデフォルト設定が、全件取得になっている場合があるため適切な値を設定すること。fetchSize
の設定が全件取得のままだと、JdbcCodeList
の読み込む件数が大きい場合に、DBからリストを取得する際の処理性能が落ちてしまい、アプリケーションの起動時間が長期化する可能性がある。(3)JdbcCodeList
の共通bean定義。他のJdbcCodeList
の共通部分を設定している。そのため、基本JdbcCodeList
のbean定義は当メソッドを呼び出す。(4)(1)で設定したjdbcTemplate
を設定。fetchSize
を設定したJdbcTemplate
を、JdbcCodeList
に格納している。(5)JdbcCodeList
のbean定義。parent属性を(3)のbean定義を親クラスとして設定することで、fetchSize
を設定したJdbcCodeList
が設定される。このbean定義では、クエリに関する設定のみを行い、必要なCodeList分作成する。(6)querySqlプロパティに取得するSQLを記述する。その際、必ず「ORDER BY」を指定し、順序を確定させること。「ORDER BY」を指定しないと、取得する度に順序が変わってしまう。(7)valueColumnプロパティに、MapのKeyに該当する値を設定する。この例ではauthority_idを設定している。(8)labelColumnプロパティに、MapのValueに該当する値を設定する。この例ではauthority_nameを設定している。
xxx-codelist.xml
<bean id="jdbcTemplateForCodeList" class="org.springframework.jdbc.core.JdbcTemplate" > <!-- (1) --> <property name="dataSource" ref="dataSource" /> <property name="fetchSize" value="${codelist.jdbc.fetchSize:1000}" /> <!-- (2) --> </bean> <bean id="AbstractJdbcCodeList" class="org.terasoluna.gfw.common.codelist.JdbcCodeList" abstract="true"> <!-- (3) --> <property name="jdbcTemplate" ref="jdbcTemplateForCodeList" /> <!-- (4) --> </bean> <bean id="CL_AUTHORITIES" parent="AbstractJdbcCodeList" > <!-- (5) --> <property name="querySql" value="SELECT authority_id, authority_name FROM authority ORDER BY authority_id" /> <!-- (6) --> <property name="valueColumn" value="authority_id" /> <!-- (7) --> <property name="labelColumn" value="authority_name" /> <!-- (8) --> </bean>
項番
説明
(1)org.springframework.jdbc.core.JdbcTemplate
クラスをbean定義する。独自にfetchSize
を設定するために必要となる。(2)fetchSize
を設定する。fetchSize
のデフォルト設定が、全件取得になっている場合があるため適切な値を設定すること。fetchSize
の設定が全件取得のままだと、JdbcCodeList
の読み込む件数が大きい場合に、DBからリストを取得する際の処理性能が落ちてしまい、アプリケーションの起動時間が長期化する可能性がある。(3)JdbcCodeList
の共通bean定義。他のJdbcCodeList
の共通部分を設定している。そのため、基本JdbcCodeList
のbean定義はこのbean定義を親クラスに設定する。abstract属性をtrueにすることで、このbeanはインスタンス化されない。(4)(1)で設定したjdbcTemplate
を設定。fetchSize
を設定したJdbcTemplate
を、JdbcCodeList
に格納している。(5)JdbcCodeList
のbean定義。parent属性を(3)のbean定義を親クラスとして設定することで、fetchSize
を設定したJdbcCodeList
が設定される。このbean定義では、クエリに関する設定のみを行い、必要なCodeList分作成する。(6)querySqlプロパティに取得するSQLを記述する。その際、必ず「ORDER BY」を指定し、順序を確定させること。「ORDER BY」を指定しないと、取得する度に順序が変わってしまう。(7)valueColumnプロパティに、MapのKeyに該当する値を設定する。この例ではauthority_idを設定している。(8)labelColumnプロパティに、MapのValueに該当する値を設定する。この例ではauthority_nameを設定している。
4.9.2.3.2. コードリストの使用¶
jspの実装例
<form:checkboxes items="${CL_AUTHORITIES}"/>
テンプレートHTML実装例
<span th:each="authority : ${CL_AUTHORITIES}">
<input type="checkbox" th:field="*{authorities}" th:value="${authority.key}">
<label th:for="${#ids.prev('authorities')}" th:text="${authority.value}"></label> <!--/* (9) */-->
</span>
項番 |
説明 |
---|---|
(9)
|
出力HTML
<span>
<input id="authorities1" name="authorities" type="checkbox" value="01"/>
<label for="authorities1">STAFF_MANAGEMENT</label>
</span>
<span>
<input id="authorities2" name="authorities" type="checkbox" value="02"/>
<label for="authorities2">MASTER_MANAGEMENT</label>
</span>
<span>
<input id="authorities3" name="authorities" type="checkbox" value="03"/>
<label for="authorities3">STOCK_MANAGEMENT</label>
</span>
<span>
<input id="authorities4" name="authorities" type="checkbox" value="04"/>
<label for="authorities4">ORDER_MANAGEMENT</label>
</span>
<span>
<input id="authorities5" name="authorities" type="checkbox" value="05"/>
<label for="authorities5">SHOW_SHOPPING_CENTER</label>
</span>
出力画面
4.9.2.3.3. Javaクラスでのコードリスト使用¶
下記に示す設定の詳細について、前述したJavaクラスでのコードリスト使用を参照されたい。
4.9.2.4. EnumCodeListの使用方法¶
org.terasoluna.gfw.common.codelist.EnumCodeList
は、
Enum
クラスに定義した定数からコードリストを作成するクラスである。
Note
以下の条件に一致するアプリケーションでコードリストを扱う場合は、EnumCodeList
を使用して、コードリストのラベルをEnum
クラスで管理することを検討してほしい。
コードリストのラベルをEnum
クラスで管理することで、コード値に紐づく情報と操作をEnum
クラスに集約する事ができる。
コード値を
Enum
クラスで管理する必要がある(つまり、Javaのロジックでコード値を意識した処理を行う必要がある)UIの国際化(多言語化)の必要がない
以下に、EnumCodeList
の使用イメージを示す。
Note
EnumCodeList
では、Enum
クラスからコードリストを作成するために必要な情報(コード値とラベル)を取得するためのインタフェースとして、org.terasoluna.gfw.common.codelist.EnumCodeList.CodeListItem
インタフェースを提供している。
EnumCodeList
を使用する場合は、作成するEnum
クラスでEnumCodeList.CodeListItem
インタフェースを実装する必要がある。
4.9.2.4.1. コードリスト設定例¶
Enumクラスの作成
EnumCodeList
を使用する場合は、EnumCodeList.CodeListItem
インタフェースを実装したEnum
クラスを作成する。
以下に作成例を示す。
package com.example.domain.model;
import org.terasoluna.gfw.common.codelist.EnumCodeList;
public enum OrderStatus
// (1)
implements EnumCodeList.CodeListItem {
// (2)
RECEIVED ("1", "Received"),
SENT ("2", "Sent"),
CANCELLED ("3","Cancelled");
// (3)
private final String value;
private final String label;
// (4)
private OrderStatus(String codeValue, String codeLabel) {
this.value = codeValue;
this.label = codeLabel;
}
// (5)
@Override
public String getCodeValue() {
return value;
}
// (6)
@Override
public String getCodeLabel() {
return label;
}
}
項番 |
説明 |
---|---|
(1)
|
コードリストとして使用する
が定義されている。 |
(2)
|
定数を定義する。 定数を生成する際に、コードリストを作成するために必要な情報(コード値とラベル)を指定する。 上記例では、以下の3つの定数を定義している。
Note
|
(3)
|
コードリストを作成するために必要な情報(コード値とラベル)を保持するプロパティを用意する。 |
(4)
|
コードリストを作成するために必要な情報(コード値とラベル)を受け取るコンストラクタを用意する。 |
(5)
|
定数が保持するコード値を返却する。 このメソッドは、 |
(6)
|
定数が保持するラベルを返却する。 このメソッドは、 |
bean定義ファイルの定義
EnumCodeList
を定義する。XxxCodelist.java
@Bean("CL_ORDERSTATUS") public EnumCodeList clEnumOrderstatus() { return new EnumCodeList(OrderStatus.class); // (7)(8) }
項番
説明
(7)コードリストの実装クラスとして、
EnumCodeList
クラスを指定する。(8)EnumCodeList
クラスのコンストラクタに、EnumCodeList.CodeListItem
インタフェースを実装したEnum
クラスを指定する。
xxx-codelist.xml
<bean id="CL_ORDERSTATUS" class="org.terasoluna.gfw.common.codelist.EnumCodeList"> <!-- (7) --> <constructor-arg value="com.example.domain.model.OrderStatus" /> <!-- (8) --> </bean>
項番
説明
(7)コードリストの実装クラスとして、
EnumCodeList
クラスを指定する。(8)EnumCodeList
クラスのコンストラクタに、EnumCodeList.CodeListItem
インタフェースを実装したEnum
クラスのFQCNを指定する。
4.9.2.4.2. コードリストの使用¶
JSP/テンプレートHTMLでコードリストを使用する方法については、前述した共通ライブラリから提供しているインタセプターの使用を参照されたい。
4.9.2.4.3. Javaクラスでのコードリスト使用¶
Javaクラスでコードリストを使用する方法については、前述したJavaクラスでのコードリスト使用を参照されたい。
4.9.2.5. I18nCodeListの使用方法¶
org.terasoluna.gfw.common.codelist.i18n.I18nCodeList
は、国際化に対応しているコードリストである。I18nCodeList
の実装クラスとして、org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList
およびorg.terasoluna.gfw.common.codelist.i18n.SimpleReloadableI18nCodeList
を提供している。
I18nCodeList(SimpleI18nCodeList)のイメージ
4.9.2.5.1. コードリスト設定例¶
I18nCodeList
は行がLocale
、列がコード値、セルの内容がラベルである2次元のテーブルをイメージすると理解しやすい。
料金を選択するセレクトボックスの場合を例に挙げると以下のようなテーブルができる。
row=Locale,column=Code |
0 |
10000 |
20000 |
30000 |
40000 |
50000 |
---|---|---|---|---|---|---|
en |
unlimited |
Less than \10,000 |
Less than \20,000 |
Less than \30,000 |
Less than \40,000 |
Less than \50,000 |
ja |
上限なし |
10,000円以下 |
20,000円以下 |
30,000円以下 |
40,000円以下 |
50,000円以下 |
この国際化対応コードリストのテーブルを構築するためにSimpleI18nCodeList
は3つの設定方法を用意している。
行単位でLocale毎の
CodeList
を設定する行単位でLocale毎の
java.util.Map
(key=コード値, value=ラベル)を設定する列単位でコード値毎の
java.util.Map
(key=Locale, value=ラベル)を設定する
基本的には、「行単位でLocale毎のCodeListを設定する」方法でコードリストを設定することを推奨する。
SimpleReloadableI18nCodeList
は更新可能なコードリストを行に持つ以下の設定方法を用意している。
行単位でLocale毎の
ReloadableCodeList
(JdbcCodeList
)を設定する
Note
terasoluna-gfw-common 5.4.2.RELEASEからリロードに対応したSimpleReloadableI18nCodeList
が追加された。
更新可能なコードリストを行に持つSimpleI18nCodeList
を利用している場合は、SimpleReloadableI18nCodeList
に置き換えることを推奨する。
CodeList
を設定する方法について説明する。Bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_I18N_PRICE") public SimpleI18nCodeList clI18nPrice() { Map<Locale, CodeList> rows = new LinkedHashMap<>(); // (1) rows.put(Locale.ENGLISH, clPriceEn()); rows.put(Locale.JAPANESE, clPriceJa()); SimpleI18nCodeList bean = new SimpleI18nCodeList(); bean.setRowsByCodeList(rows); return bean; }
項番
説明
(1)rowsByCodeListプロパティにkeyがjava.lang.Locale
のMapを設定する。Mapには、keyにロケール、value-refにロケールに対応したコードリストクラスの参照先を指定する。Mapのvalueは各ロケールに対応したコードリストクラスを参照する。
xxx-codelist.xml
<bean id="CL_I18N_PRICE" class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList"> <property name="rowsByCodeList"> <!-- (1) --> <util:map> <entry key="en" value-ref="CL_PRICE_EN" /> <entry key="ja" value-ref="CL_PRICE_JA" /> </util:map> </property> </bean>
項番
説明
(1)rowsByCodeListプロパティにkeyがjava.lang.Locale
のMapを設定する。Mapには、keyにロケール、value-refにロケールに対応したコードリストクラスの参照先を指定する。Mapのvalueは各ロケールに対応したコードリストクラスを参照する。
Locale毎にSimpleMapCodeListを用意する場合のBean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_I18N_PRICE") public SimpleI18nCodeList clI18nPrice() { Map<Locale, CodeList> rows = new LinkedHashMap<>(); rows.put(Locale.ENGLISH, clPriceEn()); rows.put(Locale.JAPANESE, clPriceJa()); SimpleI18nCodeList bean = new SimpleI18nCodeList(); bean.setRowsByCodeList(rows); return bean; } // (2) @Bean("CL_PRICE_EN") public SimpleMapCodeList clPriceEn() { Map<String, String> enMap = new LinkedHashMap<>(); enMap.put("0", "unlimited"); enMap.put("10000", "Less than \\10,000"); enMap.put("20000", "Less than \\20,000"); enMap.put("30000", "Less than \\30,000"); enMap.put("40000", "Less than \\40,000"); enMap.put("50000", "Less than \\50,000"); SimpleMapCodeList bean = new SimpleMapCodeList(); bean.setMap(enMap); return bean; } // (3) @Bean("CL_PRICE_JA") public SimpleMapCodeList clPriceJa() { Map<String, String> jaMap = new LinkedHashMap<>(); jaMap.put("0", "上限なし"); jaMap.put("10000", "10,000円以下"); jaMap.put("20000", "20,000円以下"); jaMap.put("30000", "30,000円以下"); jaMap.put("40000", "40,000円以下"); jaMap.put("50000", "50,000円以下"); SimpleMapCodeList bean = new SimpleMapCodeList(); bean.setMap(jaMap); return bean; }
項番
説明
(2)ロケールが”en”であるbean定義CL_PRICE_EN
について、コードリストクラスをSimpleMapCodeList
で設定している。(3)ロケールが”ja”であるbean定義CL_PRICE_JA
について、コードリストクラスをSimpleMapCodeList
で設定している。
xxx-codelist.xml
<bean id="CL_I18N_PRICE" class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList"> <property name="rowsByCodeList"> <util:map> <entry key="en" value-ref="CL_PRICE_EN" /> <entry key="ja" value-ref="CL_PRICE_JA" /> </util:map> </property> </bean> <bean id="CL_PRICE_EN" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList"> <!-- (2) --> <property name="map"> <util:map> <entry key="0" value="unlimited" /> <entry key="10000" value="Less than \10,000" /> <entry key="20000" value="Less than \20,000" /> <entry key="30000" value="Less than \30,000" /> <entry key="40000" value="Less than \40,000" /> <entry key="50000" value="Less than \50,000" /> </util:map> </property> </bean> <bean id="CL_PRICE_JA" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList"> <!-- (3) --> <property name="map"> <util:map> <entry key="0" value="上限なし" /> <entry key="10000" value="10,000円以下" /> <entry key="20000" value="20,000円以下" /> <entry key="30000" value="30,000円以下" /> <entry key="40000" value="40,000円以下" /> <entry key="50000" value="50,000円以下" /> </util:map> </property> </bean>
項番
説明
(2)ロケールが”en”であるbean定義CL_PRICE_EN
について、コードリストクラスをSimpleMapCodeList
で設定している。(3)ロケールが”ja”であるbean定義CL_PRICE_JA
について、コードリストクラスをSimpleMapCodeList
で設定している。
Locale毎にJdbcCodeListを用意する場合のBean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_I18N_PRICE") public SimpleReloadableI18nCodeList clI18nPrice() { Map<Locale, CodeList> rows = new LinkedHashMap<>(); rows.put(Locale.ENGLISH, clPriceEn()); rows.put(Locale.JAPANESE, clPriceJa()); SimpleReloadableI18nCodeList bean = new SimpleReloadableI18nCodeList(); // (4) bean.setRowsByCodeList(rows); return bean; } @Bean("CL_PRICE_EN") public JdbcCodeList clPriceEn() { JdbcCodeList jdbcCodeList = abstractJdbcCodeList(); // (5) jdbcCodeList.setQuerySql("SELECT code, label FROM price WHERE locale = 'en' ORDER BY code"); jdbcCodeList.setValueColumn("code"); jdbcCodeList.setLabelColumn("label"); return jdbcCodeList; } @Bean("CL_PRICE_JA") public JdbcCodeList clPriceJa() { JdbcCodeList jdbcCodeList = abstractJdbcCodeList(); // (6) jdbcCodeList.setQuerySql("SELECT code, label FROM price WHERE locale = 'ja' ORDER BY code"); jdbcCodeList.setValueColumn("code"); jdbcCodeList.setLabelColumn("label"); return jdbcCodeList; }
項番
説明
(4)更新可能なコードリストを行に持つ場合は、SimpleReloadableI18nCodeList
を利用する。(5)ロケールが”en”であるbean定義CL_PRICE_EN
について、コードリストクラスをJdbcCodeList
で設定している。(6)ロケールが”ja”であるbean定義CL_PRICE_JA
について、コードリストクラスをJdbcCodeList
で設定している。
xxx-codelist.xml
<bean id="CL_I18N_PRICE" class="org.terasoluna.gfw.common.codelist.i18n.SimpleReloadableI18nCodeList"> <!-- (4) --> <property name="rowsByCodeList"> <util:map> <entry key="en" value-ref="CL_PRICE_EN" /> <entry key="ja" value-ref="CL_PRICE_JA" /> </util:map> </property> </bean> <bean id="CL_PRICE_EN" parent="AbstractJdbcCodeList"> <!-- (5) --> <property name="querySql" value="SELECT code, label FROM price WHERE locale = 'en' ORDER BY code" /> <property name="valueColumn" value="code" /> <property name="labelColumn" value="label" /> </bean> <bean id="CL_PRICE_JA" parent="AbstractJdbcCodeList"> <!-- (6) --> <property name="querySql" value="SELECT code, label FROM price WHERE locale = 'ja' ORDER BY code" /> <property name="valueColumn" value="code" /> <property name="labelColumn" value="label" /> </bean>
項番
説明
(4)更新可能なコードリストを行に持つ場合は、SimpleReloadableI18nCodeList
を利用する。(5)ロケールが”en”であるbean定義CL_PRICE_EN
について、コードリストクラスをJdbcCodeList
で設定している。(6)ロケールが”ja”であるbean定義CL_PRICE_JA
について、コードリストクラスをJdbcCodeList
で設定している。
テーブル定義(priceテーブル)には以下のデータを投入する。
locale |
code |
label |
---|---|---|
en
|
0
|
unlimited
|
en
|
10000
|
Less than \10,000
|
en
|
20000
|
Less than \20,000
|
en
|
30000
|
Less than \30,000
|
en
|
40000
|
Less than \40,000
|
en
|
50000
|
Less than \50,000
|
ja
|
0
|
上限なし
|
ja
|
10000
|
10,000円以下
|
ja
|
20000
|
20,000円以下
|
ja
|
30000
|
30,000円以下
|
ja
|
40000
|
40,000円以下
|
ja
|
50000
|
50,000円以下
|
4.9.2.5.2. I18nCodeListにおけるロケール解決¶
I18nCodeList
は要求されたロケールがコードリストに定義されていない場合、以下の順序でロケールの解決を行う。
国と言語を組み合わせたロケール(例:ja_JP)がコードリストに定義されていない場合、対応する言語のみのロケール(例:ja)を使用する。
言語のみのロケールがコードリストに定義されていない場合、デフォルトのロケールを使用する。
デフォルトのロケールは以下の順序で決定する。
fallbackTo
プロパティが指定されている場合は、指定されたロケールを使用する。fallbackTo
プロパティが指定されていない場合は、JVMインスタンスのデフォルトロケール 、もしくは対応する言語のみのロケールを使用する。
Warning
デフォルトのロケールに対応するコードリストが定義されていなかった場合、Bean生成時にエラーとなりアプリケーションの起動に失敗する。
このため、様々な環境でアプリケーションを運用する場合や、デフォルトとしたいロケールとJVMインスタンスのデフォルトロケールが異なる場合は、fallbackTo
プロパティを指定することを強く推奨する。
fallbackTo
プロパティの設定例を以下に示す。
fallbackToプロパティの設定
@Bean("CL_I18N_PRICE")
public SimpleI18nCodeList clI18nPrice() {
Map<Locale, CodeList> rows = new LinkedHashMap<>(); // (1)
rows.put(Locale.ENGLISH, clPriceEn());
rows.put(Locale.JAPANESE, clPriceJa());
SimpleI18nCodeList bean = new SimpleI18nCodeList();
bean.setRowsByCodeList(rows);
bean.setFallbackTo(Locale.ENGLISH);
return bean;
}
項番 |
説明 |
---|---|
(1)
|
fallbackTo プロパティにロケール”en”を設定する。これにより、要求されたロケールの言語ロケールが”en”、”ja”以外の場合、ロケール”en”が使用される。
|
<bean id="CL_I18N_PRICE"
class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList">
<property name="rowsByCodeList">
<util:map>
<entry key="en" value-ref="CL_PRICE_EN" />
<entry key="ja" value-ref="CL_PRICE_JA" />
</util:map>
</property>
<property name="fallbackTo" value="en" /> <!-- (1) -->
</bean>
項番 |
説明 |
---|---|
(1)
|
fallbackTo プロパティにロケール”en”を設定する。これにより、要求されたロケールの言語ロケールが”en”、”ja”以外の場合、ロケール”en”が使用される。
|
4.9.2.5.3. コードリストの使用¶
JPS/テンプレートHTMLでコードリストを使用する方法については、前述した共通ライブラリから提供しているインタセプターの使用を参照されたい。
Note
CodeListInterceptor
は、I18nCodeList#asMap()
メソッドを利用して適切なロケールのコードリストを取得している。
asMap()
メソッドについてはJavaクラスでのコードリスト使用を参照されたい。
jspの実装例
<form:select path="basePrice" items="${CL_I18N_PRICE}" />
テンプレートHTML実装例
<select th:field="*{basePrice}"> <option th:each="price : ${CL_I18N_PRICE}" th:value="${price.key}" th:text="${price.value}"></option> </select>
出力HTML lang=en
<select id="basePrice" name="basePrice">
<option value="0">unlimited</option>
<option value="1">Less than \10,000</option>
<option value="2">Less than \20,000</option>
<option value="3">Less than \30,000</option>
<option value="4">Less than \40,000</option>
<option value="5">Less than \50,000</option>
</select>
出力HTML lang=ja
<select id="basePrice" name="basePrice">
<option value="0">上限なし</option>
<option value="1">10,000円以下</option>
<option value="2">20,000円以下</option>
<option value="3">30,000円以下</option>
<option value="4">40,000円以下</option>
<option value="5">50,000円以下</option>
</select>
出力画面 lang=en
出力画面 lang=ja
4.9.2.5.4. Javaクラスでのコードリスト使用¶
I18nCodeList
からコードリストを取得するには、以下のいずれかのメソッドを使用する。
asMap()
メソッドorg.springframework.context.i18n.LocaleContextHolder
を利用して適切なロケールのコードリストを取得する。LocaleContextHolder
はorg.springframework.web.servlet.LocaleResolver
を利用してクライアントから指定されたロケールを取得する。asMap(Locale)
メソッド指定されたロケールのコードリストを取得する。
Note
LocaleResolver
の設定方法については、国際化を参照されたい。
LocaleResolver
のdefaultLocale
プロパティを指定している場合は、コードリストのfallbackTo
プロパティに同じロケールを指定することで、LocaleResolver
で意図したロケールのコードリストを使用させることができる。
asMap()
メソッドを利用する場合、前述したJavaクラスでのコードリスト使用と同様の方法で実装を行うことができる。
import org.springframework.stereotype.Service;
import org.terasoluna.gfw.common.codelist.i18n.I18nCodeList;
import jakarta.inject.Inject;
import jakarta.inject.Named;
@Service
public class OrderServiceImpl implements OrderService {
@Inject
@Named("CL_ORDERSTATUS")
I18nCodeList orderStatusCodeList;
public boolean existOrderStatus(String target) {
return orderStatusCodeList.asMap().containsKey(target); // (1)
}
}
項番 |
説明 |
---|---|
(1)
|
I18nCodeList#asMap() メソッドでコードリストをjava.util.Map 形式で取得する。 |
業務要件によって、特定のロケールのコードリストを取得する必要がある場合はasMap(Locale)
メソッドを使用する
import java.util.Locale;
import org.springframework.stereotype.Service;
import org.terasoluna.gfw.common.codelist.i18n.I18nCodeList;
import jakarta.inject.Inject;
import jakarta.inject.Named;
@Service
public class OrderServiceImpl implements OrderService {
@Inject
@Named("CL_ORDERSTATUS")
I18nCodeList orderStatusCodeList;
public boolean existOrderStatus(String target) {
return orderStatusCodeList.asMap(Locale.ENGLISH).containsKey(target); // (1)
}
}
項番 |
説明 |
---|---|
(1)
|
I18nCodeList#asMap(Locale) メソッドで、指定したロケールのコードリストをjava.util.Map 形式で取得する。ここでは
Locale.ENGLISH (”en”)を指定している。 |
4.9.2.6. 特定のコード値からコード名を表示する¶
JSP/テンプレートHTMLからコードリストを参照する場合は、CodeListInterceptor
がリクエストスコープにコードリストを java.util.Map
で格納しているため、Map
インターフェースと同じ方法で参照することができる。
コードリストを用いて特定のコード値からコード名を表示する方法について、以下に実装例を示す。
jspの実装例
Order Status : ${f:h(CL_ORDERSTATUS[orderForm.orderStatus])} // (1)
項番 |
説明 |
---|---|
(1)
|
コードリストを定義したbeanID(この例では |
テンプレートHTML実装例
<span th:text="${orderForm.orderStatus} != null ? |Order Status : ${CL_ORDERSTATUS.get(orderForm.orderStatus)}|"></span> <!--/* (1) */-->
項番 |
説明 |
---|---|
(1)
|
コードリストを定義したbeanID(この例では |
4.9.2.7. コードリストを用いたコード値の入力チェック¶
入力値がコードリスト内に定義されたコード値であるかどうかチェックするような場合、
共通ライブラリでは、BeanValidation用のアノテーション、org.terasoluna.gfw.common.codelist.ExistInCodeList
を提供している。
BeanValidationや、メッセージ出力方法の詳細については、入力チェックを参照されたい。
4.9.2.7.1. @ExistInCodeList の設定例¶
コードリストを用いた入力チェック方法について、以下に実装例を示す。
bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_GENDER") public SimpleMapCodeList clGender() { SimpleMapCodeList bean = new SimpleMapCodeList(); Map<String, String> map = new LinkedHashMap<>(); map.put("M", "Male"); map.put("F", "Femal"); bean.setMap(map); return bean; }
xxx-codelist.xml
<bean id="CL_GENDER" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList"> <property name="map"> <map> <entry key="M" value="Male" /> <entry key="F" value="Female" /> </map> </property> </bean>
Formオブジェクト
public class Person {
@ExistInCodeList(codeListId = "CL_GENDER") // (1)
private String gender;
// getter and setter omitted
}
項番 |
説明 |
---|---|
(1)
|
入力チェックを行いたいフィールドに対して、
@ExistInCodeList アノテーションを設定し、codeListIdにチェック元となる、コードリストを指定する。
|
上記の結果、gender
にM、F以外の文字が格納されている場合、エラーになる。
Note
terasoluna-gfw-common 5.4.2.RELEASEから、@ExistInCodeList
の入力チェックの対象として、 CharSequence
インタフェースの実装クラス(String
など) または Character
に加え、Number
継承クラス(Integer
など)をサポートするよう変更された。
NumberRangeCodeList
の valueFormat
プロパティを指定している場合、 Number
型フィールドの値を当該プロパティを利用してフォーマットした値がコードリストに存在することをチェックする。
4.9.3. How to extend¶
4.9.3.1. コードリストをリロードする場合¶
例:JdbcCodeListを使用して、DBのマスタを変更した時にコードリストの更新を行う場合。
共通ライブラリでは、コードリストを更新可能とするインタフェースを提供している。
org.terasoluna.gfw.common.codelist.ReloadableCodeList
:コードリストを更新するorg.terasoluna.gfw.common.codelist.i18n.ReloadableI18nCodeList
:行に持つコードリストを含むコードリストを更新する
コードリストの更新方法としては、以下2点の方法がある。
Task Schedulerで実現する方法
Controller(Service)クラスでrefreshメソッドを呼び出す方法
本ガイドラインでは、Springから提供されているTask Schedulerを使用して、コードリストを定期的にリロードする方式を基本的に推奨する。
ただし、任意のタイミングでコードリストをリフレッシュする必要がある場合はControllerクラスでrefreshメソッドを呼び出す方法で実現すればよい。
Note
ReloadableCodeList
およびReloadableI18nCodeList
インターフェースを実装しているコードリストについては、コードリスト種類一覧を参照されたい。
4.9.3.1.1. Task Schedulerで実現する方法¶
Task Schedulerの設定例について、以下に示す。
bean定義ファイルの定義
XxxCodelistConfig.java
public class XxxCodelistConfig implements SchedulingConfigurer { // (2) @Value("${cron.codelist.refreshTime}") private String codelistRefreshTime; @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.setScheduler(taskScheduler()); // (2) taskRegistrar.addTriggerTask(() -> clCronRefreshCodelist().refresh(), // (3) new CronTrigger(codelistRefreshTime)); // (3) } // (1) @Bean("taskScheduler") public Executor taskScheduler() { return Executors.newScheduledThreadPool(10); } @Bean("CL_CRON_REFRESH_CODELIST") public JdbcCodeList clCronRefreshCodelist() { JdbcCodeList jdbcCodeList = abstractJdbcCodeList(); jdbcCodeList.setQuerySql( "SELECT authority_id, authority_name FROM t_authority ORDER BY authority_id"); jdbcCodeList.setValueColumn("authority_id"); jdbcCodeList.setLabelColumn("authority_name"); return jdbcCodeList; }
項番
説明
(1)TaskSchedulerを定義する。引数にはスレッドのプールサイズを指定する。(2)SchedulingConfigurer
のconfigureTasks
メソッドを実装し、schedulerに、(1)で定義したTaskSchedulerを設定する。(3)実行するTaskを定義する。ここではJdbcCodeList#refresh
を定義している。cron属性に、org.springframework.scheduling.support.CronExpression
でサポートされた形式で記述すること。cron属性は開発環境、商用環境など環境によってリロードするタイミングが変わることが想定されるため、プロパティファイルや、環境変数等から取得することを推奨する。cron属性の設定例「秒 分 時 月 年 曜日」で指定する。毎秒実行 「* * * * * *」毎時実行 「0 0 * * * *」平日の9-17時の毎時実行 「0 0 9-17 * * MON-FRI」cronの指定値の詳細については、CronExpressionのJavaDocを参照されたい。
xxx-codelist.xml
<task:scheduler id="taskScheduler" pool-size="10"/> <!-- (1) --> <task:scheduled-tasks scheduler="taskScheduler"> <!-- (2) --> <task:scheduled ref="CL_AUTHORITIES" method="refresh" cron="${cron.codelist.refreshTime}"/> <!-- (3) --> </task:scheduled-tasks> <bean id="CL_AUTHORITIES" parent="AbstractJdbcCodeList"> <property name="querySql" value="SELECT authority_id, authority_name FROM authority ORDER BY authority_id" /> <property name="valueColumn" value="authority_id" /> <property name="labelColumn" value="authority_name" /> </bean>
項番
説明
(1)<task:scheduler>
の要素を定義する。pool-size属性にスレッドのプールサイズを指定する。pool-size属性を指定しない場合、”1” が設定される。(2)<task:scheduled-tasks>
の要素を定義し、scheduler属性に、<task:scheduler>
のIDを設定する。(3)<task:scheduled>
要素を定義する。method属性に、refreshメソッドを指定する。cron属性に、org.springframework.scheduling.support.CronExpression
でサポートされた形式で記述すること。cron属性は開発環境、商用環境など環境によってリロードするタイミングが変わることが想定されるため、プロパティファイルや、環境変数等から取得することを推奨する。cron属性の設定例「秒 分 時 月 年 曜日」で指定する。毎秒実行 「* * * * * *」毎時実行 「0 0 * * * *」平日の9-17時の毎時実行 「0 0 9-17 * * MON-FRI」cronの指定値の詳細については、CronExpressionのJavaDocを参照されたい。
4.9.3.1.2. Controller(Service)クラスでrefreshメソッドを呼び出す方法¶
refreshメソッドを直接呼び出す場合について、JdbcCodeListのrefreshメソッドをServiceクラスで呼び出す場合の実装例を、以下に示す。
bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_AUTHORITIES") public JdbcCodeList clAuthorities() { JdbcCodeList jdbcCodeList = abstractJdbcCodeList(); jdbcCodeList.setQuerySql("SELECT authority_id, authority_name FROM t_authority ORDER BY authority_id"); jdbcCodeList.setValueColumn("authority_id"); jdbcCodeList.setLabelColumn("authority_name"); return jdbcCodeList; }
xxx-codelist.xml
<bean id="CL_AUTHORITIES" parent="AbstractJdbcCodeList"> <property name="querySql" value="SELECT authority_id, authority_name FROM authority ORDER BY authority_id" /> <property name="valueColumn" value="authority_id" /> <property name="labelColumn" value="authority_name" /> </bean>
Controllerクラス
@Controller
@RequestMapping(value = "codelist")
public class CodeListController {
@Inject
CodeListService codeListService; // (1)
@RequestMapping(method = RequestMethod.GET, params = "refresh")
public String refreshJdbcCodeList() {
codeListService.refresh(); // (2)
return "codelist/jdbcCodeList";
}
}
項番 |
説明 |
---|---|
(1)
|
ReloadableCodeListクラスのrefreshメソッドを実行するServiceクラスをインジェクションする。
|
(2)
|
ReloadableCodeListクラスのrefreshメソッドを実行するServiceクラスのrefreshメソッドを実行する。
|
Serviceクラス
以下は実装クラスのみ記述し、インターフェースクラスは省略。
@Service
public class CodeListServiceImpl implements CodeListService { // (3)
@Inject
@Named(value = "CL_AUTHORITIES") // (4)
ReloadableCodeList codeListItem; // (5)
@Override
public void refresh() { // (6)
codeListItem.refresh(); // (7)
}
}
項番 |
説明 |
---|---|
(3)
|
実装クラス
CodeListServiceImpl は、インターフェースCodeListService を実装する。 |
(4)
|
コードリストをインジェクションするとき、
@Named で、該当するコードリストを指定する。value属性に取得したいbeanのIDを指定すること。
Bean定義ファイルに定義されているbeanタグのID属性”CL_AUTHORITIES”のコードリストがインジェクションされる。
|
(5)
|
フィールドの型にReloadableCodeListインターフェースを定義すること。
(4)で指定したBeanはReloadableCodeListインターフェースを実装していること。
|
(6)
|
Serviceクラスで定義したrefreshメソッド。
Controllerクラスから呼び出されている。
|
(7)
|
ReloadableCodeListインターフェースを実装したコードリストのrefreshメソッド。
refreshメソッドを実行することで、コードリストが更新される。
|
Note
terasoluna-gfw-common 5.4.2.RELEASEで追加されたSimpleReloadableI18nCodeList
では、refreshメソッドで行に持つすべてのReloadableCodeListを更新することが可能である。
アプリケーションの実装によっては、行に持つReloadableCodeListが更新されている前提でSimpleReloadableI18nCodeList
のみ更新すれば良い場合もあり得る。
この場合は、ReloadableI18nCodeList#refresh(boolean)
メソッドの引数にfalse
をセットして実行すれば良い。
4.9.3.2. コードリストを独自カスタマイズする方法¶
項番 |
Reloadable |
継承するクラス |
実装箇所 |
---|---|---|---|
(1)
|
不要
|
org.terasoluna.gfw.common.codelist.AbstractCodeList |
asMap をオーバライド |
(2)
|
必要
|
org.terasoluna.gfw.common.codelist.AbstractReloadableCodeList |
retrieveMap をオーバライド |
org.terasoluna.gfw.common.codelist.CodeList
、org.terasoluna.gfw.common.codelist.ReloadableCodeList
インターフェースを直接実装しても実現はできるが、共通ライブラリで提供されている抽象クラスを拡張することで、最低限の実装で済む。
コードリストクラス
package com.example.sample.domain.codelist;
// omitted
public class DepYearCodeList extends AbstractCodeList { // (1)
private ClockFactory clockFactory;
public void setClockFactory(ClockFactory clockFactory) { //(2)
this.clockFactory = clockFactory;
}
@Override
public Map<String, String> asMap() { // (3)
Clock clock = clockFactory.fixed();
LocalDateTime localDateTime = LocalDateTime.now(clock);
LocalDateTime nextYearDateTime = localDateTime.plusYears(1);
Map<String, String> depYearMap = new LinkedHashMap<>();
String thisYear = String.valueOf(localDateTime.getYear());
String nextYear = String.valueOf(nextYearDateTime.getYear());
depYearMap.put(thisYear, thisYear);
depYearMap.put(nextYear, nextYear);
return Collections.unmodifiableMap(depYearMap);
}
}
項番 |
説明 |
---|---|
(1)
|
AbstractCodeList を継承する。今年と来年の年のリストを作る時、動的にシステム日付から算出して作成しているため、リロードは不要。
|
(2)
|
システム日付のDateクラスを作成する
org.terasoluna.gfw.common.time.ClockFactory をインジェクションするためのセッターを用意する。ClockFactory を利用してシステム日時を取得することができる。 |
(3)
|
asMap メソッドをオーバライドして、今年と来年の年のリストを作成する。作成したいコードリスト毎に実装が異なる。
|
bean定義ファイルの定義
XxxCodelistConfig.java
// (1) @Bean("CL_YEAR") public DepYearCodeList clYearCodelist(ClockFactory clockFactory) { DepYearCodeList bean = new DepYearCodeList(); // (1) bean.setClockFactory(clockFactory); // (2) return bean; }
項番
説明
(1)作成したコードリストクラスをbean定義する。id にCL_YEAR
を指定することで、bean定義で設定したCodeListInterceptor
によりコードリストをコンポーネント登録する。(2)システム日付のDateクラスを作成するClockFactory
を設定する。事前に、bean定義ファイルにDataFactory実装クラスを設定する必要がある。
xxx-codelist.xml
<bean id="CL_YEAR" class="com.example.sample.domain.codelist.DepYearCodeList"> <!-- (1) --> <property name="clockFactory" ref="clockFactory" /> <!-- (2) --> </bean>
項番
説明
(1)作成したコードリストクラスをbean定義する。id にCL_YEAR
を指定することで、bean定義で設定したCodeListInterceptor
によりコードリストをコンポーネント登録する。(2)システム日付のDateクラスを作成するClockFactory
を設定する。事前に、bean定義ファイルにDataFactory実装クラスを設定する必要がある。
jspの実装例
<form:select path="mostRecentYear" items="${CL_YEAR}" /> <!-- (1) -->
項番 |
説明 |
---|---|
(1)
|
items属性にコンポーネント登録した
CL_YEAR を${} プレースホルダー で指定することで、該当のコードリストを取得することができる。 |
テンプレートHTML実装例
<select th:field="*{mostRecentYear}">
<option th:each="recentYear : ${CL_YEAR}" th:value="${recentYear.key}" th:text="${recentYear.value}"></option> <!--/* (1) */-->
</select>
項番 |
説明 |
---|---|
(1)
|
コンポーネント登録した
CL_YEAR を 変数式${} で指定することで、該当のコードリストを取得することができる。 |
出力HTML
<select id="mostRecentYear" name="mostRecentYear">
<option value="2013">2013</option>
<option value="2014">2014</option>
</select>
出力画面
Note
リロード可能であるCodeListを独自カスタマイズする場合、スレッドセーフになるように実装すること。
4.9.4. Appendix¶
4.9.4.1. SimpleI18nCodeListのコードリスト設定方法¶
4.9.4.1.1. 行単位でLocale毎のjava.util.Map
(key=コード値, value=ラベル)を設定する¶
bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_I18N_PRICE") public SimpleI18nCodeList clI18nPriceMapLocale() { Map<Locale, Map<String, String>> rowsMap = new LinkedHashMap<>(); Map<String, String> enMap = new LinkedHashMap<>(); enMap.put("0", "unlimited"); enMap.put("10000", "Less than \\10,000"); enMap.put("20000", "Less than \\20,000"); enMap.put("30000", "Less than \\30,000"); enMap.put("40000", "Less than \\40,000"); enMap.put("50000", "Less than \\50,000"); Map<String, String> jaMap = new LinkedHashMap<>(); jaMap.put("0", "上限なし"); jaMap.put("10000", "10,000円以下"); jaMap.put("20000", "20,000円以下"); jaMap.put("30000", "30,000円以下"); jaMap.put("40000", "40,000円以下"); jaMap.put("50000", "50,000円以下"); rowsMap.put(Locale.ENGLISH, enMap); rowsMap.put(Locale.JAPANESE, jaMap); SimpleI18nCodeList bean = new SimpleI18nCodeList(); bean.setRows(rowsMap); // (1) bean.setFallbackTo(Locale.ENGLISH); return bean; }
項番
説明
(1)rowsプロパティに対して、”MapのMap”を設定する。外側のMapのkeyはjava.lang.Locale
である。内側のMapのkeyはコード値、valueはロケールに対応したラベルである。
xxx-codelist.xml
<bean id="CL_I18N_PRICE" class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList"> <property name="rows"> <!-- (1) --> <util:map> <entry key="en"> <util:map> <entry key="0" value="unlimited" /> <entry key="10000" value="Less than \10,000" /> <entry key="20000" value="Less than \20,000" /> <entry key="30000" value="Less than \30,000" /> <entry key="40000" value="Less than \40,000" /> <entry key="50000" value="Less than \50,000" /> </util:map> </entry> <entry key="ja"> <util:map> <entry key="0" value="上限なし" /> <entry key="10000" value="10,000円以下" /> <entry key="20000" value="20,000円以下" /> <entry key="30000" value="30,000円以下" /> <entry key="40000" value="40,000円以下" /> <entry key="50000" value="50,000円以下" /> </util:map> </entry> </util:map> </property> </bean>
項番
説明
(1)rowsプロパティに対して、”MapのMap”を設定する。外側のMapのkeyはjava.lang.Locale
である。内側のMapのkeyはコード値、valueはロケールに対応したラベルである。
4.9.4.1.2. 列単位でコード値毎のjava.util.Map
(key=Locale, value=ラベル)を設定する¶
bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_I18N_PRCL_I18N_PRICEICE_MAP_CODE") public SimpleI18nCodeList clI18nPriceMapCode() { Map<String, Map<Locale, String>> columnsMap = new LinkedHashMap<>(); Map<Locale, String> key1Map = new LinkedHashMap<>(); key1Map.put(Locale.ENGLISH, "unlimited"); key1Map.put(Locale.JAPANESE, "上限なし"); Map<Locale, String> key2Map = new LinkedHashMap<>(); key2Map.put(Locale.ENGLISH, "Less than \\10,000"); key2Map.put(Locale.JAPANESE, "10,000円以下"); Map<Locale, String> key3Map = new LinkedHashMap<>(); key3Map.put(Locale.ENGLISH, "Less than \\20,000"); key3Map.put(Locale.JAPANESE, "20,000円以下"); Map<Locale, String> key4Map = new LinkedHashMap<>(); key4Map.put(Locale.ENGLISH, "Less than \\30,000"); key4Map.put(Locale.JAPANESE, "30,000円以下"); Map<Locale, String> key5Map = new LinkedHashMap<>(); key5Map.put(Locale.ENGLISH, "Less than \\50,000"); key5Map.put(Locale.JAPANESE, "40,000円以下"); Map<Locale, String> key6Map = new LinkedHashMap<>(); key6Map.put(Locale.ENGLISH, "Less than \\50,000"); key6Map.put(Locale.JAPANESE, "50,000円以下"); columnsMap.put("0", key1Map); columnsMap.put("10000", key2Map); columnsMap.put("20000", key3Map); columnsMap.put("30000", key4Map); columnsMap.put("40000", key5Map); columnsMap.put("50000", key6Map); SimpleI18nCodeList bean = new SimpleI18nCodeList(); bean.setColumns(columnsMap); // (1) bean.setFallbackTo(Locale.ENGLISH); return bean; }
項番
説明
(1)columnsプロパティに対して、”MapのMap”を設定する。外側のMapのkeyはコード値である。内側のMapのkeyはjava.lang.Locale
、valueはロケールに対応したラベルである。
xxx-codelist.xml
<bean id="CL_I18N_PRICE" class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList"> <property name="columns"> <!-- (1) --> <util:map> <entry key="0"> <util:map> <entry key="en" value="unlimited" /> <entry key="ja" value="上限なし" /> </util:map> </entry> <entry key="10000"> <util:map> <entry key="en" value="Less than \10,000" /> <entry key="ja" value="10,000円以下" /> </util:map> </entry> <entry key="20000"> <util:map> <entry key="en" value="Less than \20,000" /> <entry key="ja" value="20,000円以下" /> </util:map> </entry> <entry key="30000"> <util:map> <entry key="en" value="Less than \30,000" /> <entry key="ja" value="30,000円以下" /> </util:map> </entry> <entry key="40000"> <util:map> <entry key="en" value="Less than \40,000" /> <entry key="ja" value="40,000円以下" /> </util:map> </entry> <entry key="50000"> <util:map> <entry key="en" value="Less than \50,000" /> <entry key="ja" value="50,000円以下" /> </util:map> </entry> </util:map> </property> </bean>
項番
説明
(1)columnsプロパティに対して、”MapのMap”を設定する。外側のMapのkeyはコード値である。内側のMapのkeyはjava.lang.Locale
、valueはロケールに対応したラベルである。
4.9.4.2. NumberRangeCodeListのバリエーション¶
4.9.4.2.1. 降順のNumberRangeCodeListの作成¶
次に、Toの値をFromの値より小さくする(To < From)場合の実装例を、以下に示す。
bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_BIRTH_YEAR") public NumberRangeCodeList clBirthYear() { NumberRangeCodeList bean = new NumberRangeCodNumberRangeCodeListeList(); bean.setFrom(2013); // (1) bean.setTo(2000); // (2) return bean; }
項番
説明
(1)範囲開始の値を指定する。name属性”to”のvalue属性の値より大きい値を指定する。この指定によって、interval分減少した値を、To~Fromの範囲分のリストとして、降順に表示する。intervalは設定していないため、デフォルトの値1が適用される。(2)範囲終了の値を設定する。本例では、2000を指定することにより、リストには2013~2000までの範囲で1ずつ減少して格納される。
xxx-codelist.xml
<bean id="CL_BIRTH_YEAR" class="org.terasoluna.gfw.common.codelist.NumberRangeCodeList"> <property name="from" value="2013" /> <!-- (1) --> <property name="to" value="2000" /> <!-- (2) --> </bean>
項番
説明
(1)範囲開始の値を指定する。name属性”to”のvalue属性の値より大きい値を指定する。この指定によって、interval分減少した値を、To~Fromの範囲分のリストとして、降順に表示する。intervalは設定していないため、デフォルトの値1が適用される。(2)範囲終了の値を設定する。本例では、2000を指定することにより、リストには2013~2000までの範囲で1ずつ減少して格納される。
jspの実装例
<form:select path="birthYear" items="${CL_BIRTH_YEAR}" />
テンプレートHTML実装例
<select th:field="*{birthYear}">
<option th:each="birthYear : ${CL_BIRTH_YEAR}" th:value="${birthYear.key}" th:text="${birthYear.value}"></option>
</select>
出力HTML
<select id="birthYear" name="birthYear">
<option value="2013">2013</option>
<option value="2012">2012</option>
<option value="2011">2011</option>
<option value="2010">2010</option>
<option value="2009">2009</option>
<option value="2008">2008</option>
<option value="2007">2007</option>
<option value="2006">2006</option>
<option value="2005">2005</option>
<option value="2004">2004</option>
<option value="2003">2003</option>
<option value="2002">2002</option>
<option value="2001">2001</option>
<option value="2000">2000</option>
</select>
出力画面
4.9.4.2.2. NumberRangeCodeListのインターバルの変更¶
次に、interval値を設定する場合の実装例を、以下に示す。
bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_BULK_ORDER_QUANTITY_UNIT") public NumberRangeCodeList clBulkOrderQuantityUnit() { NumberRangeCodeList bean = new NumberRangeCodeList(); bean.setFrom(10); bean.setTo(50); bean.setInterval(10); // (1) return bean; }
項番
説明
(1)増加(減少)値を指定する。この指定によって、interval値を増加(減少)した値を、From~Toの範囲内でコードリストとして格納する。上記の例だと、コードリストには10
,20
,30
,40
,50
の順で格納される。
xxx-codelist.xml
<bean id="CL_BULK_ORDER_QUANTITY_UNIT" class="org.terasoluna.gfw.common.codelist.NumberRangeCodeList"> <property name="from" value="10" /> <property name="to" value="50" /> <property name="interval" value="10" /> <!-- (1) --> </bean>
項番
説明
(1)増加(減少)値を指定する。この指定によって、interval値を増加(減少)した値を、From~Toの範囲内でコードリストとして格納する。上記の例だと、コードリストには10
,20
,30
,40
,50
の順で格納される。
jspの実装例
<form:select path="quantity" items="${CL_BULK_ORDER_QUANTITY_UNIT}" />
テンプレートHTML実装例
<select th:field="*{quantity}">
<option th:each="quantity : ${CL_BULK_ORDER_QUANTITY_UNIT}" th:value="${quantity.key}" th:text="${quantity.value}"></option>
</select>
出力HTML
<select id="quantity" name="quantity">
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
</select>
出力画面
Note
interval値分増加(減少)した値が、Form~Toの値が範囲を超えた場合は、コードリストに格納されない。
具体的には、
@Bean("CL_BULK_ORDER_QUANTITY_UNIT") public NumberRangeCodeList clBulkOrderQuantityUnit() { NumberRangeCodeList bean = new NumberRangeCodeList(); bean.setFrom(10); bean.setTo(55); bean.setInterval(10); return bean; }<bean id="CL_BULK_ORDER_QUANTITY_UNIT" class="org.terasoluna.gfw.common.codelist.NumberRangeCodeList"> <property name="from" value="10" /> <property name="to" value="55" /> <property name="interval" value="10" /> </bean>
という定義を行った場合、
コードリストには10
,20
,30
,40
,50
の計5つが格納される。
次のintervalである60
及び範囲の閾値である55
はコードリストに格納されない。
4.9.4.3. JSP/テンプレートHTMLから直接コードリストBeanを参照する¶
共通ライブラリから提供しているインタセプターの使用では、Spring MVCを経由する全てのリクエストに対して、CodeListIntercepter
がコードリストのBeanをリクエスト属性として登録するため、コードリストの数が多くなるとリクエスト毎のオーバーヘッドの増加が懸念される。
bean定義ファイルの定義
SpringMvcConfig.java
@EnableAspectJAutoProxy @EnableWebMvc @Configuration public class SpringMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(codeListInterceptor()).addPathPatterns("/**"); // (1) } // (1) @Bean public CodeListInterceptor codeListInterceptor() { CodeListInterceptor codeListInterceptor = new CodeListInterceptor(); codeListInterceptor.setCodeListIdPattern(Pattern.compile("CL_.+")); return codeListInterceptor; }
項番
説明
(1)CodeListInterceptor
の設定があれば、削除する。
spring-mvc.xml
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /> <bean class="org.terasoluna.gfw.web.codelist.CodeListInterceptor"> <!-- (1) --> <property name="codeListIdPattern" value="CL_.+" /> </bean> </mvc:interceptor> <!-- omitted --> </mvc:interceptors>
項番
説明
(1)CodeListInterceptor
の設定があれば、削除する。
bean定義ファイルの定義
XxxCodelistConfig.java
@Bean("CL_ORDERSTATUS") public SimpleMapCodeList clOrderstatus() { Map<String, String> codeMap = new LinkedHashMap<>(); codeMap.put("1", "Received"); codeMap.put("2", "Sent"); codeMap.put("3", "Cancelled"); SimpleMapCodeList bean = new SimpleMapCodeList(); bean.setMap(codeMap); return bean; }
xxx-codelist.xml
<bean id="CL_ORDERSTATUS" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList"> <property name="map"> <util:map> <entry key="1" value="Received" /> <entry key="2" value="Sent" /> <entry key="3" value="Cancelled" /> </util:map> </property> </bean>
jspの実装例
<spring:eval var="statuses" expression="@CL_ORDERSTATUS.asMap()"/> <!-- (1) -->
<form:select items="${statuses}" path="orderStatus" />
項番 |
説明 |
---|---|
(1)
|
SpELにより取得した
CodeList 型BeanのasMap メソッドにより、Map 形式で取得することができる。 |
テンプレートHTML実装例
<select th:field="*{orderStatus}">
<option th:each="order : ${@CL_ORDERSTATUS.asMap()}" th:value="${order.key}" th:text="${order.value}"></option> <!--/* (1) */-->
</select>
項番 |
説明 |
---|---|
(1)
|
変数式により取得したコードリストBeanのasMapメソッドにより、Map形式で参照することができる。
なお、
SimpleI18nCodeList の場合は、asMap メソッドの引数としてLocale を渡す必要がある。 |
出力HTML
<select id="orderStatus" name="orderStatus">
<option value="1">Received</option>
<option value="2">Sent</option>
<option value="3">Cancelled</option>
</select>
4.9.4.3.1. SimpleI18nCodeListをテンプレートHTMLから直接参照する方法¶
ここでは、CodeListInterceptor
の実装と同様に、リクエストのロケールに対するコードリストに定義されていなかった場合、デフォルトで設定したロケールに対するコードリストを表示する例を紹介する。
bean定義ファイルの定義
SpringMvcConfig.java
/spring-mvc.xml
はbean定義ファイルの定義と同様なため割愛する。
@Bean("CL_I18N_PRICE")
public SimpleI18nCodeList clI18nPrice() {
Map<Locale, CodeList> rows = new LinkedHashMap<>();
rows.put(Locale.ENGLISH, clPriceEn());
rows.put(Locale.JAPANESE, clPriceJa());
SimpleI18nCodeList bean = new SimpleI18nCodeList();
bean.setRowsByCodeList(rows);
return bean;
}
@Bean("CL_PRICE_EN")
public SimpleMapCodeList clPriceEn() {
Map<String, String> enMap = new LinkedHashMap<>();
enMap.put("0", "unlimited");
enMap.put("10000", "Less than \\10,000");
enMap.put("20000", "Less than \\20,000");
enMap.put("30000", "Less than \\30,000");
enMap.put("40000", "Less than \\40,000");
enMap.put("50000", "Less than \\50,000");
SimpleMapCodeList bean = new SimpleMapCodeList();
bean.setMap(enMap);
return bean;
}
@Bean("CL_PRICE_JA")
public SimpleMapCodeList clPriceJa() {
Map<String, String> jaMap = new LinkedHashMap<>();
jaMap.put("0", "上限なし");
jaMap.put("10000", "10,000円以下");
jaMap.put("20000", "20,000円以下");
jaMap.put("30000", "30,000円以下");
jaMap.put("40000", "40,000円以下");
jaMap.put("50000", "50,000円以下");
SimpleMapCodeList bean = new SimpleMapCodeList();
bean.setMap(jaMap);
return bean;
}
<bean id="CL_I18N_PRICE"
class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList">
<property name="rowsByCodeList">
<util:map>
<entry key="en" value-ref="CL_PRICE_EN" />
<entry key="ja" value-ref="CL_PRICE_JA" />
</util:map>
</property>
</bean>
<bean id="CL_PRICE_EN" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList">
<property name="map">
<util:map>
<entry key="0" value="unlimited" />
<entry key="10000" value="Less than \10,000" />
<entry key="20000" value="Less than \20,000" />
<entry key="30000" value="Less than \30,000" />
<entry key="40000" value="Less than \40,000" />
<entry key="50000" value="Less than \50,000" />
</util:map>
</property>
</bean>
<bean id="CL_PRICE_JA" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList">
<property name="map">
<util:map>
<entry key="0" value="上限なし" />
<entry key="10000" value="10,000円以下" />
<entry key="20000" value="20,000円以下" />
<entry key="30000" value="30,000円以下" />
<entry key="40000" value="40,000円以下" />
<entry key="50000" value="50,000円以下" />
</util:map>
</property>
</bean>
プロパティファイル
simpleI18nCodeList.fallback.locale = en
Controllerクラス
...
@Controller
public class OrderController {
@Value("${simpleI18nCodeList.fallback.locale}") // (1)
private Locale fallBackLocale;
@RequestMapping(value = "price", method = RequestMethod.GET)
public String price(Model model, HttpServletRequest request) {
model.addAttribute("requestLocale", RequestContextUtils
.getLocale(request)); // (2)
model.addAttribute("fallBackLocale",fallBackLocale); // (3)
return "order/price";
}
}
項番 |
説明 |
---|---|
(1)
|
リクエストで指定したロケールがコードリストに定義されていなかった場合に、どのロケールのコードリストを取得するかをプロパティファイルから取得し、
fallBackLocale 変数に設定する。 |
(2)
|
org.springframework.web.servlet.support.RequestContextUtils 利用してリクエストで指定されたロケールを取得し、Modelに登録する。RequestContextUtils のgetLocale メソッドは、引数にjakarta.servlet.http.HttpServletRequest を取るため、この場合はHttpServletRequest をハンドラメソッドの引数にとっても良い。 |
(3)
|
(1) で取得した
fallBackLocale をModelに登録する。 |
テンプレートHTML実装例
<select th:field="*{basePrice}">
<option th:each="price : ${@CL_I18N_PRICE.asMap(requestLocale).isEmpty()} ?
${@CL_I18N_PRICE.asMap(fallBackLocale)} : ${@CL_I18N_PRICE.asMap(requestLocale)}"
th:value="${price.key}" th:text="${price.value}"></option> <!--/* (1) */-->
</select>
項番 |
説明 |
---|---|
(1)
|
リクエストで指定したロケールに対応するコードリストを
Map 形式で取得する。リクエストで指定したロケールがコードリストに定義されていなかった場合、
fallbackLocale 変数に設定したロケールで対応するコードリストをMap 形式で取得する。 |
出力HTML lang=en
<select id="basePrice" name="basePrice">
<option value="0">unlimited</option>
<option value="1">Less than \10,000</option>
<option value="2">Less than \20,000</option>
<option value="3">Less than \30,000</option>
<option value="4">Less than \40,000</option>
<option value="5">Less than \50,000</option>
</select>
出力HTML lang=ja
<select id="basePrice" name="basePrice">
<option value="0">上限なし</option>
<option value="1">10,000円以下</option>
<option value="2">20,000円以下</option>
<option value="3">30,000円以下</option>
<option value="4">40,000円以下</option>
<option value="5">50,000円以下</option>
</select>
出力HTML lang=undefined
<select id="basePrice" name="basePrice">
<option value="0">unlimited</option> <!--/* (1) */-->
<option value="1">Less than \10,000</option>
<option value="2">Less than \20,000</option>
<option value="3">Less than \30,000</option>
<option value="4">Less than \40,000</option>
<option value="5">Less than \50,000</option>
</select>
項番 |
説明 |
---|---|
(1)
|
リクエストで指定したロケールがコードリストに定義されていなかった場合に、
fallbackLocale 変数で指定した”en” が設定されるため、ロケールが”en”であるCL_PRICE_EN コードリストが表示される。 |