Jersey MVC とは? †
- https://jersey.java.net/documentation/latest/mvc.html
- JAX-RS 2 は、REST ベースの Web サービスを構築するための規格
- JAX-RS 2 では、AJAX-Request に対して JSON や XML を返却することを想定していた
- Browser で動く Client Side MVC の Single page アプリケーションは、勝手に作ってください
- JAX-RS の役割は Single page アプリケーションから呼び出される API のフレームワーク
- Jersey MVC
- JAX-RS は、Object を JSON や XML 形式に変換してブラウザに返している
- だったら、Object にテンプレートを適用して HTML 形式に "変換" してブラウザに返しても良かんべ...というのが Jersey MVC
- Jersey は JAX-RS の主要な実装の一つで、Glassfish の JAX-RS は Jersey で実現されている。
- Jersey MVC は、JAX-RS 規格の範囲を超える独自実装の扱い ⇒ JavaEE 8 で JAX-RS の一機能として制式採用されるという話もある
Template として何使う? †
- Jersey MVC では、3 つのテンプレートエンジンを使える
- ◯ Mustache が消去法でよさ気な感じがする。いっちゃん簡単やしね
- ☓ Freemarker は、Struts2 のテンプレートエンジン。いやもう Struts2 という単語が出ただけでもう見たくもない
- ☓ Servlet アプリの JSP と文法が同じだと、作っていて混同してしまうおそれがある。みんな大好き古き良き Servlet アプリの JSP は、コンパイルされて Servlet になるが、Jersey MVC ではテンプレートとして使われる。両者の違いを頭に置きつつコードを書くのはチョットストレス
Hello World アプリケーション †
- 実行環境
- ソースコード : https://github.com/kagyuu/JerseyMVCExam
- 普通の Maven Web アプリ
- hello1.mustache : ブラウザへの HTTP-Response で返却する HTML のテンプレート
- ApplicationConfig?.java : JAX-RS の設定クラス
- GenericResource?.java : サービス実装クラス
- Person.java : ブラウザへの HTTP-Response に載せる情報を格納するデータBean
- web.xml は不要 (ApplicationConfig?.java とアノテーションが代わりをしている)
pom.xml †
- 通常の Maven Web プロジェクトに、jersey-mvc-mustache を追加した
- Glassfish 4.1 には、Jersey-mvc 2.10.4 が組み込まれている
- jersey-mvc-mustache も最新版ではなく 2.10.4 を使う
- jersey-mvc-mustache からの jersey-mvc への依存性を切っておく
<?xml version="1.0" encoding="UTF-8"?>
<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>com.mycompany</groupId>
<artifactId>JerseyMVCExam</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>JerseyMVCExam</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jersey-mvc>2.10.4</jersey-mvc>
</properties>
<dependencies>
<!-- Jersey MVC Mustache -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc-mustache</artifactId>
<version>${jersey-mvc}</version>
<!-- exclude Glassfish 4.1 build-in modules -->
<exclusions>
<exclusion>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Glassfish 4.1 build-in modules -->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-mvc</artifactId>
<version>${jersey-mvc}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.14.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>7.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
ApplicationConfig?.java †
package com.mycompany.jerseymvcexam;
import java.util.Set;
import javax.ws.rs.core.Application;
import org.glassfish.jersey.server.mvc.mustache.MustacheMvcFeature;
@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
// Jersey MVC
resources.add(MustacheMvcFeature.class);
// Rest Resource Classes
addRestResourceClasses(resources);
return resources;
}
/**
* Do not modify addRestResourceClasses() method.
* It is automatically populated with
* all resources defined in the project.
* If required, comment out calling this method in getClasses().
*/
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(com.mycompany.jerseymvcexam.GenericResource.class);
}
}
- Netbeans が自動生成したものに、resources.add(MustacheMvcFeature?.class); を追加した
GenericResource?.java †
package com.mycompany.jerseymvcexam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.glassfish.jersey.server.mvc.Template;
/**
* REST Web Service
*
* @author hondou
*/
@Path("generic")
public class GenericResource {
@Context
private UriInfo context;
/**
* Creates a new instance of GenericResource
*/
public GenericResource() {
}
@GET
@Path("hello")
@Produces(MediaType.TEXT_HTML)
@Template(name = "/hello1")
public Person hello() {
return new Person("Ms.","Yuko");
}
}
- RESTサービスを提供するメソッドに @Template アノテーションをつけると、テンプレートに返り値 Bean を適用してできた HTML が返されるようになる。
- テンプレートファイルの拡張子は .mustache 固定。⇒ @Template では省略可
- Jersey MVC で HTML だけを返すなら @Produces は不要。
- @Produces({MediaType?.TEXT_HTML,MediaType?.APPLICATION_JSON}) とかやると 「Glassfish JAX-RS Hypermedia」 でやったように、HTTP REQUEST の Accept Header によって Response のフォーマットを変えることができる。
Person.java / hello1.mustache †
- Java Bean (Person.java)
package com.mycompany.jerseymvcexam;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class Person {
private String title;
private String name;
}
- hello1.mustache
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>Hello {{title}} {{name}}</h1>
</body>
</html>
実行結果 †
Java#Glassfish