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 {
}
步骤二:自定义类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());
}

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

4.完美
springboot接口入参下划线转驼峰以及返回参数驼峰转下划线实现的更多相关文章
- springboot项目中接口入参的简单校验
.katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...
- Spring AOP 自定义注解获取http接口及WebService接口入参和出参
注解方法实现过程中可以采用如下获取方式:—以下为例 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHo ...
- java接口入参模板化,适用于企业化服务远程调度模板化的场景,接口入参实现高度可配置化
需求:远程服务接口模板化配置提供接入服务 模板接口分为三个模块:功能路由.参数校验.模板入库 路由:这里的实现方式很简单,就是根据业务标识找到对应的处理方法 参数校验: 参数校验这步涉及模板和校验类两 ...
- (一)将mockjs集成到VUE中后,怎样根据接口入参返回mock结果
1)安装mockjs,这一步跳过 2)在项目中建立mock模块,笔者的目录结构如下 mock模块与接口模块一一对应,有一个接口,就有一个mock 3)编写登陆模块mock接口,代码如下: import ...
- robot:接口入参为图片时如何发送请求
https://www.cnblogs.com/changyou615/p/8776507.html 接口是上传图片,通过F12抓包获得如下信息 由于使用的是RequestsLibrary,所以先看一 ...
- RobotFramework:发现一个大坑,当post接口入参为json时,千万不能用sojson转化后的json串(ride解析会有异常,非sojson工具问题),直接用浏览器粘过来的就行
问题背景: 和以往一样愉快的进行着自动化测试,突然就不停的提示我,“程序异常”,查看log发现data中的json变为了数组?????? 那算了,我不先组装入参数据直接data=json入参吧,wha ...
- Postman—上个接口返回数据作为下个接口入参
//将数据解析成json格式 var data=JSON.parse(responseBody); //获取totalRentPrice值 var totalRentPrice=jsonData.da ...
- pytest.9.使用fixture参数化接口入参
From: http://www.testclass.net/pytest/test_api_using_params/ 背景 接上一节v2ex网站的查看论坛节点信息的api.具体如下: 节点信息 获 ...
- springBoot controller入参LocalDateTime
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss") @DateTimeForma ...
- 入参是小数的String,返回小数乘以100的String
String money = request.getParameter("orderAmt"); BigDecimal moneyDecimal = new BigDecimal( ...
随机推荐
- 异步任务处理注解方法@Async实现异步多线程
异步任务处理注解方法@Async实现异步多线程 1.定义配置类,设置参数2.定义任务执行类3.执行Spring 中的ThreadPoolExecutor是借助JDK并发包中的java.util.con ...
- SpringBoot的Security和OAuth2的使用
创建项目 先创建一个spring项目. 然后编写pom文件如下,引入spring-boot-starter-security,我这里使用的spring boot是2.4.2,这里使用使用spring- ...
- ssh_exchange_identification: Connection closed by remote host 错误解决方案
问题 今天登陆服务器时候,ssh 后返回 ssh_exchange_identification: Connection closed by remote host 错误,重试了几次,会有一定概率失败 ...
- 解决模拟器中交换机不通的bug
模拟器实在是坑,相信大家都遇到过. 几个交换机连在一起,有冗余的线路,连两台PC,结果它们死活都通不了. 而且!!!交换机还会疯狂报错 *Aug 2 03:06:39.561: %AMDP2_FE-6 ...
- CLR via C# 笔记 -- 枚举(15)
1. 枚举继承System.Enum,后者继承 System.ValueType,所以枚举是值类型. 2. 枚举不能定义任何方法.属性和事件,不过可以定义扩展方法 3. ToString()方法 Co ...
- hadoop集群配置文件与功能对应解析
以三个节点的集群为例: 总括: nodemanager ,datanode --> slavesresourcemanager ----------> yarn namenode ...
- UF_MB_ask_button_id 测试
# tesy UF_MB_ask_button_id import NXOpen import NXOpen_UF as nuf def main(): ses = NXOpen.Session.Ge ...
- GUI测试
标签(空格分隔): GUI 我要用到 Chrome 浏览器,所以需要先下载 Chrome Driver 并将其放入环境变量.接下来,你可以用自己熟悉的方式建立一个空的 Maven 项目,然后在 POM ...
- js - 面向对象--手稿
- 【JavaScript】js中的浅拷贝与深拷贝与手写实现
前言 什么是深拷贝与浅拷贝?深拷贝与浅拷贝是js中处理对象或数据复制操作的两种方式.在聊深浅拷贝之前咱得了解一下js中的两种数据类型: 基本数据类型(6种) String.Number.Object ...