SpringBoot2.X之旅,Redis缓存中@Cacheable、@CacheEvict、@CachePut、@CacheConfig的使用(Web Project)

一、环境准备:

1、redis相关关键记录:

1)启动:进入到redis安装目录的src下,启动命令是:./redis-server ../redis.conf。

2)连接:在redis.conf文件内需要设置绑定地址:bind 192.168.60.129,否则远程无法访问redis。

2、项目基础是 SpringBoot2.X之旅,Mybatis+Durid+Mysql实践,mybatis自定义sql语句和多表关联查询(Web Project)这篇文章的基础上进行改造的。

3、本文是在一个基本的spring boot + mybatis的web项目中,实现CURD和简单的集合查询,把查询结果进行缓存。

用redis实现结果缓存的关键步骤:

a、添加redis的依赖

b、涉及到缓存的数据类需要实现序列化

c、添加redis数据库的地址、端口配置

d、在需要缓存返回结果的方法上加@Cacheable,设定参数

e、启动类上加@EnableCaching注解,开启缓存

f、@CacheEvict删除缓存

g、@CachePut,当数据有修改的返回值与查询相同使用,先删除缓存,再把返回值存到缓存

h、@CacheConfig同一个类里抽取出cacheNames 参数

二、项目改造:

1、添加依赖:

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

最终项目的pom.xml是:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.cobra</groupId>
    <artifactId>mybatisdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatisdemo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--加入druid依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--添加mybatis generator生成器插件-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.7</version>
                <!--生成插件的依赖-->
                <dependencies>
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.7</version>
                    </dependency>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.47</version>
                    </dependency>
                </dependencies>
                <!--所要做的事情-->
                <executions>
                    <execution>
                        <!--起个名-->
                        <id>mybatis generator</id>
                        <!--阶段-->
                        <phase>package</phase>
                        <!--目的-->
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <!--由于需要反复生成文件,这里是一些相关配置-->
                <configuration>
                    <!--允许移动生成文件-->
                    <verbose>true</verbose>
                    <!--允许覆盖文件,实际开发中这个不能为true,
                    不然可能把别人的劳动成果覆盖-->
                    <overwrite>true</overwrite>
                    <!--mybatis-generator配置文件的路径-->
                    <configurationFile>
                        src/main/resources/mybatis-generator.xml
                    </configurationFile>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2、dao层,UserInfoMapper.xml添加查询

<!--查询所有人-->
  <select id="listUser" resultMap="BaseResultMap">
    <!--
      WARNING - @mbg.generated
      This element is automatically generated by MyBatis Generator, do not modify.
      This element was generated on Sat Mar 16 10:50:50 CST 2019.
    -->
    select
    <include refid="Base_Column_List" />
    from user_info order by user_id asc;
  </select>

  UserInfoMapper接口添加查询方法

/**
     * 获取所有人
     * @return
     */
    List<UserInfo> listUser();

3、service层:

UseService添加接口:

/**
     * 查找所有UserInfo
     * @return
     */
    public List<UserInfo> findAll();

UseServiceImpl实现接口:

/**
     * 查找所有UserInfo
     *
     * @return
     */
    @Override
    public List<UserInfo> findAll() {
        return userInfoMapper.listUser();
    }

三、用@Cacheable对查询结果进行缓存(需要做的额外关键点):

1、需要返回的数据实体需要序列化,实现Serializable,生成私有id:

package com.cobra.mybatisdemo.dataobject;

import java.io.Serializable;

/**
 * UserInfo数据实体
 */
public class UserInfo implements Serializable {

    private static final long serialVersionUID = -7942802606015631488L;

    /**
     *
     * This field was generated by MyBatis Generator.
     * This field corresponds to the database column user_info.user_id
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    private Integer userId;

    /**
     *
     * This field was generated by MyBatis Generator.
     * This field corresponds to the database column user_info.username
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    private String username;

    /**
     *
     * This field was generated by MyBatis Generator.
     * This field corresponds to the database column user_info.password
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    private String password;

    /**
     *
     * This field was generated by MyBatis Generator.
     * This field corresponds to the database column user_info.email
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    private String email;

    /**
     * This method was generated by MyBatis Generator.
     * This method returns the value of the database column user_info.user_id
     *
     * @return the value of user_info.user_id
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    public Integer getUserId() {
        return userId;
    }

    /**
     * This method was generated by MyBatis Generator.
     * This method sets the value of the database column user_info.user_id
     *
     * @param userId the value for user_info.user_id
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    /**
     * This method was generated by MyBatis Generator.
     * This method returns the value of the database column user_info.username
     *
     * @return the value of user_info.username
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    public String getUsername() {
        return username;
    }

    /**
     * This method was generated by MyBatis Generator.
     * This method sets the value of the database column user_info.username
     *
     * @param username the value for user_info.username
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    public void setUsername(String username) {
        this.username = username == null ? null : username.trim();
    }

    /**
     * This method was generated by MyBatis Generator.
     * This method returns the value of the database column user_info.password
     *
     * @return the value of user_info.password
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    public String getPassword() {
        return password;
    }

    /**
     * This method was generated by MyBatis Generator.
     * This method sets the value of the database column user_info.password
     *
     * @param password the value for user_info.password
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    public void setPassword(String password) {
        this.password = password == null ? null : password.trim();
    }

    /**
     * This method was generated by MyBatis Generator.
     * This method returns the value of the database column user_info.email
     *
     * @return the value of user_info.email
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    public String getEmail() {
        return email;
    }

    /**
     * This method was generated by MyBatis Generator.
     * This method sets the value of the database column user_info.email
     *
     * @param email the value for user_info.email
     *
     * @mbg.generated Sat Mar 16 10:50:50 CST 2019
     */
    public void setEmail(String email) {
        this.email = email == null ? null : email.trim();
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

}

2、application.yml配置文件添加redis地址和端口,如果有密码需要填写密码:

spring:
  redis:
    host: 192.168.60.129
    port: 6379

3、controller层:

UserController添加映射mapping方法,加上缓存注解@Cacheable并指定参数(cacheNames = "user",key = "123456")

    /**
     * 获取所有的UserInfo
     * @return
     */
    @GetMapping("/list")
    @Cacheable(cacheNames = "user",key = "123456")
    public List<UserInfo> findAll() {
        return userService.findAll();
    }

4、启动类上加@EnableCaching注解,开启缓存:

package com.cobra.mybatisdemo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@MapperScan("com.cobra.mybatisdemo.dao")
@EnableCaching
public class MybatisdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisdemoApplication.class, args);
    }

}

四、测试:

1、打断点:

2、用debug模式启动项目:

3、首次访问:localhost:8080/user/list

4、进入断点:

5、返回结果:

6、同时使用redis管理工具查看redis,发现有存入值:

7、第二次及之后的访问,可以发现,请求不会到断点,说明数据是直接去redis读的缓存。

五、@CacheEvict删除缓存数据

当修改、添加、删除数据时,为了保证缓存数据和数据库的数据一致,需要需要删除缓存,让客户端在修改、添加、删除数据之后,首次访问数据库,再生成缓存,但是要保证cacheNames、key 和@Cacheable一致:

package com.cobra.mybatisdemo.controller;

import com.cobra.mybatisdemo.dataobject.UserInfo;
import com.cobra.mybatisdemo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @Author: Baron
 * @Description:
 * @Date: Created in 2019/3/16 12:10
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    /**
     * 添加用户
     * @param userInfo
     * @return
     */
    @PostMapping("/add")
    @CacheEvict(cacheNames = "user",key = "123456")
    public int add(UserInfo userInfo) {
        return userService.add(userInfo);
    }

    /**
     * 根据userId查找用户
     * @param userId
     * @return
     */
    @GetMapping("/{userId}")
    public UserInfo findByUserId(@PathVariable("userId") Integer userId) {
        return userService.findByUserId(userId);
    }

    /**
     * 更改用户信息
     * @param userInfo
     * @return
     */
    @PostMapping("/update")
    @CacheEvict(cacheNames = "user",key = "123456")
    public int update(UserInfo userInfo) {
        return userService.update(userInfo);
    }

    /**
     * 根据userId删除用户
     * @param userId
     * @return
     */
    @DeleteMapping("/{userId}")
    @CacheEvict(cacheNames = "user",key = "123456")
    public int deleteByUserId(@PathVariable("userId") Integer userId) {
        return userService.deleteByUserId(userId);
    }

    /**
     * 获取所有的UserInfo
     * @return
     */
    @GetMapping("/list")
    @Cacheable(cacheNames = "user",key = "123456")
    public List<UserInfo> findAll() {
        return userService.findAll();
    }

}

六、@CachePut先删原来的缓存,再把返回的缓存放入redis

适用于数据修改之后有返回值的缓存,返回类型需要与查询的一样,一般与@Cacheable结合使用,cacheNames  、key参数需要一致。

七、@CacheConfig抽取cacheNames 参数

如果在同一个类上,有多个方法使用@Cacheable、@CachePut、@CacheEvict,可以使用@CacheConfig(cacheNames = "user")把公共部分提取出来。

项目demo地址:https://github.com/yaobaron/redisdemo/

猜你喜欢

转载自blog.csdn.net/weixin_37138899/article/details/88696188