2020.03.17 springboot缓存相关

出自尚硅谷雷峰阳老师讲解的Spring Boot整合篇,地址:

http://www.atguigu.com/download_detail.shtml?v=38

1、JSR107规范

CachingProvider【管理CacheManager】、CacheManager【管理Cache】、Cache【一个cache仅被一个CacheManager管理】、Entry【一个个缓存的内容】、Expiry【有效期】
2、Spring的缓存抽象
注意两点:
①确定方法需要被缓存以及他们的缓存策略    
②从缓存中读取之前缓存存储的数据
缓存注解及作用:
@EnableCaching:开启基于注解的缓存
@Cacheable:主要针对方法配置,能够根据方法的请求参数对其结果进行缓存【主要用于查询】
@CachePut:保证方法被调用,又希望结果被缓存。【主要用于修改】
@CacheEvict:清空缓存【主要用于删除】
SPEL表达式:
名字
位置
描述
示例
methodName 
root object 当前被调用的方法名 #root.methodName
result 
evaluation context
方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,’cache put’的表达式 ’cache evict’的表达式beforeInvocation=false) 
#result 
argument name
evaluation context 
方法参数的名字. 可以直接 #参数名 ,也可以使用 #p0或#a0 的形式,0代表参数的索引; 
#iban 、 #a0 、 #p0

3、缓存使用

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>1.5.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.study.springboot</groupId>
    <artifactId>cache-study</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cache-study</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- 缓存相关 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 数据库相关 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>

        <!-- mybatis和springboot整合 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.0</version>
        </dependency>

        <!-- 数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.16</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>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

主启动类:

package com.study.springboot.cache;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class CacheStudyApplication {

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

}

yml文件:

server:
  port: 8001
  tomcat:
    uri-encoding: UTF-8
spring:
  application:
    name: springboot-cache
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot-cache?useUnicode=true&characterEncoding-utf-8&useSSL=false&serverTimezone=UTC #需要加时区
    username: root
    password: 自己的密码
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
#   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

  http:
    encoding:
      charset: utf-8
      force: true
      enabled: true
  redis:
    host: 192.168.213.128#自己的redis主机
mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities
  configuration:
    map-underscore-to-camel-case: true

  

controller:

package com.study.springboot.cache.controller;

import com.study.springboot.cache.entity.Employee;
import com.study.springboot.cache.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class EmpController {

    @Autowired
    private EmployeeService employeeService;


    @GetMapping("/emp/{id}")
    public Employee getEmpById(@PathVariable("id") Integer id){
        return employeeService.queryById(id);
    }
}

------------------------------------------------------------------------------
 
package com.study.springboot.cache.controller;


import com.study.springboot.cache.entity.Department;
import com.study.springboot.cache.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class DepartmentController {

@Autowired
private DepartmentService departmentService;

@GetMapping("/dept/{id}")
public Department getDeptById(@PathVariable("id") Integer id){
return departmentService.getDeptById(id);
}
}
 

service

package com.study.springboot.cache.service;

import com.study.springboot.cache.entity.Employee;
import com.study.springboot.cache.mapper.EmployeeMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;


    @Caching(
            cacheable = @Cacheable(value="emp",cacheManager = "employmentRedisCacheManager")
    )
    public Employee queryById(Integer id){
        log.info("查询id为:"+id+"数据");
        return employeeMapper.selectEmp(id);
    }
}

------------------------------------------------------------------------------
package com.study.springboot.cache.mapper;


import com.study.springboot.cache.entity.Department;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface DepartmentMapper {

public Department selectDeptById(@Param("id") Integer id);
}
 

mapper:

package com.study.springboot.cache.mapper;

import com.study.springboot.cache.entity.Employee;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface EmployeeMapper {

    //根据id查询
    public Employee selectEmp(@Param("id") Integer id);

    //修改
    public void updateEmp(Employee employee);

}

------------------------------------------------------------------------------

package com.study.springboot.cache.mapper;


import com.study.springboot.cache.entity.Department;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface DepartmentMapper {

public Department selectDeptById(@Param("id") Integer id);
}
 

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.springboot.cache.mapper.EmployeeMapper">



    <!--public Employee selectEmp(@Param("id") Integer id);-->
    <select id="selectEmp" parameterType="Integer" resultMap="BaseResultMap">
        select * from employee where id = #{id}
    </select>

    <!-- public void updateEmp(Employee employee); -->
    <update id="updateEmp" parameterType="com.study.springboot.cache.entity.Employee">
        update employee set
        lastName = #{lastName},
        email = #{email},
        gender = #{gender},
        d_id = #{dId}
        where
        id = #{id}
    </update>

    <resultMap id="BaseResultMap" type="com.study.springboot.cache.entity.Employee" autoMapping="true">

    </resultMap>
    
</mapper>

------------------------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.springboot.cache.mapper.DepartmentMapper">



<!--public Department selectDeptById(@Param("id") Integer id);-->
<select id="selectDeptById" parameterType="Integer" resultMap="BaseResultMap">
select * from department where id = #{id}
</select>

<resultMap id="BaseResultMap" type="com.study.springboot.cache.entity.Department" autoMapping="true">

</resultMap>

</mapper>

只有springboot版本为1.xx时才能自定义,版本为2.xx时没找到对应的构造函数 个人观点【没找到对应的构造函数】

自定义缓存管理器时注意别写get

 1 import com.study.springboot.cache.entity.Department;
 2 import com.study.springboot.cache.entity.Employee;
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.context.annotation.Primary;
 6 import org.springframework.data.redis.cache.RedisCacheManager;
 7 import org.springframework.data.redis.connection.RedisConnectionFactory;
 8 import org.springframework.data.redis.core.RedisTemplate;
 9 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
10 
11 import java.net.UnknownHostException;
12 
13 
14 @Configuration
15 public class MyRedisConfig {
16 
17 
18     @Bean
19     public RedisTemplate<Object,Employee> getEmployeeRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
20         RedisTemplate<Object,Employee> template = new RedisTemplate<Object,Employee>();
21         template.setConnectionFactory(redisConnectionFactory);
22         //自己配置序列化器
23         Jackson2JsonRedisSerializer<Employee> serializer = new Jackson2JsonRedisSerializer<Employee>(Employee.class);
24         template.setDefaultSerializer(serializer);
25         return template;
26     }
27 
28     @Bean
29     public RedisTemplate<Object,Department> getDepartmentRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
30         RedisTemplate<Object,Department> template = new RedisTemplate<Object,Department>();
31         template.setConnectionFactory(redisConnectionFactory);
32         //自己配置序列化器
33         Jackson2JsonRedisSerializer<Department> serializer = new Jackson2JsonRedisSerializer<Department>(Department.class);
34         template.setDefaultSerializer(serializer);
35         return template;
36     }
37 
38     @Bean
39     public RedisCacheManager employmentRedisCacheManager(RedisTemplate<Object,Employee> employeeRedisTemplate){
40         RedisCacheManager redisCacheManager = new RedisCacheManager(employeeRedisTemplate);
41         redisCacheManager.setUsePrefix(true);
42 
43         return redisCacheManager;
44     }
45 
46     @Primary
47     @Bean
48     public RedisCacheManager departmentRedisCacheManager(RedisTemplate<Object,Department> departmentRedisTemplate){
49         RedisCacheManager redisCacheManager = new RedisCacheManager(departmentRedisTemplate);
50         redisCacheManager.setUsePrefix(true);
51 
52         return redisCacheManager;
53     }
54 }

测试类:

redis命令网址:http://www.redis.cn/commands.html

package com.study.springboot.cache;

import com.study.springboot.cache.entity.Employee;
import com.study.springboot.cache.service.EmployeeService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class CacheStudyApplicationTests {

    @Test
    public void contextLoads() {
    }

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private RedisTemplate<Object,Employee> employeeRedisTemplate;

    @Test
    public void testRedis(){
        ValueOperations<String, String> stringValueOperations = stringRedisTemplate.opsForValue();
        //stringValueOperations.append("msg","hello");

        Employee employee = employeeService.queryById(2);
        //stringValueOperations.append("emp:1",employee.toString());

        employeeRedisTemplate.opsForValue().set("emp:1",employee);

    }

}

建表sql(老师提供的课件中有):

/*
Navicat MySQL Data Transfer

Source Server         : 本地
Source Server Version : 50528
Source Host           : 127.0.0.1:3306
Source Database       : springboot_cache

Target Server Type    : MYSQL
Target Server Version : 50528
File Encoding         : 65001

Date: 2018-04-27 14:54:04
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for department
-- ----------------------------
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `departmentName` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `lastName` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `gender` int(2) DEFAULT NULL,
  `d_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
原文地址:https://www.cnblogs.com/lxw-all/p/12512149.html