在多数的MVC请求中,不涉及此类问题,按照实际需要格式传参即可,但在特定情况下,比如请求方只能传字符串,则需要服务方在序列化到实体类之前,完成格式转换,实际操作方法如下:
说明,我们请求的参数结果大概如下
{ "reqHead": { "bb": "xx" }, "reqBody": { "aa": "xx" } } |
首先创建注解
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestObj {
boolean required() default true;
}
然后就是自定义解析处理,至于如何request中获取json对象,分享的帖子比较多,此处不做过多赘述
@Component
public class HandlerArgumentsResolverImpl implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(RequestObj.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory)
throws Exception {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
String body = HttpHelper.getBodyString(requestWrapper);
JSONObject jsonBody = JSONObject.parseObject(body);
JSONObject jsonObject = jsonBody.getJSONObject("reqBody");
Parameter[] parameters = methodParameter.getExecutable().getParameters();
for (Parameter pr : parameters) {
Class<?> oriType1 = pr.getType();
if (!oriType1.isInstance(CommonBaseReqDto.class) && !oriType1.isAssignableFrom(HttpServletRequest.class)) {
ParameterizedType parameterizedType = (ParameterizedType) pr.getParameterizedType();
Type type = parameterizedType.getActualTypeArguments()[0];
if (type instanceof Class) {
Class<?> aClass = (Class<?>) type;
Field[] declaredFields = aClass.getDeclaredFields();
for (Field p : declaredFields) {
Object s = jsonObject.get(p.getName());
if (jsonObject.containsKey(p.getName())) {
if (p.getType().isArray()) {
if (ObjectUtil.isEmpty(s)) {
jsonObject.put(p.getName(), null);
} else if (s instanceof String) {
jsonObject.put(p.getName(), JSONArray.parseArray(s.toString()).toArray(new Object[]{}));
}
} else if (p.getType().isInstance(List.class)) {
if (ObjectUtil.isEmpty(s)) {
jsonObject.put(p.getName(), null);
} else if (s instanceof String) {
jsonObject.put(p.getName(), JSONArray.parseArray(s.toString()));
}
} else {
if (ObjectUtil.isEmpty(s)) {
jsonObject.put(p.getName(), null);
}
}
}
}
}
//找到指定泛型类
break;
}
}
return jsonBody.fluentPut("reqBody", jsonObject).toJavaObject(methodParameter.getGenericParameterType());
}
}
然后是配置config,我是和拦截器共用的config
@Component
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private HandlerArgumentsResolverImpl handlerArgumentsResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(handlerArgumentsResolver);
}
}
最后就是给需要的接口加上自定义注解就行了。
欢迎大家指正讨论