rpc 的服务提供者,有时候希望可以统一执行参数校验,或者验签。
基本实现
基本实现
- PegasusServerInterceptor.java
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
*
* 可以添加下列特性:
*
* 1. mdc
* 2. 入参
* 3. 出参
* 4. 统一异常处理
*
* 暂时先处理 1/2
* @author binbin.hou
* @since 1.0.0
*/
@Aspect
@Component
@EnableAspectJAutoProxy
public class PegasusServerInterceptor {
/**
* 日志实例
* @since 1.0.0
*/
private static final Logger LOG = LoggerFactory.getLogger(PegasusServerInterceptor.class);
/**
* 拦截 services 下所有的 public方法
*/
@Pointcut("execution(public * com.xxx.pegasus.server.services..*(..))")
public void pointCut() {
//
}
/**
* 拦截处理
*
* @param point point 信息
* @return result
* @throws Throwable if any
*/
@Around("pointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
//1. 设置 MDC
LogUtil.putMdcIfAbsent();
try {
// 获取当前拦截的方法签名
String signatureShortStr = point.getSignature().toShortString();
//2. 打印入参信息
Object[] args = point.getArgs();
List filterArgs = getFilterArgs(args);
LOG.info("服务 {}, 入参: {}", signatureShortStr, JSON.toJSON(filterArgs));
//1.1 参数校验
Object firstParam = filterArgs.get(0);
if(firstParam != null) {
ValidateUtils.validate(firstParam);
//1.2 签名校验
BaseRpcRequest baseRpcRequest = (BaseRpcRequest) firstParam;
// 签名校验
Md5SignCheckUtils.checkSign(baseRpcRequest.getTraceId(), baseRpcRequest.getSign());
}
Object result = point.proceed();
LOG.info("服务 {}, 出参: {}", signatureShortStr, JSON.toJSON(result));
return result;
} finally {
LogUtil.removeMdc();
}
}
/**
* 避免 http 复杂参数异常
* @param args 参数
* @return 结果
*/
private List getFilterArgs(Object[] args) {
List list = new ArrayList<>();
if(ArrayUtil.isEmpty(args)) {
return list;
}
for(Object o : args) {
if(o instanceof HttpServletRequest) {
continue;
}
if(o instanceof HttpServletResponse) {
continue;
}
if(o instanceof MultipartFile) {
continue;
}
list.add(o);
}
return list;
}
}