SpringBoot整合Redis(一)

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 }

Fastjosn进行序列化及Redis配置

 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

结果:

 

猜你喜欢

转载自www.cnblogs.com/dalianpai/p/11656441.html