一:请求入参参数特殊字符过滤
对接平安银行等第三方接口的时候,接口入参不能包含某些字符串,但是不能做过滤器,过滤器影响面过广。
1、自定义注解
package fly.cloud.bank.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamReplace {
}
2、切面
package fly.cloud.bank.annotation.aspect;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import fly.cloud.bank.urtils.CharacterUtils;
import lombok.extern.slf4j.Slf4j;
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.springframework.stereotype.Component;
import java.util.*;
@Slf4j
@Component
@Aspect
public class ParamReplaceAspect {
@Around("@annotation(fly.cloud.bank.annotation.ParamReplace)")
public Object intercept(ProceedingJoinPoint joinPoint) throws Throwable {
//获取方法参数值数组
Object[] args = joinPoint.getArgs();
log.info("转化前参数:"+ JSON.toJSONString(args));
//得到其方法签名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//获取方法参数类型数组
Class[] paramTypeArray = methodSignature.getParameterTypes();
String[] parameterNames = methodSignature.getParameterNames();
Map<String,Object> params = new HashMap<>();
for (int i = 0; i < args.length; i++) {
params = judgeParam(args[i],parameterNames[i]);
log.info("args[i]"+ args[i]);
modifyParameterValues(params);
args[i] = changeParam(params,args[i],parameterNames[i],paramTypeArray[i]);
}
log.info("转化后参数:"+ JSON.toJSONString(args));
//动态修改其参数
//注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(Object[] args)
Object result = joinPoint.proceed(args);
log.info("响应结果为{}",result);
return result;;
}
private Object changeParam(Map<String, Object> params, Object arg, String parameterName,Class paramTypeArray) {
if ((arg instanceof String) || (arg instanceof Map) || (arg instanceof List)){ //参数为String、Map、List
arg = params.get(parameterName);
return arg;
}
arg = JSONObject.toJavaObject((JSON) JSON.toJSON(params),paramTypeArray);
return arg;
}
private Map<String, Object> judgeParam(Object arg,String parameterName) throws Throwable {
Map<String,Object> params = new HashMap<>();
if ((arg instanceof String) || (arg instanceof Map) || (arg instanceof List)){ //参数为String、Map、List
params.put(parameterName,arg);
}else{
params = new ObjectMapper().readValue(JSON.toJSONString(arg), new TypeReference<HashMap<String, Object>>() {});
}
return params;
}
/**
* 将parameter的值去除特殊字符后重写回去
*/
public void modifyParameterValues(Map<String,Object> params){
Set<String> set = params.keySet();
Iterator<String> it=set.iterator();
while(it.hasNext()){
String key= it.next();
//处理参数
getValueByKey(params,key);
}
}
private void getValueByKey(Map<String,Object> params,String key) {
Object value = judgeObject(params.get(key));
params.put(key,value);
}
private Object recursiveReplaceCharacter(Map<String, Object> vo) {
Map<String, Object> replaceMap = new HashMap<>();
for(String key : vo.keySet()){//keySet获取map集合key的集合 然后在遍历key即可
Object replaceMapValue = vo.get(key);
Object a = judgeObject(replaceMapValue);
replaceMap.put(key,a);
}
return replaceMap;
}
private Object judgeObject(Object replaceMapValue) {
if (null == replaceMapValue) {
//key对应的值为空
return null;
}
if (replaceMapValue instanceof String) {
//key对应的值为String类型, 去空格后重新放入map
return CharacterUtils.replaceBankParameter((String) replaceMapValue);
} else if (replaceMapValue instanceof Map) {
return recursiveReplaceCharacter((Map<String,Object>) replaceMapValue);
} else if (replaceMapValue instanceof List) {
//key对应的值为List类型
List<Object> alist = (List<Object>) replaceMapValue;
for (int i = 0; i < alist.size(); i++) {
//遍历list
Object vol = alist.get(i);
if (vol instanceof String) {
//list里的元素为String, 去空格
alist.set(i, CharacterUtils.replaceBankParameter((String) vol));
} else if (vol instanceof Map) {
//list里的元素为Map, 递归处理
alist.set(i, recursiveReplaceCharacter((Map<String,Object>) vol));
}
}
return alist;
}
return replaceMapValue;
}
}
3、特殊字符过滤的工具类
@Slf4j
public class CharacterUtils {
/**
* 替换银行入参特殊字符
*/
public static String replaceBankParameter(String str){
String regEx = "[‘&;\\[\\]<>|]";
str = Pattern.compile(regEx).matcher(str).replaceAll("").trim();
return str;
}
}
二、日志切面
package fly.cloud.bank.annotation;
import fly.cloud.bank.urtils.CharacterUtils;
import fly.cloud.common.base.utils.LocalThreadContextHolder;
import fly.cloud.common.base.vo.ResultVO;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Aspect
@Component
@Slf4j
public class LogAspectHandler {
@Pointcut("execution(public * fly.cloud.bank.controller..*.*(..))")
public void controllerMethod() {
}
/**
* 方法执行前
*
* @param joinPoint
* @throws Exception
*/
@Before("controllerMethod()")
public void LogRequestInfo(JoinPoint joinPoint) throws Exception {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
StringBuilder requestLog = new StringBuilder();
Signature signature = joinPoint.getSignature();
ApiOperation annotation = ((MethodSignature) signature).getMethod().getAnnotation(ApiOperation.class);
String messageName = "";
if (annotation != null) {
messageName = annotation.value();
}
requestLog.append("\n请求方法:").append(messageName).append("\n")
.append("请求信息:").append("URL = {").append(request.getRequestURI()).append("},\n")
.append("请求方式 = {").append(request.getMethod()).append("},\n")
.append("userInfoId = {").append(LocalThreadContextHolder.getUserInfoId()).append("},\n")
.append("请求IP = {").append(request.getRemoteAddr()).append("},\n")
.append("类方法 = {").append(signature.getDeclaringTypeName()).append(".")
.append(signature.getName()).append("},\n");
// 处理请求参数
String[] paramNames = ((MethodSignature) signature).getParameterNames();
Object[] paramValues = joinPoint.getArgs();
int paramLength = null == paramNames ? 0 : paramNames.length;
if (paramLength == 0) {
requestLog.append("请求参数 = {} ");
} else {
requestLog.append("请求参数 = [");
for (int i = 0; i < paramLength - 1; i++) {
requestLog.append(paramNames[i]).append("=").append(CharacterUtils.toString(paramValues[i])).append(",");
}
requestLog.append(paramNames[paramLength - 1]).append("=").append(CharacterUtils.toString(paramValues[paramLength - 1])).append("]");
}
log.info(requestLog.toString());
}
/**
* 方法执行后
* @param resultVO
* @throws Exception
*/
@AfterReturning(returning = "resultVO", pointcut = "controllerMethod()")
public void logResultVOInfo(ResultVO resultVO) throws Exception {
log.info("请求结果:" + resultVO.getCode() + "\t" + resultVO);
}
}
@Slf4j
public class CharacterUtils {
public static String toString(Object value){
log.info("value [{}]",value);
if (value instanceof MultipartFile)
log.info("对象是 MultipartFile 类的实例");
else if (value instanceof ServletRequest)
log.info("对象是 ServletRequest 类的实例");
else if(value instanceof ServletResponse)
log.info("对象是 ServletResponse 类的实例");
if(null == value){
return "";
}
if(value instanceof MultipartFile || value instanceof ServletRequest || value instanceof ServletResponse){
return "";
}
return JSONObject.toJSONString(value);
}
}