开发实战|第一篇:springmvc中get请求实体接收

1.说明

在前后端开发中经常遇到前端传入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请求),后端使用实体接收。

1.直接接收

  • 定义实体
    @Data
    public Class User(){
           
    	
    	private String id;
    
    	private String userName;
    
    	private String phone;
    }
    
  • 前端请求
    开发实战|第一篇:springmvc中get请求实体接收_第1张图片
  • 后端接收
    @getMapping(/query/user)
    public User query(User user){
           
    	return user;
    }
    
  • 返回结果
    开发实战|第一篇:springmvc中get请求实体接收_第2张图片
    根据返回结果可知,请求参数被解析返回,因此此方法能解决get请求,后端实体接收问题
  • 存在问题
    该方法只能保证前端传的参数与后端参数完全一致,即如果前端传下划线,后端字段使用驼峰接收,则无法接收,测试结果如下图所示
    开发实战|第一篇:springmvc中get请求实体接收_第3张图片

2.添加注解(@ModelAttribute)

同方法1

3.自定义注解处理映射关系

由于上述两种方式均存在前端请求参数与后端实体属性必须完全对应才能正常解析,且公司前端使用下划线而后端属性使用驼峰命名,因此上述两种方式均不能满足此时业务场景,故只有自己实现,下边为具体实现步骤。

  • 定义实体
@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) 运行结果

开发实战|第一篇:springmvc中get请求实体接收_第4张图片

你可能感兴趣的:(开发实战)