• springboot接口入参下划线转驼峰以及返回参数驼峰转下划线实现


    1.背景

    在实际开发中,通常来说java里面是使用驼峰的命名规则;

    但是有时候在对接其他三方平台的接口时,要求使用下划线的命名规则,这时候就涉及到如何让自己的接口满足三方平台的下划线;

    实现方式有

    1.java里面也使用下下划线的方式接收和响应,但是不推荐这样,因为虽然满足了接口需求,但是不符合java里面的命名规范;

    2.java里面使用驼峰,接收到参数后手动转换,这样做太麻烦.

    3.java里面使用驼峰,写一个工具方法,通过注解的方式,统一转换,推荐,也是实际开发中常用的方式

    那些地方需要转换

    1.传入参数的时候(下换线转为驼峰)

    2.响应结果的时候(驼峰转为下划线)

    因为响应结果的时候(驼峰转为下划线)比较简单,先搞定这个

    2.响应结果的时候(驼峰转为下划线)

    方式一:在返回对象的类上加注解(推介)

    @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
    案例如下:

    方法二:在字段上注解

    @JsonProperty(value = "order_card")

    3.传入参数的时候(下换线转为驼峰)

    方式一:自己手动封装,不推荐,略;

    方式二:接收为Map对接,通过Json转换(如果系统中只有少数个别接口需要转换,可以这样写);

    步骤一:接收对象上的字段上加注解 @JsonProperty(value = "order_card")

     步骤二:控制层出的写法如下

    方式三:通过实现接口HandlerMethodArgumentResolver的方式,强烈推荐

    步骤一:自定义注解 ParameterConvert

    @Target(value = ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ParameterConvert {
    }
    View Code

    步骤二:自定义类AbstractCustomizeResolver

    import org.springframework.core.Conventions;
    import org.springframework.core.MethodParameter;
    import org.springframework.core.annotation.AnnotationUtils;
    import org.springframework.validation.BindingResult;
    import org.springframework.validation.Errors;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.WebDataBinder;
    import org.springframework.web.bind.support.WebDataBinderFactory;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    import java.lang.annotation.Annotation;
    
    /**
     * @Copyright (C) XXXXXXXXXXX科技股份技有限公司
     * @Author: lidongping
     * @Date: 2021-05-13 19:24
     * @Description:
     */
    public abstract class AbstractCustomizeResolver implements HandlerMethodArgumentResolver {
        /**
         * 校验
         *
         * @param parameter
         * @param mavContainer
         * @param webRequest
         * @param binderFactory
         * @param arg
         * @throws Exception
         */
        protected void valid(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory, Object arg) throws Exception {
            String name = Conventions.getVariableNameForParameter(parameter);
            WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
            if (arg != null) {
                validateIfApplicable(binder, parameter);
                if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
                    throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
                }
            }
            mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
        }
    
        /**
         * @param binder
         * @param parameter
         */
        protected void validateIfApplicable(WebDataBinder binder, MethodParameter parameter) {
            Annotation[] annotations = parameter.getParameterAnnotations();
            for (Annotation ann : annotations) {
                Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
                if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
                    Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann));
                    Object[] validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[]{hints});
                    binder.validate(validationHints);
                    break;
                }
            }
        }
    
        protected boolean isBindExceptionRequired(WebDataBinder binder, MethodParameter parameter) {
            int i = parameter.getParameterIndex();
            Class<?>[] paramTypes = parameter.getMethod().getParameterTypes();
            boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));
            return !hasBindingResult;
        }
    
    }
    View Code

    步骤三:自定义类 UnderlineToCamelArgumentResolver

    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.BeanWrapper;
    import org.springframework.beans.PropertyAccessorFactory;
    import org.springframework.core.MethodParameter;
    import org.springframework.web.bind.support.WebDataBinderFactory;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    import java.util.Iterator;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class UnderlineToCamelArgumentResolver extends AbstractCustomizeResolver {
        /**
         * 匹配_加任意一个字符
         */
        private static final Pattern UNDER_LINE_PATTERN = Pattern.compile("_(\w)");
    
        @Override
        public boolean supportsParameter(MethodParameter methodParameter) {
            return methodParameter.hasParameterAnnotation(ParameterConvert.class);
        }
    
        @Override
        public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
                                      NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
            Object org = handleParameterNames(methodParameter, nativeWebRequest);
            valid(methodParameter, modelAndViewContainer, nativeWebRequest, webDataBinderFactory, org);
            return org;
        }
    
        /**
         * 处理参数
         *
         * @param parameter
         * @param webRequest
         * @return
         */
        private Object handleParameterNames(MethodParameter parameter, NativeWebRequest webRequest) {
            Object obj = BeanUtils.instantiate(parameter.getParameterType());
            BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(obj);
            Iterator<String> paramNames = webRequest.getParameterNames();
            while (paramNames.hasNext()) {
                String paramName = paramNames.next();
                Object o = webRequest.getParameter(paramName);
                System.out.println(paramName + "=" + o);
                wrapper.setPropertyValue(underLineToCamel(paramName), o);
            }
            return obj;
        }
    
        /**
         * 下换线转驼峰
         *
         * @param source
         * @return
         */
        private String underLineToCamel(String source) {
            Matcher matcher = UNDER_LINE_PATTERN.matcher(source);
            StringBuffer result = new StringBuffer();
            while (matcher.find()) {
                matcher.appendReplacement(result, matcher.group(1).toUpperCase());
            }
            matcher.appendTail(result);
            return result.toString();
        }
    }
    View Code

    步骤四:整合到springboot中,在WebConfig中添加如下代码

     @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            argumentResolvers.add(new UnderlineToCamelArgumentResolver());
        }
    View Code

     步骤五:使用,很简单,在接收参数的对象前加注解

    4.完美 

  • 相关阅读:
    时钟同步
    通过 profiling 定位 golang 性能问题
    览器全面禁用三方 Cookie 全栈前端精选 4月16日
    为什么Go自带的日志默认输出到os.Stderr?
    gRPC Motivation and Design Principles | gRPC https://grpc.io/blog/principles/
    应用安全开发指南
    Hash Join: Basic Steps
    Building a high performance JSON parser
    阿姆达尔定律 Amdahl's law
    贝壳找房小程序平台架构演进
  • 原文地址:https://www.cnblogs.com/newAndHui/p/14767675.html
Copyright © 2020-2023  润新知