思った以上にかんたんに実装できたわりに、ネット上にちょうどいい塩梅のサンプルが転がっていなかったのでメモ。
なお、今回のデモコードの全文は以下にありますので、実際の挙動を確認したい場合はご利用ください。
https://github.com/yo1000/com.yo1000.edu.boot.octetstream
環境
- Java 1.8.0_91
- Maven 3.3.9 (Maven wrapper)
- Spring Boot 1.4.1.RELEASE
$ ./mvnw --version
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T01:41:47+09:00)
Maven home: /Users/yo1000/.m2/wrapper/dists/apache-maven-3.3.9-bin/2609u9g41na2l7ogackmif6fj2/apache-maven-3.3.9
Java version: 1.8.0_91, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre
Default locale: ja_JP, platform encoding: UTF-8
OS name: "mac os x", version: "10.11.6", arch: "x86_64", family: "mac"
依存関係の追加
jackson-dataformat-csv
を使うと、不要な依存を追加せず、かんたんに実現できるので、今回はこれを使用します。(spring-boot-starter-parent
で、デフォルトバージョンが設定されているため、バージョン指定は不要です。)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
モデルの実装
今回はわかりやすいように、かんたんなモデルを作成します。
@JsonProperty
で設定した値が、CSV の1行目に出力されます。設定しない場合はフィールド名が出力されます。
また、@JsonPropertyOrder
を設定しない場合は、プロパティ名でソートされた順に出力されてしまうので、任意の順番で出力したい場合には注意が必要です。
package com.yo1000.edu.boot.octetstream.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import java.util.Date;
@JsonPropertyOrder({"ID", "名前", "概要", "更新日時"})
public class Demo {
@JsonProperty("ID")
private Long id;
@JsonProperty("名前")
private String name;
@JsonProperty("概要")
private String desc;
@JsonProperty("更新日時")
private Date modified;
public Demo() {}
public Demo(Long id, String name, String desc, Date modified) {
this.id = id;
this.name = name;
this.desc = desc;
this.modified = modified;
}
// Getter/Setter
}
コントローラーの実装
Object <-> JSON の変換に、ObjectMapper
を使うように、ここでは CsvMapper
というクラスを使用して、オブジェクトを CSV に変換します。
@GetMapping
の、produces
属性に、"application/octet-stream"
(MediaType.APPLICATION_OCTET_STREAM_VALUE
) と、"Content-Disposition: attachment"
を、セミコロンで区切って指定することで、ダウンロードダイアログつきで、CSV を出力できます。
また、charset
を指定することで、出力する CSV ファイルの文字セットも変更することができます。デフォルトが UTF-8
なので、今回はあえて Shift_JIS
を指定してみます。
また、ダウンロードされるファイルのデフォルトの名前は URL に準じるため、"*.csv"
という URL を割り当てておくだけで、リクエストされたファイル名でそのままダウンロードさせることが可能になります。
package com.yo1000.edu.boot.octetstream.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import com.yo1000.edu.boot.octetstream.model.Demo;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Controller
@RequestMapping("csv")
public class CsvController {
@GetMapping(value = "*.csv",
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=Shift_JIS; Content-Disposition: attachment")
@ResponseBody
public Object getCsv() throws JsonProcessingException {
List<Demo> demos = new ArrayList<Demo>() {
{
add(new Demo(1001L, "aaa", "xxx", new Date()));
add(new Demo(1002L, "bbb", "yyy", new Date()));
add(new Demo(1003L, "ccc", "zzz", new Date()));
}
};
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(Demo.class).withHeader();
return mapper.writer(schema).writeValueAsString(demos);
}
}
動作の確認
実際の動きを見てみましょう。
ダウンロードしたファイルを開いてみると、Shift JIS
にて、文字化けなく内容を表示できていることがわかります。
以上のように、これまでどおりのコントローラー記述と、jackson-dataformat-csv
を使用して、かんたんに CSV ファイルを出力することができました。Spring では、オブジェクトの変換に Jackson が使用されているので、うまく活用していきたいですね。