SpringBoot:⾃定义注解实现后台接收Json参数
0.需求
在实际的开发过程中,服务间调⽤⼀般使⽤Json传参的模式,SpringBoot项⽬⽆法使⽤@RequestParam接收Json传参
只有@RequestBody⽀持Json,但是每次为了⼀个接⼝就封装⼀次实体类⽐较⿇烦
如果使⽤Map来进⾏参数接收,则会导致参数不可控,会在接⼝中新增较多判断进⾏⼊参控制
其次,在实际的开发过程中,我们偶尔会传⼊两个实体类,如果使⽤@RequestBody也会出错springframework和springboot
因为传⼊的参数只能够读取⼀次,⼀般这⾥也会封装⼀次实体类,不够⽅便
也有重写HttpServletRequestWrapper的处理办法,但不能解决上⼀个问题
1.思路
因为⼀个注解只能读取⼀次,按照重写HttpServletRequestWrapper的思路,将请求中的Json参数进⾏缓存
另外⾃定义⼀个注解,来把参数进⾏注⼊。
1.1.⾃定义@JsonFmt注解
import java.lang.annotation.*;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface JsonFmt {
/**
* 值
*/
String value() default "";
/
**
* 是否必须
*/
boolean require() default true;
}
这⾥的值,不是给参数的默认值(defaultValue),⽽是类似于@RequestParam注解中的value、name,是⽤来指定⼊参的key
1.2.⾃定义注解的实现类
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
slf4j.Slf4j;
import MethodParameter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.t.request.NativeWebRequest;
import org.hod.support.HandlerMethodArgumentResolver;
import org.hod.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class JsonFmtHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
//⾃定义key
private static final String KEY = "TEST_JSON_BODY_KEY";
private static ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(JsonFmt.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {        Json
Fmt jsonFmt = ParameterAnnotation(JsonFmt.class);
JSONObject jsonObject = getJsonObject(webRequest);
String value = getParamName(parameter,jsonFmt);
boolean require = quire();
Object paramValue = getParamValue(jsonObject,value);
if (paramValue == null && require) {
throw new Exception("parameter[" + value + "]不能为空。");
}
if (paramValue == null) {
return null;
}
Class<?> classType = ParameterType();
if (Class().equals(JSONObject.class)){
paramValue = String(),classType);
}
return paramValue;
}
private String getParamName(MethodParameter parameter, JsonFmt jsonFmt) {
String value = jsonFmt.value();
if (StringUtils.isEmpty(value)) {
value = ParameterName();
}
return value;
}
private Object getParamValue(JSONObject jsonObject,String value) {
for (String key: jsonObject.keySet()) {
if(key.equalsIgnoreCase(value)){
(key);
}
}
return null;
}
private JSONObject getJsonObject(NativeWebRequest webRequest) throws Exception {
String jsonBody = (String) Attribute(KEY, NativeWebRequest.SCOPE_REQUEST);
if(StringUtils.isEmpty(jsonBody)){
HttpServletRequest request = NativeRequest(HttpServletRequest.class);
BufferedReader reader = Reader();
StringBuilder sb = new StringBuilder();
char[] buf = new char[1024];
int rd;
while ((rd = ad(buf)) != -1) {
sb.append(buf, 0, rd);
}
jsonBody = sb.toString();
if(StringUtils.isEmpty(jsonBody)){
Map<String,String[]> params = ParameterMap();
Map tmp = new HashMap();
for (Map.Entry<String,String[]> Set()) {
Value().length == 1){
tmp.Key(),Value()[0]);
}else{
tmp.Key(),Value());
}
}
jsonBody = JSONString(tmp);
}
webRequest.setAttribute(KEY, jsonBody, NativeWebRequest.SCOPE_REQUEST);
}
return JSONObject.parseObject(jsonBody);
}
}
⽅法说明:
supportsParameter:说明⽀持的注解,只要⽅法参数有@JsonFmt就启⽤该实现类
resolveArgument:解决⽅法,注解的具体实现
getJsonObject:获取请求体,这⾥的实现逻辑就是从请求中获取Json体,如果没有获取到,则从请求参数中获取(兼容From模式),将请求体封装为JsonObject
getParamName:获取注解参数的key,先获取注解的value,如果为空,则使⽤⽅法参数的名称
getParamValue:这个可以不加,我这⾥是为了让key不区分⼤⼩写,如果需要区分,直接使⽤(key)即可
1.3.加⼊⾃定义注解
ample.demo.jsonfmt.JsonFmtHandlerMethodArgumentResolver;
import t.annotation.Configuration;
import org.hod.support.HandlerMethodArgumentResolver;
import org.springframework.fig.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new JsonFmtHandlerMethodArgumentResolver());
}
}
2.使⽤
到这⾥我们就能愉快的使⽤我们的⾃定义注解@JsonFmt来进⾏参数接收了
⽬前在Json传参中,能完美的接收实体类、List、Map以及其他基础类型
在Form传参中,能够⽀持List、Map以及其他基础类型,对于实体类暂时还不能兼容
因为后台接收到的是Map,不容易区分哪些是实体类的字段,⽆法进⾏填充,这种建议使⽤@RequestBody

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。