自定义实现函数参数注解

如有侵权,请联系~
如有错误,欢迎批评指正!

1、自定义实现函数参数注解

背景:作为服务端参数的定义都是符合驼峰命名规则,但是客户端一般都是使用下划线。例如客户端版本号:服务端使用String versionName来接受,而客户端使用version_name进行传递。因此,服务端需要进行映射,每个接口都要进行映射,代码不够美观简练。所以函数参数注解诞生。

1.1、 声明定义注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestParamMapping {
	// 增加属性
	// boolean required() default true;
}

这个注解比较简单,没有任何属性。不过如果想要扩展功能,可以直接增加属性即可。在参数解析的时候使用

RequestParamMapping requestParamMapping = methodParameter.getParameterAnnotation(RequestParamMapping.class);
requestParamMapping.required(); // 这样就可以获取到上述属性,根据属性值做不同的逻辑处理。

1.2 实现HandlerMethodArgumentResolver接口

@Slf4j
public class ParameterNameConverterResolver implements HandlerMethodArgumentResolver {

    public static Logger SCRIBE_LOGGER = LoggerFactory.getLogger("scribe");

    /**
     * 参数中是不是有RequestParamMapping注解
     *
     * @param methodParameter the method parameter to check
     * @return
     */
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(RequestParamMapping.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
                                  NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory)
            throws Exception {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        Parameter parameter = methodParameter.getParameter();
        Class aClass = Class.forName(parameter.getType().getName());
        // 获取该类声明的所有属性
        Field[] declaredFields = aClass.getDeclaredFields();
        // 获取该类及其父类声明的所有public属性
        Field[] baseFields = aClass.getFields();
        // 去重,筛选该类中所有的public属性
        Set<Field> fieldSet = new HashSet<>(declaredFields.length + baseFields.length);
        fieldSet.addAll(Arrays.asList(declaredFields));
        fieldSet.addAll(Arrays.asList(baseFields));
        Object obj = aClass.newInstance();
        for (Field declaredField : fieldSet) {
            declaredField.setAccessible(true);
            String fieldName = declaredField.getName();
            String[] requestParameters = getRequestParamValues(request, fieldName);
            Object requestValue = null;
            try {
                requestValue = typeTransformer(declaredField, requestParameters);
            } catch (Exception e) {
                log.warn("request param transfer error", e);
            }
            // 防止赋值失败的异常,例如常量不能赋值,jacoco自动注入的变量$jacocoData
            try {
                declaredField.set(obj, requestValue);
            } catch (IllegalArgumentException | IllegalAccessException e) {
                continue;
            }
        }
        return obj;
    }

    /**
     * 从请求参数中获取数据的顺序:属性从驼峰转换成下划线 > 属性本身 > 首字母大写
     * 例如:对象属性为userId 从请求参数中获取的顺序 user_id > userId > UserId
     *
     * @param request
     * @param fieldName
     * @return
     */
    private String[] getRequestParamValues(HttpServletRequest request, String fieldName) {
        String underlineCase = StrUtil.toUnderlineCase(fieldName);
        String[] requestParameters = request.getParameterValues(underlineCase);
        if (ArrayUtil.isEmpty(requestParameters)) {
            requestParameters = request.getParameterValues(fieldName);
        }
        if (ArrayUtil.isEmpty(requestParameters)) {
            requestParameters = request.getParameterValues(StringUtils.capitalize(fieldName));
        }
        return requestParameters;
    }

    /**
     * 将获取到的数据转换为对象需要的类型
     *
     * @param declaredField
     * @param requestParameter
     * @return
     */
    private Object typeTransformer(Field declaredField, String[] requestParameter) {
        if (ArrayUtil.isEmpty(requestParameter)) {
            return null;
        }
        if (declaredField.getType().equals(Integer.class)) {
            return Integer.valueOf(requestParameter[0]);
        } else if (declaredField.getType().equals(Long.class)) {
            return Long.valueOf(requestParameter[0]);
        } else if (declaredField.getType().equals(Boolean.class)) {
            return Boolean.valueOf(requestParameter[0]);
        } else if (declaredField.getType().equals(Double.class)) {
            return Double.valueOf(requestParameter[0]);
        } else if (List.class.isAssignableFrom(declaredField.getType())) {
            return Arrays.asList(requestParameter);
        } else if (Set.class.isAssignableFrom(declaredField.getType())) {
            List<String> list = Arrays.asList(requestParameter);
            return new HashSet<>(list);
        }
        return StringUtils.join(requestParameter, ",");
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥都想学的又啥都不会的研究生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值