东莞市盛裕绒艺玩具有限公司

东莞市盛裕绒艺玩具有限公司

ope合作伙伴

15152199080
联系方式
全国服务热线: 15152199080

咨询热线:15320608695
联系人:方潘安
地址:新疆维吾尔自治省乌鲁木齐市乌鲁木齐 市市沙依巴克区西虹路2号

如何实现@ResponseBody,把Json字符串转换为指定类型

来源:ope合作伙伴   发布时间:2019-06-17   点击量:115

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

那么@ResponseBody使用的RequestResponseBodyMethodProcessor来解析的,

2.3 如何把body转换为参数类

@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {parameter = parameter.nestedIfOptional();Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());....return adaptArgumentIfNecessary(arg, parameter);}

 

 其中readWithMessageConverters方法是重点,注意MethodParameter其实就是HandlerMethod中的属性

继续往里面跳

GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;

...body = genericConverter.read(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 = inputMessage.getBody(); return JSON.parseObject(in, fastJsonConfig.getCharset(), type, fastJsonConfig.getFeatures()); } 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 = handlerMethod.getReturnType().nestedIfOptional(); // 第三步:使用Fastjson反序列化 JSONObject.parseObject(phxResult.getVal(), methodParameter.getNestedGenericParameterType());//注,bean是调用的类的实例,method是通过反射获取的具体调用方法,怎么获取不是这里的重点,省略掉获取

 

  

 

 

 

相关产品

COPYRIGHTS©2017 ope合作伙伴 ALL RIGHTS RESERVED 备案号:115