In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the knowledge of "how to use SpringBoot+Redis to achieve repeated submission". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
In actual development projects, an exposed interface is often faced with many requests. Let's explain the idempotent concept: the impact of any number of execution is the same as that of a single execution. According to this meaning, the ultimate meaning is that the impact on the database can only be one-off, can not be repeated processing. How to ensure its idempotency, there are usually the following means:
The establishment of a unique index in the database can ensure that only one piece of data is eventually inserted into the database.
Token mechanism: get a token before each API request, then add the token to the header body of the request next time, and verify it in the background. If the verification passes the deletion of the token, the token will be judged again in the next request.
Pessimistic lock or optimistic lock can guarantee that other sql cannot update data every time for update (when the database engine is innodb, the condition of select must be a unique index to prevent locking the whole table)
First query and then judge, first by querying whether there is data in the database, if the existence proof has been requested, directly reject the request, if it does not exist, it is proved to be the first time to come in and let it go directly.
Schematic diagram of redis to achieve automatic idempotency:
Build the service Api of redis
The first is to set up a redis server.
It is also possible to introduce the stater of redis in springboot, or the jedis encapsulated by Spring. The api mainly used later is its set method and exists method. Here we use the encapsulated redisTemplate of springboot.
/ * redis utility class * / @ Component public class RedisService {@ Autowired private RedisTemplate redisTemplate; / * write cache * @ param key * @ param value * @ return * / public boolean set (final String key, Object value) {boolean result = false; try {ValueOperations operations = redisTemplate.opsForValue () Operations.set (key, value); result = true;} catch (Exception e) {e.printStackTrace ();} return result } / * write cache setting aging time * @ param key * @ param value * @ return * / public boolean setEx (final String key, Object value, Long expireTime) {boolean result = false; try {ValueOperations operations = redisTemplate.opsForValue (); operations.set (key, value) RedisTemplate.expire (key, expireTime, TimeUnit.SECONDS); result = true;} catch (Exception e) {e.printStackTrace ();} return result } / * determine whether there is a corresponding value * @ param key * @ return * / public boolean exists (final String key) {return redisTemplate.hasKey (key) in the cache } / * read cache * @ param key * @ return * / public Object get (final String key) {Object result = null; ValueOperations operations = redisTemplate.opsForValue (); result = operations.get (key); return result Delete the corresponding value * @ param key * / public boolean remove (final String key) {if (exists (key)) {Boolean delete = redisTemplate.delete (key); return delete;} return false;}}
Custom Annotation AutoIdempotent
Customize an annotation. The main purpose of defining this annotation is to add it to a method that needs to achieve idempotency. Whenever a method annotated it, it will be automatically idempotent. If the background uses reflection to scan this annotation, it will process the method to achieve automatic idempotency, using meta-annotation ElementType.METHOD to indicate that it can only be placed on the method, and etentionPolicy.RUNTIME to indicate that it is at run time.
@ Target ({ElementType.METHOD}) @ Retention (RetentionPolicy.RUNTIME) public @ interface AutoIdempotent {}
Token creation and verification
Token service interface: let's create a new interface and create a token service with two main methods, one for creating token and one for validating token. The creation of token mainly produces a string, and the main purpose of verifying token is to convey the request object, so why pass the request object? The main function is to get the token in the header, then verify it, and get the specific error information back to the front end through the thrown Exception.
Public interface TokenService {/ * create token * @ return * / public String createToken (); / * verify token * @ param request * @ return * / public boolean checkToken (HttpServletRequest request) throws Exception;}
Token's service implementation class: token refers to redis service. Create token to generate random uuid strings using a random algorithm tool class, and then put them into redis (to prevent redundant retention of data, the expiration time is set to 10000 seconds, depending on the business). If the placement is successful, the token value is returned. The checkToken method is to get the value of token from header (or from paramter if you can't get it from header), and throw an exception if it doesn't exist. This exception information can be captured by the interceptor and returned to the front end.
@ Service public class TokenServiceImpl implements TokenService {@ Autowired private RedisService redisService; / * create token * * @ return * / @ Override public String createToken () {String str = RandomUtil.randomUUID (); StrBuilder token = new StrBuilder (); try {token.append (Constant.Redis.TOKEN_PREFIX) .append (str) RedisService.setEx (token.toString (), token.toString (), 10000L); boolean notEmpty = StrUtil.isNotEmpty (token.toString ()); if (notEmpty) {return token.toString ();}} catch (Exception ex) {ex.printStackTrace ();} return null } / * verify that token * * @ param request * @ return * / @ Override public boolean checkToken (HttpServletRequest request) throws Exception {String token = request.getHeader (Constant.TOKEN_NAME); if (StrUtil.isBlank (token)) {/ / header does not exist token token = request.getParameter (Constant.TOKEN_NAME) If (StrUtil.isBlank (token)) {/ / parameter also does not exist token throw new ServiceException (Constant.ResponseCode.ILLEGAL_ARGUMENT, 100);}} if (! redisService.exists (token)) {throw new ServiceException (Constant.ResponseCode.REPETITIVE_OPERATION, 200);} boolean remove = redisService.remove (token) If (! remove) {throw new ServiceException (Constant.ResponseCode.REPETITIVE_OPERATION, 200);} return true;}}
Configuration of interceptor
Web configuration class, to implement WebMvcConfigurerAdapter, the main function is to add autoIdempotentInterceptor to the configuration class, so that we can not take effect until the interceptor, pay attention to the use of @ Configuration annotation, so that it can be added to the context when the container starts
@ Configuration public class WebConfiguration extends WebMvcConfigurerAdapter {@ Resource private AutoIdempotentInterceptor autoIdempotentInterceptor; / * add interceptor * @ param registry * / @ Override public void addInterceptors (InterceptorRegistry registry) {registry.addInterceptor (autoIdempotentInterceptor); super.addInterceptors (registry);}}
Intercept processor: the main function is to intercept the scanned AutoIdempotent to the annotated method, and then call the checkToken () method of tokenService to verify whether the token is correct. If an exception is caught, the exception information is rendered as json and returned to the front end.
/ * interceptor * / @ Component public class AutoIdempotentInterceptor implements HandlerInterceptor {@ Autowired private TokenService tokenService / * param request * @ param response * @ param handler * @ return * @ throws Exception * / @ Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (! (handler instanceof HandlerMethod)) {return true } HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod (); / / scan AutoIdempotent methodmethodAnnotation marked by ApiIdempotment = method.getAnnotation (AutoIdempotent.class); if (methodAnnotation! = null) {try {return tokenService.checkToken (request) / / idempotent check, release if the check passes, throw an exception if the check fails, and return a friendly prompt} catch (Exception ex) {ResultVo failedResult = ResultVo.getFailedResult (101, ex.getMessage ()); writeReturnJson (response, JSONUtil.toJsonStr (failedResult)); throw ex through unified exception handling }} / / true must be returned, otherwise all requests return true will be intercepted } @ Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {} @ Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {} / * param response * @ param json * @ throws Exception * / private void writeReturnJson (HttpServletResponse response String json) throws Exception {PrintWriter writer = null Response.setCharacterEncoding ("UTF-8"); response.setContentType ("text/html; charset=utf-8"); try {writer = response.getWriter (); writer.print (json);} catch (IOException) {} finally {if (writer! = null) writer.close () }}}
Test case
To simulate the business request class, first we need to obtain the specific token through the getToken () method through the / get/token path, and then we call the testIdempotence method, which is annotated with @ AutoIdempotent, and the interceptor will intercept all requests. When it is determined that the processed method has this comment, it will call the checkToken () method in TokenService. If an exception is caught, the exception will be thrown to the caller. Let's simulate the request:
@ RestController public class BusinessController {@ Resource private TokenService tokenService; @ Resource private TestService testService; @ PostMapping ("/ get/token") public String getToken () {String token = tokenService.createToken (); if (StrUtil.isNotEmpty (token)) {ResultVo resultVo = new ResultVo (); resultVo.setCode (Constant.code_success); resultVo.setMessage (Constant.SUCCESS) ResultVo.setData (token); return JSONUtil.toJsonStr (resultVo);} return StrUtil.EMPTY;} @ AutoIdempotent @ PostMapping ("/ test/Idempotence") public String testIdempotence () {String businessResult = testService.testIdempotence (); if (StrUtil.isNotEmpty (businessResult)) {ResultVo successResult = ResultVo.getSuccessResult (businessResult) Return JSONUtil.toJsonStr (successResult);} return StrUtil.EMPTY;}}
Using the postman request, first access the get/token path to get specific to token:
By getting the token and putting the specific request into the header, you can see that the first request is successful, and then we request the second time:
The second request is returned to the repetitive operation. It can be seen that the repetitive verification has passed. When we make repeated requests, we will only make it successful for the first time and fail for the second time:
This is the end of the content of "how to use SpringBoot+Redis to achieve repeated submission". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.