spring cache默认缓存底层是使用CurrentHashMap, 本示例使用redis作为缓存载体

 

1. pom.xml依赖

 

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency> 

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

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

 

2. application.yml配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://120.79.xx.xx:3306/demo?useUnicode=yes&characterEncoding=UTF-8&useSSL=false
    username: root
    password: 123456
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  cache:
    type: redis
  redis:
    host: 120.79.xx.xx
    password: 123456
    port: 6379
    database: 0
    timeout: 600ms
    jedis:
      pool:
        max-active: 8
        max-wait: -1ms
        max-idle: 8
        min-idle: 0
# 显示 Mybatis 的 SQL
logging:
  level:
    qinfeng.zheng.springbootredis.repository: debug

mybatis:
  configuration:
    map-underscore-to-camel-case: true

 

3. RedisConfig配置

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import java.time.Duration;

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {

    // https://www.ibm.com/developerworks/cn/java/know-redis-and-use-it-in-springboot-projects/index.html
    @Bean
    public RedisCacheConfiguration cacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))  // redis缓存过期时间
                .disableCachingNullValues();
    }

    /**
     * spring cache管理者
     *
     * @param factory
     * @return
     */
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
        return RedisCacheManager.builder(factory)
                .cacheDefaults(cacheConfiguration())
                .transactionAware()
                .build();
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // Jackson 序列方式
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        // Jackson 默认自动识别 Public 修饰的成员变量、getter、setter
        // private、protected、public 修饰的成员变量都可以自动识别,无需都指定 getter、setter 或者 public。
        // 参考 https://blog.csdn.net/sdyy321/article/details/40298081
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 对于 8 种基本数据类型及其封装类和 String ,其他的类型在序列化的时候带上该类型和值
        // 参考 https://www.jianshu.com/p/c5fcd2a1ab49
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // Redis 链接
        template.setConnectionFactory(redisConnectionFactory);
        // Redis Key - Value 序列化使用 Jackson
        template.setKeySerializer(jackson2JsonRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // Redis HashKey - HashValue 序列化使用 Jackson
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();
        return template;
    }

    @Bean
    @ConditionalOnMissingBean(StringRedisTemplate.class)
    public StringRedisTemplate stringRedisTemplate(
            RedisConnectionFactory redisConnectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

 

@Entity
@Table(name = "user", schema = "spring")
public class User implements Serializable {
    private static final long serialVersionUID = 413797298970501130L;

    @Id
    private String username;
    private Byte age;


    public String getUsername() {
        return username;
    }

    public void setUsername(String userName) {
        this.username = userName;
    }

    public Byte getAge() {
        return age;
    }

    public void setAge(Byte age) {
        this.age = age;
    }
}

 

持久层即可以使用Mybatis也可以使用JPA

@Mapper
public interface UserMapper {
    /**
     * 根据用户名 查询用户信息
     *
     * @param username 用户名
     * @return 用户信息
     */
    @Select("Select username, age From user Where username=#{username}")
    User selectByUsername(String username);

    /**
     * 根据用户名更新用户昵称、用户年龄、用户性别 信息
     *
     * @param user 用户信息
     */
    @Update("Update user Set age=#{age} Where username=#{username}")
    void update(User user);


    /**
     * 根据用户名 删除用户信息
     *
     * @param username 用户名
     */
    @Delete("Delete From user where username=#{username}")
    void delete(String username);
}

 

import io.lettuce.core.dynamic.annotation.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import qinfeng.zheng.springbootredis.entity.User;

@Repository
public interface UserRepository  extends JpaRepository<User, String> {
    /**
     * 根据用户查询
     *
     * @param username 用户名
     * @return 用户信息
     */
    User findByUsername(@Param("username") String username);
}

 

缓存操作

import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import qinfeng.zheng.springbootredis.entity.User;
import qinfeng.zheng.springbootredis.repository.UserMapper;
import qinfeng.zheng.springbootredis.repository.UserRepository;

import javax.annotation.Resource;
import java.time.Duration;

@RestController
@CacheConfig(cacheNames = "users")  // 类级别缓存的一些公共设置
public class RedisController {
    
    @Resource
    private StringRedisTemplate stringTemplate;

    @Resource
    private RedisTemplate<String, User> redisTemplate;

    @Resource
    private UserRepository userRepository;

    @Resource
    private UserMapper userMapper;

    @RequestMapping("/setString")
    public String setString(@RequestParam(value = "key") String key,
                            @RequestParam(value = "value") String value) {
        stringTemplate.opsForValue().set(key, value);
        return "ok";
    }

    @RequestMapping("/getString")
    public String getString(@RequestParam(value = "key") String key) {
        return stringTemplate.opsForValue().get(key);
    }

    
    @RequestMapping(value = "/setUser")
    public String setUser(@RequestBody User user) {
        redisTemplate.opsForValue().set(user.getUsername(), user, Duration.ofMinutes(1));
        return "ok";
    }

    @RequestMapping("/getUser")
    public User getUser(@RequestParam(value = "key") String key) {
        return redisTemplate.opsForValue().get(key);
    }

    @RequestMapping("/delUser")
    public User delUser(@RequestParam(value = "key") String key) {
        User user = redisTemplate.opsForValue().get(key);
        redisTemplate.delete(key);
        return user;
    }

    
    @RequestMapping("/select")
    @Cacheable(key = "#username")   // 将查询结果添加到redis缓存中,redis中的key= cacheNames + key
    public User select(@RequestParam(value = "username") String username) {
        return userRepository.findByUsername(username);
    }

    @RequestMapping("/update")
    @CachePut(key = "#user.username")  // 修改
    public User update(@RequestBody User user) {
        return userRepository.save(user);
    }

    @RequestMapping("/delete")
    @CacheEvict(key = "#username")  // 删除 
    public User delete(@RequestParam(value = "username") String username) {
        User user = select(username);
        userRepository.delete(user);
        return user;
    }

    @RequestMapping("/deleteAllCache")
    @CacheEvict(allEntries = true)   // 删除所有
    public String deleteAllCache() {
        // 删除所有缓存
        return "OK";
    }

    @RequestMapping("/mySelect")
    @Cacheable(value = "users", key = "#username")
    public User mySelect(@RequestParam(value = "username") String username) {
        return userMapper.selectByUsername(username);
    }

    @RequestMapping("/myUpdate")
    @CachePut(value = "users", key = "#user.username")
    public User myUpdate(@RequestBody User user) {
        userMapper.update(user);
        return userMapper.selectByUsername(user.getUsername());
    }

    @RequestMapping("/myDelete")
    @CacheEvict(value = "users", key = "#username")
    public User myDelete(@RequestParam(value = "username") String username) {
        userMapper.delete(username);
        return userMapper.selectByUsername(username);
    }

}

 

最后一步,在启动类上开启Cache操作

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


@EnableCaching   // 启用缓存
@SpringBootApplication
public class RedisApplication {

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

}

 

完毕!

 

感觉使用起来还是挺简单的,只需要添加几个注解即可!

@Cacheable 
@CacheEvict
@CachePut

  

 

posted on 2020-04-28 22:26  显示账号  阅读(478)  评论(0编辑  收藏  举报