Spring Cloud学习笔记3——天气预报系统(2)用redis提升应用的并发访问能力
为什么要使用Redis
- 及时响应:
Redis
是一个基于内存的缓存系统,查询、响应的速度快 - 减少服务调用
开发环境
JDK8+
Gradle4+
Redis 3.2.100
Apache HttpClient 4.5.3
Spring Boot Web Starter
Spring Boot Data Redis Starter
新建项目
复制之前的micro-weather-basic
项目,将副本改名为micro-weather-redis
修改源码
修改build.gradle
配置,加入redis
的依赖:
//依赖关系
dependencies {
//该依赖用于编译阶段
compile('org.springframework.boot:spring-boot-starter-web')
//HttpClient
compile('org.apache.httpcomponents:httpclient:4.5.6')
//Redis
compile('org.springframework.boot:spring-boot-starter-data-redis')
//该依赖用于测试阶段
testCompile('org.springframework.boot:spring-boot-starter-test')
}
修改WeatherDataServiceImpl.java
:
package com.study.spring.cloud.weather.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.study.spring.cloud.weather.vo.WeatherResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
@Service
public class WeatherDataServiceImpl implements WeatherDataService {
//在应用中添加日志
private final static Logger logger=LoggerFactory.getLogger(WeatherDataService.class);
private static final String WEATHER_URI="http://wthrcdn.etouch.cn/weather_mini?";
private static final long TIME_OUT=10L;
@Autowired
//对rest客户端的封装
private RestTemplate restTemplate;
@Autowired
//对redis api的封装
private StringRedisTemplate stringRedisTemplate;
@Override
public WeatherResponse getDataByCityId(String cityId) {
String uri=WEATHER_URI + "citykey=" + cityId;
return this.doGetWeather(uri);
}
@Override
public WeatherResponse getDataByCityName(String cityName) {
String uri=WEATHER_URI + "city=" + cityName;
return this.doGetWeather(uri);
}
private WeatherResponse doGetWeather(String uri) {
String key=uri;
String strBody=null;
ObjectMapper mapper=new ObjectMapper();
WeatherResponse resp=null;
//ValueOperations类可通过get()获取缓存中的数据
ValueOperations<String,String> ops = stringRedisTemplate.opsForValue();
//先查缓存,缓存有的取缓存中的数据
if(stringRedisTemplate.hasKey(key)){
logger.info("Redis has data");
strBody = ops.get(key);
}else{
logger.info("Redis doesn't have data");
//缓存没有,再调用服务接口来获取
//得到json字符串
ResponseEntity<String> respString = restTemplate.getForEntity(uri, String.class);
//判断ResponseEntity的状态码是否为200,为200时取出strBody
if(respString.getStatusCodeValue()==200) {
strBody=respString.getBody();
}
//数据写入缓存
ops.set(key, strBody, TIME_OUT, TimeUnit.SECONDS);
}
//用json反序列化成我们想要的数据
try {
/*
* strBody:要解析的参数内容,从respString获取
* WeatherResponse.class:要转成的对象类型
*/
resp=mapper.readValue(strBody,WeatherResponse.class);
}catch(IOException e) {
logger.error("Error!",e);
}
return resp;
}
}
运行
运行Redis
:
进入Redis
的安装目录:
运行结果如下:
启动应用:
运行结果如下:
访问http://localhost:8080/weather/cityId/101020100
页面:
刷新几次,观察日志输出:
证明设置的超时时间10
秒是有效的,接下来将测试时使用的10
秒改为正式使用时的半小时(即1800
秒):
//在应用中添加日志
private final static Logger logger=LoggerFactory.getLogger(WeatherDataService.class);
private static final String WEATHER_URI="http://wthrcdn.etouch.cn/weather_mini?";
private static final long TIME_OUT=1800L;