业务描述
从一个博客数据库中查询所有的文章标签,然后存储到缓存(Cache),后续查询时可从缓存获取。提高其查询性能。
准备工作
初始化数据
初始化数据库中数据,SQL脚本如下:
DROP DATABASE IF EXISTS `blog`;
CREATE DATABASE `blog` DEFAULT character set utf8mb4;
SET names utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
USE `blog`;
CREATE TABLE `tb_tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(255) NOT NULL COMMENT 'data_id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tb_tag';
insert into `tb_tag` values (null,"mysql"),(null,"redis");
添加项目依赖
在jt-template工程的原有依赖基础上添加mysql数据库访问依赖,例如:
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
添加数据库访问配置
在项目的配置文件(例如application.yml)中添加数据库访问配置,例如:
spring:
datasource:
url: jdbc:mysql:///blog?serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root
password: root
业务逻辑代码设计及实现
Domain对象设计
创建一个Tag类,基于此类型的对象存储Tag(标签信息),代码如下:
package com.jt.blog.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
/**
* 标签的设计
*/
@Data
@TableName("tb_tag")
public class Tag implements Serializable {
private static final long serialVersionUID = 4504013456197711455L;
//标签id
@TableId(type = IdType.AUTO)
private Long id;
//标签名
private String name;
}
Dao 逻辑对象设计
创建Tag信息的数据访问接口,代码如下:
package com.jt.blog.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.blog.domain.Tag;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface TagMapper extends BaseMapper<Tag> {
}
创建单元测试类,TagMapper中的相关方法进行单元测试,例如:
package com.jt.blog.dao;
import com.jt.blog.domain.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class TagMapperTests {
@Autowired
private TagMapper tagMapper;
@Test
void testSelectList(){
List<Tag> tags = tagMapper.selectList(null);
for (Tag t:tags){
System.out.println(t);
//System.out.println(t.getId()+"/"+t.getName());//如果没有set,get方法
}
}
}
Service 逻辑对象设计
设计TagService接口及实现类,定义Tag(标签)业务逻辑。
第一步:定义TagService接口,代码如下:
package com.jt.blog.service;
import com.jt.blog.domain.Tag;
import org.springframework.stereotype.Service;
import java.util.List;
public interface TagService {
/**
* 查询所有标签
* @return
*/
List<Tag> selectTags();
}
第二步:定义TagServiceImpl类,代码如下:
package com.jt.blog.service.impl;
import com.jt.blog.dao.TagMapper;
import com.jt.blog.domain.Tag;
import com.jt.blog.service.TagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TagServiceImpl implements TagService {
//RedisAutoConfiguration 类中做的RedisTemplate的配置
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private TagMapper tagMapper;
@Override
public List<Tag> selectTags() {
//1.从redis查询Tag信息,redis有则直接返回
ValueOperations<String,List<Tag>> valueOperations =
redisTemplate.opsForValue();
List<Tag> tags=valueOperations.get("tags");
if(tags!=null&&!tags.isEmpty())return tags;
//2.从redis没有获取tag信息,查询mysql
tags = tagMapper.selectList(null);
//3.将从mysql查询到tag信息存储到redis
valueOperations.set("tags", tags);
//4.返回查询结果
return tags;
}
}
说明,假如将List存储到redis,此时Tag必须实现Serializable接口。
第三步:定义TagServiceTests单元测试类并进行单元测试,代码如下:
package com.jt.blog.service;
import com.jt.blog.domain.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class TagServiceTests {
@Autowired
private TagService tagService;
@Test
void testSelectTags(){
List<Tag> tags=
tagService.selectTags();
System.out.println(tags);
}
}
Controller逻辑对象设计
创建Tag控制逻辑对象,用于处理请求和响应逻辑,代码如下:
package com.jt.blog.controller;
import com.jt.blog.domain.Tag;
import com.jt.blog.service.TagService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/tag")
public class TagController {
@Autowired
private TagService tagService;
@GetMapping
public List<Tag> doSelectTags(){
return tagService.selectTags());//1.redis,2.mysql
}
}
启动服务,打开浏览器进行访问测试。同时思考,我们是否可以在这个层加一个本地cache。
总结(Summary)
本章节重点是学习项目中缓存(Cache)的一种应用思想。