spring boot json and xml, xhtml converter selection

When our address ends with json and xml, spring boot will select the corresponding converter for conversion. For
example, enter

 

http://ip:port/hello.json The result returns {"code":100,"msg":"hello"} in json format

 

http://ip:port/hello.xml returns the result in xml format

<xml>

   <code>100</code>

   <msg>hello</msg>

</xml

First of all, when the system is initialized, it usually loads

org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport in two formats: json and xml

	protected Map<String, MediaType> getDefaultMediaTypes() {
		Map<String, MediaType> map = new HashMap<String, MediaType>(4);
		if (romePresent) {
			map.put("atom", MediaType.APPLICATION_ATOM_XML);
			map.put("rss", MediaType.APPLICATION_RSS_XML);
		}
		if (jaxb2Present || jackson2XmlPresent) {
			map.put("xml", MediaType.APPLICATION_XML);
		}
		if (jackson2Present || gsonPresent) {
			map.put("json", MediaType.APPLICATION_JSON);
		}
		return map;
	}

 

If he can't find it in DefaultMediaTypes, he will look it up in MimeMappings

So where are the other types, org.springframework.boot.context.embedded.MimeMappings

 

static {

MimeMappings mappings = new MimeMappings();

mappings.add("abs", "audio/x-mpeg");

mappings.add("ai", "application/postscript");

mappings.add("aif", "audio/x-aiff");

mappings.add("aifc", "audio/x-aiff");

                 .....too much, no more copying

mappings.add("xhtml", "application/xhtml+xml");

 

So this is why xhtml can finally output xml format

 

 

in AbstractMessageConverterMethodProcessor

turn up

 

protected <T> void writeWithMessageConverters(T value, MethodParameter returnType,
			ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
			throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

		Object outputValue;
		Class<?> valueType;
		Type declaredType;

		if (value instanceof CharSequence) {
			outputValue = value.toString();
			valueType = String.class;
			declaredType = String.class;
		}
		else {
			outputValue = value;
			valueType = getReturnValueType(outputValue, returnType);
			declaredType = getGenericType(returnType);
		}

		HttpServletRequest request = inputMessage.getServletRequest();
                //Here gets the MediaType from the request (the end of the header or uri)
		List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request);
		List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType);

		if (outputValue != null && producibleMediaTypes.isEmpty()) {
			throw new IllegalArgumentException("No converter found for return value of type: " + valueType);
		}

....


	if (selectedMediaType != null) {
			selectedMediaType = selectedMediaType.removeQualityValue();
                       //loop to match the corresponding convert converter
			for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
				if (messageConverter instanceof GenericHttpMessageConverter) {
					if (((GenericHttpMessageConverter) messageConverter).canWrite(
							declaredType, valueType, selectedMediaType)) {
						outputValue = (T) getAdvice().beforeBodyWrite(outputValue, returnType, selectedMediaType,
								(Class<? extends HttpMessageConverter<?>>) messageConverter.getClass(),
								inputMessage, outputMessage);
						if (outputValue != null) {
							addContentDispositionHeader(inputMessage, outputMessage);
							((GenericHttpMessageConverter) messageConverter).write(
									outputValue, declaredType, selectedMediaType, outputMessage);
							if (logger.isDebugEnabled()) {
								logger.debug("Written [" + outputValue + "] as \"" + selectedMediaType +
										"\" using [" + messageConverter + "]");
							}
						}
						return;
					}
				}
				else if (messageConverter.canWrite(valueType, selectedMediaType)) {
					outputValue = (T) getAdvice().beforeBodyWrite(outputValue, returnType, selectedMediaType,
							(Class<? extends HttpMessageConverter<?>>) messageConverter.getClass(),
							inputMessage, outputMessage);
					if (outputValue != null) {
						addContentDispositionHeader(inputMessage, outputMessage);
						((HttpMessageConverter) messageConverter).write(outputValue, selectedMediaType, outputMessage);
						if (logger.isDebugEnabled()) {
							logger.debug("Written [" + outputValue + "] as \"" + selectedMediaType +
									"\" using [" + messageConverter + "]");
						}
					}
					return;
				}
			}
		}

 

 

PathExtensionContentNegotiationStrategy keyword acquisition

You can see that the keywords at the end of the URI (json or xml or xhtml ...) are intercepted here

 

	protected String getMediaTypeKey(NativeWebRequest webRequest) {
		HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
		if (request == null) {
			logger.warn("An HttpServletRequest is required to determine the media type key");
			return null;
		}
		String path = this.urlPathHelper.getLookupPathForRequest(request);
		String extension = UriUtils.extractFileExtension(path);
		return (StringUtils.hasText(extension) ? extension.toLowerCase(Locale.ENGLISH) : null);
	}

 

 

 

AbstractMappingContentNegotiationStrategy

 

	public List<MediaType> resolveMediaTypeKey(NativeWebRequest webRequest, String key)
			throws HttpMediaTypeNotAcceptableException {

		if (StringUtils.hasText(key)) {
                        //Find a match from getDefaultMediaTypes()
			MediaType mediaType = lookupMediaType(key);
			if (mediaType != null) {
				handleMatch(key, mediaType);
				return Collections.singletonList(mediaType);
			}
                        //Find from servletContext (I use embedded tomcat, so I use MimeMappings)
			mediaType = handleNoMatch(webRequest, key);
			if (mediaType != null) {
				addMapping(key, mediaType);
				return Collections.singletonList(mediaType);
			}
		}
		return Collections.emptyList();
	}

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326117160&siteId=291194637