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 { }
步骤二:自定义类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; } }
步骤三:自定义类 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(); } }
步骤四:整合到springboot中,在WebConfig中添加如下代码
@Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(new UnderlineToCamelArgumentResolver()); }
步骤五:使用,很简单,在接收参数的对象前加注解