在前后端开发中经常遇到前端传入get
请求,后端使用对应字段接收,即可完成参数与值的映射,形如下边代码所示:
http://localhost:8080/query/user?id=123&user_name=zhangsan&phone=13647567643
@getMapping(/query/user)
public User query(@requestParam("id") String id,@requestParam("user_name") String userName,@requestParam("phone") String phone){
return userService.queryUser(id,userName,phone);
}
如果请求参数较少,可采用上述方式进行参数接收,且非常方便,但实际工作中会遇到请求参数非常多,但使用get
请求接收,也许有同学会说,参数多为何不用post
请求,实际情况会存在某些祖传代码不可修改,后续做功能兼容则会出现,因为本人在项目中就遇到如此情况。下边就是为了解决遇到的问题,保证前端请求方式不变(get
请求),后端使用实体接收。
@Data
public Class User(){
private String id;
private String userName;
private String phone;
}
@getMapping(/query/user)
public User query(User user){
return user;
}
get
请求,后端实体接收问题同方法1
由于上述两种方式均存在前端请求参数与后端实体属性必须完全对应才能正常解析,且公司前端使用下划线而后端属性使用驼峰命名,因此上述两种方式均不能满足此时业务场景,故只有自己实现,下边为具体实现步骤。
@Data
public Class User(){
private String id;
@JsonProprty("user_name")
private String userName;
private String phone;
}
模仿
springmvc
中存在的注解@RequestBody
定义注解,主要用于后续请求参数对应实体解析
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtRequestBody {
}
processor
参考
springmvc
中定义的processor
实现参数解析
public class ExtRequestBodyMethodProcessor implements HandlerMethodArgumentResolver {
private static final String SET = "set";
private static final String SPLITTER = ",";
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(ExtRequestBody.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) {
ExtRequestBody ann = parameter.getParameterAnnotation(ExtRequestBody.class);
Assert.state(ann != null, "No GetBody annotation");
Class<?> clazz = parameter.getParameterType();
Object target;
try {
target = processFiledValue(webRequest, clazz);
} catch (Exception e) {
throw new BusinessException(e.getMessage(), ResultCode.INVALID_ARGS.getCode());
}
return target;
}
/**
* @description:处理请求参数值
* @author:milk
* @date: 2020/1/8 下午1:36
*/
private Object processFiledValue(NativeWebRequest webRequest, Class<?> clazz) throws Exception {
Object target = clazz.newInstance();
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
JsonProperty annotation = declaredField.getAnnotation(JsonProperty.class);
String filedName = Objects.nonNull(annotation) ? annotation.value() : declaredField.getName();
String value = getParamValue(webRequest, filedName);
if (StringUtils.isEmpty(value)) {
continue;
}
Object parseObj = processFiledType(declaredField, value);
Method declaredMethod = clazz
.getMethod(getMethodName(declaredField.getName()), declaredField.getType());
declaredField.setAccessible(true);
declaredMethod.invoke(target, parseObj);
}
return target;
}
/**
* @description:参数值类型转换
* @author:milk
* @date: 2020/1/8 下午2:51
*/
private Object processFiledType(Field declaredField, String value) {
Object resultValue = value;
String fieldType = declaredField.getType().getName();
try {
if (Objects.equals(fieldType, Integer.class.getName())) {
resultValue = Integer.valueOf(value);
} else if (Objects.equals(fieldType, String.class.getName())) {
resultValue = value;
} else if (Objects.equals(fieldType, Byte.class.getName())) {
resultValue = Byte.valueOf(value);
} else if (Objects.equals(fieldType, Long.class.getName())) {
resultValue = Long.valueOf(value);
} else if (Objects.equals(fieldType, Double.class.getName())) {
resultValue = Double.valueOf(value);
}
} catch (Exception e) {
throw new BusinessException(ResultCode.INVALID_ARGS);
}
return resultValue;
}
/**
* @description:获取set方法名
* @author:milk
* @date: 2020/1/8 下午1:56
*/
private String getMethodName(String name) {
return SET + name.substring(0, 1).toUpperCase() + name.substring(1);
}
/**
* @description:获取请求参数
* @author:milk
* @date: 2020/1/8 下午1:32
*/
private String getParamValue(NativeWebRequest webRequest, String fieldName) {
return webRequest.getParameter(fieldName);
}
}
processor
加载进spring
@Configuration
public class ExtWebFluxConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new ExtRequestBodyMethodProcessor());
}
}
功能实现步骤
1.GetBody ann = parameter.getParameterAnnotation(ExtRequestBody.class);
,判断接收接口是否添加注解ExtRequestBody
2.根据请求webRequest
获取参数实体类型,并反射获取实体属性
3.实体中填加fastJson
中注解JsonProperty
,该注解后边值即为前端传入参数格式
4.根据字段属性值获取请求参数值,并将值赋值给实体对应属性
5.最后返回反射对象
测试结果
(1) 后端接收
@GetMapping("/query/user")
public User querUser(@GetBody User user) {
return user;
}
(2) 运行结果