Java Springの逆引きメモ -7ページ目

Java Springの逆引きメモ

JavaのSpring frameworkのメモを書いていきます!
初心者の勉強ノートなので間違いがあるかもしれませんが、何かヒントになることがあれば幸いです。

プロパティファイルを読み込むのはちょっと面倒です。

しかし、Springでは簡単にできます!


 ※プロパティファイルというのは、「キー = 値」の組でデータを記述していくファイルです。



【サンプル(Springファイル)】


<bean id="testProperty"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>file:c:/test1.properties</value>
<value>file:c:/test2.properties</value>
</list>
</property>
</bean>



【プログラム側のPropertiesの受け取り方】


Properties p = (Properties)applicationContext.getBean("testProperty");



【説明】

さて、ほとんど説明は要らないですよね!

簡単!簡単!


要は、PropertiesFactoryBeanを使用するだけです。


valueタグ内のファイルパスについて補足すると、file:は、接頭語です。

無いと頭に"/"が自動付与されるので、Windowsでは"c:/"というパスを記述すると

「/c:/test1.properties」

のように解釈されて、ファイルが見つからないことになります。


また、環境変数をパスの指定に使用できます。

このあたりは別の記事にもう少し記述していますので、よければ参照くださいにひひ

 ・DIの設定ファイルで外部ファイル(プロパティファイル)を参照するには?



このような機能を自作で作成してしまうのはあまりよくないです。

Springの機能の方が当然ながら、プログラムレスででき、しかも、安全、機能豊富です。

是非利用して、効率のよい開発をしましょう!




参照:

・トップ

・DIの設定ファイルを書くには?

・DIの設定ファイルで外部ファイル(プロパティファイル)を参照するには?

・DIの設定ファイル内から外部DIファイルを参照するには?

・Controller内でApplicationContextを取得するには?
・システムプロパティとは?

前回の記事 ではDIファイル内からプロパティファイルを参照する方法を見てみました。

今回は、DIファイル内からDIファイルを参照する方法です!

というか、これを先にやるべきでしたね。。えっ



【サンプル】

簡単です。Spring設定ファイル内(DIファイル内)で以下のように記述します。


<import resource="file:D:/${USERNAME}/test.xml"/>




【説明】

特に説明は要らないかと思います。

importタグを使用します!

これだけで、importタグとtest.xmlの内容が置き換わったのと同じ効果があります。

しかもファイルパスには、環境変数やシステムプロパティを${}で使用することができます。

Windowsの場合、USERNAMEはログインのユーザIDです。


${}については、前回の記事を参照ください。

PropertyPlaceholderConfigurerクラスを使用して書き換えることもできます。



Springは、かなり便利ですね~。



参考:

・トップ

・DIの設定ファイルを書くには?

・DIの設定ファイルで外部ファイル(プロパティファイル)を参照するには?

・プロパティファイルをPropertiesクラスのbeanにするには?
・システムプロパティとは?

ここでは、Springの設定ファイルで外部ファイル(プロパティファイル)を参照する方法を書いてみます。

え!?わざわざ外部のファイルをみなくてもそのままSpringの設定ファイルに書けばいいじゃない、と

思った方は下の「前座」を読んでみてください。



【前座】

Springの設定ファイルでクラスの初期値も設定できます。

これの便利なところは、わざわざ外部定義読み込みようの機能を実装しなくても、設定を外部定義できるところです!


しかし、WEBなどではSpringのファイルはwarの中に入れなければなりません。

これは少し問題です。

環境が複数あり、環境ごとにDBの接続先のID/PWが違う場合はどうしましましょうか?

Mavenの機能で環境ごとに接続先を書き換えるようにすればだいぶ解決しますが、

お客さんが「ベンダーには運用機のDBのID/PWは教えたくない!」といわれたらどうします?

お客さんに「Springの設定ファイルをいじってwarファイルを作リ直して!」、といいます?


そうなんです。

Springに設定を書くととても楽なのですが、環境ごとに設定を変えたい場合は、外部参照ファイルをwarファイルとは別に作成して利用できると解決できることが多そうです!

いろいろな立場の人物が介入するような場合は特にですね。



【サンプル】

<applicationContext.xml>

※beansタグは省略しています。他の記事を参照してみてください。


<bean id="dbPlaceConf" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:D:/test.properties"/>
</bean>


<!-- Data Source -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>



<test.propertiesファイル(外部参照ファイル)>

db.driver=org.postgresql.Driver
db.url=jdbc:postgresql://localhost/test?useUnicode=true&characterEncoding=utf-8
db.username=postgres
db.password=postgres




【説明】

PropertyPlaceholderConfigurerというSpringのクラスを使用すると、${}の形でプロパティファイル内の値を参照することができます。

ですので、上記のDataSourceのようにキーワードで記述すれば外部ファイルに記述した値が埋め込まれます。

便利ですよね。

サーバごとにこのプロパティファイルを変えれは、tomcatでデプロイするwarファイルをサーバごとに作り直す必要がなくなります。ニコニコ

楽ですね!


 ※一応、locationプロパティについて補足しておきましょうか。

  これはSpringのResouceインタフェースになっています。

  文字列を設定できるのは、Springが自動で変換してくれているからです。

  この変換はなかなか面白いです。

  上記では、「file:」を先頭に記述していますが、実は書かなくてもファイルパスは書けます。

  しかし、WEB-INFをルートとしてそこからの絶対パス、または相対パスとなるため、

  warの外に外部ファイルを置きたいという目的に合いません。

  今回のようにシステムの絶対パスを指定したい場合は、「file:」という接頭語をつけるとSpringが

  変換してくれます!

  他にも、「classpath:」という接頭語もあるようです。

  このあたりをうまく使って、いろいろ自由に設定をしてみましょう。

  自作のクラスのsetterの引数にResouceを使用してファイルを取得するのも柔軟性が高くなって

  面白そうですねー。



<環境変数またはシステムプロパティを使用する場合>

環境変数を使用できると、1つのサーバ内で複数の環境を構築する場合も楽になります。

実は環境変数やシステムプロパティ も${}で参照します!


例えばWindowsXPの場合、USERNAMEという変数があり、ログインしているユーザIDが参照できます。

これを使った例を見てみましょう。


<bean id="dbPlaceConf" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:C:/Documents and Settings/${USERNAME}/test.properties"/>

</bean>


これだけです!

これは、上記のPropertyPlaceholderConfigurerの設定上だけではなく、すべてのbeanの設定でも同じです。


さて、すると問題が出てきます。

プロパティファイルに記述したキーワードと、環境変数の名前がかぶった場合はどうなるんでしょう?


実は、これも設定できるのです。

PropertyPlaceholderConfigurerのbeanタグ内で以下を設定します。


<property name="searchSystemEnvironment" value="true"/>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>



1行目は、環境変数を使用するかどうか?を設定します。(デフォルトtrue)

2行目は、環境変数とプロパティファイルのどちらを優先にするか?を設定します。

使用できる設定は以下のとおりです。

設定値 意味
SYSTEM_PROPERTIES_MODE_FALLBACK

プロパティファイルにキーワードが見つからないとき、環境変数またはシステムプロパティを探しに行きます。

デフォルト値です。

SYSTEM_PROPERTIES_MODE_NEVER 環境変数およびシステムプロパティは一切参照しません。
SYSTEM_PROPERTIES_MODE_OVERRIDE 環境変数およびシステムプロパティの設定を優先します。





参考:

・トップ

・DIの設定ファイルを書くには?

・DIの設定ファイル内から外部DIファイルを参照するには?

・プロパティファイルをPropertiesクラスのbeanにするには?

・システムプロパティとは?

apacheが提供しているフレームワークで、SpringでもStrutsでも使用できます。

このフレームワークは、HTMのLデザインをテンプレート化することができます。


具体的に見てみた方が早いので、サンプルを見てみることにしましょう!



【サンプルテンプレート(JSPファイル)】

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles " prefix="tiles" %>
<html>
<head>
<title><tiles:getAsString name="title"/></title>
</head>
<body>
<table>
<tr>
<td colspan="2">
</td>
</tr>
<tr>
<td colspan="2">
<tiles:insertAttribute name="footer" />
</td>
</tr>
</table>
</body>
</html>


insertAttribute でfooterが割り当てられています。

footerにどのJSPファイルを当てはめるかは定義ファイルという別ファイルで定義します。


titleのような文字列も定義ファイルで別に記述できます。


ですので、1つのテンプレートファイルを何度も再利用して画面を作っていくことができます。

特に画面デザインがほとんどの画面で同じときはテンプレートファイルは1種類か2種類くらいですみます。

tilesを使用しなければ、

100画面くらい存在するシステムで「デザインを変更したい」となると、100個のJSPファイルを変更しなければならないでしょう。

でもtilesを使用すれば1ファイルを変更するだけです。

これがtilesが重宝される理由です。


逆にすべての画面が違うデザインになるような場合は使用しない方がいいかも知れないです。



【補足】

tilesの定義ファイルはXMLになっていて、1画面につき1つのタグで記述されます。

つまり100画面あれば100個分の定義を書く必要があります。


それを軽減してくれるのが、tiles2.1以降のワイルドカードの機能です。

以下のような感じで記述できます!


<definition name="test.definition*.message*" template="/layout.jsp">
<put-attribute name="title" value="This definition has a message: {2}."/>
<put-attribute name="header" value="/header.jsp"/>
<put-attribute name="body" value="/body{1}.jsp"/>
</definition>


これならJSPファイル名と画面定義名の命名規則さえ決めておけば自動で割り当てられそうですね!



しかしSpringの場合、tiles2.1系のものは使用できないようです。

自作でConfig用のクラスを作成すればいけるそうですが、JavaのバージョンやTomcatのバージョンによっては

できないかもしれません。


この辺は以下の参考のtilesについてに記述してみましたので参考にしてみてください!



参考:

・トップ

・tilesについて

・SpringMVCの機能について




'2012.03.23 追記

このブログで扱っているSpringMVCのバージョンは2.5で、情報が古くなっています。

現状、アノテーションを使用してかなり柔軟で使いやすくなっていますにひひ

この記事を削除することはしませんが、最新の情報を検索されることをお勧めします。

Spring MVC 3.xについて(日本語の記事)




-----------------------

SpringにもTilesがあるぞ!

ということで、ちょっと調べたメモです。



【使用あたって】

まず、apacheのtilesのバージョンによっては使用できないということをお伝えせねばなりませぬ。。


tilesは、apacheのフレームワークです。

 http://tiles.apache.org/


現在の最新バージョンは 2.1.2です。

そしてSpringが対応したバージョンは、tilesの2.0.4のようです。


どうも、tiles 2.1.x以降ではエラーがでるようです。


以下に記述するのは実際試したわけではなく、WEBのいろいろな方のブログなどを読んだ情報です。



<エラーの原因>

SpringではSpringで用意しているTilesConfigurerというクラスを使用してTilesの初期化をするようです。

その初期化の際に、tiles2.1.xではdepricatedされたメソッドを呼び出しているようです。

そのためエラーになっているようです。


 http://forum.springsource.org/archive/index.php/t-65907.html



<回避方法>

上記のリンクに原因とともに回避方法も書かれているのですが、自分はうまく行きませんでした。

すみません。単に英語が良く分かっていないからだと思うので、

こちらも参照してもし解決されたら幸いです!


TilesConfigurerを自作して回避する方法:

http://richardbarabe.wordpress.com/2009/02/23/apache-tiles-2-integration-with-spring-mvc/



結局、tilesの2.0.xの古いバージョンを使用するか、Strutsを使用するのが手っ取り早そうです。

また、上記のリンクによると、現在の最新Spring3でも改修されていなくて、予想では次のリリースなどで

改修されるかもとのことのようです。


tilesの2.0.x系のダウンロードは例えば以下でできます。

 http://mirrors.isc.org/pub/apache/tiles/v2.0.7/


 ※ただし、tilesのdefinitionの中でワイルドカードを使用できるのは2.1.x以降のようです。
  http://tiles.apache.org/framework/tutorial/advanced/wildcard.html



【使用方法】

使用方法は、こちらのリンクに書かれています。

SpringのTiles機能(Spring本家のHP)


このリンクを参照すれば問題ないかと思います。

でも一応、tiles 2.0.7を使用した場合の例を軽く見ていきます!


<準備>

①tilesをダウンロードします。(tiles-2.0.7-bin.zip)

 http://mirrors.isc.org/pub/apache/tiles/v2.0.7/  


②eclipseのlibにjarをドラッグ&ドロップします。

 tiles-api-2.0.7.jar

 tiles-core-2.0.7.jar

 tiles-jsp-2.0.7.jar



<Spring設定ファイル(/WEB-INF/xxx-servlet.xml)>

以下の記述を追記します。


<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles/defs/tiles-def.xml</value>
</list>
</property>
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>


<!-- マッピング -->

<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/ttt.html">tileNameController</prop>
</props>
</property>
</bean>


<!-- テスト用のコントローラ。何でもいいです。 -->
<bean id="tileNameController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController">
</bean>



<tiles定義ファイルの作成(/WEB-INF/tiles/defs/tiles-def.xml)>

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd ">


<tiles-definitions>
<definition name="ttt" template="/WEB-INF/tiles/layouts/classic.jsp">
<put-attribute name="title" value="Tiles tutorial homepage" />
<put-attribute name="footer" value="/WEB-INF/tiles/footer.jsp" />
</definition>

</tiles-definitions>



<classicファイルの作成(/WEB-INF/tiles/layouts/classic.jsp)>

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles " prefix="tiles" %>
<html>
<head>
<title><tiles:getAsString name="title"/></title>
</head>
<body>
<table>
<tr>
<td colspan="2">
</td>
</tr>
<tr>
<td colspan="2">
<tiles:insertAttribute name="footer" />
</td>
</tr>
</table>
</body>
</html>



<footerファイルの作成(/WEB-INF/tiles/footer.jsp)>

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>

ふったです!



<表示>

以下のURLでおそらく表示できると思います。

 http://localhost:8080/XXX/ttt.html


 XXXは自分で設定したドキュメントルートを記述してください。



【説明】

なんとなくどのようになっているかは分かると思います。

Springの設定ファイルに、tilesのbean (tilesConfigurer)が設定されています。

初期化と、tilesの定義ファイルを決めることができます。


tileNameControllerはSpringで用意されているコントローラで、UrlFilenameViewControllerクラスです。

リクエストのあったURLをそのままJSPファイルのパスに置き換えて、

置き換えられたパスにあるJSPファイルを表示します。


ただし今回の場合は、viewResolverでTilesを設定しています。

これはJSPファイル名の変わりにtilesで定義された定義名を呼び出すことになります

つまり、http://localhost:8080/XXX/ttt.html  にアクセスがあった場合、"ttt"という定義を

tiles-def.xmlファイルから探します。


すぐに見つかりますね!

それが表示されるのです。



【tiles-definitionsの内容(tiles-def.xml)】

定義ファイルでは、定義名と、使用する文字列やJSPファイルを記述します。


titleは文字どおりタイトルの文字列を記述していて、classic.jspで

 <tiles:getAsString name="title"/>

というように取り出しています。

footerは、JSPファイルのパスを指定していて、classic.jspで

 <tiles:insertAttribute name="footer" />

というように取り出しています。


こうすることで、classic.jspのようなファイルを1つ作って何回も使いまわしできますよね。

定義ファイルでいくらでもfooterに使うJSPファイルやタイトルを変更できますから!



補足:

ここではファイルを/WEB-INF/tilesなどの下に置くようにしました。
定義ファイルへの記述が長くなって大変かと思います。

/WEB-INFのひとつ上のパスに置けば、/footer.jspなどのように簡潔に記述できます。

tilesのデフォルトサンプルではそうなっていますが、ここではいきなり/footer.jspなどと記述しても

どこにおいていいか分からないかと思い、わざとWEB-INFの下におく構成にしました。


各自分かりやすい場所におきましょう!



補足2:

tiles-def.xmlで使用できる定義名について。

定義名には、ピリオド「.」、スラッシュ「/」なども使用できるようです。

ですので、

<definition name="/WEB-INF/jsp/top.jsp" template="/WEB-INF/jsp/top.jsp">
</definition>

なんて記述することもできます。





参考:

・トップ

・tilesとは?

・SpringMVCの機能について