読者です 読者をやめる 読者になる 読者になる

Spring BootでJSONやExcelファイルを返すエンドポイントを作ってみる

「Spring Bootで簡単なWebアプリケーションを書いてみる」では、Spring Bootで簡単なWebアプリケーションを書いた。 ここでは作成したアプリケーションをベースに、APIとしてJSONを返したり、Excelファイルとしてダウンロードするエンドポイントを作ってみる。

環境

Windows 10 Pro、Java SE 8、Spring Framework 4.3.7.RELEASE(Spring Boot 1.5.2.RELEASE)

>systeminfo
OS 名:                  Microsoft Windows 10 Pro
OS バージョン:          10.0.14393 N/A ビルド 14393
OS ビルドの種類:        Multiprocessor Free
システムの種類:         x64-based PC
プロセッサ:             1 プロセッサインストール済みです。
                        [01]: Intel64 Family 6 Model 69 Stepping 1 GenuineIntel ~1596 Mhz

>java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

APIとしてJSONを返してみる

まず、APIとして直近のメッセージをJSONとして返すエンドポイントを作ってみる。 以下のコードは、「Spring Bootで簡単なWebアプリケーションを書いてみる」で作ったアプリケーションをベースとする。

JSONを返すエンドポイントを作るには、Controllerに次のようなメソッドを追加する。

  • src/main/java/com.example/MessageController.java
package com.example;

(snip)
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MessageController {

    @Autowired
    private MessageService service;

    (snip)

    @RequestMapping("/messages.json")
    @ResponseBody
    public List<Message> messagesJson() {
        List<Message> messages = service.getRecentMessages(100);
        return messages;
    }

}

@RequestMappingはGET、POSTを問わないエンドポイントを表す。 メソッドに@ResponseBodyをつけJavaオブジェクトを返すようにすると、返り値がJacksonライブラリにより自動的にJSONに変換されて返される。

アプリケーションを起動した後適当なメッセージを投稿し、http://localhost:8080/messages.json にアクセスすると次のようになる。

$ curl -v http://localhost:8080/messages.json
(snip)
> GET /messages.json HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.1
> Accept: */*
>
(snip)
< HTTP/1.1 200
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Thu, 06 Apr 2017 13:49:22 GMT
<
(snip)
[{"id":3,"name":"name3","text":"text3","remoteAddr":"0:0:0:0:0:0:0:1","createdAt":1491486551864},{"id":2,"name":"name2","text":"text2","remoteAddr":"0:0:0:0:0:0:0:1","createdAt":1491486548343},{"id":1,"name":"name1","text":"text1","remoteAddr":"0:0:0:0:0:0:0:1","createdAt":1491486544112}]

テーブルの内容がJSONで返ってきていることが確認できる。

Excelファイルとしてダウンロードできるようにしてみる

業務アプリケーションでは、データベースの内容をExcelファイルとしてエクスポートする機能が求められる場合がある。 Spring Frameworkでは、Apache POIというライブラリを使うことでExcelファイルを返すViewを作ることができる。 ここでは、直近のメッセージをxlsx形式でダウンロードする機能を作ってみる。

Apache POIは標準では付属しないので、まずプロジェクトにライブラリを追加する必要がある。 保存するファイル形式がxls形式の場合はpoiライブラリ、xlsx形式の場合はpoi-ooxmlライブラリが必要となる。

STSでは、標準でプロジェクトマネージャとしてMavenを使いライブラリを管理している。 ここで、MavenのCentral Repositoryを検索すると、poi-ooxmlの最新stable版が3.15であることがわかる。

プロジェクトにpoi-ooxml 3.15を追加するには次のようにする。

  • 「demo [boot]」を右クリックして、「Maven」→「Add Dependency」を選択
  • ダイアログの各フィールドに以下の文字列を入力してOK
    • GroupId: org.apache.poi
    • ArtifactId: poi-ooxml
    • Version: 3.15

これにより、poi-ooxmlが依存する各種ライブラリも合わせて追加される。

Excelファイルを返すエンドポイントを作るには、Controllerに次のようなメソッドを追加する。

  • src/main/java/com.example/MessageController.java
package com.example;

(snip)
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MessageController {

    @Autowired
    private MessageService service;

    (snip)

    @RequestMapping("/messages.xlsx")
    public ModelAndView messagesXlsx() {
        List<Message> messages = service.getRecentMessages(100);
        return new ModelAndView(new MessagesXlsxView(), "messages", messages);
    }

}

Excelファイルを構築するViewは次のようになる。

  • src/main/java/com.example/MessagesXlsxView.java
package com.example;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.springframework.web.servlet.view.document.AbstractXlsxView;

public class MessagesXlsxView extends AbstractXlsxView {

    @Override
    protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        @SuppressWarnings("unchecked")
        List<Message> messages = (List<Message>) model.get("messages");
        
        Sheet sheet = workbook.createSheet("Recent messages");
        
        // create header
        Row row = sheet.createRow(0);
        row.createCell(0).setCellValue("ID");
        row.createCell(1).setCellValue("Name");
        row.createCell(2).setCellValue("Text");
        row.createCell(3).setCellValue("RemoteAddr");
        row.createCell(4).setCellValue("CreatedAt");
        
        // create body
        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (int i=0; i<messages.size(); i++) {
            Message message = messages.get(i);
            row = sheet.createRow(i+1);
            row.createCell(0).setCellValue(message.getId());
            row.createCell(1).setCellValue(message.getName());
            row.createCell(2).setCellValue(message.getText());
            row.createCell(3).setCellValue(message.getRemoteAddr());
            row.createCell(4).setCellValue(dateFormatter.format(message.getCreatedAt()));
        }
        
        // enable auto filter
        sheet.setAutoFilter(new CellRangeAddress(0, 0, 0, 4));
        
        // adjust column width
        for (int i=0; i<5; i++) {
            sheet.autoSizeColumn(i);
        }
    }

}

xlsx形式の場合はAbstractXlsxView、xls形式の場合はAbstractXlsViewを継承する。

アプリケーションを起動した後適当なメッセージを投稿し、http://localhost:8080/messages.xlsx にアクセスすると次のようになる。

$ curl -I http://localhost:8080/messages.xlsx
HTTP/1.1 200
Pragma: private
Cache-Control: private, must-revalidate
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Language: ja-JP
Content-Length: 3711
Date: Thu, 06 Apr 2017 13:49:29 GMT

3713バイトのapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetが返っていることがわかる。 また、ブラウザでアクセスすると、構築したExcelファイルがダウンロードできることが確認できる。

f:id:inaz2:20170406225333p:plain

PDFファイルの構築とダウンロード

Springでは、AbstractPdfViewとitextライブラリを使うことで、PDFファイルを構築して返すことも可能である。 全体の流れはExcelファイルの場合と同様であるため、ここでは省略する。

関連リンク