docker启动redis
1 docker run -p 6379:6379 --name myredis redis 2 查看容器 3 4 [root@topcheer ~]# docker ps -l 5 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6 14b1139f889d f7302e4ab3a8 "docker-entrypoint..." 20 hours ago Up 20 hours 0.0.0.0:6379->6379/tcp myredis 7 [root@topcheer ~]# 8 注:本文只讲整合,后面补充docker及redis知识
整合Redis
application.yml 配置文件
1 spring: 2 datasource: 3 username: scott 4 password: tiger 5 url: jdbc:oracle:thin:@//localhost:1521/ORCL 6 driver-class-name: oracle.jdbc.driver.OracleDriver 7 redis: 8 host: 192.168.180.113 9 port: 6379
pom.xml (选取开发所需的依赖)
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-jdbc</artifactId> 4 </dependency> 5 <dependency> 6 <groupId>org.springframework.boot</groupId> 7 <artifactId>spring-boot-starter-cache</artifactId> 8 </dependency> 9 <dependency> 10 <groupId>org.springframework.boot</groupId> 11 <artifactId>spring-boot-starter-web</artifactId> 12 </dependency> 13 <dependency> 14 <groupId>com.alibaba</groupId> 15 <artifactId>druid</artifactId> 16 <version>1.1.18</version> 17 </dependency> 18 19 <dependency> 20 <groupId>org.projectlombok</groupId> 21 <artifactId>lombok</artifactId> 22 <optional>true</optional> 23 </dependency> 24 25 <dependency> 26 <groupId>com.baomidou</groupId> 27 <artifactId>mybatis-plus-boot-starter</artifactId> 28 <version>3.2.0</version> 29 </dependency> 30 31 <dependency> 32 <groupId>org.springframework.boot</groupId> 33 <artifactId>spring-boot-starter-data-redis</artifactId> 34 </dependency> 35 36 <dependency> 37 <groupId>com.alibaba</groupId> 38 <artifactId>fastjson</artifactId> 39 <version>1.2.33</version> 40 </dependency> 41 42 <dependency> 43 <groupId>com.oracle</groupId> 44 <artifactId>ojdbc8</artifactId> 45 <version>12.2.0.1.0</version> 46 </dependency>
启动类加上注解
1 /* 整合redis作为缓存 2 * Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 3 * 1、安装redis:使用docker; 4 * 2、引入redis的starter 5 * 3、配置redis 6 * 4、测试缓存 7 * 原理:CacheManager===Cache 缓存组件来实际给缓存中存取数据 8 * 1)、引入redis的starter,容器中保存的是 RedisCacheManager; 9 * 2)、RedisCacheManager 帮我们创建 RedisCache 来作为缓存组件;RedisCache通过操作redis缓存数据的 10 * 3)、默认保存数据 k-v 都是Object;利用序列化保存;如何保存为json 11 * 1、引入了redis的starter,cacheManager变为 RedisCacheManager; 12 * 2、默认创建的 RedisCacheManager 操作redis的时候使用的是 RedisTemplate<Object, Object> 13 * 3、RedisTemplate<Object, Object> 是 默认使用jdk的序列化机制 14 * 4)、自定义CacheManager; 15 * 16 */ 17 @MapperScan("com.topcheer.*.*.dao") 18 @SpringBootApplication 19 @EnableCaching //开启缓存 20 public class Oss6Application { 21 22 public static void main(String[] args) { 23 SpringApplication.run(Oss6Application.class, args); 24 } 25 26 }
Web层
1 /** 2 * @author WGR 3 * @create 2019/9/7 -- 15:14 4 */ 5 6 @RestController 7 @RequestMapping("/sys/user") 8 @Slf4j 9 public class UserController { 10 11 @Autowired 12 UserService userService; 13 14 //根据主键查询 15 @GetMapping("/findById") 16 public R findById(Integer id) { 17 return userService.findById(id); 18 } 19 20 21 }
Service层
/** * @author WGR * @create 2019/9/7 -- 15:14 */ @Service public class UserService { @Autowired(required = false) UserMapper userMapper; /** * 缓存的数据能存入redis; * 第二次从缓存中查询就不能反序列化回来; * 存的是dept的json数据;CacheManager默认使用RedisTemplate<Object, Employee>操作Redis * * * @param id * @return */ @Cacheable(cacheNames = "user",key="#root.methodName+'['+#id+'}'") public R findById(Integer id) { return R.ok().addData( userMapper.selectById(id) ); } }
注解JSR107缓存说明(当pom加入redis时,生效的是RedisCacheConfiguration)
将方法的运行结果进行缓存;以后再要相同的数据,直接从缓存中获取,不用调用方法;
CacheManager管理多个Cache组件的,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字;
1 原理: 2 1、自动配置类;CacheAutoConfiguration 3 2、缓存的配置类 4 org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration 5 org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration 6 org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration 7 org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration 8 org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration 9 org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration 10 org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration 11 org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration 12 org.springframework.boot.autoconfigure.cache.GuavaCacheConfiguration 13 org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration【默认】 14 org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration 15 3、哪个配置类默认生效:SimpleCacheConfiguration; 16 17 4、给容器中注册了一个CacheManager:ConcurrentMapCacheManager 18 5、可以获取和创建ConcurrentMapCache类型的缓存组件;他的作用将数据保存在ConcurrentMap中; 19 20 运行流程: 21 @Cacheable: 22 1、方法运行之前,先去查询Cache(缓存组件),按照cacheNames指定的名字获取; 23 (CacheManager先获取相应的缓存),第一次获取缓存如果没有Cache组件会自动创建。 24 2、去Cache中查找缓存的内容,使用一个key,默认就是方法的参数; 25 key是按照某种策略生成的;默认是使用keyGenerator生成的,默认使用SimpleKeyGenerator生成key; 26 SimpleKeyGenerator生成key的默认策略; 27 如果没有参数;key=new SimpleKey(); 28 如果有一个参数:key=参数的值 29 如果有多个参数:key=new SimpleKey(params); 30 3、没有查到缓存就调用目标方法; 31 4、将目标方法返回的结果,放进缓存中 32 33 @Cacheable标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存, 34 如果没有就运行方法并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据; 35 36 核心: 37 1)、使用CacheManager【ConcurrentMapCacheManager】按照名字得到Cache【ConcurrentMapCache】组件 38 2)、key使用keyGenerator生成的,默认是SimpleKeyGenerator 39 40 41 几个属性: 42 cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存; 43 44 key:缓存数据使用的key;可以用它来指定。默认是使用方法参数的值 1-方法的返回值 45 编写SpEL; #i d;参数id的值 #a0 #p0 #root.args[0] 46 getEmp[2] 47 48 keyGenerator:key的生成器;可以自己指定key的生成器的组件id 49 key/keyGenerator:二选一使用; 50 51 52 cacheManager:指定缓存管理器;或者cacheResolver指定获取解析器 53 54 condition:指定符合条件的情况下才缓存; 55 ,condition = "#id>0" 56 condition = "#a0>1":第一个参数的值》1的时候才进行缓存 57 58 unless:否定缓存;当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断 59 unless = "#result == null" 60 unless = "#a0==2":如果第一个参数的值是2,结果不缓存; 61 sync:是否使用异步模式
Dao层
1 /** 2 * @author WGR 3 * @create 2019/9/7 -- 15:10 4 */ 5 public interface UserMapper extends OssMapper<User> { 6 }
Bo类
1 @AllArgsConstructor 2 @NoArgsConstructor 3 @Data 4 @TableName("Z010_USER") 5 @KeySequence(value="SEQ_Z010_USER",clazz=Integer.class) 6 public class User implements Serializable{ 7 8 private static final long serialVersionUID = 1L; 9 10 @TableId 11 private Integer id; // 主键 12 private String account; // 账号,唯一,可供登录(同时作为密码的盐值) 13 private String name; // 姓名 14 @JSONField(serialize=false) 15 private String password; // 密码,MD5盐值加密 16 @Code 17 private String gender; // 性别,字典 18 private Date birthday; // 出生日期 19 @Code 20 private String certType; // 证件类型,字典 21 private String certNumber; // 证件号码 22 private String telNumber; // 固定电话 23 private String mobNumber; // 手机号码 24 private String faxNumber; // 传真号码 25 private String email; // 电子邮件,唯一,可供登录 26 private String empId; // 工号,唯一,可供登录 27 @Code 28 private String position; // 职位 29 private Integer managerId; // 直属上级 20180417 30 @JSONField(format="yyyy-MM-dd") 31 private Date loginLastTime; // 最后登录时间 32 private Integer loginSuccessCount; // 登录成功次数(成功登录时+1) 33 private String passwordStatus; // 密码状态,0-临时密码 1-永久密码(临时密码登录提示修改密码) 34 private Integer passwordTryCount; // 密码尝试次数(错误累计,成功登录清零) 35 @JSONField(format="yyyy-MM-dd") 36 private Date passwordTryLastTime; // 密码最后尝试时间 37 @JSONField(format="yyyy-MM-dd") 38 private Date passwordExpiryDate; // 密码过期日期(密码即将过期提示, 已经过期强制修改密码) 39 private String wxOpenid; // 微信公众号openId 40 41 private String headPic; // 用户头像 42 43 private String createUser; // 创建人员 44 @JSONField(format="yyyy-MM-dd") 45 private Date createTime; // 创建时间 46 private String modifyUser; // 修改人员 47 @JSONField(format="yyyy-MM-dd") 48 private Date modifyTime; // 修改时间 49 @Code 50 private String status; // 状态, 0-禁用 1-启用 51 @TableLogic 52 @JSONField(serialize=false) 53 private String delFlag; // 数据删除标记, 0-已删除 1-有效 54 private String remark; // 备注 55 56 @TableField(exist=false) 57 private String permType; // 权限类型 58 59 60 }
1 /** 2 * @author WGR 3 * @create 2019/10/10 -- 23:47 4 */ 5 public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> { 6 7 public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 8 9 private Class<T> clazz; 10 11 static { //开启白名单,不能序列化的时候会报错 12 ParserConfig.getGlobalInstance().addAccept("com.topcheer.oss."); 13 } 14 15 public FastJson2JsonRedisSerializer(Class<T> clazz) { 16 super(); 17 this.clazz = clazz; 18 } 19 20 public byte[] serialize(T t) throws SerializationException { 21 if (t == null) { 22 return new byte[0]; 23 } 24 return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); 25 } 26 27 public T deserialize(byte[] bytes) throws SerializationException { 28 if (bytes == null || bytes.length <= 0) { 29 return null; 30 } 31 String str = new String(bytes, DEFAULT_CHARSET); 32 return (T) JSON.parseObject(str, clazz); 33 } 34 35 } 36 /** 37 * @author WGR 38 * @create 2019/10/10 -- 23:33 39 */ 40 @Configuration 41 public class RedisConfig extends CachingConfigurerSupport { 42 43 @Bean("redisCacheManager") 44 @Primary 45 public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { 46 //初始化一个RedisCacheWriter 47 RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); 48 FastJson2JsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJson2JsonRedisSerializer<>(Object.class); 49 RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer); 50 RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); 51 //设置过期时间 30天 52 defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofDays(30)); 53 //初始化RedisCacheManager 54 RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig); 55 56 ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 57 // ParserConfig.getGlobalInstance().addAccept("com.topcheer.oss."); 58 return cacheManager; 59 } 60 61 @Bean(name = "redisTemplate") 62 @SuppressWarnings("unchecked") 63 @ConditionalOnMissingBean(name = "redisTemplate") 64 public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { 65 RedisTemplate<Object, Object> template = new RedisTemplate<>(); 66 //使用fastjson序列化 67 FastJson2JsonRedisSerializer fastJsonRedisSerializer = new FastJson2JsonRedisSerializer(Object.class); 68 // value值的序列化采用fastJsonRedisSerializer 69 template.setValueSerializer(fastJsonRedisSerializer); 70 template.setHashValueSerializer(fastJsonRedisSerializer); 71 // key的序列化采用StringRedisSerializer 72 template.setKeySerializer(new StringRedisSerializer()); 73 template.setHashKeySerializer(new StringRedisSerializer()); 74 template.setConnectionFactory(redisConnectionFactory); 75 return template; 76 } 77 78 } 79
结果: