ぺーぺーSEのブログ

備忘録・メモ用サイト。

RESTful Web Service using SpringMVC事始め 〜bean定義ファイル編〜

RESTful Web Service using SpringMVC事始めでは「Java-Based Configuration」にしたが「XML-Based Configuration」バージョンにしてみる。

Gradleベースでやる。

環境は下記。

>gradle -v

------------------------------------------------------------
Gradle 2.3
------------------------------------------------------------

Build time:   2015-02-16 05:09:33 UTC
Build number: none
Revision:     586be72bf6e3df1ee7676d1f2a3afd9157341274

Groovy:       2.3.9
Ant:          Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM:          1.7.0_71 (Oracle Corporation 24.71-b01)
OS:           Windows 7 6.1 amd64

(1)プロジェクト用ディレクトリ作成
   ここでは「SpringMVC」にした。
(2)「gradle init --type java-library」でもたたいてひな形作成
(3)build.gradleを下記のように修正

■build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'war'
apply plugin: 'tomcat'

[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:1.2.5'
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.springframework:spring-webmvc:4.1.5.RELEASE'
    compile 'javax.servlet:javax.servlet-api:3.1.0'
    runtime 'com.fasterxml.jackson.core:jackson-databind:2.5.1'
    runtime 'com.sun.xml.bind:jaxb-impl:2.2.7'

    def tomcatVersion = '8.0.20'
    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
           "org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
    tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
        exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
    }
}

jaxb-implは2.2.11が最新だったけど、このバグ引くから2.2.7にした。
https://jira.spring.io/browse/SPR-12360

(4)「gradle eclipse」してからEclipseでコーディング

■hello.Greeting.java

package hello;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Greeting {

    private long id;
    private String content;

    protected Greeting(){}

    public Greeting(long id, String content) {
        this.id = id;
        this.content = content;
    }

    public long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }

    @XmlElement
    public void setId(long id) {
        this.id = id;
    }

    @XmlElement
    public void setContent(String content) {
        this.content = content;
    }
}

■hello.GreetingController.java

package hello;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping(value="/greeting", method=RequestMethod.GET)
    public Greeting greetingGet(@RequestParam(value="name", required=false, defaultValue="World") String name) {
        return new Greeting(counter.incrementAndGet(),
                            String.format(template, name));
    }

    @RequestMapping(value="/greeting", method=RequestMethod.POST)
    public Greeting greetingPost(@RequestBody Greeting greeting) {
        return greeting;
    }
}

■spring/applicationContext.xml(hello.AppConfig.javaの代わり)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-4.1.xsd">
</beans>

毎度お馴染み「src/main/resources」配下ね。

■spring/spring-mvc.xml(hello.WebMvcConfig.javaの代わり)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

  <context:component-scan base-package="hello" />
  <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
      <property name="favorPathExtension" value="true" />
      <property name="favorParameter" value="true" />
      <property name="parameterName" value="format" />
      <property name="defaultContentType" value="application/json" />
      <property name="mediaTypes">
          <map>
              <entry key="xml" value="application/xml" />
          </map>
      </property>
  </bean>
  <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
</beans>

毎度お馴染み「src/main/resources」配下ね。

■web.xml(hello.WebAppInitializer.javaの代わり)

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  id="serv" version="3.0">
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
            classpath*:spring/applicationContext.xml
        </param-value>
  </context-param>
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:spring/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

(5)「gradle clean build
(6)「gradle tomcatRunWar
(7)ブラウザか何かで「http://localhost:8080/SpringMVC/greeting」へアクセスするとJSONが返却される

その他送受信

コンテンツネゴシエーションは下記のような感じ。
詳細はRESTful Web Service using SpringMVC事始め参照。

POSTメソッドで「http://localhost:8080/SpringMVC/greeting」へHTTPヘッダ「Content-Type: application/json」を付与して下記の電文を投げるとそのまま返ってくる。

{"id":100,"content":"Hello, World!"}

ちなみに「http://localhost:8080/SpringMVC/greeting.xml」へ投げるとXML形式で帰ってくる。
JSONで投げたとしてもコンテンツネゴシエーションで受け取るメディアタイプを指定できる。