Spring Boot 는 AOP 를 사용 하여 중복 제출 을 방지 하 는 방법 예시
상술 한 사고방식 은 사실 문제 가 없 지만 앞 뒤 가 약간 바 뀌 어야 한다.만약 에 업무 개발 이 끝나 고 이것 을 더 하면 개 동량 이 좀 크다.본 절의 실현 방안 은 전단 협조,순 백 엔 드 처리 가 필요없다.
사고의 방향
모 르 는 친구 가 여기에 도장 을 찍다=>Redis 분산 잠 금 의 정확 한 실현 방식
Redis 를 사용 하 는 것 은 부하 균형 배 치 를 위 한 것 입 니 다.단일 기기 의 배 치 된 프로젝트 라면 Redis 대신 안전 한 로 컬 Cache 를 사용 할 수 있 습 니 다.
Code
여기에 AOP 클래스 와 테스트 클래스 만 붙 여 져 있 습 니 다.전체 코드 는=>Gitee참조.
@Aspect
@Component
public class RepeatSubmitAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(RepeatSubmitAspect.class);
@Autowired
private RedisLock redisLock;
@Pointcut("@annotation(com.gitee.taven.aop.NoRepeatSubmit)")
public void pointCut() {}
@Around("pointCut()")
public Object before(ProceedingJoinPoint pjp) {
try {
HttpServletRequest request = RequestUtils.getRequest();
Assert.notNull(request, "request can not null");
// token JSessionId
String token = request.getHeader("Authorization");
String path = request.getServletPath();
String key = getKey(token, path);
String clientId = getClientId();
boolean isSuccess = redisLock.tryLock(key, clientId, 10);
LOGGER.info("tryLock key = [{}], clientId = [{}]", key, clientId);
if (isSuccess) {
LOGGER.info("tryLock success, key = [{}], clientId = [{}]", key, clientId);
// ,
Object result = pjp.proceed();
//
redisLock.releaseLock(key, clientId);
LOGGER.info("releaseLock success, key = [{}], clientId = [{}]", key, clientId);
return result;
} else {
// ,
LOGGER.info("tryLock fail, key = [{}]", key);
return new ApiResult(200, " , ", null);
}
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return new ApiResult(500, " ", null);
}
private String getKey(String token, String path) {
return token + path;
}
private String getClientId() {
return UUID.randomUUID().toString();
}
}
다 중 루틴 테스트테스트 코드 는 다음 과 같 습 니 다.10 개의 요청 을 동시에 제출 하 는 것 을 모 의 합 니 다.
@Component
public class RunTest implements ApplicationRunner {
private static final Logger LOGGER = LoggerFactory.getLogger(RunTest.class);
@Autowired
private RestTemplate restTemplate;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(" ");
String url="http://localhost:8000/submit";
CountDownLatch countDownLatch = new CountDownLatch(1);
ExecutorService executorService = Executors.newFixedThreadPool(10);
for(int i=0; i<10; i++){
String userId = "userId" + i;
HttpEntity request = buildRequest(userId);
executorService.submit(() -> {
try {
countDownLatch.await();
System.out.println("Thread:"+Thread.currentThread().getName()+", time:"+System.currentTimeMillis());
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
System.out.println("Thread:"+Thread.currentThread().getName() + "," + response.getBody());
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
countDownLatch.countDown();
}
private HttpEntity buildRequest(String userId) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "yourToken");
Map<String, Object> body = new HashMap<>();
body.put("userId", userId);
return new HttpEntity<>(body, headers);
}
}
중복 제출 을 방지 하 는 데 성공 하 였 습 니 다.콘 솔 로 그 는 다음 과 같 습 니 다.10 개의 스 레 드 의 시작 시간 이 거의 동시에 시작 되 었 고 한 개의 요청 만 제출 되 었 습 니 다.이 절 데모
여기에 찔러 라=>Gitee
build 프로젝트 후 로 컬 redis 를 시작 하고 프로젝트 를 실행 하면 자동 으로 테스트 방법 을 실행 합 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.