Spring AOP切面注解类应用实例:请求入参参数特殊字符过滤、日志切面

一:请求入参参数特殊字符过滤

对接平安银行等第三方接口的时候,接口入参不能包含某些字符串,但是不能做过滤器,过滤器影响面过广。

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);
    }
}

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值