io.github.alphajiang.hyena.aop.IdempotentAround Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hyena-core Show documentation
Show all versions of hyena-core Show documentation
Micro service for user score hosting.
/*
* Copyright (C) 2019 Alpha Jiang. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.github.alphajiang.hyena.aop;
import io.github.alphajiang.hyena.HyenaConstants;
import io.github.alphajiang.hyena.biz.idempotent.HyenaIdempotent;
import io.github.alphajiang.hyena.model.base.BaseResponse;
import io.github.alphajiang.hyena.model.param.PointOpParam;
import io.github.alphajiang.hyena.utils.JsonUtils;
import io.github.alphajiang.hyena.utils.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@Component
@Aspect
public class IdempotentAround {
private final Logger logger = LoggerFactory.getLogger(IdempotentAround.class);
@Autowired
private HyenaIdempotent hyenaIdempotent;
@Around("@annotation(Idempotent)")
public Object around(ProceedingJoinPoint point) throws Throwable {
Method method = ((MethodSignature) point.getSignature()).getMethod();
Idempotent shelter = method.getAnnotation(Idempotent.class);
String name = shelter.name();
Object[] args = point.getArgs();
HttpServletRequest request = (HttpServletRequest) args[0];
PointOpParam param = (PointOpParam) args[1];
BaseResponse res;
// String seq = request.getParameter(HyenaConstants.REQ_IDEMPOTENT_SEQ_KEY);
String seq = param.getSeq();
request.setAttribute(HyenaConstants.REQ_IDEMPOTENT_SEQ_KEY, seq);
res = this.preProceed(name, param, method);
if (res != null) {
return res;
}
res = (BaseResponse) point.proceed(point.getArgs());
this.postProceed(name, param, res);
return res;
}
private BaseResponse preProceed(String name, PointOpParam param, Method method)
throws NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException {
BaseResponse res = null;
if (StringUtils.isBlank(param.getSeq())) {
return res;
}
String key = getKey(name, param);
String resMsg = this.hyenaIdempotent.getByKey(key);
if (StringUtils.isNotBlank(resMsg)) { // cache match
res = (BaseResponse) JsonUtils.fromJson(resMsg, method.getReturnType());
logger.info("idempotent cache matched. res = {}", JsonUtils.toJsonString(res));
return res;
}
if (!this.hyenaIdempotent.lock(key)) {
res = (BaseResponse) method.getReturnType().getDeclaredConstructor().newInstance();
res.setStatus(HyenaConstants.RES_CODE_DUPLICATE_IDEMPOTENT);
res.setError("请勿重复提交");
}
return res;
}
private void postProceed(String name, PointOpParam param, BaseResponse res) {
if (StringUtils.isNotBlank(param.getSeq())) {
String key = getKey(name, param);
res.setSeq(param.getSeq());
this.hyenaIdempotent.setByKey(key, res);
this.hyenaIdempotent.unlock(key);
}
}
private String getKey(String name, PointOpParam param) {
StringBuilder buf = new StringBuilder();
if (StringUtils.isNotBlank(name)) {
buf.append(name).append("-");
}
if (StringUtils.isNotBlank(param.getType())) {
buf.append(param.getType()).append("-");
}
buf.append(param.getSeq());
return buf.toString();
}
}