Building a Restful Web Service(最好的Spring入门教程 --来自Spring官网的Guides)

搭建一个Restful Web服务

本文档将引导你用Spring搭建一个“Hello,World!”Restful Web服务。

你要搭建的是什么?

你将搭建一个Web服务,这个服务可以接收一个像http://localhost:8080/greeting 这样的Http Get请求,并返回一个greeting的json数据。这个json数据如下所示:

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

你也可以自定义查询字符串中的一个可选name参数,如下所示:

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

传过来name参数的值将覆盖掉name参数的默认值"World",从而我们的response也会变成:

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

你需要什么

  • 大约15分钟
  • 一个最喜欢的编辑器或者IDE
  • JDK1.8或者以上
  • Gradle 4+ 或者 Maven3.2+
  • 你也可以将代码直接import到你的IDE中去

如何完成这个guide

像大多数Spring “Getting Started Guides”一样,你可以从头开始依次完成每一个步骤,也可以跳过那些你已经熟悉的步骤。无论哪种方式都可以。

创建项目

对于所有的Spring应用,你应该使用Spring Initializr来初始化项目。Spring Initializr可以让你快速拉取你需要的依赖和为你做许多配置的工作。在本例中我们只需要Spring Web依赖。(我使用的是Idea,Idea创建项目时也可以使用Spring Inititlizr来初始化项目)具体步骤如下所示:

从上面的图中可以看到,我在Group中填入了com.aihs(你也可以填其他的),在Artifact中填入了rest-service。对于依赖只选择了Spring Web这一个依赖。 下面展示了pom.xml的内容:
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.aihs</groupId>
    <artifactId>rest-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>rest-service</name>
    <description>Demo project for Spring Boot</description>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

创建一个Resource Representation Class(即POJO)

首先我们来思考一下服务的交互过程。这个服务会处理 / g r e e t i n g \color{blue}{/greeting} /greeting G e t \color{green}{Get} Get请求,在请求串中还有一个可选的 n a m e \color{blue}{name} name参数。这个请求会带来一个代码为 200 \color{green}{200} 200的响应,这个响应里包含一个代表greeting的JSON数据。这个JSON数据会像如下一样:

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

属性id是 g r e e t i n g \color{blue}{greeting} greeting的一个唯一标识,而属性 c o n t e n t \color{blue}{content} content是greeting的具体内容。
想要model greeting,我们就要创建一个POJO。这个POJO中应该有 i d \color{blue}{id} id c o n t e n t \color{blue}{content} content属性,应该有构造器,应该有getter、setter方法。这个POJO如下所示(src/main/java/com/aihs/model/Greeting.java):

package com.aihs.restservice.model;

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;
    }
}

这个应用程序使用Jackson JSON库自动将Greeting类型实例封装为JSON数据。spring-boot-starter-web 中默认包含了Jackson。

创建一个Resource Controller

用Spring的方式来创建Restful Web服务时,Http Requests会被一个Controller处理。这些Controller应该由 @ R e s t C o n t r o l l e r \color{green}{@RestController} @RestController来注解。 G r e e t i n g C o n t r o l l e r \color{blue}{GreetingController} GreetingController(src/main/java/com/aihs/controller/GreetingController.java)能够处理 / g r e e t i n g \color{blue}{/greeting} /greeting G E T \color{blue}{GET} GET请求并返回一个新的Greeting类实例,GreetingController的代码如下所示:

package com.aihs.restservice.controller;

import com.aihs.restservice.model.Greeting;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.atomic.AtomicLong;

@RestController
public class GreetingController {
    private static final String template = "Hello,%s!";
    private final AtomicLong counter = new AtomicLong();

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

这个Controller是精确简洁的,它的底层完成了大量的工作。我们将逐步分解。
@ G e t M a p p i n g \color{blue}{@GetMapping} @GetMapping注解确保向 / g r e e t i n g \color{blue}{/greeting} /greeting的HTTP GET请求都映射到了$\color{blue}{greeting()}方法中去。

对于其他的HTTP动作也有相应的注解(例如针对POST请求的 @ P o s t M a p p i n g \color{blue}{@PostMapping} @PostMapping)。还有一个叫 @ R e q u e s t M a p p i n g \color{blue}{@RequestMapping} @RequestMapping的注解,用它也可以达到相同的结果(例如 @ R e q u e s t M a p p i n g ( m e t h o d = G E T ) \color{blue}{@RequestMapping(method=GET)} @RequestMapping(method=GET))。

@ R e q u e s t P a r a m \color{blue}{@RequestParam} @RequestParam注解将query string中的 n a m e \color{blue}{name} name g r e e t i n g ( ) \color{blue}{greeting()} greeting()中的 n a m e \color{blue}{name} name参数绑定了起来。如果请求中没有 n a m e \color{blue}{name} name属性值,那么 d e f a u l t V a l u e \color{blue}{defaultValue} defaultValue的值将被使用。

g r e e t i n g ( ) \color{blue}{greeting()} greeting()这个方法创建并返回一个新的带有 i d \color{blue}{id} id c o n t e n t \color{blue}{content} content属性的 G r e e t i n g \color{blue}{Greeting} Greeting对象,其中 i d \color{blue}{id} id属性的值是由 c o u n t e r \color{blue}{counter} counter而来的, c o n t e n t \color{blue}{content} content是由 n a m e \color{blue}{name} name t e m p l a t e \color{blue}{template} template用String format而来的

传统的MVC Controller与Restful Web服务的Controller关键的不同之处表明了HTTP的response体是更容易被创建的。Restful Web服务的Controller是返回一个 G r e e t i n g \color{blue}{Greeting} Greeting对象,而不是依赖于一个视图层的技术将greeting的数据插入进HTML里。这个 G r e e t i n g \color{blue}{Greeting} Greeting对象会以JSON的格式直接写入HTTP的response中去。

代码使用 @ R e s t C o n t r o l l e r \color{blue}{@RestController} @RestController注解把一个类当作为一个Controller。而Controller类中每个方法返回时一个对象而不再是一个视图。 @ R e s t C o n t r o l l e r \color{blue}{@RestController} @RestController是包含了 @ C o n t r o l l e r \color{blue}{@Controller} @Controller @ R e s p o n s e B o d y \color{blue}{@ResponseBody} @ResponseBody的简写。

这个 G r e e t i n g \color{blue}{Greeting} Greeting对象必须被转换成JSON数据。由于Spring的HTTP message converter的支持,你不需要手动去完成这个转换。因为Jackson 2被用了进来,Spring的 M a p p i n g J a c k s o n 2 H t t p M e s s a g e C o n v e r t e r \color{blue}{MappingJackson2HttpMessageConverter} MappingJackson2HttpMessageConverter会自动将 G r e e t i n g \color{blue}{Greeting} Greeting实例转换为JSON数据。

@ S p r i n g B o o t A p p l i c a t i o n \color{blue}{@SpringBootApplication} @SpringBootApplication是一个很方便的的注解,它增加了一下内容:

  • @ C o n f i g u r a t i o n \color{blue}{@Configuration} @Configuration:把该类标志为作为应用上下文中Bean定义的源
  • @ E n a b l e A u t o C o n f i g u r a t i o n \color{blue}{@EnableAutoConfiguration} @EnableAutoConfiguration:告诉Spring Boot根据类路径设置,其他beans和各种属性设置开始添加beans。例如,如果 s p r i n g − w e b m v c \color{blue}{spring-webmvc} springwebmvc在类路径上,则此注解会将应用程序标记为Web应用程序并激活诸如设置 D i s p a t c h S e r v l e t \color{blue}{DispatchServlet} DispatchServlet这类的关键行为。
  • @ C o m p o n e n t S c a n \color{blue}{@ComponentScan} @ComponentScan:告诉Spring去查找 c o m / a i h s \color{blue}{com/aihs} com/aihs包下面的其他组件、配置和服务,让它找到控制器。

m a i n ( ) \color{blue}{main()} main()方法使用Spring Boot的 S p r i n g A p p l i c a t i o n . r u n ( ) \color{blue}{SpringApplication.run()} SpringApplication.run()方法来启动一个应用。你有没有注意到没有一行XML代码。在这里没有 w e b . x m l \color{blue}{web.xml} web.xml等其他XML文件。这个Web应用是100%纯Java的,你不需要处理任何管道和基础设施的配置工作。

编译为一个可执行的JAR

你可以使用Gradle或者Maven命令行来运行这个应用。你也可以将它打包成一个包含必要的依赖、类和资源的可执行JAR包然后执行它。打成可执行的JAR包使得在整个开发生命周期中、跨不同执行环境等等的情况下都可以轻松的将服务作为应用程序进行发布、版本化和部署。

由于我们使用的是maven,所以我们可以使用 . / m v n w \color{blue}{./mvnw} ./mvnw s p i r n g − b o o t : r u n \color{blue}{spirng-boot:run} spirngboot:run来运行这个应用。

你也可以使用 . / m v n w \color{blue}{./mvnw} ./mvnw c l e a n \color{blue}{clean} clean p a c k a g e \color{blue}{package} package来生成JAR包,然后使用如下的命令来运行这个JAR包:

java -jar target/gs-rest-service-0.1.0.jar

测试这个服务

现在这个服务已经启动起来了,访问 h t t p : / / l o c a l h o s t : 8080 / g r e e t i n g \color{blue}{http://localhost:8080/greeting} http://localhost:8080/greeting,你会看到:

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

当提供一个name值时,如 h t t p : / / l o c a l h o s t : 8080 / g r e e t i n g ? n a m e = U s e r \color{blue}{http://localhost:8080/greeting?name=User} http://localhost:8080/greeting?name=User,注意content的值从 H e l l o , W o r l d ! \color{blue}{Hello,World!} Hello,World!变成了 H e l l o , U s e r ! \color{blue}{Hello,User!} Hello,User!,如下所示:

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

这个改变表明了 G r e e t i n g C o n t r o l l e r \color{blue}{GreetingController} GreetingController中的 @ R e q u e s t P a r a m \color{blue}{@RequestParam} @RequestParam像预期的那样起作用了。 n a m e \color{blue}{name} name属性有一个默认的值 W o r l d \color{blue}{World} World,但是我们可以通过query string去显式的重写默认值。

我们还要注意到 i d \color{blue}{id} id属性值时如何从 1 \color{blue}{1} 1变到 2 \color{blue}{2} 2的。这个证明了不同的请求经过了相同的 G r e e t i n g C o n t r o l l e r \color{blue}{GreetingController} GreetingController实例处理,并且它的 c o u n t e r \color{blue}{counter} counter属性如我们预期的那样被增加了。

总结

祝贺你!你已经成功得使用Spring开发了一个Restful Web服务!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值