使用springboot缓存

1.缓存的作用
1)加速系统的访问,以及提升系统性能;
比如:
    如果商品信息存在数据库中;
    每次访问都要查询数据库,耗时;并且访问量大时,系统压力大;
    可以将这类热点数据存入缓存;
    当访问数据时,先从缓存中找,如果缓存中没有,就从数据库找到并放入缓存方便下次查找;
    使用缓存可以提升性能,因为应用程序和缓存的交互相对较快;
 
2)保存临时数据
比如:
    手机验证之类的临时信息,通常需要在几分钟之内删除;
    如果存入数据库,不划算,影响系统性能;
    可以将这类数据存入缓存;
 
2.JSR-107
缓存的使用非常广泛;
为了统一缓存的开发规范,j2ee发布了JSR-107缓存规范;
 
Java Caching定义了5个核心接口,分别是CachingProvider, CacheManager, Cache, Entry和 Expiry;
    • CachingProvider    ->定义了创建、配置、获取、管理和控制多个CacheManager。一个应用可以在运行期访问多个CachingProvider。
    • CacheManager    ->定义了创建、配置、获取、管理和控制多个唯一命名的Cache,这些Cache存在于CacheManager的上下文中。一个CacheManager仅被一个CachingProvider所拥有。
    • Cache    ->是一个类似Map的数据结构并临时存储以Key为索引的值。一个Cache仅被一个CacheManager所拥有。
    • Entry    ->是一个存储在Cache中的key-value对。
    • Expiry    -> 每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期的状态。一旦过期,条目将不可访问、更新和删除。缓存有效期可以通过ExpiryPolicy设置。
 
应用程序想使用缓存:
    通过缓存提供者CachingProvider得到缓存管理器CacheManager;
    缓存提供者可以管理多个缓存管理器;
    每个缓存管理器管理特定类型的缓存;比如:CacheManager1管理redis缓存、CacheManager2管理memcache缓存;
    缓存管理器用来管理缓存Cache;
    一个缓存管理器管理多个缓存;比如:Cache1用来保存员工数据、Cache2用来缓存部门数据;
    缓存中保存多条数据,每一条数据是一个键值对;
    Cache接口中提供了一些api,用来对数据进行增删改查操作;
 
3.spring缓存抽象
Spring也定义了类似JSR-107类似的缓存抽象和缓存注解;
Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;
 
spirng缓存抽象的核心概念和注解:
CacheManager    ->缓存管理器,可以指定多种缓存管理器,例如:redis、memcache、concurrentHashMap等等;
Cache    ->缓存,一个缓存管理器可以管理多个缓存,缓存中以键值对存放数据;比如:Cache-1专门用来存放员工信息,Cache-2用来存放部门信息等待;
@Cacheable    ->标记查询方法,将查询的结果放入缓存;查询时缓存中有数据就不查数据库了;
@CacheEvit    ->标记删除方法,会在数据库中删除的同时也清除缓存;
@CachePut    ->标记修改方法,会将修改后的数据也更新在缓存上;与@Cacheable不同的是该注解标记的方法即使缓存中有数据也会去查数据库;
 
注解参数:
      
 
注解参数中用到的el表达式:
 
4.使用spring缓存
1)搭建工程
新建一个web工程,这里使用mysql、数据访问使用mybatis;需要引入相关依赖;
 
配置yml:
    配数据源,以及mybatis的配置文件路径
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root
 
mybatis:
  config-location: classpath:mybatis-config.xml     #指定全局配置文件的位置
  mapper-locations: classpath:com/example/demo/dao/mapper/*.xml  #指定sql映射文件的位置
 
实体类:
public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private Integer gender;
    private Integer dId;
 
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public Integer getGender() {
        return gender;
    }
    public void setGender(Integer gender) {
        this.gender = gender;
    }
    public Integer getdId() {
        return dId;
    }
    public void setdId(Integer dId) {
        this.dId = dId;
    }
}
 
数据映射接口:
public interface EmployeeDao {
 
    public Employee get(Integer id);
 
    public void update(Employee employee);
 
    public void delete(Integer id);
    
}
 
为了能扫描到数据映射接口,需要在工程启动类上加注解:
@MapperScan(value = "com.example.demo.dao")
 
数据映射xml文件:
    如果不知道怎么写,可以去github中搜mybatis,然后看说明文档;
<?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.example.demo.dao.EmployeeDao">
  <!--通过id查询-->
  <select id="get" parameterType="java.lang.Integer" resultType="com.example.demo.entity.Employee">
    select * from employee where id = #{id}
  </select>
 
  <!--编辑-->
  <update id="update" parameterType="com.example.demo.entity.Employee">
    UPDATE employee SET
      `lastName` = #{lastName},
      `email` = #{email},
      `gender` = #{gender},
      `d_id` = #{d_id}
    WHERE
      `id` = #{id}
  </update>
 
  <!--删除-->
  <delete id="delete" parameterType="java.lang.Integer">
      DELETE FROM employee WHERE id = #{id}
  </delete>
</mapper>
 
mybatis全局配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <settings>
      <!--配置驼峰命名法与数据库命名法的映射-->
      <setting name="mapUnderscoreToCamelCase" value="true"/>
  </settings>
</configuration>

controller:
@RestController
public class EmployeeController {
    @Autowired(required = false)      //加required=false,防止报红
    private EmployeeDao dao;
 
    @RequestMapping("/get/{id}")
    public Employee get(@PathVariable("id") Integer id){
        return dao.get(id);
    }
    
    @RequestMapping("/del/{id}")
    public void delete(@PathVariable("id") Integer id){
        dao.delete(id);
    }
    
    @RequestMapping("/edit")
    public void edit(@RequestBody Employee emp){
        dao.update(emp);
    }
}
 
踩坑:
    如果mybatis的数据映射xml文件放src/main/java目录下时,可能会漏打包;
    导致的结果是数据库映射接口绑定错误;
解决:
    在pom中的<build>中加一个插件;
<!--防止mybatis的xml不打包-->
<plugin>
  <artifactId>maven-resources-plugin</artifactId>
  <executions>
     <execution>
        <id>copy-xmls</id>
        <phase>process-sources</phase>
        <goals>
           <goal>copy-resources</goal>
        </goals>
        <configuration>
           <outputDirectory>${basedir}/target/classes</outputDirectory>
           <resources>
              <resource>
                 <directory>${basedir}/src/main/java</directory>
                 <includes>
                    <include>**/*.xml</include>
                 </includes>
              </resource>
           </resources>
        </configuration>
     </execution>
  </executions>
</plugin>
不过启动工程时还是可能会漏打包xml文件;
需要在启动工程前手动点maven的package才行;
为了不这么麻烦,还是直接将数据库映射xml放resource目录下可能会好一点;
 
浏览器访问:
    可以正常访问数据库了
 
2)使用缓存
工程搭建好后,接下来使用缓存;
 
在springboot中使用注解式缓存的步骤:
    1】 引入spring-boot-starter-cache模块
    2】 @EnableCaching开启缓存
    3】 使用缓存注解
    4】 切换为其他缓存
 
pom中添加缓存依赖:
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
 
开启基于注解的缓存:
    在工程启动类上加注解@EnableCaching
 
配置yml:
    为了调用数据库映射接口时,sql被打印在控制台
logging:
  level:
    com:
      example:
        demo:
          dao: debug
 
添加缓存注解:
    在数据库映射接口中的查询方法中添加缓存注解@Cacheable
public interface EmployeeDao {
 
    @Cacheable(cacheNames = {"emp"})
    public Employee get(Integer id);
 
    public void update(Employee employee);
 
    public void delete(Integer id);
}
 
测试:
请求controller的查询接口;
第一次请求时,控制台会打印sql,说明请求了数据库;    
清空控制台,再次请求 :
    可以看到没打印sql,说明数据是从缓存中得到的,而不是从数据库;
      
 
 
 
 
posted @ 2020-06-15 10:26  L丶银甲闪闪  阅读(540)  评论(0编辑  收藏  举报