学习如何使用Spring的RestTemplate检索网页数据。
实现效果:
创建RESTful Web服务获取并处理另外一个RESTful Web服务提供的数据。
使用Spring的RestTemplate获取
https://gturnquist-quoters.cfapps.io/api/random
这个API返回的随机值,并处理.
项目结构
└── src
└── main
└── java
└── hello
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>
<groupId>org.springframework</groupId>
<artifactId>gs-consuming-rest</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.获取REST资源
已在https://gturnquist-quoters.cfapps.io/api/random开启了一个RESTful服务。 它随机获取 一个Spring Boot的引用并返回JSON文本。
通过Web浏览器或curl请求该URL,将返回类似下方的JSON文本:
{
type: "success",
value: {
id: 10,
quote: "Really loving Spring Boot, makes stand alone Spring apps easy."
}
}
很容易,但通过浏览器或通过curl获取不是非常有用。
更有用的方法是使用REST Web服务编程方式获取。Spring提供了一个名为RestTemplate的模板类。 RestTemplate能和大多数单行请求RESTful服务交互。 还可以将数据绑定到自定义类型。
首先创建一个实体类,包含type, value.其中value也是一个josn,包含id和quote.
src/main/java/hello/Quote.java
package hello;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Quote {
private String type;
private Value value;
public Quote() {
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Value getValue() {
return value;
}
public void setValue(Value value) {
this.value = value;
}
@Override
public String toString() {
return "Quote{" +
"type='" + type + '\'' +
", value=" + value +
'}';
}
}
这是一个简单的Java类,具有一些属性和匹配的getter
方法。使用Jackson JSON
类库中的@JsonIgnoreProperties
进行注解,表示应忽略此类中未绑定的任何属性。
为了直接将数据绑定到自定义类型,需要指定API返回的JSON中的key完全相同的变量名称。如果JSON 中的变量名称和key不匹配,则需要使用@JsonProperty注解指定JSON文本的key。
创建第二个实体类对应value
src/main/java/hello/Value.java
package hello;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Value {
private Long id;
private String quote;
public Value() {
}
public Long getId() {
return this.id;
}
public String getQuote() {
return this.quote;
}
public void setId(Long id) {
this.id = id;
}
public void setQuote(String quote) {
this.quote = quote;
}
@Override
public String toString() {
return "Value{" +
"id=" + id +
", quote='" + quote + '\'' +
'}';
}
}
执行程序
修改Application 类,用RestTemplate 从上面的Spring boot 引用服务抓取 数据
src/main/java/hello/Application.java
package hello;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.client.RestTemplate;
public class Application {
private static final Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String args[]) {
RestTemplate restTemplate = new RestTemplate();
Quote quote = restTemplate.getForObject("https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
log.info(quote.toString());
}
}
由于 Jackson JSON
库在类路径中,RestTemplate
将使用它(通过消息转换器)将传入的JSON
数据转换为Quote
对象。 Quote对象的内容将打印到控制台。
除了HTTP GET请求。RestTemplate还支持其他HTTP动作,如POST,PUT和DELETE。
使用Spring Boot管理应用程序生命周期
到目前为止,还没有在应用程序中使用Spring Boot,这样做有一些优点,也不难做到。其中一个优点是可以让Spring Boot管理RestTemplate中的消息转换器,以便以注解的方式轻松添加自定义内容。为此,在主类上使用@SpringBootApplication并转换main方法 启动,就像在任何Spring Boot应用程序中一样。最后,run方法回调RestTemplate返回CommandLineRunner类型的值,这样就由Spring Boot管理其生命周期:
修改Application类
src/main/java/hello/Application.java
package hello;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class Application {
private static final Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String args[]) {
SpringApplication.run(Application.class);
}
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
return args -> {
Quote quote = restTemplate.getForObject(
"https://gturnquist-quoters.cfapps.io/api/random", Quote.class);
log.info(quote.toString());
};
}
}
RestTemplateBuilder由Spring注入,使用它来创建RestTemplate, Spring Boot会自动使用消息转换器和请求工厂的所有自动配置。 还可将RestTemplate提取到@Bean中,以便更容易测试(可以通过这种方式更容易地进行模拟测试)。
建立一个可执行的 JAR
利用maven
打包war或者jar运行,这里不做介绍.
java -jar target/gs-consuming-rest-0.1.0.jar
测试
运行后将会出现类似下方的日志输出:
2015-09-23 14:22:26.415 INFO 23613 --- [main] hello.Application : Quote{type='success', value=Value{id=12, quote='@springboot with @springframework is pure productivity! Who said in #java one has to write double the code than in other langs? #newFavLib'}}
如果出现如下错误:
Could not extract response: no suitable HttpMessageConverter found for response type [class hello.Quote]
可能由于你的网络环境不能访问
https://gturnquist-quoters.cfapps.io/api/random