java 自定义注解 生成json_SpringBoot:自定义注解实现后台接收Json参数
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参数相关推荐
- Java接收json参数
Java接收json参数 import java.util.List; import java.util.Map; import org.springframework.web.bind.annota ...
- SpringBoot自定义注解接收json参数
SpringBoot如果接受json参数的话需要定义实体类然后使用@RequestBody注解,但是如果每个接口都创建一个实体类的话太麻烦,因此可以使用自定义注解的方法接收.从网上发现了这篇博客,解决 ...
- @RequestBody接收Json参数 | 用自定义注解对Vo对象中Date类型日期格式校验
标题太长有木有?主要是为了把问题描述清楚,免得进错文章. 问题描述 昨天测试的同事测试接口的时候,测试出来一个Date类型校验问题. 要求输入的日期格式是:yyyy-MM-dd HH:mm:ss,Vo ...
- 【iText5 生成PDF】纯Java代码实现生成PDF(自定义表格、文本水印、单元格样式)
工作中遇到需要生成PDF.最终选择了iText.其他也有通过html再生成.感觉不太适合就用了代码实现. 使用iText 5.5.13.1版本.纯Java代码实现 1.自定义表格合并指定行列完成数据填 ...
- java后台接收json map值
使用postman软件模拟 post 请求,并且用post方式提交一个Map.Content-Type为applicationon/json.(这个软件对于测试接口很nice,大家可以尝试使用) 我们 ...
- 今天搞一下 MultipartFile java后台接收图片参数,并转存到本地
public Stringuploadtaskpic(@RequestParam("multipartFile") MultipartFile multipartFile,@Api ...
- java后台接收json数据
1.以@RequestParam接收 @PostMapping("ccc1")public String ccc1(@RequestParam("name") ...
- java 8 重复注解报错,重复注解 · Java 8 Document Translation · 看云
在某些情况下,您希望将相同的注解应用于声明或类型.从Java SE 8发行版开始,重复注解使您可以执行此操作. 例如,您正在编写代码以使用计时器服务,该服务使您能够在给定时间或某个时间表上运行方法,与 ...
- JAVA 接收JSON数据,并进行转换处理
在日常业务中经常需要与外部系统交互处理数据,在此文章中记录一下我在项目中处理json数据流程. 第一种以实体类处理 以文档中的数据结构构建实体类,使字段与需要接收转换的JSON字段变量名尽量保持一致, ...
最新文章
- python字符串find函数-python字符串查找函数的用法详解
- 【温故知新】HTML学习笔记(表格)
- 中断底半部:softirq、tasklet、workqueue
- oracle 更新参数,Oracle动态、静态参数参数修改规则
- leetcode851. 喧闹和富有(dfs)
- 推辞掉得不是你的工作,而是你的未来
- Memcached(四)Memcached的CAS协议
- scala中的数组的转换操作
- Matlab入门变量篇
- 减速器课程设计指导系统使用方法
- Android应用测试篇
- 常用分辨率、帧率、码率
- almost unreal歌词翻译_Almost Lover歌词
- 用PS绘出真实火焰效果
- java map 队列_JavaSE-List/Map/Queue
- 众筹网站项目第七天之zTree树形结构实现(2)
- 我的2018——上懂机器学习,下懂微信建群
- vue 使用高德地图点击标记点以及经纬度转地理位置
- 回顾“90后”——MISRA的25年岁月
- 云之家OA系统排名?云之家OA办公系统怎么选?什么是用户口碑最好的云之家OA系统?
热门文章
- SAP 电商云 Spartacus UI 的双重 layout 配置层设计
- SAP CRM organization Model(组织架构模型)自动决定的逻辑分析
- OpenSAP Fiori Elements 公开课第四单元视频的中文字幕
- TypeScript 的 Object Types
- SAP Spartacus 代码提交的git message规范
- 如何自行查询SAP Spartacus Organization Unit List的取数逻辑
- SAP Cloud for Customer里新的Lead UI对Mashup集成的支持原理
- SAP Fiori Elements - how drop down list with description is correctly rendered
- OPA 16 - how is mocked transaction types loaded in the runtime
- SAP HANA数据库里对中文字符串排序的实现