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.完美 

posted @ 2021-05-14 10:54  李东平|一线码农  阅读(17430)  评论(3编辑  收藏  举报