**

springboot缓存

**

**

基本环境的搭建

**

1创建springboot项目,并添加相应的依赖

spring boot 禁止明文cookie_mysql

2.配置yml文件

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
    #redis
   redis:
    host: localhost
    port: 6379
    password: 123456
 

#配置mybatis
mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml    # mapper文件
  type-aliases-package: com.swj.domain    # 别名
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl   #输出sql语句

3.编写实体类+编写mapper接口

public class tbUser{
    private int  id;
    private String name;
    private String pwd;
    private int teaId;
    //get,set省略(或者可以添加lombok)
}
@Mapper //表示这是mybatis的mapper类
@Repository //表示这是dao层
public interface UserMapper {
    //根据id查询用户
    tbUser getUserById(int id);

    int addUser(tbUser user);

    int updateUser(tbUser user);

    int deleteUser(int id);
}

4.编写mapper的配置文件

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.swj.mapper.UserMapper">

    <select id="getUserById" parameterType="int" resultType="tbuser">
   select * from mybatis.tbuser where id= #{id}
    </select>

    <insert id="addUser" parameterType="tbuser">
        insert into mybatis.tbuser (name,pwd,teaId) values  (#{name},#{pwd},#{teaId})

    </insert>

    <update id="updateUser" parameterType="tbuser">
        update mybatis.tbuser set name = #{name} where id = #{id}
    </update>

    <delete id="deleteUser" parameterType="int">
        delete from mybatis.tbuser where id = #{id}
    </delete>
</mapper>

mapper配置文件所在路径

spring boot 禁止明文cookie_java_02

5.编写service层

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public tbUser getUserById(int id) {
        System.out.println("查询了" + id + "号用户");
        return userMapper.getUserById(id);

    }

    public int addUser(tbUser user) {
        return userMapper.addUser(user);
    }
    public int updateUser(tbUser user) {
        return userMapper.updateUser(user);
    }
    public int deleteUser(int id) {
        return userMapper.deleteUser(id);
    }
}

6.编写controller层

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/getUserById/{id}")
    public tbUser getUserById(@PathVariable("id") int id) {
        return userService.getUserById(id);
    }
    @RequestMapping("/addUser")
    public String addUser() {
        tbUser tbUser = new tbUser(31,"阿毛","234",1);
       userService.addUser(tbUser);
       return "ok";
    }

    @RequestMapping("/updateUser")
    public String updateUser() {
        tbUser tbUser = new tbUser(20,"阿刘","456",1);
        userService.updateUser(tbUser);
        return "ok";
    }
    @RequestMapping("/deleteUser/{id}")
    public String deleteUser(@PathVariable("id") int id) {
        userService.deleteUser(id);
        return "ok";
    }
}

7.环境搭建成功,启动项目,测试没有问题即可!

**

添加缓存配置

**

1.在启动类用注解(@EnableCaching)开启缓存

@SpringBootApplication
@EnableCaching //开启基于注解的缓存
public class SpringbootCacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootCacheApplication.class, args);
    }

}

2.在service层中添加注解

@Service
@CacheConfig(cacheNames = "user") //抽取缓存的公共位置
public class UserService {
    @Autowired
    private UserMapper userMapper;

    //将方法的运行结果进入缓存,这样以后再相同的数据直接从缓存中取,不用再调用方法(减少了数据库的交互,提高了效率)
    //属性介绍:
    // cacheNames/value:缓存组件的名称:用来存放该方法返回值的地方,用数组的方式来存储,可以指定多个缓存
    //key:缓存数据用来指定的key,默认key使用方法的参数,或者使用keyGenerator(这个使用在config类中配置),就是key生成器,二选一即可
    //CacheManager:指定从哪个缓存管理器取 或者CacheResolver缓存解析器,两者功能一样
    //Condition:指定符合条件下,才会进行缓存,condition="#id">0 的情况下才会缓存
    //unless:否定缓存,当unless指定的条件时true是就不缓存,可以回去结果进行判断 #result==null;
    //sync:是否使用异步模式
    @Cacheable(key = "#root.methodName+'['+#id+']'")
    public tbUser getUserById(int id) {
        System.out.println("查询了" + id + "号用户");
        return userMapper.getUserById(id);

    }

    public int addUser(tbUser user) {
        return userMapper.addUser(user);
    }

    /**
     * @CachePut 该注解表示及调用方法, 又更新数据库缓存  同步更新缓存
     * 修改某个数据更新缓存
     * 运行时机:
     * 先调用目标方法,然后把方法的结果缓存起来
     * key  要和查询的key保持一致
     */

    @CachePut(key = "#root.methodName+'['+#id+']'")
    public int updateUser(tbUser user) {
        return userMapper.updateUser(user);
    }

    /***
     *@CacheEvict 清除缓存
     * allEntries = true 清除所有缓存
     * beforeInvocation 是否在方法之前执行,默认是false
     */
    @CacheEvict(key = "#root.methodName+'['+#id+']'")
    public int deleteUser(int id) {
        return userMapper.deleteUser(id);
    }
}

3.启动项目测试,以查找为例

3.1在url地址栏上输入:http://localhost:8080/getUserById/2测试

spring boot 禁止明文cookie_数据库_03


测试完后,查看控制台的输出信息

spring boot 禁止明文cookie_java_04


控制台上输出了service方法中的语句,证明调用了service方法,数据是从数据库中取出的,

3.2先把控制台上的信息清空,在url地址栏可以重复多刷新几遍,但是控制台上并没有任何信息,证明我们的数据没有调用数据库,是从缓存中取出的

spring boot 禁止明文cookie_mybatis_05


springboot整合redis缓存(基于springboot缓存的例子继续整合redis)


1.安装redis数据库跟redis的可视化工具

2.安装成功以后,可以去http://www.redis.cn/commands.html这个网站上查看关于redis一些操作的命令

spring boot 禁止明文cookie_java_06


3.去springboot官网上找redis的启动器:https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/html/using-spring-boot.html#using-boot-starter

spring boot 禁止明文cookie_redis_07

pom

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring2.X集成redis所需common-pool2-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.6.0</version>
</dependency>

spring boot 禁止明文cookie_java_08

4.配置yml

继续编写yml配置文件了

```yaml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    username: root
    password: 123456
  redis:
    host: 127.0.0.1

#配置mybatis
mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml    # mapper文件
  type-aliases-package: com.swj.domain    # 别名
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl   #输出sql语句

spring boot 禁止明文cookie_redis_09


spring boot 禁止明文cookie_java_10

5.在test里进行简单的测试,看看基本的redis环境是否搭建成功(这里测试用的stringRedisTemplate来进行测试)

@SpringBootTest
class SpringbootCacheApplicationTests {
    @Autowired
    RedisTemplate redisTemplate;//专门操作key-value都是对象的
    @Autowired
    StringRedisTemplate stringRedisTemplate;//专门操作key-value都是字符串的

    /**
     * redis常见操作的5大类型
     * 1. stringRedisTemplate.opsForValue(字符串);
     * 2. stringRedisTemplate.opsForList(list列表);
     * 3. stringRedisTemplate.opsForSet(set集合);
     * 4.stringRedisTemplate.opsForHash(hash散列);
     * 5.stringRedisTemplate.opsZst(Zst有序集合);
     */
    @Test
    //测试保存字符串
    void test() {
        stringRedisTemplate.opsForValue().append("hello", "swj!");
    }
}

spring boot 禁止明文cookie_java_11


spring boot 禁止明文cookie_mybatis_12

6.stringRedisTemplate测试成功以后,我们在继续测redisTemplate

6.1 添加一个test方法测试redisTemplate

@Autowired
 UserMapper userMapper;

  @Test //测试保存对象
    void test1() throws JsonProcessingException {
        tbUser user = userMapper.getUserById(1);
        //默认如果保存对象,使用jdk序列化机制,序列化后的数据保存到redis中
        redisTemplate.opsForValue().set("user", user);
    }

启动项目,查看测试是否成功,项目启动后,发现报错了,报错原因是因为序列化

spring boot 禁止明文cookie_mybatis_13

6.2将实体类序列化

什么是java的序列化呢?
序列化:将 Java 对象转换成字节流的过程。
反序列化:将字节流转换成 Java 对象的过程。
当 Java 对象需要在网络上传输 或者 持久化存储到文件中时,就需要对 Java 对象进行序列化处理。

序列化的实现:类实现 Serializable 接口,这个接口没有需要实现的方法。实现 Serializable 接口是为了告诉 jvm 这个类的对象可以被序列化。

注意事项:

1.某个类可以被序列化,则其子类也可以被序列化
2.声明为 static 和 transient 的成员变量,不能被序列化。static 成员变量是描述3.类级别的属性,transient 表示临时数据
4.反序列化读取序列化对象的顺序要保持一致

public class tbUser  implements Serializable {
    private int  id;
    private String name;
    private String pwd;
    private int teaId;
}

序列化完以后,我们在继续启动项目,查看是否成功

spring boot 禁止明文cookie_mybatis_14


数据已经存在了redis中,但是却不是我们能够看懂的数据,所以我们选择第二种,让数据变成我们能够看懂的json格式

6.3配置redisConfig类

方式一

@Configuration
public class MyRedisConfig {
    @Bean
    public RedisTemplate<Object, Object> jsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
        template.setConnectionFactory(redisConnectionFactory);
        //解决日期序列化问题
        ObjectMapper om = new ObjectMapper();
        om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om);
        template.setDefaultSerializer(genericJackson2JsonRedisSerializer);
        return template;

    }
}

方式二

@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        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);
        template.setConnectionFactory(factory);
        //key序列化方式
        template.setKeySerializer(redisSerializer);
        //value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }

    @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);
        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
              .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}

配置类完成以后,我们去test里用我们刚刚编写的jsonRedisTemplate继续测试,

@SpringBootTest
class SpringbootCacheApplicationTests {
    @Autowired
    RedisTemplate redisTemplate;//专门操作key-value都是对象的
    @Autowired
    StringRedisTemplate stringRedisTemplate;//专门操作key-value都是字符串的
    @Autowired
    UserMapper userMapper;
    @Autowired
    RedisTemplate jsonRedisTemplate;// 定义jsonRedisTemplate
    @Test
    //测试保存字符串
    void test() {
        stringRedisTemplate.opsForValue().append("hello", "swj!");
    }

    @Test //测试保存对象
    void test1() throws JsonProcessingException {
        tbUser user = userMapper.getUserById(1);
        //默认如果保存对象,使用jdk序列化机制,序列化后的数据保存到redis中
        jsonRedisTemplate.opsForValue().set("user", user);
    }

    @Test
    void contextLoads() {
    }

}

启动项目,其数据库中查看结果

spring boot 禁止明文cookie_java_15

7. 启动项目测试,以查找为例

7.1在url地址栏上输入:http://localhost:8080/getUserById/2测试,

spring boot 禁止明文cookie_java_16


报错原因大概是不能够反序列化

7.2编写RedisCacheManager方法,自定义一些缓存规则

@Configuration
public class MyRedisConfig {
    @Bean
    public RedisTemplate<Object, Object> jsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
        template.setConnectionFactory(redisConnectionFactory);
        //解决日期序列化问题
        ObjectMapper om = new ObjectMapper();
        om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(om);
        template.setDefaultSerializer(genericJackson2JsonRedisSerializer);
        return template;

    }

    @Bean
    //自定义一些缓存规则
    public RedisCacheManager jsonRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
        RedisCacheConfiguration cacheConfiguration =
                RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofDays(1))   // 设置缓存过期时间为一天
                        .disableCachingNullValues()     // 禁用缓存空值,不缓存null校验
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
                                GenericJackson2JsonRedisSerializer()));     // 设置CacheManager的值序列化方式为json序列化,可加入@Class属性
        return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build();     // 设置默认的cache组件
    }
}

7.3在进行测试,并查看网页上的结果,

http://localhost:8080/getUserById/11

spring boot 禁止明文cookie_mysql_17


8.如果在编码中想对缓存进行操作

@Service
@CacheConfig(cacheNames = "user") //抽取缓存的公共位置
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MyRedisConfig myRedisConfig;
    @Autowired
    RedisConnectionFactory redisConnectionFactory;
 
    @Cacheable(key = "#root.methodName+'['+#id+']'")
    public tbUser getUserById(int id) {
        System.out.println("查询了" + id + "号用户");
        Cache user = myRedisConfig.jsonRedisCacheManager(redisConnectionFactory).getCache("user::getUserById[11]").;
        System.out.println("################"+user); //获取了缓存以后,可以对缓存进行操作
        return userMapper.getUserById(id);

    }    
}

spring boot 禁止明文cookie_mysql_18