参考文档:Consuming a RESTful Web Service
目标接口(要从这个接口中取数据):quoters.apps.pcfone.io/api/random
1. demo说明
本demo要点:
- 构建一个springboot web应用
- 要能从一个restful风格的接口中获取数据,并输出到console中
- 从接口 quoters.apps.pcfone.io/api/random 中拿数据
要用到的内容:
spring web依赖
:所以照常需要初始化一个安装了spring web依赖的脚手架RestTemplate
:通过这个springframework
中的包,来解析RESTful接口CommandLineRunner
:在springboot的控制台,自定义输出结果内容Logger
:这是一个springboot的日志对象内容,可以用它的info()
方法,把我们要自定义的信息放里面,让控制台输出
备注
:以下步骤,忽略了上面提到的,从初始化一个springboot web应用脚手架的部分,直接进入创建代码的部分
2. 搭建并运行demo
2.1 网页访问接口地址,查看数据格式,进行分析
接口地址:quoters.apps.pcfone.io/api/random
可知,接口的内容是:
{
type: "success",
value: {
id: 10,
quote: "Really loving Spring Boot, makes stand alone Spring apps easy."
}
}
复制代码
这是一个两层结构的json对象,第一层包含了type和value,第二层在value内,包含了id和quote
所以按照标准的java原则,如果要将这个结果存为java的对象,那么每层都应该有一个对应java类:
Value类
:声明id
和quote
,并提供getter()
和setter()
Quote类
:声明type
和value
,提供对应的getter()
和setter()
,且value是使用的上面创建的Value类
最后在application应用执行的类中,对接口数据对象进行解析,存为Quote类型,然后以字符串形式输出
2.2 创建restfulConsuming
package
2.3 创建Value类,声明id和quote字段
@JsonIgnoreProperties annotation:
- 以下部分没有声明的变量,JSON解析的时候就忽略掉
package com.example.springbootDemos.restfulConsuming;
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 + ''' +
'}';
}
}
复制代码
2.4 创建Quote类,存储整个接口返回的内容
以下代码中,value对象是用Value类来声明的
package com.example.springbootDemos.restfulConsuming;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/*
Annotated with @JsonIgnoreProperties from the Jackson JSON
processing library to indicate that any properties not bound in this type
should be ignored.
*/
@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 +
'}';
}
}
复制代码
2.5 编写运行文件,让接口的结果在控制台输出
package com.example.springbootDemos.restfulConsuming;
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 restfulConsumingApplication {
// A logger, to send output to the log (the console, in this example)
private static final Logger log = LoggerFactory.getLogger(restfulConsumingApplication.class);
public static void main(String[] args) {
SpringApplication.run(restfulConsumingApplication.class, args);
}
// A RestTemplate, which uses the Jackson JSON processing library to process the incoming data.
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
// A CommandLineRunner that runs the RestTemplate (and, consequently, fetches our quotation) on startup.
@Bean
public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
return args -> {
// 用RestTemplate解析接口拿到的对象,并存为quote
Quote quote = restTemplate.getForObject("https://quoters.apps.pcfone.io/api/random", Quote.class);
// 在console中输出quote
log.info(quote.toString());
// 直接通过println打印quote
System.out.println("quote result: " + quote.toString());
};
}
}
复制代码
2.6 运行结果
2.7 扩展:定时轮询接口,获取最新数据
介于提供样例的接口,是一个随机出quote的接口,所以如果我们想要写一个定时每3秒请求一次接口获取最新数据的方法,该怎么办呢?
常规传统解决方法
:写一个java的Runner+sleep()的方法,在线程里面进行定时请求
由于那片代码也有点多,那么在springboot脚手架下,有没有更为优雅的处理方法呢?
有!
springboot的scheduled方法!用注解来解决!
直接上代码:
package com.example.springbootDemos.restfulConsuming;
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.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@Configuration
@EnableScheduling // 开启定时任务
public class restfulConsumingApplication {
// A logger, to send output to the log (the console, in this example)
private static final Logger log = LoggerFactory.getLogger(restfulConsumingApplication.class);
public static void main(String[] args) {
SpringApplication.run(restfulConsumingApplication.class, args);
}
// A RestTemplate, which uses the Jackson JSON processing library to process the incoming data.
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
RestTemplate restTemplate = new RestTemplate(); // 创建一个RESTTemplate对象
// 定时任务,用fixedRate来告诉定时器,每隔多久执行一次,也可以直接传一个cron表达式字符串,更为灵活的执行定时任务
@Scheduled(fixedRate = 3000)
private void scheduledTask() {
Quote quote = restTemplate.getForObject("https://quoters.apps.pcfone.io/api/random", Quote.class);
log.info(quote.toString());
}
}
复制代码
有几个要注意的点:
- @EnableScheduling要放在类前面,不是方法前面
- @Scheduled要放在方法前面,但是这个方法不能有参数
上面这段扩展代码还有个问题就是,没有使用CommandLineRunner在一开始就执行一次,且没有设置定时任务取数据异常的抛出(以后具体研究annotation的时候再说吧~)