代码:
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- mybatis 持久层-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
application.properties
server.port=8081
# ============数据库============
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3308/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
# ============mybatis============
mybatis.mapper-locations=classpath:/mapper/*.xml
mybatis.type-aliases-package=com.example.entity
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# ============redis============
# 默认是使用0号数据库,这里我们使用1号,笔者现在0号有其他数据- -
spring.redis.database=1
spring.redis.host=localhost
spring.redis.port=6379
# 默认密码为空
spring.redis.password=
# 连接池最大连接数
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间
spring.redis.lettuce.pool.max-wait=-1ms
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
RedisConfig.java
package com.example.redispractice.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
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.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* @author seanwang
* @date 2021/7/2 0002 上午 10:09
*/
@Configuration
@SuppressWarnings("all")
@EnableCaching
public class RedisConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
UserDao.java
package com.example.redispractice.dao;
import com.example.redispractice.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
@Mapper
public interface UserDao {
int deleteByPrimaryKey(Integer id);
int insert(User record);
int insertSelective(User record);
User selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
List<User> queryAllUser();
}
UserService.java
package com.example.redispractice.service;
import com.example.redispractice.entity.User;
import java.util.List;
/**
* @author seanwang
* @date 2021/7/2 0002 上午 9:11
*/
public interface UserService {
int deleteByPrimaryKey(Integer id);
int insert(User record);
int insertSelective(User record);
User selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(User record);
int updateByPrimaryKey(User record);
List<User> queryAllUser();
int get1();
int get2();
int put1();
int evict();
}
UserServiceImpl.java
package com.example.redispractice.service.impl;
import com.example.redispractice.dao.UserDao;
import com.example.redispractice.entity.User;
import com.example.redispractice.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
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.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author seanwang
* @date 2021/7/2 0002 上午 9:12
*/
@Service
@CacheConfig(cacheNames = "userCache")
public class UserServiceImpl implements UserService {
@Resource
UserDao userDao;
static int i = 0;
@Override
public int deleteByPrimaryKey(Integer id) {
return userDao.deleteByPrimaryKey(id);
}
@Override
public int insert(User record) {
return userDao.insert(record);
}
@Override
public int insertSelective(User record) {
return userDao.insertSelective(record);
}
@Override
@Cacheable
public User selectByPrimaryKey(Integer id) {
return userDao.selectByPrimaryKey(id);
}
@Override
public int updateByPrimaryKeySelective(User record) {
return userDao.updateByPrimaryKeySelective(record);
}
@Override
public int updateByPrimaryKey(User record) {
return userDao.updateByPrimaryKey(record);
}
@Override
@Cacheable(value = "allUser")
public List<User> queryAllUser() {
return userDao.queryAllUser();
}
@Override
@Cacheable(value="cache1")
public int get1() {
return ++i;
}
/**
* Cacheable注解会根据设置的value先读缓存,读取到value值下的缓存就不走方法,没有对应的才会执行方法,(没有缓存才执行)
* @return 更新后的i值
*/
@Override
@Cacheable(value="cache2")
public int get2() {
return ++i;
}
/**
* CachePut注解会执行方法,判断设置的value是否有对应缓存来进行新增/更新缓存
* @return 返回操作后的i值
*/
@Override
@CachePut(value={"cache1"})
public int put1() {
return ++i;
}
/**
* 清空CacheEvict指定value的缓存,并执行方法。
* @return 返回操作后的i值
*/
@Override
@CacheEvict(value={"cache1","cache2"})
public int evict() {
System.out.println("some thing");
return --i;
}
}
UserController.java
package com.example.redispractice.controller;
import com.example.redispractice.entity.User;
import com.example.redispractice.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* @author seanwang
* @date 2021/7/2 0002 下午 1:57
*/
@RestController
public class UserController {
@Resource
private UserService userService;
@GetMapping("/list")
public List<User> getAllUsers() {
return userService.queryAllUser();
}
@GetMapping("/{id}")
public User getUserById(@PathVariable("id") int id) {
return userService.selectByPrimaryKey(id);
}
@RequestMapping("/login")
public String login(HttpServletRequest request){
System.out.println(userService.get1());
System.out.println(userService.get2());
return "fail";
}
@RequestMapping("/put")
public String put(HttpServletRequest request){
userService.put1();
return "fail";
}
@RequestMapping("/evict")
public int evict(HttpServletRequest request){
return userService.evict();
}
}
测试:
访问localhost:8081/list:
此时Service中的查询方法上的注解@Cacheable(value = “allUser”)生效,会保存到缓存:
再次访问localhost:8081/list:
直接走缓存里的数据,并没有走方法执行sql:
注解介绍:
@CacheConfig
@Cacheable
优先读取缓存,缓存读到了就不走方法了。缓存如果没有则执行方法,并缓存到redis。
@CachePut
CachePut注解会执行方法,判断设置的value是否有对应缓存来进行新增/更新缓存
@CacheEvict
清空CacheEvict指定value的缓存,并执行方法。