1. What is cache cache
The word Cache first came from CPU design
When the CPU wants to read a data, it first looks up from the CPU cache, and immediately reads it and sends it to the CPU for processing if it is found; if it is not found, it is read from the relatively slow memory and sent to the CPU for processing. At the same time, the data block where this data is located is called into the cache, so that the entire block of data can be read from the cache in the future without calling memory. It is this reading mechanism that makes the CPU read cache hit rate very high (most CPUs can reach about 90%), which means that 90% of the data the CPU will read next time is in the CPU cache, and only about 10% need to be read from memory. This greatly saves the CPU time to read memory directly, and also makes it impossible for the CPU to read data without waiting. In general, the order in which the CPU reads data is cached first and then memory.
Later, we first went to hard disk cache, then to application cache, browser cache, web cache, etc.!
Cache is king! !
Spring Cache
Spring Cache is a complete set of application caching solutions given by Spring applications.
Spring Cache itself does not provide cache implementation, but uses unified interfaces and code specifications, configurations, annotations, etc. to enable you to use various caches in Spring applications without having to pay too much attention to the details of the cache. With Spring Cache, you can use it easily
Various cache implementations, including ConcurrentMap, Ehcache 2.x, JCache, Redis, etc.
The definition of Cache in Spring
The definition of cache in Spring, including in the interface org.springframework.cache.Cache.
It mainly provides the following methods
// Get the value according to the specified key <T> T get(Object key, Class<T> type)// Save the specified value to the cache according to the corresponding key void put(Object key, Object value);// Recycle the specified value void evict(Object key)
It is not difficult to see from the definition that Cache is actually a key-value structure. We operate the corresponding value through a specified key.
Cache Manager
Cache is a collection of key-values, but in our project, there may be different caches of various business topics, such as user caches, department caches, etc. These caches are logically separate. In order to distinguish these caches, org.springframework.cache.CacheManager is provided to manage various caches. This interface contains only two methods
// Get the cache of the corresponding topic according to the name Cache getCache(String name);// Get the cache of all topics Collection<String> getCacheNames();
In this interface, adding and deleting operations are not allowed to be performed on Cache. These operations should be completed internally by various CacheManager implementations and should not be disclosed.
Annotation-based cache
In theory, the cache operation of data is not very relevant to the business itself. We should separate the read and write operations of Cache from the main code logic. The way Spring is separated is based on annotation (of course, like JSR-107, etc. is also based on annotation).
Spring provides a series of annotations, including @Cacheable, @CachePut, @CacheEvict and other annotations to simplify our operation of caches. These annotations are located in the org.springframework.cache.annotation package.
2. Examples
A simple example of using Spring Boot using Spring Cache
Let's build an example based on Spring Boot Cache step by step
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>
Among them, spring-boot-starter-cache is the key dependency of cache.
Modify the Application class and add the annotation that enables cache @EnableCaching
@SpringBootApplication@EnableCachingpublic class CacheSimpleApplication { public static void main(String[] args) { SpringApplication.run(CacheSimpleApplication.class, args); }}@EnableCache annotation starts Spring's caching mechanism, which will enable the application to detect all cache-related annotations and start working. It will also create a CacheManager bean that can be injected and used by our application.
Create a new RestController class
@RestController@RequestMapping("/")public class CacheController { @Autowired private CacheTestService cacheTestService; /** * Get information based on the ID* * @param id * @return */ @GetMapping("{id}") public String test(@PathVariable("id") String id) { return cacheTestService.get(id); } /** * Delete information about an ID* * @param id * @return */ @DeleteMapping("{id}") public String delete(@PathVariable("id") String id) { return cacheTestService.delete(id); } /** * Save information about an ID* * @param id * @return */ @PostMapping public String save(@RequestParam("id") String id, @RequestParam("value") String value) { return cacheTestService.save(id, value); } /** * Information about a new ID* * @param id * @return */ @PutMapping("{id}") public String update(@PathVariable("id") String id, @RequestParam("value") String value) { return cacheTestService.update(id, value); }}This class calls a service to implement the actual operation of adding, deleting, modifying and checking.
Service implementation
Next, we want to implement our Service
@Servicepublic class SimpleCacheTestServiceImpl implements CacheTestService { private static final Logger logger = LoggerFactory.getLogger(SimpleCacheTestServiceImpl.class); private final Map<String, String> entities = new HashMap<>(); public SimpleCacheTestServiceImpl() { entities.put("1", "this no 1"); } @Autowired private CacheManager cacheManager; @Override @Cacheable(cacheNames = "test") public String get(String id) { // Record the time of data generation, used to test and compare long time = new Date().getTime(); // Print the used cacheManager logger.info("The cacheManager is" + cacheManager); // Print the log logger.info("Get value by id=" + id + ", The time is " + time); return "Get value by id=" + id + ", the value is" + entities.get(id); } @Override public String delete(String id) { return entities.remove(id); } @Override public String save(String id, String value) { logger.info("save value " + value + " with key " + id); entities.put(id, value); return value; } @Override public String update(String id, String value) { return entities.put(id, value); }}cache
First, add the @Cacheable annotation to the get method and run the code test.
We use postman for testing, the test address is http://localhost:8080/1, the browser responds to Get value by id=1, the value isthis no 1, the server console prints two lines of logs
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. The reason is that when we call it the second time, Spring no longer executes the method, but directly gets the cached value. Spring Cache caches the return value of the function as the key in the cache named test.
Here we use the @Cacheable annotation, and the cacheNames in the annotation specifies which cache is read here. Here, we will search for the cache object whose key is id in the cacheName="test".
Delete cached data
In the above program, if we delete the specified value through the delete request and send the delete request to http://localhost:8080/1 , at this time, the value has been deleted from the map, but when we get the request to http://localhost:8080/1 , we can still get the value. This is because when we delete the data, we did not delete the data in the cache. In the previous get method, the operation result of the method is still saved. Spring will not re-read it, but will directly read the cache. At this time, we add annotations before the method
@Override@CacheEvict(cacheNames = "test")public String delete(String id) { return entities.remove(id);}After testing, first call the get request, the return value will be correctly displayed as Get value by id=1, the value is 1
Then call delete request. Delete the data from the cache and map, and call the get request again. At this time, the Get value by id=1, the value is null, which means that the value has indeed been deleted from the cache.
Here we use the @CacheEvict annotation. cacheNames specifies which cache data to delete. By default, the method parameters will be used as the deleted key.
Update cache
When the program reaches this point, if we run the post request, the request body is id=1&value=new1. At this time, the console prints save value new value1 with key 1, and the code will save the value to the map, but when we run the get request, we will find that the return value is still in the previous state. 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 entities.put(id, value);}Re-execute the code, we first send a delete request to delete the data from the map and cache. Then send a post request and write the data to the map. Finally, if you send a get request, you will find that the value can be retrieved correctly now, and the console does not print the log of the data obtained from the map.
The @CachePut annotation is used here. The function of this annotation is to write the return value of the method into the cache specified by cacheNames according to the given key.
Similarly, we need to add the @CachePut annotation to the put method so that the modification can also refresh the cached data.
At this point, a simple cache application including addition, deletion, modification and query is completed.
3. Key points
A few notes
Notice
@Cacheable and @Cacheput will both put the execution result of the method into the cache according to the specified key. When @Cacheable is executed, it will first detect whether there is data in the cache. If so, it will be read directly from the cache. If not, execute the method and put the return value into the cache, @Cacheput will execute the method first, and then write the execution result to the cache. The method using @Cacheput will definitely be executed
The complete sample code is at https://github.com/ldwqh0/cache-test
Summarize
The above is the method of using cache cache in Spring Boot introduced to you by the editor. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. Thank you very much for your support to Wulin.com website!