如何实现@ResponseBody,把Json字符串转换为指定类型1.问题
spring 是如何把 http中的body,转换为指定类的,⾥⾯的难点其实在于泛型的处理。
2.Spring的处理
2.1 HandlerMethod
这个类Spring对Method的封装,例如使⽤@RequestMapping注解⽅法,会使⽤HandlerMethod封装(其实是其⼦类InvocableHandlerMethod)。然后由InvocableHandlerMethod对其进⾏调⽤
HandlerMethod的属性如下
private final Object bean;
private final BeanFactory beanFactory;
private final Class<?> beanType;
private final Method method;
private final Method bridgedMethod;
private final MethodParameter[] parameters; //重点是这个
private HttpStatus responseStatus;
private String responseStatusReason;
private HandlerMethod resolvedFromHandlerMethod;
2.2 如何解析参数的
参考InvocableHandlerMethod的getMethodArgumentValues的⽅法,其中会使⽤各种HandlerMethodArgumentResolver 对Spring mvc调⽤参数解析
例如,路径的中的参数 /path/${var} 使⽤的PathVariableMapMethodArgumentResolver 相关注解 @PathVariable
例如,header中的参数 使⽤ RequestHeaderMapMethodArgumentResolver 来解析,相关注解@RequestHeader
parse error怎么解决那么@ResponseBody使⽤的RequestResponseBodyMethodProcessor来解析的,
2.3 如何把body转换为参数类
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
parameter = stedIfOptional();
Object arg = readWithMessageConverters(webRequest, parameter, NestedGenericParameterType());
....
return adaptArgumentIfNecessary(arg, parameter);
}
其中readWithMessageConverters⽅法是重点,注意MethodParameter其实就是HandlerMethod中
的属性
继续往⾥⾯跳
GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
...
body = ad(targetType, contextClass, inputMessage);
其中上⾯的那段代码就是读取http的body,并转换为指定类。我们就拿常见Fastjson的FastJsonHttpMessageConverter中的代码来看,很简单
public Object read(Type type, //
Class<?> contextClass, //
HttpInputMessage inputMessage //
) throws IOException, HttpMessageNotReadableException {
return readType(getType(type, contextClass), inputMessage);
}
private Object readType(Type type, HttpInputMessage inputMessage) throws IOException {
try {
InputStream in = Body();
return JSON.parseObject(in, Charset(), type, Features());
} catch (JSONException ex) {
throw new HttpMessageNotReadableException("JSON parse error: " + ex.getMessage(), ex);
} catch (IOException ex) {
throw new HttpMessageNotReadableException("I/O error while reading input message", ex);
}
}
3 如何⾃⼰实现
通过上⾯的分析,如何实现⼀个简单的数据mock回放,(假设的我们mock的数据使⽤json来存储的)
// 第⼀步:创建⼀个HandlerMethod
HandlerMethod handlerMethod = new HandlerMethod(bean, method);
// 第⼆步:获取返回类型的MethodParameter
MethodParameter methodParameter = ReturnType().nestedIfOptional();
// 第三步:使⽤Fastjson反序列化
JSONObject.Val(), NestedGenericParameterType());
//注,bean是调⽤的类的实例,method是通过反射获取的具体调⽤⽅法,怎么获取不是这⾥的重点,省略掉获取
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论