起因
本番環境では、エラーが発生し、振り返ってみることで、あなたは、インターフェイスやメソッドのエラーを見つけることができますが、引数がない場合は、問題を再現することはできませんので、リクエストの記録パラメータということ、質問を繰り返しすることが重要です
需要
図1は、方法及び印刷要求のパラメータ
2、及び関連するユーザは、リストタイプ(ロング)印刷パラメータがないパスワード
実装プロセス
1、AOPクラスを追加、実行モードセクションを使用
@Slf4j
@Aspect
@Component
public class ControllerLog {
private static final ThreadLocal<Long> START_TIME_THREAD_LOCAL =
new NamedThreadLocal<>("ThreadLocal StartTime");
private static final ThreadLocal<Integer> ID_THREAD_LOCAL =
new NamedThreadLocal<>("ThreadLocal ID");
private static final ThreadLocal<String> LOG_PREFIX_THREAD_LOCAL =
new NamedThreadLocal<>("ThreadLocal LogPrefix");
/**
* <li>Before : 在方法执行前进行切面</li>
* <li>execution : 定义切面表达式</li>
* <p>public * com.example.javadevelopmentframework.javadevelopmentframework.controller..*.*(..))
* <li>public :匹配所有目标类的public方法,不写则匹配所有访问权限</li>
* <li>第一个* :方法返回值类型,*代表所有类型 </li>
* <li>第二个* :包路径的通配符</li>
* <li>第三个..* :表示impl这个目录下所有的类,包括子目录的类</li>
* <li>第四个*(..) : *表示所有任意方法名,..表示任意参数</li>
* </p>
*
* @param
*/
@Pointcut("execution(public * XXX.XXX.XXX.*.*.controller..*.*(..))")
public void exectionMethod() {
}
@Before("exectionMethod()")
public void doBefore(JoinPoint joinPoint) {
START_TIME_THREAD_LOCAL.set(System.currentTimeMillis());
// 接收到请求,记录请求内容
StringBuilder argsDes = new StringBuilder();
//获取方法名
String className = joinPoint.getSignature().getDeclaringType().getSimpleName();
String methodName = joinPoint.getSignature().getName();
String logPrefix = className + "." + methodName + "()";
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Object[] args = joinPoint.getArgs();
Method method = signature.getMethod();
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
if (args != null && paramNames != null) {
argsDes.append(LogUtil.getMethodParams(signature, args, paramNames));
}
LOG_PREFIX_THREAD_LOCAL.set(logPrefix);
int id = RandomUtil.randomInt();
ID_THREAD_LOCAL.set(id);
log.info("id={} =========开始请求:{},参数:{}", id, logPrefix, argsDes.toString());
}
@AfterReturning(pointcut = "exectionMethod()", returning = "rtn")
public Object doAfter(Object rtn) {
long endTime = System.currentTimeMillis();
long begin = START_TIME_THREAD_LOCAL.get();
if (rtn instanceof R) {
R result = (R) rtn;
if (result.getErrcode() != HttpStatus.OK.value()) {
log.warn("请求异常:{},响应结果:{}", getLogPrefix(), rtn);
}
}
log.info("id={} =========结束请求:{},耗时:{} ms", ID_THREAD_LOCAL.get(), getLogPrefix(), endTime - begin);
destroyThreadLocal();
return rtn;
}
private static String getLogPrefix() {
return LOG_PREFIX_THREAD_LOCAL.get();
}
private static void destroyThreadLocal() {
START_TIME_THREAD_LOCAL.remove();
LOG_PREFIX_THREAD_LOCAL.remove();
ID_THREAD_LOCAL.remove();
}
}
2、LogUtil.getMethodParams実装方法
public static StringBuilder getMethodParams(MethodSignature signature, Object[] args, String[] paramNames) {
StringBuilder params = new StringBuilder();
//密码类型的信息,不打印出来
PasswordType passwordType = signature.getMethod().getAnnotation(PasswordType.class);
if (null == passwordType) {
for (int i = 0; i < args.length; i++) {
//参数类型为List的参数也不打印值
if (args[i] instanceof List) {
params.append(paramNames[i]).append("=").append("【List类型的参数不打印】").append(",");
} else {
params.append(paramNames[i]).append("=").append(args[i]).append(",");
}
}
} else {
String[] fieldNames = passwordType.fieldNames();
for (int i = 0; i < args.length; i++) {
Map<String, Object> map = JsonUtil.objectToMap(args[i]);
for (String fieldName : fieldNames) {
if (map != null && map.containsKey(fieldName) && null != map.get(fieldName)) {
map.put(fieldName, "*");
}
}
params.append(paramNames[i]).append("=").append(map).append(",");
}
}
return params;
}
3、@PasswordTypeノート、デフォルトのパスワードが、他の名前があるかもしれません
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PasswordType {
String[] fieldNames() default {"password"};
}
4、@ PasswordTypeは例を使用して
、パスワードを変更するには、JSONのパラメータの受け渡しを
@PasswordType(fieldNames = {"password","newPassword"})
@PostMapping("/editPwd")
public R changePwd(@Valid @RequestBody UserChangePwdParamDTO dto) {
}
効果
04-09 15:24:12.245 INFO [xxx.xxx.xxx.aop.ControllerLog] - id=1638566979 =========开始请求:XXXXController.getSetting(),参数:yxH=10572,
04-09 15:24:12.255 INFO [xxx.xxx.xxx..aop.ControllerLog] - id=1638566979 =========结束请求:XXXXController.getSetting(),耗时:11 ms