缓存配置
当系统的访问量增大时,相应的数据库的性能就逐渐下降。但是,大多数请求都是在重复的获取相同的数据,如果使用缓存,将结果数据放入其中可以很大程度上减轻数据库的负担,提升系统的响应速度。
本篇将介绍 Spring Boot 中缓存和 NoSQL 的使用。
整合缓存
Spring Boot 针对不同的缓存技术实现了不同的封装,本篇主要介绍 EhCache 和 Redis 缓存。
Spring Boot 提供了以下几个注解实现声明式缓存:
|
注解
|
说明
|
| --- | --- |
|
@EnableCaching
|
开启缓存功能,放在配置类或启动类上
|
|
@CacheConfig
|
缓存配置,设置缓存名称
|
|
@Cacheable
|
执行方法前先查询缓存是否有数据。有则直接返回缓存数据;否则查询数据再将数据放入缓存
|
|
@CachePut
|
执行新增或更新方法后,将数据放入缓存中
|
|
@CacheEvict
|
清除缓存
|
|
@Caching
|
将多个缓存操作重新组合到一个方法中
|
EhCache 缓存
添加依赖
org.springframework.boot
spring-boot-starter-cache
net.sf.ehcache
ehcache
在 src/main/resources 目录下创建 ehcache.xml 文件,内容如下:
xsi:noNamespaceSchemaLocation="ehcache.xsd">
application.properties :
spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:ehcache.xml
打印日志,查看 sql
logging.level.com.light.springboot=DEBUG
在持久层篇的基础上,结合 Mybatis 测试:
Service 层:
@CacheConfig(cacheNames = "department")
@Service
public class DepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
@CachePut(key = "#department.id")
public Department save(Department department) {
System.out.println("保存 id=" + department.getId() + " 的数据");
this.departmentMapper.insert(department);
return department;
}
@CachePut(key = "#department.id")
public Department update(Department department) {
System.out.println("修改 id=" + department.getId() + " 的数据");
this.departmentMapper.update(department);
return department;
}
@Cacheable(key = "#id")
public Department getDepartmentById(Integer id) {
System.out.println("获取 id=" + id + " 的数据");
Department department = this.departmentMapper.getById(id);
return department;
}
@CacheEvict(key = "#id")
public void delete(Integer id) {
System.out.println("删除 id=" + id + " 的数据");
this.departmentMapper.deleteById(id);
}
}
控制层:
@Controller
@RequestMapping("department")
@ResponseBody
public class DepartmentController {
@Autowired
private DepartmentService departmentService;
@RequestMapping("save")
public Map save(Department department) {
this.departmentService.save(department);
Map map = new HashMap();
map.put("code", "200");
map.put("msg", "保存成功");
return map;
}
@RequestMapping("get/{id}")
public Map get(@PathVariable("id") Integer id) {
Department department = this.departmentService.getDepartmentById(id);
Map map = new HashMap();
map.put("code", "200");
map.put("msg", "获取成功");
map.put("data", department);
return map;
}
@RequestMapping("update")
public Map update(Department department) {
this.departmentService.update(department);
Map map = new HashMap();
map.put("code", "200");
map.put("msg", "修改成功");
return map;
}
@RequestMapping("delete/{id}")
public Map delete(@PathVariable("id") Integer id) {
this.departmentService.delete(id);
Map map = new HashMap();
map.put("code", "200");
map.put("msg", "删除成功");
return map;
}
}
启动类:
添加 @EnableCaching 注解,开启缓存功能。
@EnableCaching
@SpringBootApplication
public class SpringbootNosqlApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootNosqlApplication.class, args);
}
}
测试说明
发送保存接口
[图片上传中...(image-49dfa3-1524634441874-7)]
发送查询接口
[图片上传中...(image-a3cef6-1524634441874-6)]
再次发送查询接口
[图片上传中...(image-d8f1c8-1524634441874-5)]
说明数据是从缓存中获取。
发起修改请求:
[图片上传中...(image-dce6b1-1524634441874-4)]
发送查询接口
[图片上传中...(image-826dd4-1524634441874-3)]
没有sql日志打印,但返回修改后的对象数据,说明缓存中的数据已经同步。
发起删除请求:
[图片上传中...(image-210460-1524634441874-2)]
删除成功后,立刻发起查询请求,控制台打印 sql 语句,说明缓存数据被删除,需要查询数据库。
[图片上传中...(image-46c621-1524634441874-1)]
Redis 缓存
添加依赖
org.springframework.boot
spring-boot-starter-data-redis
添加配置
application.properties :
spring.redis.host=192.168.1.254
spring.redis.port=6379
spring.redis.password=123456
spring.redis.database=6
spring.redis.pool.max-active=8
spring.redis.pool.max-idle=8
spring.redis.pool.max-wait=-1
spring.redis.pool.min-idle=0
spring.redis.timeout=0
注意:spring.cache.type=redis,缓存类型设置成 redis。
完成上边 2 个步骤后,其他步骤与测试 Ehcache 时的步骤一致。
测试结果也一致,此处省略。
整合 Redis
在添加 redis 依赖包启动项目后,Spring Boot 会自动配置 RedisCacheManger 和 RedisTemplate 的 Bean。如果开发者不想使用 Spring Boot 写好的 Redis 缓存,而是想使用其 API 自己实现缓存功能、消息队列或分布式锁之类的需求时,可以继续往下浏览。
Spring Data Redis 为我们提供 RedisTemplate 和 StringRedisTemplate 两个模板进行数据操作,它们主要 的访问方法如下:
|
方法
|
说明
|
| --- | --- |
|
opsForValue()
|
操作简单属性的数据
|
|
opsForList()
|
操作含有 list 的数据
|
|
opsForSet()
|
操作含有 set 的数据
|
|
opsForZSet()
|
操作含有 zset 的数据
|
|
opsForHash()
|
操作含有 hash 的数据
|
添加依赖
org.springframework.boot
spring-boot-starter-data-redis
配置连接
spring.redis.host=192.168.1.254
spring.redis.port=6379
spring.redis.password=123456
spring.redis.database=6
spring.redis.pool.max-active=8
spring.redis.pool.max-idle=8
spring.redis.pool.max-wait=-1
spring.redis.pool.min-idle=0
spring.redis.timeout=0
编码
@Component
public class RedisDao {
@Autowired
private StringRedisTemplate stringRedisTemplate;
public void set(String key, String value) {
this.stringRedisTemplate.opsForValue().set(key, value);
}
public String get(String key) {
return this.stringRedisTemplate.opsForValue().get(key);
}
public void delete(String key) {
this.stringRedisTemplate.delete(key);
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisDaoTest {
@Autowired
private RedisDao redisDao;
@Test
public void testSet() {
String key = "name";
String value = "zhangsan";
this.redisDao.set(key, value);
}
@Test
public void testGet() {
String key = "name";
String value = this.redisDao.get(key);
System.out.println(value);
}
@Test
public void testDelete() {
String key = "name";
this.redisDao.delete(key);
}
}
测试结果
[图片上传中...(image-745fa0-1524634441874-0)]
整合 MongoDB
Spring Data MongoDB 提供了 MongoTemplate 模板 和 Repository 让开发者进行数据访问。
添加依赖
org.springframework.boot
spring-boot-starter-data-mongodb
配置连接
spring.data.mongodb.host=192.168.2.25
spring.data.mongodb.port=27017
spring.data.mongodb.database=test
编码
使用 MongoTemplate
@Component
public class MongodbDao {
@Autowired
private MongoTemplate mongoTemplate;
public void insert(User user) {
this.mongoTemplate.insert(user);
}
public void deleteById(int id) {
Criteria criteria = Criteria.where("id").is(id);
Query query = new Query(criteria);
this.mongoTemplate.remove(query, User.class);
}
public void update(User User) {
Criteria criteria = Criteria.where("id").is(User.getId());
Query query = new Query(criteria);
Update update = new Update();
update.set("password", User.getPassword());
this.mongoTemplate.updateMulti(query, update, User.class);
}
public User getById(int id) {
Criteria criteria = Criteria.where("id").is(id);
Query query = new Query(criteria);
return this.mongoTemplate.findOne(query, User.class);
}
public List getAll() {
List userList = this.mongoTemplate.findAll(User.class);
return userList;
}
}
使用 Repository
public interface UserRepository extends MongoRepository
}
测试方式与 Redis 测试大同小异,测试结果省略...
参考资料
https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html 官方文档