예방 반복 요청 API에 의해 AOP 스프링 부팅

아이디어의 실현

봄 부팅 2.x를 기반으로

API를 표시하는 데 사용됩니다 사용자 정의 주석, 반복 요청 여부를 모니터링 할 필요가있다

스프링 AOP는 모니터링, 컨트롤러 계층에 의해 절단하는

토큰 + ServletPath + SHA1RequestParas : 검사를 반복 키를 요청

  1. 토큰 : 사용자가 로그인이 생성 토큰
  2. ServletPath : 경로 요청
  3. SHA1RequestParas : 요청 파라미터 사용되는 암호화 알고리즘을 SHA-1 해시

위의 세 가지 매개 변수를 사용하여 반복 요청 여부를 판사로 키 접합

사용 레디 스 저장 키, 그리고 레디 스의 특성, 키는 자동으로 지정된 시간 내에 삭제하도록 설정할 수 있습니다. 여기서 지정된 시간을 반복 할 수없는 API는 규정 된 시간 내에 제출된다.

 

사용자 정의 주석 ( 컨트롤러 API 층에 주석 연기 )

@Target (ElementType.METHOD) 
@Retention (RetentionPolicy.RUNTIME) 
공공 @의 인터페이스 NoRepeatSubmission { 
 
}

  

논리 섹션

SLF4J @ 
@Aspect 
@Component 
공공  클래스 NoRepeatSubmissionAspect { 
 
    @Autowired 
    RedisTemplate <문자열, 문자열> redisTemplate; 
 
    / ** 
     *环绕通知
     * @param PJP 
     * @param ARS 
     * @return 
     * / 
    @Around ( "실행 (공개 com.example.apirepeatrequest.controller * .. *. * (...)) && @annotation (ARS) " )
     공공 객체 doAround (ProceedingJoinPoint의 PJP, NoRepeatSubmission의 ARS) { 
        ValueOperations <문자열, 문자열> opsForValue = redisTemplate.opsForValue ();
        시도 {
             경우 (ARS == null이 ) {
                 반환 ) (pjp.proceed을; 
            } 
 
            HttpServletRequest의 요청 = ((ServletRequestAttributes) Objects.requireNonNull (RequestContextHolder.getRequestAttributes ())) 대해 GetRequest ().; 
 
            문자열 토큰 = request.getHeader ( "토큰" );
            만약 (! checkToken) (토큰) {
                 반환 Result.failure를 ( "토큰无效" ); 
            } 
            문자열은 servletPath = )를 request.getServletPath (; 
            문자열 jsonString는 = .getRequestParasJSONString (PJP); 
            문자열 SHA1 = .generateSHA1 (jsonString); 
 
            // 키 = 토큰 + 서블릿 경로 
            문자열 키 = 토큰 + "-"+ servletPath + "-"+ SHA1; 
 
            log.info ( "\ n {\ n \ tServlet 경로 : {} \ n \ tToken : {} \ n \ tJson 문자열 : {} \ n \ tSHA-1 : {} \ n \ tResult 키 : {} \ n } " , servletPath, 토큰, jsonString, SHA1, 키); 
 
            // 如果레디 스中有这个키则URL视为重复请求
            경우 (opsForValue.get (키) == ) { 
                O 개체 = pjp.proceed (); 
                opsForValue.set (키 한 String.valueOf ( 0), 3 , TimeUnit.SECONDS);
                반환 O; 
            } 다른 {
                 반환 Result.failure ( "마 반복하지 요청" ); 
            } 
        } 캐치 (Throwable의 E) { 
            e.printStackTrace (); 
            반환 ( "알 수없는 인증 이상 반복 요청"Result.failure ); 
        } 
    } 
 
    / ** 
     * 취득 요구 파라미터 
     * @param PJP 
     * @return 
     * / 
    개인 문자열 getRequestParasJSONString (ProceedingJoinPoint PJP) { 
        문자열 [] parameterNames = ((MethodSignature) pjp.getSignature ())에 대해 getParameterNames을 ();
        ConcurrentHashMap의 <문자열, 문자열> 인수 = ; 
 
        경우 (Objects.nonNull (parameterNames)) { 
            인수 = 새로운 ConcurrentHashMap의 <> (parameterNames.length);
            위한 ( INT I ++; I <parameterNames.length I 0 = {) 
                문자열 값 = pjp.getArgs ()를 [I]! = null이 ? pjp.getArgs () [I]로 .toString () "널 (null)" ; 
                args.put (parameterNames [I]의 값); 
            } 
        } 
        리턴 JacksonSerializer.toJSONString (인수)를; 
    } 
}

 

코드 부분의 메인 로직은 요청에 관련된 정보를 획득하는 것, 그리고 키에 접합, 레디 스이, 존재하지 않는이고, 소정 시간은 자동 삭제 설정되면 추가 반복 요청의 존재 여부를 판정한다.

 

추천

출처www.cnblogs.com/21-Gram/p/11971340.html