1. Concept: The impact of any multiple executions is the same as the impact of one execution.
According to this meaning, the final meaning is that the impact on the database can only be one-time and cannot be processed repeatedly. How to ensure its idempotence, usually the following methods are used:
1: The database establishes a unique index, which can ensure that only one piece of data is finally inserted into the database
2: Token mechanism, each interface request First obtain a token, and then add this token to the header body of the request the next time, and verify it in the background. If the verification passes, delete the token, and judge the token again for the next request
3: Pessimistic lock Or optimistic locking, pessimistic locking can ensure that other sql cannot update data every time for update (when the database engine is innodb, the select condition must be a unique index to prevent the entire table from being locked)
4: First To judge after querying, first check whether the data exists in the database. If it exists, it proves that the request has been made, and the request is directly rejected. If it does not exist, it proves that it is the first time to come in, and it is directly released.
Redis realizes the schematic diagram of automatic idempotence:
1: First, build the redis server .
2: Introduce the redis stater in springboot, or the jedis encapsulated by Spring. The main api used later is its set method and exists method. Here we use springboot’s encapsulated redisTemplate
The code is as follows:
/* redis工具类 */ @Component public class RedisService { @Autowired private RedisTemplate redisTemplate; /** * 写入缓存 * @param key * @param value * @return */ public boolean set(final String key,Object value){ boolean result = false; try { ValueOperations<Serializable,Object> operations = redisTemplate.opsForValue(); operations.set(key,value); result = true; }catch (Exception e){ result = false; e.printStackTrace(); } return result; } /** * 写入缓存有效期 * @return */ public boolean setEx(final String key ,Object value,Long expireTime){ boolean result = false; try { ValueOperations<Serializable,Object> operations = redisTemplate.opsForValue(); operations.set(key,value); redisTemplate.expire(key,expireTime, TimeUnit.SECONDS);//有效期 result = true; }catch (Exception e){ result = false; e.printStackTrace(); } return result; } /** * 判断缓存中是否有对应的value * @param key * @return */ public boolean exists(final String key){ return redisTemplate.hasKey(key); } /** * 读取缓存 * @param key * @return */ public Object get(final String key){ Object obj = null; ValueOperations<Serializable,Object> operations= redisTemplate.opsForValue(); obj = operations.get(key); return obj; } /** * 删除对应的value * @param key * @return */ public boolean remvoe(final String key){ if(exists(key)){ Boolean delete = redisTemplate.delete(key); return delete; } return false; } }
Customize an annotation. The main purpose of defining this annotation is to add it to methods that need to be idempotent. Whenever a certain If the method is annotated, it will be automatically idempotent. If this annotation is scanned using reflection in the background, the method will be processed to achieve automatic idempotence. The meta-annotation ElementType.METHOD is used to indicate that it can only be placed on the method, and etentionPolicy.RUNTIME indicates that it is used during runtime.
package com.yxkj.springboot_redis_interceptor.annotion; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AutoIdempotent { }
We create a new interface to create a token service. There are mainly two methods, one for creating tokens and one for verifying tokens. Creating a token mainly generates a string. When checking the token, it mainly conveys the request object. Why do we need to pass the request object? The main function is to get the token in the header, and then check it, and get the specific error information through the thrown Exception and return it to the front end
public interface TokenService { /** * 创建token * @return */ String createToken(); /** * 检验token的合法性 * @param request * @return * @throws Exception */ boolean checkToken(HttpServletRequest request) throws Exception; }
token references redis Service, create token, use random algorithm tool class to generate random uuid string, and then put it into redis (in order to prevent redundant retention of data, the expiration time is set here to 10000 seconds, depending on the business), if the put is successful , and finally return this token value. The checkToken method is to get the token from the header to the value (if it cannot be obtained from the header, get it from paramter). If it does not exist, it will throw an exception directly. This exception information can be caught by the interceptor and then returned to the front end.
The above is the detailed content of How springboot implements automatic idempotent interfaces. For more information, please follow other related articles on the PHP Chinese website!