0.需求

在实际的开发过程中,服务间调用一般使用Json传参的模式,SpringBoot项目无法使用@RequestParam接收Json传参

只有@RequestBody支持Json,但是每次为了一个接口就封装一次实体类比较麻烦

如果使用Map来进行参数接收,则会导致参数不可控,会在接口中新增较多判断进行入参控制

其次,在实际的开发过程中,我们偶尔会传入两个实体类,如果使用@RequestBody也会出错

因为传入的参数只能够读取一次,一般这里也会封装一次实体类,不够方便

也有重写HttpServletRequestWrapper的处理办法,但不能解决上一个问题

1.思路

因为一个注解只能读取一次,按照重写HttpServletRequestWrapper的思路,将请求中的Json参数进行缓存

另外自定义一个注解,来把参数进行注入。

1.1.自定义@JsonFmt注解

import java.lang.annotation.*;

@Target(ElementType.PARAMETER)

@Retention(RetentionPolicy.RUNTIME)

@Documentedpublic @interfaceJsonFmt {/*** 值*/String value()default "";/*** 是否必须*/

boolean require() default true;

}

这里的值,不是给参数的默认值(defaultValue),而是类似于@RequestParam注解中的value、name,是用来指定入参的key

1.2.自定义注解的实现类

importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.JSONObject;importcom.fasterxml.jackson.databind.ObjectMapper;importlombok.extern.slf4j.Slf4j;importorg.springframework.core.MethodParameter;importorg.springframework.util.StringUtils;importorg.springframework.web.bind.support.WebDataBinderFactory;importorg.springframework.web.context.request.NativeWebRequest;importorg.springframework.web.method.support.HandlerMethodArgumentResolver;importorg.springframework.web.method.support.ModelAndViewContainer;importjavax.servlet.http.HttpServletRequest;importjava.io.BufferedReader;importjava.util.HashMap;importjava.util.Map;

@Slf4jpublic class JsonFmtHandlerMethodArgumentResolver implementsHandlerMethodArgumentResolver {//自定义key

private static final String KEY = "TEST_JSON_BODY_KEY";private static ObjectMapper objectMapper = newObjectMapper();

@Overridepublic booleansupportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(JsonFmt.class);

}

@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throwsException {

JsonFmt jsonFmt= parameter.getParameterAnnotation(JsonFmt.class);

JSONObject jsonObject=getJsonObject(webRequest);

String value=getParamName(parameter,jsonFmt);boolean require =jsonFmt.require();

Object paramValue=getParamValue(jsonObject,value);if (paramValue == null &&require) {throw new Exception("parameter[" + value + "]不能为空。");

}if (paramValue == null) {return null;

}

Class> classType =parameter.getParameterType();if (paramValue.getClass().equals(JSONObject.class)){

paramValue=objectMapper.readValue(paramValue.toString(),classType);

}returnparamValue;

}privateString getParamName(MethodParameter parameter, JsonFmt jsonFmt) {

String value=jsonFmt.value();if(StringUtils.isEmpty(value)) {

value=parameter.getParameterName();

}returnvalue;

}privateObject getParamValue(JSONObject jsonObject,String value) {for(String key: jsonObject.keySet()) {if(key.equalsIgnoreCase(value)){returnjsonObject.get(key);

}

}return null;

}private JSONObject getJsonObject(NativeWebRequest webRequest) throwsException {

String jsonBody=(String) webRequest.getAttribute(KEY, NativeWebRequest.SCOPE_REQUEST);if(StringUtils.isEmpty(jsonBody)){

HttpServletRequest request= webRequest.getNativeRequest(HttpServletRequest.class);

BufferedReader reader=request.getReader();

StringBuilder sb= newStringBuilder();char[] buf = new char[1024];intrd;while ((rd = reader.read(buf)) != -1) {

sb.append(buf,0, rd);

}

jsonBody=sb.toString();if(StringUtils.isEmpty(jsonBody)){

Map params =request.getParameterMap();

Map tmp= newHashMap();for (Map.Entryparam:params.entrySet()) {if(param.getValue().length == 1){

tmp.put(param.getKey(),param.getValue()[0]);

}else{

tmp.put(param.getKey(),param.getValue());

}

}

jsonBody=JSON.toJSONString(tmp);

}

webRequest.setAttribute(KEY, jsonBody, NativeWebRequest.SCOPE_REQUEST);

}returnJSONObject.parseObject(jsonBody);

}

}

方法说明:

supportsParameter:说明支持的注解,只要方法参数有@JsonFmt就启用该实现类

resolveArgument:解决方法,注解的具体实现

getJsonObject:获取请求体,这里的实现逻辑就是从请求中获取Json体,如果没有获取到,则从请求参数中获取(兼容From模式),将请求体封装为JsonObject

getParamName:获取注解参数的key,先获取注解的value,如果为空,则使用方法参数的名称

getParamValue:这个可以不加,我这里是为了让key不区分大小写,如果需要区分,直接使用jsonObject.get(key)即可

1.3.加入自定义注解

importcom.example.demo.jsonfmt.JsonFmtHandlerMethodArgumentResolver;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.method.support.HandlerMethodArgumentResolver;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;importjava.util.List;

@Configurationpublic class AppConfig implementsWebMvcConfigurer {

@Overridepublic void addArgumentResolvers(Listresolvers) {

resolvers.add(newJsonFmtHandlerMethodArgumentResolver());

}

}

2.使用

到这里我们就能愉快的使用我们的自定义注解@JsonFmt来进行参数接收了

目前在Json传参中,能完美的接收实体类、List、Map以及其他基础类型

在Form传参中,能够支持List、Map以及其他基础类型,对于实体类暂时还不能兼容

因为后台接收到的是Map,不容易区分哪些是实体类的字段,无法进行填充,这种建议使用@RequestBody

java 自定义注解 生成json_SpringBoot:自定义注解实现后台接收Json参数相关推荐

  1. Java接收json参数

    Java接收json参数 import java.util.List; import java.util.Map; import org.springframework.web.bind.annota ...

  2. SpringBoot自定义注解接收json参数

    SpringBoot如果接受json参数的话需要定义实体类然后使用@RequestBody注解,但是如果每个接口都创建一个实体类的话太麻烦,因此可以使用自定义注解的方法接收.从网上发现了这篇博客,解决 ...

  3. @RequestBody接收Json参数 | 用自定义注解对Vo对象中Date类型日期格式校验

    标题太长有木有?主要是为了把问题描述清楚,免得进错文章. 问题描述 昨天测试的同事测试接口的时候,测试出来一个Date类型校验问题. 要求输入的日期格式是:yyyy-MM-dd HH:mm:ss,Vo ...

  4. 【iText5 生成PDF】纯Java代码实现生成PDF(自定义表格、文本水印、单元格样式)

    工作中遇到需要生成PDF.最终选择了iText.其他也有通过html再生成.感觉不太适合就用了代码实现. 使用iText 5.5.13.1版本.纯Java代码实现 1.自定义表格合并指定行列完成数据填 ...

  5. java后台接收json map值

    使用postman软件模拟 post 请求,并且用post方式提交一个Map.Content-Type为applicationon/json.(这个软件对于测试接口很nice,大家可以尝试使用) 我们 ...

  6. 今天搞一下 MultipartFile java后台接收图片参数,并转存到本地

    public Stringuploadtaskpic(@RequestParam("multipartFile") MultipartFile multipartFile,@Api ...

  7. java后台接收json数据

    1.以@RequestParam接收 @PostMapping("ccc1")public String ccc1(@RequestParam("name") ...

  8. java 8 重复注解报错,重复注解 · Java 8 Document Translation · 看云

    在某些情况下,您希望将相同的注解应用于声明或类型.从Java SE 8发行版开始,重复注解使您可以执行此操作. 例如,您正在编写代码以使用计时器服务,该服务使您能够在给定时间或某个时间表上运行方法,与 ...

  9. JAVA 接收JSON数据,并进行转换处理

    在日常业务中经常需要与外部系统交互处理数据,在此文章中记录一下我在项目中处理json数据流程. 第一种以实体类处理 以文档中的数据结构构建实体类,使字段与需要接收转换的JSON字段变量名尽量保持一致, ...

最新文章

  1. python字符串find函数-python字符串查找函数的用法详解
  2. 【温故知新】HTML学习笔记(表格)
  3. 中断底半部:softirq、tasklet、workqueue
  4. oracle 更新参数,Oracle动态、静态参数参数修改规则
  5. leetcode851. 喧闹和富有(dfs)
  6. 推辞掉得不是你的工作,而是你的未来
  7. Memcached(四)Memcached的CAS协议
  8. scala中的数组的转换操作
  9. Matlab入门变量篇
  10. 减速器课程设计指导系统使用方法
  11. Android应用测试篇
  12. 常用分辨率、帧率、码率
  13. almost unreal歌词翻译_Almost Lover歌词
  14. 用PS绘出真实火焰效果
  15. java map 队列_JavaSE-List/Map/Queue
  16. 众筹网站项目第七天之zTree树形结构实现(2)
  17. 我的2018——上懂机器学习,下懂微信建群
  18. vue 使用高德地图点击标记点以及经纬度转地理位置
  19. 回顾“90后”——MISRA的25年岁月
  20. 云之家OA系统排名?云之家OA办公系统怎么选?什么是用户口碑最好的云之家OA系统?

热门文章

  1. SAP 电商云 Spartacus UI 的双重 layout 配置层设计
  2. SAP CRM organization Model(组织架构模型)自动决定的逻辑分析
  3. OpenSAP Fiori Elements 公开课第四单元视频的中文字幕
  4. TypeScript 的 Object Types
  5. SAP Spartacus 代码提交的git message规范
  6. 如何自行查询SAP Spartacus Organization Unit List的取数逻辑
  7. SAP Cloud for Customer里新的Lead UI对Mashup集成的支持原理
  8. SAP Fiori Elements - how drop down list with description is correctly rendered
  9. OPA 16 - how is mocked transaction types loaded in the runtime
  10. SAP HANA数据库里对中文字符串排序的实现