Spring Cache y EhCache realizan la gestión de caché

1. Conozca Spring Cache

Spring Cache es un conjunto de soluciones de almacenamiento en caché proporcionadas por Spring. No proporciona implementación de caché en sí, pero proporciona una interfaz unificada y especificaciones de código, configuración, anotaciones, etc., para integrar varias soluciones de caché, de modo que los usuarios no tengan que preocuparse por los detalles de Cache.

Spring admite la adición "transparente" de un caché a la aplicación, aplicando el caché al método y verificando si hay datos disponibles en el caché antes de que se ejecute el método. Esto puede reducir el número de ejecuciones de métodos y aumentar la velocidad de respuesta. La aplicación de la caché es "transparente" y no causará ninguna interferencia a la persona que llama. Siempre que el soporte de almacenamiento en caché esté habilitado a través de la anotación @EnableCaching, Spring Boot manejará automáticamente la configuración básica de la caché.

Spring Cache actúa sobre los métodos. Cuando se llama a un método de caché, los parámetros del método y el resultado devuelto se almacenarán en el caché como una "clave / valor" (clave / valor), y el método ya no se ejecutará cuando se llame al método con los mismos parámetros. la próxima vez. En su lugar, obtenga el resultado directamente del caché y devuélvalo. Por lo tanto, al usar Spring Cache, debe asegurarse de que se devuelvan los mismos resultados cuando el método almacenado en caché y los parámetros del método son los mismos.

Las anotaciones de caché declarativas proporcionadas por Spring Boot son las siguientes:

anotación Descripción
@EnableCaching Activa el almacenamiento en caché.
@Cacheable Se puede utilizar en clases y métodos para almacenar en caché los valores de retorno de clases o métodos en forma de pares clave-valor.
@CachePut Se llama al método y el resultado se almacena en caché.
@CacheEvict Vaciar el caché.
@Caching Se utiliza para combinar varias etiquetas de anotación.

Uso detallado de anotaciones de caché declarativas: "Spring usa Cache e integra Ehcache"

 

2. Conozca EhCache

Spring Boot admite muchos productos de almacenamiento en caché diferentes. La caché simple se usa de forma predeterminada y no se recomienda usarla en un entorno formal. Podemos configurar algunos cachés más potentes, como Ehcache.

Ehcache es un caché distribuido de Java de código abierto ampliamente utilizado. Tiene características tales como almacenamiento de memoria y disco, cargador de caché, extensión de caché, manejo de excepciones de caché, caché GZIP, filtro de servlet y soporte para API REST y SOAP.

 

3. Cree un proyecto de integración entre SpringBoot y MyBatis

[Ejemplo] Cree un proyecto de integración de SpringBoot y MyBatis para realizar las funciones de consultar, agregar, modificar y eliminar información del usuario. Y use Spring Cache y EhCache para lograr la administración de caché, los resultados de la ejecución son los siguientes:

3.1 Crear una tabla de datos

Cree una tabla de información de usuario (tb_user) en la base de datos MySQL y agregue datos.

-- 判断数据表是否存在,存在则删除
DROP TABLE IF EXISTS tb_user;
 
-- 创建“用户信息”数据表
CREATE TABLE IF NOT EXISTS tb_user
( 
	user_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',
	user_name VARCHAR(50) NOT NULL COMMENT '用户姓名',
	age INT DEFAULT(0) NOT NULL COMMENT '年龄',
	blog_url VARCHAR(50) NOT NULL COMMENT '博客地址',
	blog_remark VARCHAR(50) COMMENT '博客信息'
) COMMENT = '用户信息表';
 
-- 添加数据
INSERT INTO tb_user(user_name,age,blog_url,blog_remark) VALUES('pan_junbiao的博客',32,'https://blog.csdn.net/pan_junbiao','您好,欢迎访问 pan_junbiao的博客');

3.2 Crear un proyecto 

(1) Cree un proyecto SpringBoot, la estructura del proyecto es la siguiente:

(2) Agregar información de configuración pom.xml

Agregue MyBatis, controlador de base de datos MySQL JDBC, iniciador de soporte de caché Spring Boot, caché Ehcache, etc. en el archivo de configuración pom.xml.

<!-- MyBatis与SpringBoot整合依赖 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>

<!-- MySQL的JDBC数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.20</version>
</dependency>

<!-- 引入Thymeleaf模板引擎 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- Spring Boot缓存支持启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.3.2.RELEASE</version>
</dependency>

<!-- Ehcache缓存管理器 -->
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

(3) Información relacionada con la configuración

Modifique el sufijo del archivo application.properties predeterminado a ".yml", es decir, el nombre del archivo de configuración es: application.yml, y configure la siguiente información:

#Spring配置
spring:
  #缓存管理器
  cache:
    type: ehcache
    ehcache:
      config: classpath:ehcache.xml #缓存加载配置文件
  #使用Thymeleaf模板引擎
  thymeleaf:
    mode: HTML5
    encoding: UTF-8
    cache: false  #使用Thymeleaf模板引擎,关闭缓存
    servlet:
      content-type: text/html
  #DataSource数据源
  datasource:
    url: jdbc:mysql://localhost:3306/db_admin?useSSL=false&amp
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

#MyBatis配置
mybatis:
  type-aliases-package: com.pjb.entity #别名定义
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #指定 MyBatis 所用日志的具体实现,未指定时将自动查找
    map-underscore-to-camel-case: true #开启自动驼峰命名规则(camel case)映射
    lazy-loading-enabled: true #开启延时加载开关
    aggressive-lazy-loading: false #将积极加载改为消极加载(即按需加载),默认值就是false
    #lazy-load-trigger-methods: "" #阻挡不相干的操作触发,实现懒加载
    cache-enabled: true #打开全局缓存开关(二级环境),默认值就是true

 

4. Configurar el administrador de caché de EhCache

4.1 Crear archivo de configuración ehcache.xml

En los recursos (directorio de recursos), cree el archivo de configuración ehcache.xml, la información de configuración es la siguiente:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

    <!-- 这个是磁盘存储路径,当内存缓存满了的时候,就会往这里面放,
      java.io.tmdir是操作系统缓存的临时目录,不同操作系统缓存目录不一样 -->
    <diskStore path="java.io.tmpdir"/>

    <!--defaultCache:echcache的默认缓存策略  -->
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>
    <cache name="userCache"
           maxElementsInMemory="10000"
           eternal="false"
           timeToIdleSeconds="120"
           timeToLiveSeconds="120"
           maxElementsOnDisk="10000000"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </cache>
</ehcache>

Descripción del atributo de configuración: 

Atributos Descripción
<diskStore path = "java.io.tmpdir" /> Esta es la ruta de almacenamiento en disco. Cuando la memoria caché está llena, se colocará en ella. Java.io.tmdir es el directorio temporal de la memoria caché del sistema operativo. El directorio de la memoria caché de los diferentes sistemas operativos es diferente.
maxElementsInMemory El número máximo de elementos que se pueden almacenar en la memoria caché. Si los elementos colocados en la caché exceden este valor, existen las siguientes dos situaciones:
(1) Si overflowToDisk = true, los elementos adicionales en la caché se colocarán en el archivo de disco.
(2) Si overflowToDisk = false, reemplace los elementos originales en la caché de acuerdo con la estrategia memoryStoreEvictionPolicy.
overflowToDisk Si se habilita el almacenamiento en caché del disco cuando la memoria es insuficiente.
eterno Si los objetos de la caché son válidos de forma permanente.
timeToIdleSeconds El tiempo de inactividad permitido (unidad: segundo) de los datos almacenados en caché antes de la invalidación. Solo se usa cuando eterno = falso. El valor predeterminado es 0, lo que significa que el tiempo de inactividad es infinito. Si no se accede a ningún elemento de la caché durante más de este tiempo , entonces este elemento se borrará de la caché.
timeToLiveSeconds El tiempo de supervivencia total de los datos almacenados en caché (unidad: segundo), solo se usa cuando es eterno = falso, comienza desde la creación y termina con la invalidación.
maxElementsOnDisk El número máximo de elementos que se pueden almacenar en la caché del disco, 0 significa infinito.
diskExpiryThreadIntervalSeconds El intervalo de ejecución del subproceso de limpieza de la memoria caché del disco es de 120 segundos de forma predeterminada.
memoryStoreEvictionPolicy Estrategia de liberación y almacenamiento de memoria, es decir, cuando se alcanza el límite de maxElementsInMemory, Ehcache limpiará la memoria de acuerdo con la estrategia especificada. Hay tres estrategias: LRU (menos recientemente usada), LFU (más comúnmente usada) y FIFO ( primero en entrar primero en salir).
defaultCache El método de almacenamiento en caché predeterminado.
cache Método de caché personalizado, establezca el nombre usted mismo.

4.2 Configurar el administrador de caché

Configure el administrador de caché de destino en el archivo de configuración application.yml para admitir Ehcache, Generic, Redis, Jcache, etc. Esta configuración usa Ehcache.

#Spring配置
spring:
  #缓存管理器
  cache:
    type: ehcache
    ehcache:
      config: classpath:ehcache.xml #缓存加载配置文件

4.3 Activar la función de caché

Agregue la anotación @EnableCaching a la clase de entrada de inicio del proyecto SpringBoot para habilitar la función de almacenamiento en caché.

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

@SpringBootApplication
@EnableCaching
public class SpringcacheDemoApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(SpringcacheDemoApplication.class, args);
    }
}

 

5. Use EhCache para implementar la administración de caché

5.1 Crear una clase de entidad (capa de entidad)

En el paquete com.pjb.entity, cree una clase UserInfo (clase de entidad de información del usuario).

package com.pjb.entity;

import java.io.Serializable;

/**
 * 用户信息实体类
 * @author pan_junbiao
 **/
public class UserInfo implements Serializable
{
    private int userId; //用户编号
    private String userName; //用户姓名
    private int age; //年龄
    private String blogUrl; //博客地址
    private String blogRemark; //博客信息

    //省略getter与setter方法...
}

Nota: La clase de entidad debe implementar la interfaz serializable; de ​​lo contrario, la función de caché no se puede implementar.

5.2 Capa de mapeo de la base de datos (capa de mapeador)

En el paquete com.pjb.mapper, cree la interfaz UserMapper (interfaz de proxy dinámico Mapper de información de usuario).

package com.pjb.mapper;

import com.pjb.entity.UserInfo;
import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Repository;

/**
 * 用户信息Mapper动态代理接口
 * @author pan_junbiao
 **/
@Mapper
@Repository
public interface UserMapper
{
    /**
     * 根据用户ID,获取用户信息
     */
    @Select("SELECT * FROM tb_user WHERE user_id = #{userId}")
    public UserInfo getUserById(int userId);

    /**
     * 新增用户,并获取自增主键
     */
    @Insert("INSERT INTO tb_user(user_name,age,blog_url,blog_remark) VALUES(#{userName},#{age},#{blogUrl},#{blogRemark});")
    @Options(useGeneratedKeys = true, keyColumn = "user_id", keyProperty = "userId")
    public int insertUser(UserInfo userInfo);

    /**
     * 修改用户
     */
    @Update("UPDATE tb_user SET user_name = #{userName} ,age = #{age} ,blog_url = #{blogUrl} ,blog_remark = #{blogRemark} WHERE user_id = #{userId}")
    public int updateUser(UserInfo userInfo);

    /**
     * 删除用户
     */
    @Delete("DELETE FROM tb_user WHERE user_id = #{userId}")
    public int deleteUser(int userId);
}

5.3 Capa de lógica empresarial (capa de servicio)

Cree la interfaz UserService (interfaz de lógica empresarial de información de usuario) en el paquete com.pjb.service.

package com.pjb.service;

import com.pjb.entity.UserInfo;

/**
 * 用户信息业务逻辑接口
 * @author pan_junbiao
 **/
public interface UserService
{
    /**
     * 根据用户ID,获取用户信息
     */
    public UserInfo getUserById(int userId);

    /**
     * 新增用户,并获取自增主键
     */
    public UserInfo insertUser(UserInfo userInfo);

    /**
     * 修改用户
     */
    public UserInfo updateUser(UserInfo userInfo);

    /**
     * 删除用户
     */
    public int deleteUser(int userId);
}

En el paquete com.pjb.service.impl, cree la clase UserServiceImpl (clase de lógica empresarial de información de usuario).

package com.pjb.service.impl;

import com.pjb.entity.UserInfo;
import com.pjb.mapper.UserMapper;
import com.pjb.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * 用户信息业务逻辑类
 * @author pan_junbiao
 **/
//注意:必须对应配置文件ehcache.xml中cache节点的name属性值
//@CacheConfig(cacheNames = "userCache")
@Service
public class UserServiceImpl implements UserService
{
    @Autowired
    private UserMapper userMapper;

    //注意:必须对应配置文件ehcache.xml中cache节点的name属性值
    private static final String CACHE_NAME = "userCache";

    /**
     * 根据用户ID,获取用户信息
     */
    @Override
    @Cacheable(value = CACHE_NAME, key = "#userId")
    public UserInfo getUserById(int userId)
    {
        return userMapper.getUserById(userId);
    }

    /**
     * 新增用户,并获取自增主键
     */
    @Override
    @CachePut(value = CACHE_NAME, key = "#userInfo.userId")
    public UserInfo insertUser(UserInfo userInfo)
    {
        userMapper.insertUser(userInfo);
        return userInfo;
    }

    /**
     * 修改用户
     */
    @Override
    @CachePut(value = CACHE_NAME, key = "#userInfo.userId")
    public UserInfo updateUser(UserInfo userInfo)
    {
        userMapper.updateUser(userInfo);
        return userInfo;
    }

    /**
     * 删除用户
     */
    @Override
    @CacheEvict(value = CACHE_NAME, key = "#userId")
    public int deleteUser(int userId)
    {
        return userMapper.deleteUser(userId);
    }
}

Como se puede ver en el código anterior, el método de consultar a los usuarios usa la anotación @Cacheable para habilitar el almacenamiento en caché. Para agregar y modificar métodos, se usa la anotación @CachePut, que primero procesa el método y luego almacena en caché el resultado. Para eliminar datos, debe usar la anotación @CacheEvict para borrar el caché.

Anotación @CacheConfig: Si todo @Cacheable () tiene un atributo value = "xxx", obviamente es agotador escribir si hay más métodos, si puede declararlo todo a la vez, se ahorrará problemas, por lo que existe With @ CacheConfig esta configuración, @CacheConfig es una anotación a nivel de clase que permite compartir los nombres de la caché. Si escribe otro nombre en el método, prevalecerá el nombre del método.

5.4 Método de controlador (capa de controlador)

En el paquete com.pjb.controller, cree la clase UserController (controlador de usuario) para realizar la consulta, adición, modificación y eliminación de datos de usuario y realizar la devolución de datos.

package com.pjb.controller;

import com.pjb.entity.UserInfo;
import com.pjb.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

/**
 * 用户信息控制器
 * @author pan_junbiao
 **/
@Controller
@RequestMapping("/user")
public class UserController
{
    @Autowired
    private UserService userService;

    /**
     * 获取用户信息
     */
    @RequestMapping("getUserById")
    public ModelAndView getUserById(int userId)
    {
        //根据用户ID,获取用户信息
        UserInfo userInfo = userService.getUserById(userId);

        if(userInfo==null)
        {
            userInfo = new UserInfo();
        }

        //返回结果
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("userInfo",userInfo);
        modelAndView.setViewName("/user-info.html");
        return modelAndView;
    }

    /**
     * 新增用户
     */
    @ResponseBody
    @RequestMapping("insertUser")
    public boolean insertUser()
    {
        //创建新用户
        UserInfo userInfo = new UserInfo();
        userInfo.setUserName("pan_junbiao的博客");
        userInfo.setAge(32);
        userInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao");
        userInfo.setBlogRemark("您好,欢迎访问 pan_junbiao的博客");

        //执行新增方法
        userService.insertUser(userInfo);

        //返回结果
        return userInfo.getUserId() > 0 ? true : false;
    }

    /**
     * 修改用户
     */
    @ResponseBody
    @RequestMapping("updateUser")
    public boolean updateUser(int userId)
    {
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(userId);
        userInfo.setUserName("pan_junbiao的博客_02");
        userInfo.setAge(35);
        userInfo.setBlogUrl("https://blog.csdn.net/pan_junbiao");
        userInfo.setBlogRemark("您好,欢迎访问 pan_junbiao的博客");

        //执行修改方法
        userService.updateUser(userInfo);

        //返回结果
        return true;
    }

    /**
     * 删除用户
     */
    @ResponseBody
    @RequestMapping("deleteUser")
    public boolean deleteUser(int userId)
    {
        //执行新增方法
        int result = userService.deleteUser(userId);

        //返回结果
        return result > 0 ? true : false;
    }
}

5.5 Página de visualización (capa de visualización)

Cree una página de visualización de información de usuario user-info.html en el directorio resources / templates.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户信息</title>
    <meta name="author" content="pan_junbiao的博客">
    <style>
        table { border-collapse: collapse; margin-bottom: 10px}
        table,table tr th, table tr td { border:1px solid #000000; padding: 5px 10px;}
    </style>
</head>
<body>

<div align="center">
    <table>
        <caption>用户信息</caption>
        <tr>
            <th>用户ID:</th>
            <td th:text="${userInfo.userId}"></td>
        </tr>
        <tr>
            <th>用户名称:</th>
            <td th:text="${userInfo.userName}"></td>
        </tr>
        <tr>
            <th>年龄:</th>
            <td th:text="${userInfo.age}"></td>
        </tr>
        <tr>
            <th>博客地址:</th>
            <td th:text="${userInfo.blogUrl}"></td>
        </tr>
        <tr>
            <th>备注信息:</th>
            <td th:text="${userInfo.blogRemark}"></td>
        </tr>
    </table>
</div>
</body>
</html>

Hasta el momento, el proyecto se ha escrito y el resultado de la ejecución es el siguiente:

Luego, ejecute otros métodos del proyecto y luego visite la URL del método de consulta varias veces para experimentar el efecto de caché. La observación principal es si la base de datos ha sido operada, si la base de datos no tiene datos de operación y devuelve datos normalmente, significa que la caché es exitosa.

 

Supongo que te gusta

Origin blog.csdn.net/pan_junbiao/article/details/107999734
Recomendado
Clasificación