SpringBoot搭建一个简单的天气预报系统(二)

0. 项目结构

整个项目结构图如下:
在这里插入图片描述
github源码下载

1. 剧情回顾

SpringBoot搭建一个简单的天气预报系统(一)博客中已经实现了一个非常简单的天气预报系统------用户访问这个天气预报系统的时候,那么系统会响应给用户一个天气数据。但这个数据的来源并不是我们自己产生的,我们是依赖于一个第三方的天气预报的数据API。通过调用这个API,我们将返回的Json数据进行解析,再返回给使用这个系统的用户。

2. 存在的问题

这种系统架构会存在什么问题呢?

  1. 我们的数据来源是依赖第三方的API,这种强依赖会导致系统服务的延迟(用户调用我们的系统接口时,而系统再通过HTTP(很耗时)去调用第三方的API,调用结束后,第三方接口将Json数据响应给系统,然后,系统再进行解析,并返回给系统用户,这样的结果会导致响应时间不及时)
  2. 我们使用的是别人的接口(虽然是免费,有些还限制调用次数),这种情况是有风险的:1)、有限制调用次数,会达到上限;2)、不稳定,随时挂掉;3)、若此第三方的API并发做的不太理想,我们这边系统并发稍微高一点,就有可能将第三方API系统给调死了。

3. SpringBoot集成Redis

3.1 解决方案

面对以上问题,这里采用Redis缓存来解决-----期望使用Redis提升应用的并发访问能力

3.2 为什么选择Redis?

这里针对此系统简要说说Redis的优点吧:

  1. 可以使请求响应得更及时:它是基于内存的缓存系统,查询、响应等速度很快(先将天气数据缓存到Redis中去,获取数据时,先从Redis中获取,如果有,直接返回;如果没有,再调用第三方API,调用完毕后,再把数据添加到Redis中去)
  2. 可以有效地减少服务调用的次数:天气的数据信息并不会实时更新,即使是真实的天气预报系统也是半小时或1小时更新,这种场景就非常适合使用缓存(半个小时就调用一次(一天12h也就调用了24次)第三方的API,将数据缓存到Redis中去,在半个小时内,都是从Redis中获取数据的)

3.3 使用Redis

3.3.1 开发环境

  • IDEA:2018.2(安装lombok插件)
  • JDK:8
  • MAVEN:3.6.0
  • SpringBoot:2.3.0
  • Redis:3.0.504

3.3.2 添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

3.3.3 功能需求

        用户访问这个天气预报系统的时候,系统先从Redis缓存中进行获取数据,如果有,直接返回;如果没有,再调用第三方API,调用完毕后,将数据返回,并把数据添加到Redis中去

3.3.4 手动编码

这里主要修改WeatherDataServiceImpl类中的doGetWeather()方法
WeatherDataServiceImpl
添加了个注解@Slf4j和StringRedisTemplate 成员变量

@Service
@Slf4j
public class WeatherDataServiceImpl implements WeatherDataService {
   
    private static final String WEATHER_URL = "http://wthrcdn.etouch.cn/weather_mini?";

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    ...
}

doGetWeather()

private <T> T doGetWeather(String uri, Class<T> type) {
   
    String key = uri;
    String strBody = null;
    ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
    // 先查询缓存,如果缓存有,则从缓存中取
    if (stringRedisTemplate.hasKey(key)) {
   
        log.info("Redis has data");
        strBody = ops.get(key);
    } else {
   
        log.info("Redis don't has data");
        // 如果缓存没有,则再调用服务接口
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
        if (StatusCodeConstant.OK == responseEntity.getStatusCodeValue()) {
   
            strBody = responseEntity.getBody();
        }
        // 将数据写入缓存
        ops.set(key, strBody, RedisConstant.TIME_OUT, TimeUnit.SECONDS);
    }

    ObjectMapper objectMapper = new ObjectMapper();
    T t = null;
    try {
   
        t = objectMapper.readValue(strBody, type);
    } catch (Exception e) {
   
        log.error("Error!", e);
    }
    return t;
}
  1. 使用Redis,需要用到一个类:StringRedisTemplate,它对Redis的API做了一层封装
  2. Redis是K-V的数据结构。这里的K是uri,V是根据uri返回的Json数据
  3. 这里也使用了日志注解@Slf,使用日志进行打印

RedisConstant

public interface RedisConstant {
   
    // 过期时间:1800s
    Long TIME_OUT = 1800L;
}

3.3.5 测试

        启动项目之前,先启动Redis。测试时,可以先把过期时间设置短一点,如:10s。完成之后,再可以设置成1800s。假如设置10s的话,你第一次访问,控制台会打印“Redis don’t has data”,在10s以内再次访问时,会打印“Redis has data”,因为数据已经被存储到了Redis中去了,可通过Redis的客户端工具Redis DeskTop Manager进行查看。超过10s后,再访问,就会打印“Redis don’t has data”,因为数据在Redis中过期了。

4. SpringBoot集成Quartz

Quartz是一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。

4.1 为什么要进行天气数据的同步

        在此之前,这个系统使用了Redis缓存来减少了调用第三方API的次数,但我们还是对它是强依赖,毕竟我们仅仅只是数据的搬运工,并不是产生者。况且,我们也做不了产生者,我们只能依赖于第三方的天气服务商来提供数据给我们。
        之前使用Redis缓存来减少调用第三方API的次数是如何做的-----当用户访问系统时,系统才会触发去调用第三方接口(缓存中没有此数据)的动作。实际上,这个动作应该自动完成,不应该等到用户请求时,再去拉取最新的数据(如果是这样的话,这就比较迟了)。

4.2 如何实现天气数据的同步呢?

        实现数据同步就需要一个定时器来帮助我们实现这种定时任务,因为我们的天气数据大概半小时或1小时变更一次,那么,我们的定时器就设置为半小时或1小时去执行这个定时动作。这里的定时器就选择Quartz,它在业界算比较流行

4.3 使用Quartz

4.3.1 添加依赖

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

4.3.2 手动编码

WeatherDataSyncJob
定义了一个Job

@Slf4j
public class WeatherDataSyncJob extends QuartzJobBean {
   

    @Autowired
    private CityDataService cityDataService;
    @Autowired
    private WeatherDataService weatherDataService;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
   
        log.info("Weather Data Sync Job. Start!");
    }
}

这里用日志打印一条语句,先不做任何业务逻辑

QuartzConfig
这个配置类是用来配置Quartz的

@Configuration
public class QuartzConfig {
   
	// 频率(多长时间执行一次)
    private static final Integer TIME = 1800;

    @Bean
    public JobDetail weatherDataSyncJobJobDetail() {
   
        return JobBuilder
                .newJob(WeatherDataSyncJob.class)
                .withIdentity("weatherDataSyncJobJobDetail")
                .storeDurably()
                .build();
    }

    @Bean
    public Trigger weatherDataSyncJobTrigger() {
   
 
  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
作为AI助手,我可以为您提供以下步骤: 1. 创建SpringBoot项目 首先需要在IDE中创建一个SpringBoot项目。可以在IDE中选择New Project,然后选择Spring Initializr,填写相关信息,如项目名称、包名、依赖等,最后点击Generate按钮即可生成一个基础的SpringBoot项目。 2. 配置数据库 在项目中添加数据库依赖,如MySQL或者其他数据库。然后在application.properties中配置数据库连接信息,如数据库地址、用户名、密码等。 3. 创建实体类 在项目中创建一个学生实体类,包含学生的基本信息,如学号、姓名、性别、年龄等。可以使用JPA注解将实体类映射到数据库中的表。 4. 创建DAO层 创建一个学生DAO层,使用JPA的Repository接口操作数据库。可以定义一些基本的查询方法,如根据学号查询学生、根据姓名查询学生等。 5. 创建Service层 创建一个学生Service层,处理业务逻辑。可以定义一些方法,如添加学生、删除学生、更新学生信息等。 6. 创建Controller层 创建一个学生Controller层,处理HTTP请求。可以定义一些API接口,如查询学生、添加学生、删除学生、更新学生信息等。 7. 编写前端页面 可以使用一些前端框架,如Bootstrap、jQuery等,编写学生管理系统的前端页面。可以包含查询学生、添加学生、删除学生、更新学生信息等功能。 8. 测试 在完成以上步骤后,可以进行测试。可以使用Postman等工具进行API测试,也可以在前端页面进行测试。 以上就是使用SpringBoot搭建一个学生管理系统的基本步骤。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值