使用springboot2创建RESTful Web Service.
记录
原文:https://spring.io/guides/gs/rest-service/
建立工程
参考 http://blog.csdn.net/tiaya/article/details/78346460
假设已经安装了eclipse4.7
建立maven工程,编辑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.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M5</version>
</parent>
<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>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
Spring Boot Maven Plugin 提供了一些方便的特性:
- 收集classpath下的jar文件,打包成单一可执行的jar文件。
- 查找
public static void main()
方法,并标记这个类为可执行类。 - 内建了Spring Boot的版本依赖默认匹配功能,能根据parent的版本推导Spring Boot包的版本。可以手动添加版本号覆盖这个默认设置。
我们的功能
假设:
我们的service的功能,处理GET请求 /greeting ,可以附加参数 name ,返回JSON格式字符,内容类似这样:
{
"id": 1,
"content": "Hello, World!"
}
有个pojo对象来处理这个json中的字段。使用Jackson JSON做json转换。
提供两个链接供参考:
http://blog.csdn.net/xiaoke815/article/details/52920405
https://www.zhihu.com/question/44199956
// 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;
}
}
回头来看Spring controller,由@RestController
注解标记。
// src/main/java/hello/GreetingController.java
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
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("/greeting")
public Greeting greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
- @RequestMapping 确保HTTP请求 /greeting 会被映射到这个 greeting() 方法上。如果要指定HTTP方法,可以这样写:
@RequestMapping(method=GET)
- @RequestParam 把查询参数(URL参数) name 绑定到了方法参数 name 上,如果请求缺少这个查询参数,就会使用defaultValue 的默认值。
- greeting() 方法返回Greeting对象。
- 传统Controller 与 RestController的关键区别就是产生 HTTP响应的方式。传统Controller返回了视图内容,而RestController只是返回了数据对象。(或者说,@RestController就是传统@Controller+@ResponseBody的简写方式。)这个数据对象由Spring 的HttpMessageConverter(默认是MappingJackson2HttpMessageConverter)自动转换成JSON。
最后是启动方法。除了传统的war方式,现在可以方便的当作独立应用启动:使用Spring支持的方式内嵌Tomcat 服务器。
// 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 标记class为Spring的容器的bean
- @EnableAutoConfiguration 告诉Spring根据classpath中的内容向Spring的容器中添加bean
- @EnableWebMvc 如果classpath中有Spring webmvc,这个注解会自动被加上。标记这是一个web应用,启动相关的设定,比如 DispatcherServlet。
- @ComponentScan 告诉Spring 在hello包(这个文件所在的package)下查找其他的组件,配置,服务等信息。
- main()方法:使用SpringApplication.run() 启动应用。
- 所有配置信息以注解方式体现,由Spring自动扫描,可以省略 web.xml。
启动服务
用maven可以方便的执行:maven spring-boot:run
或者打包:maven clean package
然后启动:java -jar target/gs-rest-service 0.0.1-SNAPSHOT.jar
测试:
http://localhost:8080/greeting
或者
http://localhost:8080/greeting?name=tom
遇到的问题
工程启动时提示class not found 信息,web请求时出错:
JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'com.fasterxml.jackson.databind.ObjectMapper' (OnClassCondition)
从内容上看,首先怀疑是缺少依赖。检查maven依赖关系:
能看到依赖关系没有问题,eclipse工程中也没有提示maven发生了什么错误。排查没有结果,甚至怀疑spring提供的教程有问题… …
最后莫名怀疑maven本地库文件有问题。由于网络关系,有时候文件下载过程会出错,但是这时候文件的整合性检查会发现问题。抱着试试看的态度,删除了本地库中的 jackson-databind-2.9.1.jar 所在目录,重新强制更新maven工程,编译工程,上面的错误消失。
以上