JSF(JavaServer Faces)の基本
JSF2.2の基本をまとめる。(2.2感は無いかも)
JSF2.2はJavaEE7のコンポーネントベースのMVCフレームワーク。
コンポーネントベースは、「リクエストの際URIを意識せずサーバサイドのロジックを直接呼ぶ」って感じかな。
対してStrutsのようなリクエスト駆動型ってやつは、「リクエストの際URIを意識してサーバサイドのリクエストURIに紐づいたロジックを呼ぶ」。
JSF2.2のMVCは以下の通り。
- モデル(M)
- ビュー(V)
- コントローラ(C)
■ビューの例(Facelets+EL式)
<h:inputText id="textField" value="#{sampleManagedBean.input}" /> <h:commandButton value="送信" action="#{sampleManegedBean.pushButton()}" />
「
タグ内のvalue属性、action属性の中身がEL式。
EL式は下記のJSFマネージドBeanに紐づいている。
EL式内の「sampleManagedBean」という記述と下記JSFマネージドBeanの@Namedアノテーション内value属性値「sampleManagedBean」が紐づいている。
EL式内の「sampleManagedBean.」後の記述が下記JSFマネージドBeanのフィールド変数inputやメソッドpushButton()に紐づいている。
■モデルの例(CDI管理のJSFマネージドBean)
@Named(value = "sampleManagedBean") @RequestScoped public class SampleManagedBean { private String input; // GetterとSetterは書いてね! public String pushButton() { System.out.println(this.input); return ""; } }
「@RequestScoped」アノテーションで文字通りこのクラスはリクエストスコープになる。
サンプルアプリ(Tomcat)
テキストフィールドにメッセージを入力するとAPサーバの標準出力に出るだけのアプリ。
Maven Tomcat Pluginで動かしてみる。
■POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.sample</groupId> <artifactId>jsf-sample</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>jsf-sample</name> <properties> <!-- Generic properties --> <jdk.version>1.7</jdk.version> <encoding>UTF-8</encoding> <!-- lib versions --> <jsf.version>2.2.4</jsf.version> <el.version>2.2</el.version> </properties> <build> <finalName>jsf-sample</finalName> <plugins> <!-- compiler --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${jdk.version}</source> <target>${jdk.version}</target> <encoding>${encoding}</encoding> </configuration> </plugin> <!-- Tomcat Maven Plugin --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <charset>${encoding}</charset> <uriEncoding>${encoding}</uriEncoding> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <scope>provided</scope> <version>2.5</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> <version>${jsf.version}</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> <version>${jsf.version}</version> </dependency> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet</artifactId> <version>2.1.0.Final</version> </dependency> <dependency> <groupId>javax.el</groupId> <artifactId>el-api</artifactId> <version>${el.version}</version> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>el-impl</artifactId> <version>${el.version}</version> </dependency> </dependencies> </project>
■web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <!-- CDI用リスナー(GlassFishだと不要) --> <listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener> <!-- EL式用(GlassFishだと不要) --> <context-param> <param-name>com.sun.faces.expressionFactory</param-name> <param-value>com.sun.el.ExpressionFactoryImpl</param-value> </context-param> <!-- JSF用 --> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> <welcome-file-list> <welcome-file>faces/index.xhtml</welcome-file> </welcome-file-list> </web-app>
■faces-config.xml(web.xmlと同じ階層におく、なくてもいい)
<?xml version="1.0" encoding="UTF-8"?> <faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" version="2.2"> </faces-config>
特に設定不要。
■beans.xml(web.xmlと同じ階層におく)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all"> </beans>
「bean-discovery-mode」の設定バリエーションは下記の通り。
- all
- 全てのクラスにインジェクション
- annotated
- アノテーションが付与されたクラスに対してのみインジェクション
- none
- インジェクションしない?
■index.xml(webapp直下)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang="ja" xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html"> <h:head> <meta charset="UTF-8" /> <title>JSF Sample</title> </h:head> <h:body> はろー Facelets <h:form> <h:inputText id="textField" value="#{sampleManagedBean.input}"/> <h:commandButton value="Send Message" action="#{sampleManagedBean.pushButton()}"/><br/> </h:form> </h:body> </html>
一応HTML5仕様。JSFはHTML5フレンドリらしいので。
■JSFマネージドBean(org.sample.managedbean.SampleManagedBean)
package org.sample.managedbean; import javax.enterprise.context.RequestScoped; import javax.inject.Named; @Named(value = "sampleManagedBean") @RequestScoped public class SampleManagedBean { private String input; public SampleManagedBean() { } public String pushButton() throws Exception { System.out.println(getInput()); return ""; } public String getInput() { return input; } public void setInput(String input) { this.input = input; } }
下記を実行するとTomcatが起動する。
mvn tomcat:run-war
なんだがよくわからんが、EL式(テキストフィールド入力)経由で渡した日本語が文字化けする。。。
setCharacterEncodingとかTomcatのcharsetとか一般的なやつは試したのだが、、、
JSF特有の設定とかあるのかね?
GlassFish4だとGlassFishディスクリプタ「glassfish-web.xml」で下記のように設定しておくと化けないんだけどなぁ。
■GlassFishディスクリプタ「glassfish-web.xml」(web.xmlと同じ階層におく)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1Servlet 3.0//EN" "http://glassfish.org/dtds/glassfishweb-app_3_0-1.dtd"> <glassfish-web-app error-url=""> <class-loader delegate="true"/> <jsp-config> <property name="keepgenerated" value="true"> <description> Keep a copy of the generated servlet class' java code. </description> </property> </jsp-config> <parameter-encoding default-charset="UTF-8" /> </glassfish-web-app>
サンプル(GlassFish)
GlassFishをローカル(Windows)にインストールして、Maven GlassFish Pluginでデプロイして動かす例。
アプリの内容はさっきと一緒。ただし、glassfish-web.xmlは配置しておく。
GlassFishのダウンロード
- ダウンロード
- 今回はGlassFish4を選択
- glassfish4\binにPATHを通す
- glassfish4\bin\asadminをリネーム(asadmin_bkなど)
GlassFishのドメイン作成
- 下記コマンドでドメインを作成し、ユーザ名とパスワードを入力する。
asadmin.bat create-domain my_domain
- 下記コマンドを実行し、ドメインを起動する。
asadmin.bat start-domain my_domain
Maven GlassFish Pluginの設定
- POMに下記を追記
<plugin> <groupId>org.glassfish.maven.plugin</groupId> <artifactId>maven-glassfish-plugin</artifactId> <version>2.1</version> <configuration> <!-- ドメイン作成時に指定したユーザ --> <user>user</user> <!-- GlassFishのインストール先 --> <glassfishDirectory>C:/〜/glassfish-4.0</glassfishDirectory> <!-- ドメイン作成時に指定したパスワード --> <adminPassword>PassWord</adminPassword> <debug>true</debug> <echo>true</echo> <components> <component> <name>${project.artifactId}</name> <artifact>${project.build.directory}/${project.build.finalName}.war</artifact> </component> </components> <domain> <name>my_domain</name> <adminPort>4848</adminPort> </domain> </configuration> </plugin>
- デプロイ実行
mvn clean package glassfish:deploy
- 下記へアクセスする
http://localhost:8080/jsf-sample/
MavenからGlassFishをコントロールするゴール
- glassfish:create-domain
- ドメインの作成
- glassfish:start-domain
- ドメインの起動
- glassfish:deploy
- アプリのデプロイ
- glassfish:redeploy
- アプリの再デプロイ
- glassfish:undeploy
- アプリのアンデプロイ
- glassfish:stop-domain
- ドメインの停止
- glassfish:delete-domain
- ドメインの削除
参考
http://himalab.hatenablog.com/entry/2012/04/16/213051
https://maven-glassfish-plugin.java.net/
JSF系参考
JSF勉強メモ
http://d.hatena.ne.jp/maji-KY/20100426/1272248157
↓
FacesContextでリクエスト情報
JSF + WebSocket で実装した IMAP Web メール・クライアント
http://yoshio3.com/2013/12/11/imap-client-created-by-jsf-websocket/
What's New JSF 2.2 & CDI & EL
http://www.oracle.com/technetwork/jp/ondemand/java/whatsnewjsf22-cdi-el-2014283-ja.pdf