javascript
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参数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下如何修改ip地址
- 下一篇: java js 正则表达式_如何在Jav