Help us understand the problem. What is going on with this article?

Spring4勉強会 第六回

More than 3 years have passed since last update.

Spring4勉強会 第六回

今回はRESTfulAPIをSpringMVC4で作成するサンプルを紹介します。
REST周りについて、言葉の説明は形式上載せますが、今回、下記「動かしてみよう」で作成するのは以下のようなものです。

  1. HTMLではなく、テキストを返却する
  2. xmlを返却する
  3. 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に書いちゃってます。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away