欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Boot + MyBatis + Redis整合小案例

程序员文章站 2022-05-03 14:41:34
...

Redis 缓存

一、介绍

       Redis缓存是一个高性能的key-value数据库,在大流量场景下,需要将一些经常展现和不会频繁变更的数据,存放在存取速率更快的地方,在技术选型中,常使用Redis作为缓存数据库。
应用场景:例如常见的电商场景,根据商品ID获取商品信息,这是就可以把店铺信息和商品详细信息写入redis,减少了去数据库查询的次数。

二、更新缓存的策略

       更新缓存的四种策略:Cache aside, Read through, Write through, Write behind caching。具体参考 酷 壳 – CoolShell:https://coolshell.cn/articles/17416.html
其中Cache Aside Pattern是最常用的一种模式了。这也是这个小案例所使用的方式。

三、Redis的安装

windows版本下载地址:https://github.com/MicrosoftArchive/redis/releases
Spring Boot + MyBatis + Redis整合小案例
将文件解压,打开cmd窗口,运行cd切换到解压目录下,运行命令:redis-server.exe redis.windows.conf
Spring Boot + MyBatis + Redis整合小案例
注意:这个窗口不能关闭,否则就不能访问服务端了。

测试:

另开一个cmd窗口,切换到redis目录下,运行:redis-cli.exe
设置key-Value
Spring Boot + MyBatis + Redis整合小案例

四、简单案例

1.构建Spring Boot项目

      这个可以参考网上的教程,此处不多说。可以进入http://start.spring.io进行项目的快速构建。

2.数据库设计

      创建city表

DROP TABLE IF EXISTS city;

CREATE TABLE city (
        id int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '城市编号',
        province_id int(10) UNSIGNED NOT NULL COMMENT '省份编号',       -- UNSIGNED是无符号int,表示都为整数
        city_name VARCHAR(25) DEFAULT NULL COMMENT '城市名称',
        description VARCHAR(25) DEFAULT null COMMENT '描述',
        PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

insert into city VALUES(1,1,'南京市','六朝古都');

3.配置文件

需要在Spring Boot的配置文件中配置数据源,Redis,MyBatis等相关配置

# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdb?useUnicode=true&characterEncoding=utf8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root

# MyBatis配置
mybatis.type-aliases-package=cn.hzr0523.entity
mybatis.mapper-locations=classpath:mapper/*.xml

# Redis配置
## Redis数据库索引(默认为0)
spring.redis.database=0
## Redis服务器地址
spring.redis.host=127.0.0.1
## Redis服务器连接端口
spring.redis.port=6379
## Redis服务器连接密码(默认为空)
spring.redis.password=
## 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
## 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
## 连接池最大空闲连接
spring.redis.pool.max-idle=8
## 连接池最小空闲连接
spring.redis.pool.min-idle=0
## 连接超时时间(毫秒)
spring.redis.timeout=0

4.代码

Controller

@RestController
public class CityController {
    @Autowired
    private ICityService cityService;

    @RequestMapping(value = "/api/city", method = RequestMethod.POST)
    public Long saveCity(@RequestBody City city) {
        return cityService.saveCity(city);
    }

    @RequestMapping(value = "/api/city/{id}", method = RequestMethod.GET)
    public City findOneCity(@PathVariable("id") Long id){
        return cityService.findCityById(id);
    }

    @RequestMapping(value = "/api/city", method = RequestMethod.PUT)
    public Long updateCity(@RequestBody City city) {
        return cityService.updateCity(city);
    }

    @RequestMapping(value = "/api/city/{id}", method = RequestMethod.DELETE)
    public Long deleteCity(@PathVariable("id") Long id) {
        return cityService.deleteCity(id);
    }

}

Service

/**
 * hezhi
 * 2018/3/2 15:36
 */
@Service
public class CityServiceImpl implements ICityService {
    private static final Logger LOGGER = LoggerFactory.getLogger(CityServiceImpl.class);

    @Autowired(required = false)
    private CityDao cityDao;

    @Resource
    private RedisTemplate redisTemplate;

    public List<City> findAllCity() {

        return null;
    }

    /**
     * 获取城市逻辑:
     * 如果缓存存在,获取缓存中的城市信息
     * 如果缓存不存在,从DB中获取城市信息,然后插入缓存
     * @param id
     * @return
     */
    public City findCityById(Long id) {
        String key = "city_" + id ;
        ValueOperations<String, City> operations = redisTemplate.opsForValue();

        //缓存存在
        boolean hasKey = redisTemplate.hasKey(key);
        if(hasKey) {
            City city = operations.get(key);
            LOGGER.info("CityServiceImpl.findCityById:从缓存中获取了城市 >> " + city.toString());
            return city;
        }
        //从DB中获取城市信息
        City city = cityDao.findCityById(id);
        //插入缓存
        operations.set(key,city,10, TimeUnit.SECONDS);
        LOGGER.info("CityServiceImpl.findCityById:从数据库中获取了城市 >> " + city.toString());
        return city;
    }

    @Override
    public Long saveCity(City city) {
        return cityDao.saveCity(city);
    }

    @Override
    public Long updateCity(City city) {
        Long ret = cityDao.updateCity(city);
        //如果缓存存在,删除缓存
        String key = "city_" + city.getId();
        boolean haskey = redisTemplate.hasKey(key);
        if(haskey) {
            redisTemplate.delete(key);
            LOGGER.info("CityServiceImpl.updateCity:从缓存中删除了城市 >>" + city.toString());
        }
        return ret;
    }

    @Override
    public Long deleteCity(Long id) {
        Long ret = cityDao.deleteCity(id);
        //如果缓存存在,删除缓存
        String key = "city_" + id;
        boolean haskey = redisTemplate.hasKey(key);
        if(haskey) {
            redisTemplate.delete(key);
            LOGGER.info("CityServiceImpl.updateCity:从缓存中删除了城市ID >>" + id);
        }
        return ret;
    }
}

mappe.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.hzr0523.dao.CityDao">
    <resultMap id="BaseResultMap" type="cn.hzr0523.entity.City">
        <result column="id" property="id" />
        <result column="province_id" property="provinceId" />
        <result column="city_name" property="cityName" />
        <result column="description" property="description" />
    </resultMap>

    <parameterMap id="City" type="cn.hzr0523.entity.City"/>

    <sql id="Base_Column_List">
        id, province_id, city_name, description
    </sql>

    <select id="findCityById" resultMap="BaseResultMap" parameterType="java.lang.Long">
        select
        <include refid="Base_Column_List" />
        from city
        where id = #{id}
    </select>

    <select id="findAllCity" resultMap="BaseResultMap" >
        select
        <include refid="Base_Column_List" />
        from city
    </select>

    <insert id="saveCity" parameterMap="City" useGeneratedKeys="true" keyProperty="id">
        insert into
        city(id,province_id,city_name,description)
        values
        (#{id},#{provinceId},#{cityName},#{description})
    </insert>

    <update id="updateCity" parameterMap="City">
        update
        city
        set
        <if test="provinceId!=null">
            province_id = #{provinceId},
        </if>
        <if test="cityName!=null">
            city_name = #{cityName},
        </if>
        <if test="description!=null">
            description = #{description}
        </if>
        where
        id = #{id}
    </update>

    <delete id="deleteCity" parameterType="java.lang.Long">
        delete from
        city
        where
        id = #{id}
    </delete>

</mapper>