缓存
使用缓存可以减少请求服务器压力。
SpringBoot整合Cache
-
新建SpringBoot工程
-
修改pom文件
<?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.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.chen</groupId> <artifactId>springboot-cache</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springboot-cache</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>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</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-redis</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.54</version> </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> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
-
修改配置文件
spring: datasource: url: jdbc:mysql://localhost/test?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false username: root password: root driver-class-name: com.mysql.jdbc.Driver type: com.zaxxer.hikari.HikariDataSource redis: database: 0 host: 127.0.0.1 port: 6379
-
新建User实体类
package com.chen.app.entity; import lombok.Data; import java.io.Serializable; @Data public class User implements Serializable { private Long id; private String name; private Integer age; private String email; }
-
新建UserMapper类
package com.chen.app.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.chen.app.entity.User; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper extends BaseMapper<User> { }
-
新建UserService接口
package com.chen.app.service; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.extension.service.IService; import com.chen.app.entity.User; import java.util.List; public interface UserService extends IService<User> { User addUser(User user); User editUser(User user); boolean delUser(long id); User selectById(long id); List<User> selectList(); }
-
新建UserServiceImpl实现类,在此处加入缓存配置
package com.chen.app.service.impl; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.chen.app.entity.User; import com.chen.app.mapper.UserMapper; import com.chen.app.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 java.util.List; @Service @CacheConfig(cacheNames = "user") public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService { @Autowired private UserMapper userMapper; @Override public User addUser(User user) { userMapper.insert(user); return user; } @Override @CachePut(key = "#p0") public User editUser(User user) { userMapper.updateById(user); return user; } @Override @CacheEvict(key = "#p0") public boolean delUser(long id) { int i = userMapper.deleteById(id); return i > 0 ? true : false; } @Override @Cacheable(key = "'selectById:' + #p0") public User selectById(long id) { return userMapper.selectById(id); } @Override @Cacheable(keyGenerator = "keyGenerator") public List<User> selectList() { return userMapper.selectList(null); } }
-
配置扫描
package com.chen.app; 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.chen.app.mapper") @EnableCaching public class SpringbootCacheApplication { public static void main(String[] args) { SpringApplication.run(SpringbootCacheApplication.class, args); } }
-
新建UserController访问类
package com.chen.app.controller; import com.chen.app.entity.User; import com.chen.app.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @RequestMapping("/add") public User add(){ User user = new User(); user.setName("test"); user.setAge(18); user.setEmail("947796393@qq.com"); userService.addUser(user); return user; } @RequestMapping("/edit") public User edit(){ User user = new User(); user.setId(1L); user.setAge(26); userService.editUser(user); return user; } @RequestMapping("/del") public void del(){ userService.delUser(1L); } @RequestMapping("/selectOne") public User selectOne(){ return userService.selectById(1L); } @RequestMapping("/selectAll") public List<User> selectAll(){ return userService.selectList(); } }
-
接口测试
此时,redis里面的数据是序列化过后的,为了显示能正常,需要自定义序列化。
新建RedisConfig类
package com.chen.app.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import java.time.Duration;
@Configuration
@EnableCaching
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport {
/**
* 设置 redis 数据默认过期时间,默认1天
* 设置@cacheable 序列化方式
* @return
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(){
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofDays(1));
return configuration;
}
@Bean(name = "redisTemplate")
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
//序列化
FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
// value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(fastJsonRedisSerializer);
template.setHashValueSerializer(fastJsonRedisSerializer);
// 全局开启AutoType,不建议使用
// ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 建议使用这种方式,小范围指定白名单
ParserConfig.getGlobalInstance().addAccept("com.chen.app.entity");
// key的序列化采用StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
/**
* 自定义缓存key生成策略
* 使用方法 @Cacheable(keyGenerator="keyGenerator")
* @return
*/
@Bean
@Override
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(JSON.toJSONString(obj).hashCode());
}
return sb.toString();
};
}
}
新建序列化类
package com.chen.app.config;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
public FastJsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return (T) JSON.parseObject(str, clazz);
}
}
package com.chen.app.config;
import com.alibaba.fastjson.JSON;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.util.Assert;
import java.nio.charset.Charset;
/**
* 重写序列化器
*
* @author /
*/
public class StringRedisSerializer implements RedisSerializer<Object> {
private final Charset charset;
private final String target = "\"";
private final String replacement = "";
public StringRedisSerializer() {
this(Charset.forName("UTF8"));
}
public StringRedisSerializer(Charset charset) {
Assert.notNull(charset, "Charset must not be null!");
this.charset = charset;
}
@Override
public String deserialize(byte[] bytes) {
return (bytes == null ? null : new String(bytes, charset));
}
@Override
public byte[] serialize(Object object) {
String string = JSON.toJSONString(object);
if (string == null) {
return null;
}
string = string.replace(target, replacement);
return string.getBytes(charset);
}
}