- Cache 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache
- CacheManager 缓存管理器,管理各种缓存(cache)组件
- @Cacheable 主要针对方法配置,能够根据方法的请求参数对其进行缓存
- @CacheEvict 清空缓存
- @CachePut 保证方法被调用,又希望结果被缓存。与@Cacheable区别在于是否每次都调用方法,常用于更新
- @EnableCaching 开启基于注解的缓存
- keyGenerator 缓存数据时key生成策略
- serialize 缓存数据时value序列化策略
- @CacheConfig 统一配置本类的缓存注解的属性
package com.programb.trans;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;@SpringBootApplication
@EnableCaching
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}}
package com.programb.trans.config;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcConstants;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.sql.SQLException;@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class DruidProperties {private String url;private String username;private String password;private String driverClassName = "com.mysql.cj.jdbc.Driver";private Integer initialSize = 10;private Integer minIdle = 3;private Integer maxActive = 60;private Integer maxWait = 60000;private Boolean removeAbandoned = true;private Integer removeAbandonedTimeout = 180;private Integer timeBetweenEvictionRunsMillis = 60000;private Integer minEvictableIdleTimeMillis = 300000;private String validationQuery = "SELECT 'x'";private Boolean testWhileIdle = true;private Boolean testOnBorrow = false;private Boolean testOnReturn = false;private Boolean poolPreparedStatements = true;private Integer maxPoolPreparedStatementPerConnectionSize = 50;private String filters = "stat";public void config(DruidDataSource dataSource) {dataSource.setDbType(JdbcConstants.MYSQL);dataSource.setUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);dataSource.setDriverClassName(driverClassName);dataSource.setInitialSize(initialSize); dataSource.setMinIdle(minIdle); dataSource.setMaxActive(maxActive); dataSource.setMaxWait(maxWait); dataSource.setRemoveAbandoned(removeAbandoned); dataSource.setRemoveAbandonedTimeout(removeAbandonedTimeout); dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);dataSource.setValidationQuery(validationQuery);dataSource.setTestWhileIdle(testWhileIdle);dataSource.setTestOnBorrow(testOnBorrow);dataSource.setTestOnReturn(testOnReturn);dataSource.setPoolPreparedStatements(poolPreparedStatements);dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);try {dataSource.setFilters(filters);} catch (SQLException e) {e.printStackTrace();}}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getDriverClassName() {return driverClassName;}public void setDriverClassName(String driverClassName) {this.driverClassName = driverClassName;}public Integer getInitialSize() {return initialSize;}public void setInitialSize(Integer initialSize) {this.initialSize = initialSize;}public Integer getMinIdle() {return minIdle;}public void setMinIdle(Integer minIdle) {this.minIdle = minIdle;}public Integer getMaxActive() {return maxActive;}public void setMaxActive(Integer maxActive) {this.maxActive = maxActive;}public Integer getMaxWait() {return maxWait;}public void setMaxWait(Integer maxWait) {this.maxWait = maxWait;}public Integer getTimeBetweenEvictionRunsMillis() {return timeBetweenEvictionRunsMillis;}public void setTimeBetweenEvictionRunsMillis(Integer timeBetweenEvictionRunsMillis) {this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;}public Integer getMinEvictableIdleTimeMillis() {return minEvictableIdleTimeMillis;}public void setMinEvictableIdleTimeMillis(Integer minEvictableIdleTimeMillis) {this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;}public String getValidationQuery() {return validationQuery;}public void setValidationQuery(String validationQuery) {this.validationQuery = validationQuery;}public Boolean getTestWhileIdle() {return testWhileIdle;}public void setTestWhileIdle(Boolean testWhileIdle) {this.testWhileIdle = testWhileIdle;}public Boolean getTestOnBorrow() {return testOnBorrow;}public void setTestOnBorrow(Boolean testOnBorrow) {this.testOnBorrow = testOnBorrow;}public Boolean getTestOnReturn() {return testOnReturn;}public void setTestOnReturn(Boolean testOnReturn) {this.testOnReturn = testOnReturn;}public Boolean getPoolPreparedStatements() {return poolPreparedStatements;}public void setPoolPreparedStatements(Boolean poolPreparedStatements) {this.poolPreparedStatements = poolPreparedStatements;}public Integer getMaxPoolPreparedStatementPerConnectionSize() {return maxPoolPreparedStatementPerConnectionSize;}public void setMaxPoolPreparedStatementPerConnectionSize(Integer maxPoolPreparedStatementPerConnectionSize) {this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;}public String getFilters() {return filters;}public void setFilters(String filters) {this.filters = filters;}public Boolean getRemoveAbandoned() {return removeAbandoned;}public void setRemoveAbandoned(Boolean removeAbandoned) {this.removeAbandoned = removeAbandoned;}public Integer getRemoveAbandonedTimeout() {return removeAbandonedTimeout;}public void setRemoveAbandonedTimeout(Integer removeAbandonedTimeout) {this.removeAbandonedTimeout = removeAbandonedTimeout;}
}
package com.programb.trans.config;import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.annotation.Resource;@Configuration
@EnableTransactionManagement(order = 2)
@MapperScan(basePackages = {"com.programb.trans.dao.repository"})
public class MybatisPlusConfig {@Resourceprivate DruidProperties druidProperties;@Beanpublic DruidDataSource singleDatasource() {DruidDataSource dataSource = new DruidDataSource();druidProperties.config(dataSource);return dataSource;}@Beanpublic PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();}
}
package com.programb.trans.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer;
import org.springframework.cache.CacheManager;
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.core.env.Environment;
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.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.lang.reflect.Method;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;@Configuration
@EnableCaching
public class RedisCacheConfig {private Logger logger = LoggerFactory.getLogger(this.getClass());@Autowiredprivate Environment env;@Beanpublic LettuceConnectionFactory redisConnectionFactory() {RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();redisConf.setHostName(env.getProperty("spring.redis.host"));redisConf.setPort(Integer.parseInt(env.getProperty("spring.redis.port")));redisConf.setPassword(RedisPassword.of(env.getProperty("spring.redis.password")));return new LettuceConnectionFactory(redisConf);}@Beanpublic RedisCacheConfiguration cacheConfiguration() {RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600)).disableCachingNullValues();return cacheConfig;}@Beanpublic RedisCacheManager cacheManager() {RedisCacheManager rcm = RedisCacheManager.builder(redisConnectionFactory()).cacheDefaults(cacheConfiguration()).transactionAware().build();return rcm;}@Bean(name = "KeyGenerator")public KeyGenerator myKeyGenerator() {return new KeyGenerator() {@Overridepublic Object generate(Object o, Method method, Object... params) {logger.info("programb" + Arrays.toString(params));return params[0];}};}
}
package com.programb.trans.dao.entity;import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;import java.io.Serializable;@TableName(value = "t_user")
public class User extends Model<User> {@TableId(value="id", type= IdType.INPUT)private Integer id;private String username;private String password;public User() {}public User(Integer id, String username, String password) {this.id = id;this.username = username;this.password = password;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overrideprotected Serializable pkVal() {return this.id;}
}
package com.programb.trans.dao.repository;import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.programb.trans.dao.entity.User;public interface UserMapper extends BaseMapper<User> {
}
package com.programb.trans.service;import com.baomidou.mybatisplus.mapper.Condition;
import com.programb.trans.dao.entity.User;
import com.programb.trans.dao.repository.UserMapper;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.util.List;@Service
@Transactional
public class UserService {private Logger logger = LoggerFactory.getLogger(this.getClass());@Resourceprivate UserMapper userMapper;@Cacheable(value = "userCache", key = "#id", unless="#result == null")public User getById(int id) {logger.info("获取用户start...");return userMapper.selectById(id);}@Cacheable(value = "allUsersCache", unless = "#result.size() == 0")public List<User> getAllUsers() {logger.info("获取所有用户列表");return userMapper.selectList(null);}@Caching(put = {@CachePut(value = "userCache", key = "#user.id")},evict = {@CacheEvict(value = "allUsersCache", allEntries = true)})public User createUser(User user) {logger.info("创建用户start..., user.id=" + user.getId());userMapper.insert(user);return user;}@Caching(put = {@CachePut(value = "userCache", key = "#user.id")},evict = {@CacheEvict(value = "allUsersCache", allEntries = true)})public User updateUser(User user) {logger.info("更新用户start...");userMapper.updateById(user);return user;}@Caching(evict = {@CacheEvict(value = "userCache", key = "#id"),@CacheEvict(value = "allUsersCache", allEntries = true)})public void deleteById(int id) {logger.info("删除用户start...");userMapper.deleteById(id);}}
server.port: 8092spring:profiles:active: devdatasource:url: jdbc:mysql://127.0.0.1:3306/test?useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8username: rootpassword: 123456mybatis-plus:mapper-locations: classpath*:com/programb/trans/dao/repository/mapping
<?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><groupId>com.programb</groupId><artifactId>springboot-cache</artifactId><version>1.0.0-SNAPSHOT</version><packaging>jar</packaging><name>springboot-cache</name><description>SpringBoot Transaction</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.4.RELEASE</version><relativePath/></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version><druid.version>1.1.2</druid.version><mysql-connector.version>8.0.7-dmr</mysql-connector.version><mybatis-plus.version>2.1.8</mybatis-plus.version><mybatisplus-spring-boot-starter.version>1.0.5</mybatisplus-spring-boot-starter.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>com.vaadin.external.google</groupId><artifactId>android-json</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector.version}</version><scope>runtime</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency><!-- MyBatis plus增强和springboot的集成--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus</artifactId><version>${mybatis-plus.version}</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatisplus-spring-boot-starter</artifactId><version>${mybatisplus-spring-boot-starter.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.6.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.20</version><configuration><skip>true</skip></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><executions></executions></plugin></plugins><resources><resource><directory>src/main/resources</directory></resource><resource><directory>src/main/java</directory><includes><include>**