Spring MVC 前端json字符串封装成服务端对象

本文环境

fastjson 1.2.47
spring 4.3.18.RELEASE

spring 整合fastjson

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>
<!--JSON映射 转换器 -->
<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <!-- 配置fastjson中实现HttpMessageConverter接口的转换器 -->
        <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>application/json;charset=UTF-8</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.java

public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
		NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

	parameter = parameter.nestedIfOptional();
	Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
	String name = Conventions.getVariableNameForParameter(parameter);

	WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
	if (arg != null) {
		validateIfApplicable(binder, parameter);
		if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
			throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
		}
	}
	mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());

	return adaptArgumentIfNecessary(arg, parameter);
}

protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter parameter,
		Type paramType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {

	HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
	ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(servletRequest);

	Object arg = readWithMessageConverters(inputMessage, parameter, paramType);
	if (arg == null) {
		if (checkRequired(parameter)) {
			throw new HttpMessageNotReadableException("Required request body is missing: " +
					parameter.getMethod().toGenericString());
		}
	}
	return arg;
}

org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.java

protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter,
		Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {

	MediaType contentType;
	boolean noContentType = false;
	try {
		contentType = inputMessage.getHeaders().getContentType();
	}
	catch (InvalidMediaTypeException ex) {
		throw new HttpMediaTypeNotSupportedException(ex.getMessage());
	}
	if (contentType == null) {
		noContentType = true;
		contentType = MediaType.APPLICATION_OCTET_STREAM;
	}

	Class<?> contextClass = (parameter != null ? parameter.getContainingClass() : null);
	Class<T> targetClass = (targetType instanceof Class ? (Class<T>) targetType : null);
	if (targetClass == null) {
		ResolvableType resolvableType = (parameter != null ?
				ResolvableType.forMethodParameter(parameter) : ResolvableType.forType(targetType));
		targetClass = (Class<T>) resolvableType.resolve();
	}

	HttpMethod httpMethod = ((HttpRequest) inputMessage).getMethod();
	Object body = NO_VALUE;

	try {
		inputMessage = new EmptyBodyCheckingHttpInputMessage(inputMessage);

		for (HttpMessageConverter<?> converter : this.messageConverters) {
			Class<HttpMessageConverter<?>> converterType = (Class<HttpMessageConverter<?>>) converter.getClass();
			if (converter instanceof GenericHttpMessageConverter) {
				GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
				if (genericConverter.canRead(targetType, contextClass, contentType)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
					}
					if (inputMessage.getBody() != null) {
						inputMessage = getAdvice().beforeBodyRead(inputMessage, parameter, targetType, converterType);
						body = genericConverter.read(targetType, contextClass, inputMessage);
						body = getAdvice().afterBodyRead(body, inputMessage, parameter, targetType, converterType);
					}
					else {
						body = getAdvice().handleEmptyBody(null, inputMessage, parameter, targetType, converterType);
					}
					break;
				}
			}
			else if (targetClass != null) {
				if (converter.canRead(targetClass, contentType)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
					}
					if (inputMessage.getBody() != null) {
						inputMessage = getAdvice().beforeBodyRead(inputMessage, parameter, targetType, converterType);
						body = ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage);
						body = getAdvice().afterBodyRead(body, inputMessage, parameter, targetType, converterType);
					}
					else {
						body = getAdvice().handleEmptyBody(null, inputMessage, parameter, targetType, converterType);
					}
					break;
				}
			}
		}
	}
	catch (IOException ex) {
		throw new HttpMessageNotReadableException("I/O error while reading input message", ex);
	}

	if (body == NO_VALUE) {
		if (httpMethod == null || !SUPPORTED_METHODS.contains(httpMethod) ||
				(noContentType && inputMessage.getBody() == null)) {
			return null;
		}
		throw new HttpMediaTypeNotSupportedException(contentType, this.allSupportedMediaTypes);
	}

	return body;
}

获取到FastJsonHttpMessageConver对象
这里写图片描述
判断是否支持该类型
这里写图片描述
此处的application/json;charset=UTF-8是在ajax请求中设置的
这里写图片描述
而前面在配置FastJsonHttpMessageConverter时也设置了支持的类型
这里写图片描述
调用HttpMessageConverterread()读取数据
这里写图片描述
com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter.java

   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);
       }
   }

JSON.parseObject(in, fastJsonConfig.getCharset(), type, fastJsonConfig.getFeatures());

com.alibaba.fastjson.JSON.java

   public static <T> T parseObject(byte[] bytes, int offset, int len, Charset charset, Type clazz, Feature... features) {
       if (charset == null) {
           charset = IOUtils.UTF8;
       }
       
       String strVal;
       if (charset == IOUtils.UTF8) {
           char[] chars = allocateChars(bytes.length);
           int chars_len = IOUtils.decodeUTF8(bytes, offset, len, chars);
           if (chars_len < 0) {
               return null;
           }
           strVal = new String(chars, 0, chars_len);
       } else {
           if (len < 0) {
               return null;
           }
           strVal = new String(bytes, offset, len, charset);
       }
       return (T) parseObject(strVal, clazz, features);
   }

从输入流中获取到提交的JSON字符串,调用parseObject()将字符串填充到目标类中(clazz),并返回该类的实例对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值