はじめに
前回は、Spring Bootを用いて、MySQLのデータベースから読み込んだデータを返すRESTful APIを作成しました。
今回は、Web APIではなく、Viewを作成してみます。JavaのViewと言えばJSPが定番ですが、Spring BootではJarへの組み込みのサーブレットを使用する関係上、機能が制限されるためJSPの使用は避けるべきとReferenceに記述されています。
使用できるテンプレートは以下に紹介されています。
http://docs.spring.io/spring-boot/docs/1.2.2.RELEASE/reference/htmlsingle/#boot-features-spring-mvc-template-engines
今回はFreeMarkerを用いて、基本的なViewの作成、ModelデータのViewへの受け渡しといったことを行います。
FreeMarker http://freemarker.incubator.apache.org/
基本的な構成
ディレクトリ構成
build.gradleに必要なライブラリを追加します。今回はデータベースにアクセスしないのでシンプルに以下の二つだけです。
....
jar {
baseName = 'spring-web-sample'
version = '0.1.0'
}
....
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-freemarker")
}
Model, Serviceの作成
今回作成するサンプルアプリケーションは、メッセージの入力をフォームから行い、そのリストを表示するというシンプルなものです。まず、メッセージを保持するモデルクラスを作成します。
Message.java
public class Message {
@NotEmpty
private String message = "";
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
次にメッセージを格納取得するためのサービスを作成します。サービスの実装は、Spring FrameworkらしくDependency Injectionを用いたいのでBean化します。@Serviceアノテーションがそれにあたります。@Serviceは@Component同様、@Autowireアノテーションで変数に割り当てることが可能です。(後で使用します)
MessageService.java
public interface MessageService {
void addMessage(String message);
List<Message> getMessages();
}
MessageServiceImpl.java
@Service
public class MessageServiceImpl implements MessageService {
private List<Message> messages;
public MessageServiceImpl() {
messages = new ArrayList<Message>();
}
@Override
public void addMessage(String message) {
Message messageObj = new Message();
messageObj.setMessage(message);
messages.add(messageObj);
}
@Override
public List<Message> getMessages() {
return messages;
}
}
ControllerおよびViewの作成
Viewを作成するControllerは前回の記事で使用した@RestControllerではなく@Controllerを用います。@ControllerでViewを返す方法はいくつかの方法があります。ここでは、シンプルにページの名前を返します。("index")
@Controller
public class IndexController {
@Autowired
private MessageService servie;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String showTopPage() {
return "index";
}
}
次にViewのテンプレートを作成します。FreeMarkerは本家のページでも記述されているようにテンプレート + Javaのコードからのデータの挿入でHTMLファイルを作成します。テンプレートファイルの置き場所をapplication.propertiesに記述します
spring.freemarker.template-loader-path=/WEB-INF/templates
この画面ではフォームを使ってメッセージを入力するだけなので、FreeMarker的な記述はほとんど入っていません。message変数にユーザが入力したメッセージが挿入されてController側にPOSTで渡ります。
index.ftl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hello Spring</title>
</head>
<body>
<form role="form" action="" method="post">
<div>
<label for="message">message</label>
<input type="message" name="message" id="message" required autofocus/>
</div>
<button type="submit">submit</button>
</form>
</body>
</html>
先ほど作成した、IndexControllerにフォームからのメッセージを受信する部分を作成します。@MdelAttributeを用いて、フォームからの入力メッセージをMessageクラスのオブジェクトとして受け取ることができます。受け取ったメッセージは、@Autowiredで取得したMessageServiceを通して保存します。"redirec:messages"でmessageビューに遷移をします。
@Controller
public class IndexController {
@Autowired
private MessageService servie;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String showTopPage() {
return "index";
}
@RequestMapping(method=RequestMethod.POST)
public String handleMessage(@Valid @ModelAttribute("form") Message message) {
servie.addMessage(message.getMessage());
return "redirect:messages";
}
}
messageビューは、今までのメッセージのリストを表示します。<#list messages as message>という記述でmessagesオブジェクトをfor文のように順にmessageオブジェクトとして扱うことができます。
message.ftl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Messages</title>
</head>
<body>
<hr>
<#list messages as message>
${message.message}
<hr>
</#list>
<a href="/">Back to Home</a>
</body>
</html>
messageビューにmessagesオブジェクトを渡すコントローラーは以下のようになります。ModelAndViewというクラスを返すことで、ビューページ名の指定と引き渡すJavaのオブジェクト(モデル)指定することができます。
@Controller
@RequestMapping("/messages")
public class MessageController {
@Autowired
private MessageService service;
@RequestMapping(method= RequestMethod.GET)
public ModelAndView showMessagesPage() {
return new ModelAndView("messages", "messages", service.getMessages());
}
}
最後にApplicationクラス作成します。これは特に通常と変わりません。
@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#動作確認
ビルド、および実行は以下のGradleで以下のように行います
$ ./gradlew build
$ java -jar build/libs/spring-web-sample-0.1.0.jar
http://localhost:8080
にアクセスすると以下のような画面が見れます
メッセージを入力して、Submitボタンを押すとhttp://locahost:8080/messages
に移動します
"Back to Home"を押して、再度メッセージを追加するとどんどんリストに表示されます。
もちろんデータベースなどを用いて永続化しているわけではないので、起動しなおすとメッセージは全て消えます。