Spring4勉強会 第六回
今回はRESTfulAPIをSpringMVC4で作成するサンプルを紹介します。
REST周りについて、言葉の説明は形式上載せますが、今回、下記「動かしてみよう」で作成するのは以下のようなものです。
- HTMLではなく、テキストを返却する
- xmlを返却する
- JSONを返却する
- RESTとは
- RESTfulとは
- 動かしてみよう
- 解説
RESTとは
REpresentational State Transferの略
WEBの設計思想の一つ。
WEBアプリケーション中のリソースをURIで示せる。
保守性・拡張性に対応可能な設計。
XMLやJSONを扱うことで、他システムとの連携がしやすい。
細かい話は以下の資料がわかりやすいので、以下を参照で。ここでは割愛します。
※引用・参照下 →http://www.slideshare.net/unsolublesugar/res-tful
RESTfulとは
RESTの規約に則ったこと
動かしてみよう
早速、APIを作成していきます。
テキストを返却する
まずはテキストから。
これはjsp/Servletでも「contentType="text/plain"」で返せるので馴染みがある人はいるかもしれません。
「jp.co.kenshu.controller.api」パッケージに「RestfulController.java」を作成してください。
package jp.co.kenshu.controller.api;
import java.util.List;
import jp.co.kenshu.dto.test.TestDto;
import jp.co.kenshu.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RestfulController {
// テキストが返る※@RestControllerが付いているので、@ResponseBodyが不要
@RequestMapping(value = "/api/text/")
public String getTestMember() {
return "aaaa";
}
}
テキストを返却する例はこの記述のみで完了です。
ではhttp://localhost:8080/SpringKenshu/api/text/にアクセスしてみましょう。
「aaa」が返却されましたか??
今まで作成してきたControllerではreturnした文字列にマッチするViewファイルが返却され、結果としてHTMLが表示されていたと思います。
しかし、今回は
@RestController
public class RestfulController {
こんな記述があります。
「@RestController」このアノテーションを付与することで、SpringMVCのControllerはRest基調のControllerとして
認識されます。
これは以下のように、「@Controller + @ResponseBody」を指定した場合と同様の挙動をとります。
@Controller
public class RestfulController {
@RequestMapping(value = "/api/text/")
@ResponseBody
public String getTestMember() {
return "aaaa";
}
}
@ResponseBodyは戻り値自体がレスポンスであることを示してます。
xmlをレスポンスとして返却する
RestfulController.javaに以下の記述を追加します。
// XMLを返却する例
@RequestMapping(value = "/xml/", produces = "application/xml")
public String xml1() {
return "<a><b>content</b></a>";
}
注目すべきは
produces = "application/xml"
のみです。produceでメディアタイプを指定してます。
あとは戻り値がそもそもXML形式の文字列である必要があります。
JSONを返却する
まずはJSONを扱うにあたり、jacksonライブラリを利用します。
pom.xmlに以下の記述を追記します。
<!-- JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.1.1</version>
</dependency>
jacksonをpomに記述したら、「実行」→「Maven Install」を実行します。
これでこのPJにjacksonがインストールされます。
では実装していきましょう。
まずはRestfulController.javaに以下のフィールド記述を追加します。
@Autowired
private TestService service;
続いて、以下のメソッドを追記します。
// JSON返却する例※jackson.coreとjackson-databindがPOMに必要
@RequestMapping("/api/json/")
public List<TestDto> json() {
List<TestDto> tests = service.getTestAll();
return tests;
}
最後にTestDtoの作成
jp.co.kenshu.dto.test下に
TestDto.javaを作成
package jp.co.kenshu.dto.test;
import lombok.Data;
@Data
public class TestDto {
private Integer id;
private String name;
}
これでhttp://localhost:8080/SpringKenshu/api/json/にアクセスしてみましょう。
前回登録したTestテーブルの一覧が以下のようなJSON文字列として返却されました。
※TestService#getTestAll()は前回紹介したTestテーブルからselect allした結果がListとして返却されます。
[{"id":17,"name":"hogehoge"},{"id":18,"name":"hogehogehoge"},{"id":23,"name":"芳賀"},{"id":27,"name":"pppppっぽ"},{"id":28,"name":"五右衛門"}]
リスト情報をよしなにjacksonのほうで解析し、JSON文字列を組み立ててくれます。
JSON構造を変更したい場合は、独自にJSON文字列情報を組み立てる必要があります。
今回は以上です。
APIから返却されたJSONをパースして、画面に表示してみよう
以上じゃないです。嘘です。追加です。
せっかくAPI作成したので、別のControllerからAPIをコールし、受け取ったJSON文字列をパースして画面に表示してみよう。
- Controllerの作成
jp.co.kenshu.controller.api下に以下のControllerを追加
TestReceiveController.java
package jp.co.kenshu.controller.api;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;
import jp.co.kenshu.dto.test.TestDto;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller
public class TestReceiveController {
private static final String API_URL = "http://localhost:8080/SpringKenshu/api/json/";
@RequestMapping(value = "/api/result/", method = RequestMethod.GET)
public String test(Model model) throws JsonParseException, JsonMappingException, IOException {
List<TestDto> dtoList = convertTest(executeGet(API_URL));
model.addAttribute("dtoList", dtoList);
return "apiresult";
}
private List<TestDto> convertTest(String json) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
List<TestDto> list = mapper.readValue(json, new TypeReference<List<TestDto>>() {
});
return list;
}
private String executeGet(final String urlStr) {
StringBuilder sb = new StringBuilder();
try {
URL url = new URL(urlStr);
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
try (InputStreamReader isr = new InputStreamReader(connection.getInputStream(),
StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(isr)) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
}
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
}
- JSPの作成
WEB-INF/view下に以下のjspを作成
apiresult.jsp
<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<meta charset="utf-8">
<title>Welcome</title>
</head>
<body>
<c:forEach items="${dtoList}" var="test">
<p><c:out value="${test.id}" /></p>
<p><c:out value="${test.name}" /></p>
</c:forEach>
</body>
</html>
これで、APIから取得したJSONをdecodeし、TestDtoに変換して、画面に表示されます。
※ビジネスロジックは実際にはServiceなどに記述するようにしてください。
面倒だったので、Controllerに書いちゃってます。