Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize automatic idempotency of interface by Springboot+redis+Interceptor+ custom annotation

2025-01-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article will explain in detail about Springboot+redis+Interceptor+ custom annotation how to achieve interface auto-idempotency. The editor thinks it is very practical, so I share it with you for reference. I hope you can get something after reading this article.

One: set up redis service Api

1: the first thing is to build a redis server, which has been built before, so I won't repeat it. For details, please refer to: https://www.cnblogs.com/wyq178/p/10340234.html

2: 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 * / @ Componentpublic 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.printStackTrace ();} return result } / * determine whether there is a corresponding value * @ param key * @ return * / public boolean exists (final String key) {return redisTemplate.hasKey (key);} / * 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;}}

Two: custom annotations 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 {}

Three: token creation and verification

1: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;}

2:token 's service implementation class

Token references the redis service, creates a token that uses a random algorithm utility class to generate a random uuid string, then puts it into the redis, and returns this token value if the placement is successful. 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.

@ Servicepublic 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 (), 1000L); boolean notEmpty = StrUtil.isNotEmpty (token.toString ()); if (notEmpty) {return token.toString () }} catch (Exception ex) {ex.printStackTrace ();} return null;} / * * verify token * * @ param request * @ return * / @ Override public boolean checkToken (HttpServletRequest request) throws Exception {String token = request.getHeader (Constant.TOKEN_NAME); token token = request.getParameter (Constant.TOKEN_NAME) does not exist in if (StrUtil.isBlank (token)) {/ / header There is no token throw new ServiceException in if (StrUtil.isBlank (token)) {/ / parameter;}} 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;}}

IV: configuration of interceptor

1: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

@ Configurationpublic class WebConfiguration extends WebMvcConfigurerAdapter {@ Resource private AutoIdempotentInterceptor autoIdempotentInterceptor; / * add interceptor * @ param registry * / @ Override public void addInterceptors (InterceptorRegistry registry) {registry.addInterceptor (autoIdempotentInterceptor); super.addInterceptors (registry);}}

2: 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 * / @ Componentpublic class AutoIdempotentInterceptor implements HandlerInterceptor {@ Autowired private TokenService tokenService; / * preprocessing * * @ 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 methodAnnotation 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;} @ 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 {} / * return json value * @ 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 e) {} finally {if (writer! = null) writer.close ();}

Five: test cases

1: simulate 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. The interceptor will intercept all requests. When it is determined that there is such a comment on the method being processed, the checkToken () method in TokenService will be called. If an exception is caught, the exception will be thrown to the caller. Let's simulate the request:

@ RestControllerpublic 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;}}

2: request using postman

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 this article on "how to realize interface auto-idempotency in Springboot+redis+Interceptor+ custom annotation". I hope the above content can be helpful to you, so that you can learn more knowledge. if you think the article is good, please share it out for more people to see.

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.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report