demo2. 获取一个RESTful接口的数据

参考文档: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

image.png

可知,接口的内容是:

{
   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类:声明idquote,并提供getter()setter()
  • Quote类:声明typevalue,提供对应的getter()setter(),且value是使用的上面创建的Value类

最后在application应用执行的类中,对接口数据对象进行解析,存为Quote类型,然后以字符串形式输出

2.2 创建restfulConsumingpackage

image.png

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 运行结果

image.png

2.7 扩展:定时轮询接口,获取最新数据

介于提供样例的接口,是一个随机出quote的接口,所以如果我们想要写一个定时每3秒请求一次接口获取最新数据的方法,该怎么办呢?

常规传统解决方法:写一个java的Runner+sleep()的方法,在线程里面进行定时请求

由于那片代码也有点多,那么在springboot脚手架下,有没有更为优雅的处理方法呢?

有!

springboot的scheduled方法!用注解来解决!

参考:springboot执行定时任务的几种方式

直接上代码:

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的时候再说吧~)

猜你喜欢

转载自juejin.im/post/7031480200395390983