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