get请求拦截解码
最近项目需要书写一个简单的AOP去拦截解码GET请求的所有参数,在网上看了一下,没有找到现成可用的,所有个人完成后发出来大家分享一下。废话不多说,直接上代码。
@Aspect
@Order
@Component
@Slf4j
public class GetMethodsTranscodingHandler {
//此处因为是拦截get请求,我们项目是springboot框架,所有get方法都有@getting注解,所有切此注解。
@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
public void GetMapping() {
}
//设置切面, 多个切入点字段加解密aop技术,反射机制
@Around("GetMapping()")
public Object doProcess(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
MethodSignature signature = (MethodSignature)proceedingJoinPoint.getSignature();
Method method = signature.getMethod();
log.info(method +"=====请求解码=======");
//捕获方法参数列表
Object[] methodArgs = proceedingJoinPoint.getArgs();
//参数名称列表
// List<String> paramterNames = getParamterName(method);
List<Object> list = new ArrayList<>();
//循环所有参数
for (int i = 0; i < methodArgs.length; i++) {
Object arg = methodArgs[i];
if(arg == null){
list.add(arg);
continue;
}
// 获取对象类型
Class<?> classType = arg.getClass();
//判断是否是基本类型 是否是java./javax/org.等开头的spring中的参数,比如request if (classType.isPrimitive() || classType.getName().startsWith("java.")
|| classType.getName().startsWith("javax.") || classType.getName().startsWith("org.")) {
arg = URLDecoder.decode(String.valueOf(arg), "UTF-8");
list.add(arg);
} else {
//递归处理参数
dealWithFileds(arg);
list.add(arg);
}
}
Object result = proceedingJoinPoint.proceed(list.toArray());
return result;
}
//递归解码所有的方法参数
private void dealWithFileds(Object arg) {
Field[] fields = arg.getClass().getDeclaredFields();
for (Field f : fields) {
Class<?> clazzType = f.getType();
try {
//设置private属性可以访问
f.setAccessible(true);
//此处必须判空,否则下面的decode方法会将null转为"null"字串
Object o = f.get(arg);
if (o == null){
continue;
}
//直到递归至所有参数都到基本类型和最底层
if (clazzType.isPrimitive() || clazzType.getName().startsWith("java.")
|| clazzType.getName().startsWith("javax.") || clazzType.getName().startsWith("org.")) {
//中英文解码,只需要解码字串
if(arg instanceof String) {
f.set(arg, URLDecoder.decode(String.valueOf(o), "UTF-8"));
}
} else {
dealWithFileds(f);
}
} catch (Exception e) {
log.error("get 请求解码异常");
}
}
}
}
扩展一下关于AOP的其他知识,上面用的是切spring自带的@Getting注解的方式,我们也可以去自定义注解,然后加到自己 想切的方法上。
@Target({ElementType.METHOD})//作用于方法维度
@Retention(RUNTIME)
public @interface AOPTest {
string name;
...
}
public class Method{
@AOPTetst
public void test(){
}
}
还有,如果觉得使用注解去切太麻烦,可以使用execution表达式 去定义切面。
//第一个*代表任意返回值
//*..*代表任意包名
//比如切到service可以这么写
//然后.*就是任意方法(..)代表任意参数,如果不写..就是代表无参方法
@before(value="execution(* *..*.*.*servicecImpl.*(..))")
public Object doProcess(){}
写的不够优雅,欢迎交流。抛出一个问题,大家觉得的可以用拦截器或者过滤器来实现吗?
此致 敬礼!