Spring Boot:建立一个RESTful Web Service

原文地址:https://spring.io/guides/gs/rest-service/
项目地址:https://github.com/spring-guides/gs-rest-service

示例环境:
IDE: IntelliJ IDEA 2016.2.1
JRE: 1.8.0_101-b13 amd64
JVM: Java HotSpot(TM) 64-Bit Server VM by Oracle Corporation


功能

构建一个服务器,能够接收如下的HTTP GET请求:

http://localhost:8080/greeting

并返回一个JSON格式的数据:

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

你也可以通过指定查询字符串中的可选参数name来定制问候语:

http://localhost:8080/greeting?name=User

参数name的值覆盖了默认值“World”,得到的响应为:

{"id":1,"content":"Hello, User!"}

步骤

1. 在IntellJ中建立一个maven项目。

2. 创建资源描述类

这个服务要处理/greeting的GET请求,其查询字符串包含一个可选的name参数。这个GET请求应该一个200 OK的响应,以及JSON结构的描述问候语的内容。格式如下:

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

id域是问候语的唯一标识,content域是问候语的文本描述。
为了对问候语的描述进行建模,创建了一个资源描述类。提供了一个包含域(id和content)、构造方法和访问器(getter和setter)的pojo(pain old java object)类:

// 文件地址:src/main/java/hello/Greeting.java
package hello;

public class Greeting {

    private final long id;
    private final String content;

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

    public long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }
}

3. 创建资源控制器

下面的步骤中,Spring使用了Jackson JSON库将Greeting类型的实例编码成JSON格式。
采用Spring构建RESTful web services时,采用控制器处理HTTP请求。控制器组件通过@Controller注解来标识,下面的GreetingController类处理/greeting的GET请求,并返回一个Greeting类的新的实例:

// 文件地址:src/main/java/hello/GreetingController.java
package hello;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class GreetingController {

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

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

这个controller很精炼,但是其内部做了大量工作,麻雀虽小,五脏俱全。我们一步一步的解释。
@RequestMapping注解确保对/greeting的HTTP请求映射到greeting()方法。
注意:上述例子中没有写明GET、PUT、POST等等。这是因为@RequestMapping注解默认情况下映射所有的HTTP操作。使用@RequestMapping(method=GET)指定只映射GET请求。
@RequestParam把查询字符串中name参数的值绑定到greeting()方法的name参数上。该查询参数不是必须的(required=false);如果请求时没有指定该参数,则使用其默认值“World”(defaultValue)。
方法体的实现创建并返回了一个新的Greeting对象,该对象的id属性每次自增1,content属性采用template和name组合而来。
传统的MVC控制器和上述RESTful web service控制器的一个关键区别在于:HTTP响应体的创建方式。前者采用视图层技术(view technology)实现把服务器端的数据渲染为HTML,后者则返回一个Greeting对象。对象数据将会直接以JSON格式写到HTTP响应中。
通过以下方式实现上述功能,greeting()方法的@ResponseBody注解告诉Spring MVC不需要使用服务器端视图层渲染问候语对象(the greeting object),取而代之的是,返回的问候语对象时一个response body,而且应该直接写出。
Greeting对象必须转换成JSON格式。由于Spring支持HTTP报文转换,你不需要手工进行转换。由于Jackson 2在classpath中,因而Spring的MappingJackson2HttpMessageConverter会自动将Greeting实例转换为JSON格式。

4. 使程序可执行

虽然可以将这个service打包成传统的WAR文件,并部署到一个外部的应用服务器上,但是我们采用了一个更简单的方式:创建一个独立的(standalone)应用程序。把所有文件打包到一个可执行的JAR文件中,由古老的main()方法驱动。采用Spring提供的嵌入的Tomcat Servlet容器作为HTTP运行时环境,而不用部署一个外部的运行时环境实例。

// 文件地址:src/main/java/hello/Application.java
package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@SpringBootApplication是一个方便的注解,他自动把下面这些注解添加到程序中来:

  • @Configuration标签,把一个java的class作为一个bean定义的应用程序上下文。
  • @EnableAutoConfiguration注解基于你的classpath的内容打开合理的默认行为。告诉Spring在引导加载beans时要基于环境变量、其他的beans、后者其他的属性配置文件等等。例如,由于应用程序依赖于嵌入版的Tomcat(tomcat-embed-core.jar),一个Tomcat服务器会自动建立并进行合理的默认配置。应用程序也依赖于Spring MVC(spring-webmvc.jar),一个Spring MVC DispatcherServlet会为你配置和注册–不需要web.xml!自动配置(Auto-configuration)是一种强大的灵活的机制。详请参考API文档。
  • @EnableWebMvc通常情况下为了开发SpringMVC应用,应当添加@EnableWebMvc标签,但是Spring在引导阶段如果看到环境变量中有这个,会自动添加这个标签。
  • @ComponentScan注解告诉Spring递归地搜索hello包和其子包中直接或间接标记为@Component的类。这确保Spring发现并注册GreetingController,由于它被标记为@Controller,而@Controller是一类@Component注解。

main()方法调用了SpringApplication帮助类,把Application.class传递给它的run()方法作为参数。这样Spring就会去从Application读取注解,并作为Spring application context的一个组件进行管理。

5. 配置pom.xml文件


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>org.springframeworkgroupId>
    <artifactId>gs-rest-serviceartifactId>
    <version>0.1.0version>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.4.0.RELEASEversion>
    parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>com.jayway.jsonpathgroupId>
            <artifactId>json-pathartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>ch.qos.logbackgroupId>
            <artifactId>logback-classicartifactId>
            <version>1.1.7version>
            <scope>providedscope>
        dependency>
    dependencies>

    <properties>
        <java.version>1.8java.version>
    properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

    <repositories>
        <repository>
            <id>spring-releasesid>
            <url>https://repo.spring.io/libs-releaseurl>
        repository>
    repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-releasesid>
            <url>https://repo.spring.io/libs-releaseurl>
        pluginRepository>
    pluginRepositories>

project>

6. 执行

在IntellJ中,可以直接在Application.java文件中右击鼠标,选择:
Run Application.main()
在控制台中出现如下日志,说明执行成功:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.4.0.RELEASE)

八月 12, 2016 5:47:50 下午 org.apache.catalina.core.StandardService startInternal
INFO: Starting service Tomcat
八月 12, 2016 5:47:50 下午 org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/8.5.4
八月 12, 2016 5:47:51 下午 org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring embedded WebApplicationContext

此时,服务器已经启动,可以访问http://localhost:8080/greeting,你会看到:

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

查询字符串中指定一个name参数,如http://localhost:8080/greeting?name=User。content的值从”Hello, World!”变为”Hello, User!”:

{"id":2,"content":"Hello, User!"}

这说明GreetingController类中的@RequestParam注解起作用了。name参数给定的默认值为”World”,但是可以通过在查询字符串中设定值覆盖它。

注意id属性从1变为2。这表明你在多次请求中访问了同一个GreetingController实例,它的counter域每次访问时会自增1。

你可能感兴趣的:(Java)