Spring Boot uses the cache cache method

  • 2020-12-22 17:39:09
  • OfStack

1. What is cache Cache

The first word Cache comes from the CPU design

When CPU wants to read one data, it first looks it up from the CPU cache and immediately reads it and sends it to CPU for processing. If it is not found, it is read from the relatively slow memory and sent to CPU for processing. At the same time, the data block in which this data is located is transferred to the cache, so that later reads of the whole data block are carried out from the cache without calling the memory. It is this reading mechanism that makes the CPU cache hit ratio very high (most CPU are around 90%), meaning that 90% of the data read in a secondary session under CPU is in the CPU cache and only about 10% needs to be read from memory. This greatly saves CPU the time it takes to read the memory directly and eliminates the need to wait for CPU to read the data. In general, THE order in which CPU reads data is cache first and memory later.

Later on, the hard disk cache, then the application cache, browser cache, Web cache, and so on!

Cache is king!!

Spring Cache

Spring Cache is a complete set of application caching solution given by Spring for Spring applications.

Spring Cache itself does not provide a caching implementation, but instead uses interface and code specifications, configuration, annotations, and so on to enable you to use various Cache in Spring applications without worrying too much about the details of Cache. With Spring Cache, you can easily use it

Various cache implementations, including ConcurrentMap,Ehcache 2.ES46en,JCache,Redis, etc.

Definition of Cache in Spring

Sping about the definition of the cache, including in the interface org. springframework. cache. Cache,

It mainly provides the following methods


//  According to the specified key Get the value 
<T> T get(Object key, Class<T> type)
//  Will specify the value according to the corresponding key And save it in the cache 
void put(Object key, Object value);
//  Retrieves the specified value based on the key 
void evict(Object key)

It is not hard to see from the definition that Cache is in fact the structure of one ES66en-ES67en, and we operate the corresponding value through the specified key

Cache Manager

Cache is the collection of ES76en-ES77en, but in our project, there may be different Cache for various business topics, such as cache for users, Cache for departments, etc. These cache are logically separated. In order to distinguish these Cache, provides org springframework. cache. Various Cache CacheManager used to management. The interface contains only two methods


//  Gets the cache for the topic by name 
Cache getCache(String name);
//  Gets a cache for all topics 
Collection<String> getCacheNames();

In this interface, additions and deletions to Cache are not allowed, and should be done internally within the various CacheManager implementations, rather than publicly.

Annotation-based caching

Caching operations on data is not theoretically relevant to the business itself, and we should separate read and write operations on Cache from the main code logic. The way Spring separates is annotation-based (of course, so is JSR-107, etc.).

Spring provides a series of annotations, including @ Cacheable, @ CachePut, @ CacheEvict 1 series such as annotations to simplify our fuck do to cache, these annotations are located in org. springframework. cache. annotation package.

Example 2.

A simple example of Spring Boot using Spring Cache

Let's go step by step and build an example based on Spring Boot Cache

Create a new Spring Boot project and introduce the following dependencies


<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>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

spring-boot-starter-cache is the key dependency of cache.

Modify the Application class to include the caching enabled annotation @EnableCaching


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

The @EnableCache annotation initiates the caching mechanism of Spring, which enables the application to detect all cache-related annotations and get to work, as well as creating an CacheManager bean that can be injected by our application.

Create a new RestController class


@RestController
@RequestMapping("/")
public class CacheController {
  @Autowired
  private CacheTestService cacheTestService;
  /**
   *  According to the ID Access to information 
   * 
   * @param id
   * @return
   */
  @GetMapping("{id}")
  public String test(@PathVariable("id") String id) {
    return cacheTestService.get(id);
  }
  /**
   *  Delete a ID The information of 
   * 
   * @param id
   * @return
   */
  @DeleteMapping("{id}")
  public String delete(@PathVariable("id") String id) {
    return cacheTestService.delete(id);
  }
  /**
   *  Save a ID The information of 
   * 
   * @param id
   * @return
   */
  @PostMapping
  public String save(@RequestParam("id") String id, @RequestParam("value") String value) {
    return cacheTestService.save(id, value);
  }
  /**
   *  With the new one ID The information of 
   * 
   * @param id
   * @return
   */
  @PutMapping("{id}")
  public String update(@PathVariable("id") String id, @RequestParam("value") String value) {
    return cacheTestService.update(id, value);
  }
}

This class calls some Service to implement the actual add, delete, change and check operation.

Service implementation

Next, we will implement our Service


@Service
public class SimpleCacheTestServiceImpl implements CacheTestService {
  private static final Logger logger = LoggerFactory.getLogger(SimpleCacheTestServiceImpl.class);
  private final Map<String, String> enties = new HashMap<>();
  public SimpleCacheTestServiceImpl() {
    enties.put("1", "this no 1");
  }
  @Autowired
  private CacheManager cacheManager;
  @Override
  @Cacheable(cacheNames = "test")
  public String get(String id) {
    //  Record the time the data is generated for test comparisons 
    long time = new Date().getTime();
    //  Print used by cacheManager
    logger.info("The cacheManager is" + cacheManager);
    //  When the data is not from cache When fetched inside, print log 
    logger.info("Get value by id=" + id + ", The time is " + time);
    return "Get value by id=" + id + ",the value is" + enties.get(id);
  }
  @Override
  public String delete(String id) {
    return enties.remove(id);
  }
  @Override
  public String save(String id, String value) {    
    logger.info("save value " + value + " with key " + id);
    enties.put(id, value);
    return value;
  }
  @Override
  public String update(String id, String value) {
    return enties.put(id, value);
  }
}

The cache

First, run the code tests by annotating the get method with the @Cacheable annotation.

We used postman for the test, the test address was http://localhost:8080/1, the browser responded Get value by id=1,the value isthis no 1, the server console printed two lines of the log


Get value by id=1,the value isthis no 1 
Get value by id=1, The time is 1516004770216 

But when we refresh the browser address again, the browser returns normally, but the console no longer prints, because on the second call, Spring no longer executes the method, but directly fetches the cached value. Spring Cache cache the return value of a function as a function argument, key, cached in a cache called test.

Here we use the @Cacheable annotation. cacheNames in the annotation specifies which Cache is read here. In cacheName="test", cache is the cache object of id.

Deletes cached data

In the above program, if we request delete a specified value, through delete delete request sent to http: / / localhost: 8080/1, this time, the value has been deleted from the map, but we request to http get: / / localhost: 8080/1 of the time, still can get value, it is because we at the time of deleting data, not delete the data in the cache, but in front of the get method, the method of operation result is still preserved, Spring does not re-read, but reads the cache directly. At this point, we annotate the method


@Override
@CacheEvict(cacheNames = "test")
public String delete(String id) {
  return enties.remove(id);
}

Test successively, call get request first, will show the return value is Get value by id=1,the value is 1 correctly

The delete request is then invoked. The data is removed from cache and map, and the get request is invoked again, when Get value by id=1,the value is null is returned, indicating that the value has indeed been removed from the cache.

Here we use the @CacheEvict annotation. cacheNames specifies which data in cache to delete, and the default is to use the method parameter as the key to delete

Update the cache

When the program gets here, if we run the post request, the body of the request is id=1 & value=new1, when the console prints save value new value1 with key 1, the code will save the value to map, but when we run the get request, we will find that the return value is still the same as before. This is what we can use


@Override
@CachePut(cacheNames = "test", key = "#id")
public String save(String id, String value) {
  logger.info("save value " + value + " with key " + id);
  return enties.put(id, value);
}

To re-execute the code, we first send the delete request to delete the data from map and cache. An post request is then sent and the data is written to map. When you finally send the get request, you will find that the values are now correctly fetched, and the console does not print the log of the data fetched from map.

The @CachePut annotation is used to write the return value of the method to the cache specified by cacheNames, given key.

Again, we need to add the @CachePut annotation to the put method so that the changes can also refresh the cached data.

At this point, a simple cache application containing add, delete, change and check is complete.

3. To highlight

A few notes

EnableCaching enables cache configuration Cacheable specifies that the return value of a method is cacheable. Specify the cache rule in the annotation property. Cacheput caches the return value of the method into the specified key CacheEvict deletes the specified cached data

Pay attention to

Both @ES299en and @ES300en will put the execution result of the method into the cache according to the specified key. When @ES302en executes, it will first check whether there is data in the cache, and if there is data, it will read directly from the cache. If not, the method is executed and the return value is put into the cache, while @Cacheput executes the method first and then writes the result to the cache. Method 1 using @Cacheput will execute

Complete sample code in https: / / github com/ldwqh0 / cache - test

conclusion


Related articles: