有属性的自定义注解,如何获取到post请求中RequestBody中对象的一个属性值?

1,写两个自定义注解,一个作用于方法的,一个作用于字段的
作用于方法的自定义注解代码:

package com.youku.nintendo.annotation;


import enums.PermissionPatternEnum;
import enums.PermissionTypeEnum;

import java.lang.annotation.*;


@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
    PermissionTypeEnum permissionItem();
    PermissionPatternEnum permissionPattern() default PermissionPatternEnum.ACT_CONGIG_PERMISSION;
    String parameterName();
}

作用于字段的自定义注解代码:

package com.youku.nintendo.annotation;

import java.lang.annotation.*;


@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER,ElementType.FIELD})
public @interface PermissionKey {

    String value();
}

怎么写权限切面呢?如何获取到post请求中RequestBody中对象的一个属性值呢?

package com.youku.nintendo.aspect;


import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.taobao.hsf.annotation.Order;
import com.youku.nintendo.annotation.Permission;
import com.youku.nintendo.annotation.PermissionKey;
import com.youku.nintendo.api.base.result.RttResult;
import com.youku.nintendo.common.constant.ActivityCfgType;
import com.youku.nintendo.manager.AclManager;
import com.youku.nintendo.manager.ActivityCfgManager;
import com.youku.nintendo.utils.MathUtil;
import com.youku.nintendo.vo.ActivityCfgVo;
import enums.PermissionTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.youku.nintendo.common.constant.ErrorCode.ERR_ACTIVITY_CONFIG_DATA_ERROR;

@Aspect
@Component
@Order(2)
@Slf4j
public class ACLPermission {

   
    @Around(value = "@annotation(permission)")
    public Object aroundHttpPermission(ProceedingJoinPoint thisJoinPoint, Permission permission) throws Throwable{
        log.info("aroundHttpPermission into: {}", JSON.toJSONString(permission));
        Object[] args = thisJoinPoint.getArgs();
        log.info("JoinPoint,args={}", JSON.toJSONString(args));
        Method method = ((MethodSignature) thisJoinPoint.getSignature()).getMethod();
        log.info("JoinPoint,method={}", JSON.toJSONString(method));
        String parameter = getParameter(permission.parameterName(),method.getParameters(),args);
        log.info("aroundHttpPermission parameter: {}", JSON.toJSONString(parameter));
        if (parameter==null){
            return thisJoinPoint.proceed();
        }

     
        return thisJoinPoint.proceed();
    }

    public String getParameter(String parameterName, Parameter[] parameters, Object[] args) throws IllegalAccessException, InvocationTargetException {
        Map<String,Object> keyAndArgMap = Maps.newHashMap();
        for (int i = 0; i < parameters.length; i++) {
            PermissionKey permissionKey = parameters[i].getAnnotation(PermissionKey.class);
            if (Objects.nonNull(permissionKey)){
                keyAndArgMap.put(permissionKey.value(),args[i]);
            }
        }
            if (parameterName.startsWith("${") && parameterName.endsWith("}")){
                String realKey = parse(parameterName, keyAndArgMap);
                if (StringUtils.isNotBlank(realKey)){
                   return realKey;
                }
            }else {
                Object arg = keyAndArgMap.get(parameterName);
                if (Objects.isNull(arg)){

                }
                return String.valueOf(arg);
            }
            return null;
    }

    /**
     * 解析 目前只简单解析"."符号
     * @param key
     * @param keyAndArgMap
     * @return
     * @throws IllegalAccessException
     */
    private String parse(String key, Map<String,Object> keyAndArgMap) throws IllegalAccessException, InvocationTargetException {
        int index = key.indexOf("${");
        int lastIndex = key.lastIndexOf("}");
        String realKey = key.substring(index + 2, lastIndex);
        String[] split = realKey.split("\\.");
        Object target = keyAndArgMap.get(split[0]);
        if (Objects.isNull(target)){
            //配置有误
        }
        for (int i = 1; i <split.length; i++) {
            Method[] methods = target.getClass().getMethods();
            boolean find = false;
            for (Method method : methods) {
                String name = method.getName();
                String upperCaseFirst = buildGetMethodName(split[i]);
                if (name.equals(upperCaseFirst)){
                    method.setAccessible(true);
                    target = method.invoke(target);
                    find = true;
                }
            }
            if (!find){
                //如果没有匹配到真实值,说明配置有误
            }
        }
        return String.valueOf(target);
    }

    private String buildGetMethodName(String str){
        char upperCase = Character.toUpperCase(str.charAt(0));
        StringBuilder builder = new StringBuilder(str.length());
        builder.append("get");
        builder.append(upperCase);
        for (int i = 1; i < str.length(); i++) {
            builder.append(str.charAt(i));
        }
        return builder.toString();
    }

}


注意:关于 method.setAccessible(true);
target = method.invoke(target);这两句代码啥意思?
见文章:
https://blog.csdn.net/qq_42292373/article/details/102469975
http://www.wityx.com/post/22598_1_1.html

如何使用这个自定义注解?


    @Permission(permissionItem = PermissionTypeEnum.CONFIG, parameterName = "${acfg.activityCfgCode}")
    **@PostMapping**("activityCfg/update/white/user")
    public RttResult<Void> updateActivityConfigWhiteUser(@RequestBody @PermissionKey("acfg") ActivityCfgUpdateRequest activityCfgUpdateRequest) {
    }
   

那上面是post请求的获取请求参数值的方式,那get请求呢?

get请求就很简单了,使用方式如下:

 @Permission(permissionItem = PermissionTypeEnum.CONFIG, parameterName = "activityCfgCode")
    @PostMapping("activityCfg/update/version")
    public RttResult<Void> updateActivityConfigVersion(@RequestParam @PermissionKey("activityCfgCode") String activityCfgCode) {
    }

这种是请求参数直接就是想要获取的值,
我发现前提是get请求,如果请求参数在request中,此时也能直接在自定义注解中的属性中获取到request中的某一参数值。
示例如下代码中的idParameterName = “act_id”

 @Permission(permissionItem = PermissionItemEnum.ACTIVITY, permissionPattern = PermissionPatternEnum.LINE_PERMISSION, idParameterName = **"act_id"**)
    @ResponseBody
    @RequestMapping(value = "/visualOptimization", method = RequestMethod.GET)
    public ResultDTO visualOptimization(HttpServletRequest request) {
      Map<String, String[]> parameterMap = new HashMap<String, String[]>(r**equest.getParameterMap());**
        Set<String> keys = parameterMap.keySet();
        int size = keys.size();
        int k = 0;
        for (String pkey : keys) {
            k++;
            String[] b = parameterMap.get(pkey);
            url += pkey + "=";
            if (b != null && b.length != 0) {
                String value = null;
                try {
                    value = URLEncoder.encode(b[0], "UTF-8");

                    //替换活动id
                    **if ("act_id".equals(pkey)) {**
                        HollywoodActivityDO activityDO = activityService.queryById(Long.parseLong(value));
                        value = activityDO.getActivityId();
                    }
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                if (k != size) {
                    url += value + "&";
                } else {
                    url += value;
                }
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值