Публичный аккаунт WeChat: отличная трата времени Если у вас есть какие-либо вопросы или предложения, оставьте сообщение в фоновом режиме, и я сделаю все возможное, чтобы решить вашу проблему.
предисловие
Если это, сегодня введен тайнобот в кеш данных. Знал, что разработка программы состоит в том, что узкое место базы данных, мы также знаем, что скорость памяти намного быстрее, чем жесткий диск, когда вам нужно получить те же данные, повторяющиеся, снова и снова, или запросить службы удаленной базы данных, В результате много времени, потраченного на запросы к базе данных или на вызове удаленного метода, что приведет к ухудшению производительности, что является кэшем данных для решения проблемы.
Поддержка кэширования Spring
Spring определяет интерфейсы org.springframework.cache.CacheManager и org.springframework.cache.Cache для унификации различных технологий кэширования. Среди них CacheManager — это абстрактный интерфейс различных технологий кэширования, предоставляемых Spring, а интерфейс Cache включает в себя различные операции кэширования (добавление, удаление и получение кеша, как правило, напрямую не связанные с этим интерфейсом).
* 1, * Spring поддерживает CacheManager
Для разных технологий кэширования реализованы разные CacheManagers. Spring определяет CacheManagers, показанные в следующей таблице:
CacheManager | описывать |
---|---|
SimpleCacheManager | Используйте простую коллекцию для хранения кеша, в основном для тестирования |
ConcurrentMapCacheManager | CONDURRENTMAP Используйте кэш для хранения |
NoOpCacheManager | Только в целях тестирования, никакие данные не будут кэшироваться. |
EhCacheCacheManager | Использование EhCache в качестве технологии кэширования |
GuavaCacheManager | Использование Google Guava GuavaCache в качестве технологии кэширования |
HazelcastCacheManager | Использование Hazelcast в качестве технологии кэширования |
JCacheCacheManager | Реализация, поддерживающая стандарт JCache (JSR-107) в качестве технологии кэширования, например ApacheCommonsJCS. |
RedisCacheManager | Используйте Redis в качестве технологии кэша |
При использовании любого из CacheManager, реализованного выше, вам необходимо зарегистрировать bean-компонент, который реализовал CacheManager, например:
@Bean
public EhCacheCacheManager cacheManager(CacheManager
ehCacheCacheManager){
return new EhCacheCacheManager(ehCacheCacheManager);
}
Обратите внимание, что каждая технология кэширования имеет множество дополнительных настроек, но настройка cacheManager необходима.
*2, *Аннотации декларативного кэша
Spring предоставляет 4 аннотации для объявления правил кэширования (опять же, пример использования Annotated AOP). 4 аннотации следующие:
аннотация | объяснять |
---|---|
@Cacheable | В методе Spring сначала просмотрите кеш в кеше, если есть, верните данные кеша напрямую, если данных нет, метод вызова вернет метод в кеш. |
@CachePut | В любом случае, возвращаемое значение метода помещается в кэш. |
@CacheEvict | Удалить один или несколько фрагментов данных из кеша |
@Caching | Несколько стратегий аннотаций можно комбинировать в методе с помощью аннотации @Caching. |
@Cachable, @Cacheput, и @Cacheeevict все имеют атрибут Value, который указывает имя кэша для использования; атрибут ключа указывает клавишу для хранения данных в кэше.
*3, *Включить поддержку декларативного кэша
Включить декларативное кэширование легко, просто используйте аннотацию @EnableCaching в классе конфигурации, например:
@Configuration
@EnableCaching
public class AppConfig{
}
Поддержка Springboot
Ключом к использованию технологии кэширования в Spring является настройка CacheManager, а SpringBoot настраивает для нас несколько реализаций CacheManager.
Его автоконфигурация размещена в пакете org.springframework.boot.autoconfigure.cache.
Без какой-либо настройки по умолчанию используется SimpleCacheConfiguration, то есть используется ConcurrentMapCacheManager. SpringBoot поддерживает настройку кешей с префиксами. Например:
spring.cache.type= # 可选 generic、ehcache、hazelcast、infinispan、jcache、redis、guava、simple、none
spring.cache.cache-names= # 程序启动时创建的缓存名称
spring.cache.ehcache.config= # ehcache 配置文件的地址
spring.cache.hazelcast.config= # hazelcast配置文件的地址
spring.cache.infinispan.config= # infinispan配置文件的地址
spring.cache.jcache.config= # jcache配置文件的地址
spring.cache.jcache.provider= # 当多个 jcache 实现在类路径的时候,指定 jcache 实现
# 等等。。。
В среде SpringBoot для использования технологии кэширования нужно только импортировать зависимости соответствующей технологии кэширования в проект и использовать @EnableCaching в классе конфигурации, чтобы включить поддержку кэширования.
Код
Эта статья будет использовать SpringBoot по умолчанию ConcurrentMapcachemanager в качестве технологии кэширования, чтобы продемонстрировать @cachable, @Cacheput и @Cacheevict.
*1, *Подготовка
- IDEA
- JDK 1.8
- SpringBoot 2.1.3
*2, *Зависимость файла Pom.xml
<?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>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.nasus</groupId>
<artifactId>cache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cache</name>
<description>cache Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- cache 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- JPA 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- web 启动类 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mysql 数据库连接类 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- lombok 依赖,简化实体 -->
<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>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Комментарии ясны и не нужны. Не просто гуглите.
*3, *Конфигурация файла Application.yaml
spring:
# 数据库相关
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=true
username: root
password: 123456
# jpa 相关
jpa:
hibernate:
ddl-auto: update # ddl-auto: 设为 create 表示每次都重新建表
show-sql: true
* 4, * класс сущности
package com.nasus.cache.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@Id
@GeneratedValue
private Integer id;
private String name;
private Integer age;
}
*5, *дао слой
package com.nasus.cache.repository;
import com.nasus.cache.entity.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends JpaRepository<Student,Integer> {
}
*6, *сервисный уровень
package com.nasus.cache.service;
import com.nasus.cache.entity.Student;
public interface StudentService {
public Student saveStudent(Student student);
public void deleteStudentById(Integer id);
public Student findStudentById(Integer id);
}
Класс реализации:
package com.nasus.cache.service.impl;
import com.nasus.cache.entity.Student;
import com.nasus.cache.repository.StudentRepository;
import com.nasus.cache.service.StudentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class StudentServiceImpl implements StudentService {
// 使用 slf4j 作为日志框架
private static final Logger LOGGER = LoggerFactory.getLogger(StudentServiceImpl.class);
@Autowired
private StudentRepository studentRepository;
@Override
@CachePut(value = "student",key = "#student.id")
// @CachePut 缓存新增的或更新的数据到缓存,其中缓存名称为 student 数据的 key 是 student 的 id
public Student saveStudent(Student student) {
Student s = studentRepository.save(student);
LOGGER.info("为id、key 为{}的数据做了缓存", s.getId());
return s;
}
@Override
@CacheEvict(value = "student")
// @CacheEvict 从缓存 student 中删除 key 为 id 的数据
public void deleteStudentById(Integer id) {
LOGGER.info("删除了id、key 为{}的数据缓存", id);
//studentRepository.deleteById(id);
}
@Override
@Cacheable(value = "student",key = "#id")
// @Cacheable 缓存 key 为 id 的数据到缓存 student 中
public Student findStudentById(Integer id) {
Student s = studentRepository.findById(id).get();
LOGGER.info("为id、key 为{}的数据做了缓存", id);
return s;
}
}
Код объясняет комментарий, очень подробный.
*7, *уровень контроллера
package com.nasus.cache.controller;
import com.nasus.cache.entity.Student;
import com.nasus.cache.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.Mapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/student")
public class StudentController {
@Autowired
private StudentService studentService;
@PostMapping("/put")
public Student saveStudent(@RequestBody Student student){
return studentService.saveStudent(student);
}
@DeleteMapping("/evit/{id}")
public void deleteStudentById(@PathVariable("id") Integer id){
studentService.deleteStudentById(id);
}
@GetMapping("/able/{id}")
public Student findStudentById(@PathVariable("id") Integer id){
return studentService.findStudentById(id);
}
}
*8, *приложение включает функцию кэширования
package com.nasus.cache;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching // 开启缓存功能
@SpringBootApplication
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
контрольная работа
Перед тестированием взгляните на текущие данные в базе данных следующим образом:
*1, *Тест @Cacheable
доступhttp://localhost:8080/student/able/2Консоль распечатает оператор SQL Query и указанный журнал. Объясните, что на этот раз программа является результатом, полученным непосредственно запрашивая базу данных.
2019-02-21 22:54:54.651 INFO 1564 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 11 ms
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from student student0_ where student0_.id=?
2019-02-21 22:54:59.725 INFO 1564 --- [nio-8080-exec-1] c.n.c.service.impl.StudentServiceImpl : 为id、key 为2的数据做了缓存
Результаты первого теста почтальона:
посетить сноваhttp://localhost:8080/student/able/2Результат показан ниже. Но в консоли нет инструкции SQL, ниКэшированные данные с идентификатором и ключом 2Это предложение вывода.
Описание @CacHeable создает кеш данных, второй результат теста получается из кеша данных и прямой базы данных нет.
*2, *Тест @CachePut
Как показано ниже, Postman Accesshttp://localhost:8080/student/putВставить данные:
Ниже консоль распечатывает оператор вставки SQL и указанный журнал. Указывает, что программа находится в кэше.
Hibernate: insert into student (age, name, id) values (?, ?, ?)
2019-02-21 23:12:03.688 INFO 1564 --- [nio-8080-exec-8] c.n.c.service.impl.StudentServiceImpl : 为id、key 为4的数据做了缓存
Результат, возвращаемый вставкой данных:
Результат в базе:
доступhttp://localhost:8080/student/able/4Результаты почтальона показаны ниже. Консоль не имеет вывода и проверяет, что @CacHeput действительно создает кеш, и из кеша получаются следующие данные.
*3, *Тест @CacheEvict
визит почтальонаhttp://localhost:8080/student/able/3Кэшируйте данные с ID = 3.
почтальон снова в гостяхhttp://localhost:8080/student/able/3Подтвердите, что данные получены из кеша.
визит почтальонаhttp://localhost:8080/student/evit/3
Удалить закэшированные данные с ключом 3 из кеша:
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from student student0_ where student0_.id=?
2019-02-21 23:26:08.516 INFO 8612 --- [nio-8080-exec-2] c.n.c.service.impl.StudentServiceImpl : 为id、key 为3的数据做了缓存
2019-02-21 23:27:01.508 INFO 8612 --- [nio-8080-exec-4] c.n.c.service.impl.StudentServiceImpl : 删除了id、key 为3的数据缓存
почтальон снова в гостяхhttp://localhost:8080/student/able/3Наблюдайте за фоном и переделайте кеш данных:
Hibernate: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from student student0_ where student0_.id=?
2019-02-21 23:27:12.320 INFO 8612 --- [nio-8080-exec-5] c.n.c.service.impl.StudentServiceImpl : 为id、key 为3的数据做了缓存
Этот набор тестовых процедур доказывает, что @CacheEvict действительно удаляет кеш данных.
Загрузка исходного кода
Технология кэширования коммутатора
Технология Cache переключения используется так же, как и вышеуказанная демонстрация кода, за исключением того, что в файл POM добавляется соответствующая конфигурация пакета зависимости.
*1, *Переключить EhCache Добавьте зависимость Encache к pom:
<!-- EhCache 依赖 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
Файл конфигурации ehcache.xml, требуемый Ehcache, нужно только поместить в путь к классам (каталог ресурсов), и SpringBoot автоматически просканирует, например:
<?xml version="1.0" encoding="UTF-8">
<ehcache>
<cache name="student" maxElementsInMmory="1000">
<ehcache>
SpringBoot автоматически настроит bean-компонент EhcacheManager.
*2, *Переключить гуаву
Просто добавьте зависимость Guava к вашему pom:
<!-- GuavaCache 依赖 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
SpringBoot автоматически настроит bean-компонент GuavaCacheManager.
*3, *Переключение RedisCache
Как и в случае с Guava, просто добавьте зависимость в pom:
<!-- cache 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
SpringBoot автоматически настроит bean-компоненты RedisCacheManager и RedisTemplate.
Кроме того, переключение на другие методы кэширования аналогичны. Еще не разработано здесь.
послесловие
Учебник для кэша данных Scraphboot.
Если эта статья поможет вам хоть немного, пожалуйста, помогите.
Ваша привлекательная внешность мотивирует меня продолжать писать.
Кроме того, я отправляю его после того, как обратил внимание1024Вы можете получить бесплатные учебные материалы. Подробности информационного содержания см. в этой старой статье:Python, C++, Java, Linux, Go, интерфейс, алгоритмы, обмен данными