--- title: SpringMVC 4.1のProtocol Buffer対応が強力だった件 tags: ["Java", "Protocol Buffers", "Spring", "Spring Boot", "Spring MVC"] categories: ["Programming", "Java", "org", "springframework", "http", "converter", "protobuf"] date: 2014-12-14T16:08:20Z updated: 2014-12-14T16:08:20Z --- 前回、[SpringMVC 4.1のProtocol Buffers対応](http://blog.ik.am/#/entries/287)を紹介しましたが、今イチ使いどころがわからない感じでした。 ただ、[ProtobufHttpMessageConverter](https://github.com/spring-projects/spring-framework/blob/master/spring-web/src/main/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverter.java)のソースコードを読んでいると面白いことがわかりました。Content Negotiation対応しているのです。 つまり、デフォルトではProtobufに対応しますが、**JSONをリクエストすればJSON形式で返しますし、XMLをリクエストすればXML形式で返します**。 例えば、Protobufで用意したAPIをデバッグするのにはJSONで見た方が分かりやすいでしょうし、WebブラウザにはJSONでやり取りした方が効率が良いでしょう。テストもJSONの方がやりやすいです。 この機能を有効にするには[protobuf-java-format](https://code.google.com/p/protobuf-java-format/)を依存ライブラリに追加する必要があります。 ``` xml com.googlecode.protobuf-java-format protobuf-java-format 1.2 ``` [前回のサンプルコード](https://github.com/making/spring-mvc-tutorial-protobuf)で試してみましょう。 Controllerを再掲しておくと ``` java @RestController public class AddressBookController { @RequestMapping("person") AddressBookProtos.Person person() { return AddressBookProtos.Person.newBuilder() .setId(1234) .setName("John Doe") .setEmail("jdoe@example.com") .addPhone( AddressBookProtos.Person.PhoneNumber.newBuilder() .setNumber("555-4321") .setType(AddressBookProtos.Person.PhoneType.HOME)) .build(); } } ``` こんなんでした。 ### Protobuf ``` bash $ curl -v http://localhost:8080/person > GET /person HTTP/1.1 > User-Agent: curl/7.30.0 > Host: localhost:8080 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < X-Protobuf-Schema: src/main/proto/tutorial/addressbook.proto < X-Protobuf-Message: tutorial.Person < Content-Type: application/x-protobuf;charset=UTF-8 < Content-Length: 45 < Date: Sun, 14 Dec 2014 15:39:05 GMT < John Doe� jdoe@example.com" ``` ### JSON ``` bash $ curl -v http://localhost:8080/person.json > GET /person.json HTTP/1.1 > User-Agent: curl/7.30.0 > Host: localhost:8080 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Sun, 14 Dec 2014 15:39:42 GMT < {"name": "John Doe","id": 1234,"email": "jdoe@example.com","phone": [{"number": "555-4321","type": "HOME"}]} ``` or ``` bash $ curl -v -H "Accept: application/json" http://localhost:8080/person > GET /person HTTP/1.1 > User-Agent: curl/7.30.0 > Host: localhost:8080 > Accept: application/json > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < Date: Sun, 14 Dec 2014 15:40:35 GMT < {"name": "John Doe","id": 1234,"email": "jdoe@example.com","phone": [{"number": "555-4321","type": "HOME"}]} ``` ### XML ``` bash $ curl -v http://localhost:8080/person.xml > GET /person.xml HTTP/1.1 > User-Agent: curl/7.30.0 > Host: localhost:8080 > Accept: */* > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/xml;charset=UTF-8 < Transfer-Encoding: chunked < Date: Sun, 14 Dec 2014 15:41:48 GMT < John Doe1234jdoe@example.com555-4321HOME ``` or ``` bash $ curl -v -H "Accept: application/xml" http://localhost:8080/person > GET /person HTTP/1.1 > User-Agent: curl/7.30.0 > Host: localhost:8080 > Accept: application/xml > < HTTP/1.1 200 OK < Server: Apache-Coyote/1.1 < Content-Type: application/xml;charset=UTF-8 < Transfer-Encoding: chunked < Date: Sun, 14 Dec 2014 15:42:26 GMT < John Doe1234jdoe@example.com555-4321HOME ``` E2Eテストコードは[こんな](https://github.com/making/spring-mvc-tutorial-protobuf/blob/master/src/test/java/com/example/tutorial/AddressBookControllerTest.java)感じ。 --- こいつ、かなりやれるぞ・・・! ProtocolBuffers RPCのサーバーサイド用途にかなり合っているのではないでしょうか。