内容协商 & 消息转换

在这里我讨论了 "客户端有责任告知服务器自己期望接受的内容类型"
ResponseBody 乱码问题
那么现在来看看什么是内容协商和消息转换

ContentNegotiatingViewResolver
Implementation of ViewResolver that resolves a view based on the request file name or Accept header.
ViewResolver的实现,它基于请求文件名或Accept标头解析视图。

The ContentNegotiatingViewResolver does not resolve views itself, but delegates to other ViewResolvers. By default, these other view resolve
rs are picked up automatically from the application context, though they can also be set explicitly by using the viewResolvers property. Not
e that in order for this view resolver to work properly, the order property needs to be set to a higher precedence than the others (the defa
ult is Ordered.HIGHEST_PRECEDENCE).
ContentNegotiatingViewResolver不会自行解析视图,而是委托给其他ViewResolver。默认情况下,这些其他视图解析器会自动从应用程序上下文中拾取,尽管
也可以使用viewResolvers属性对其进行显式设置。请注意,为了使此视图解析器正常工作,需要将order属性设置为比其他属性更高的优先级(默认属性为Orde
red.HIGHEST_PRECEDENCE)。

This view resolver uses the requested media type to select a suitable View for a request. The requested media type is determined through the
configured ContentNegotiationManager. Once the requested media type has been determined, this resolver queries each delegate view resolver
for a View and determines if the requested media type is compatible with the view's content type). The most compatible view is returned.
该视图解析器使用请求的媒体类型为请求选择合适的视图。通过配置的ContentNegotiationManager确定请求的媒体类型。确定请求的媒体类型后,此解析器将
向每个委托视图解析器查询一个视图,并确定请求的媒体类型是否与视图的内容类型兼容。返回最兼容的视图。

Additionally, this view resolver exposes the defaultViews property, allowing you to override the views provided by the view resolvers. Note
that these default views are offered as candidates, and still need have the content type requested (via file extension, parameter, or Accept
header, described above).
此外,此视图解析器还公开defaultViews属性,使您可以覆盖视图解析器提供的视图。请注意,这些默认视图是作为候选提供的,仍然需要具有请求的内容类型
(通过文件扩展名,参数或接受标头,如上所述)。

For example, if the request path is /view.html, this view resolver will look for a view that has the text/html content type (based on the ht
ml file extension). A request for /view with a text/html request Accept header has the same result.
例如,如果请求路径为/view.html,则此视图解析器将查找具有text / html内容类型(基于html文件扩展名)的视图。带有text / html request Accept标头
的/ view请求具有相同的结果。

由此看来, 内容协商是关于选择控制器, 设置Context-Type的 查看使用方法

常用的还有消息转换器

package emcat

import global
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.Configuration
import org.springframework.context.event.ContextRefreshedEvent
import org.springframework.context.event.EventListener
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver

@Configuration
open class EventListener {
    @Autowired var mWebApplicationContext: ApplicationContext? = null

    @EventListener fun onStarted(event: ContextRefreshedEvent) {
        val requestMappingHandlerAdapter = mWebApplicationContext!!.getBean(RequestMappingHandlerAdapter::class.java);
        val messageConverters = requestMappingHandlerAdapter.getMessageConverters();
        val sb = StringBuilder(1024);
        sb.append("Spring共加载了 ${ messageConverters.size } 个消息转换器对象:\n");
        for (mc in messageConverters) {
            sb.append(mc::class.java.getCanonicalName());
            sb.append("\n");
        }
        global.log(sb.toString())
    }
}

/* Output:
Spring共加载了 7 个消息转换器对象:
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.ResourceHttpMessageConverter
org.springframework.http.converter.ResourceRegionHttpMessageConverter
org.springframework.http.converter.xml.SourceHttpMessageConverter
org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter
*/

<>记载:

@ResponseBody注解会告知Spring,我们要将返回的对象作为资源发送给客户端,并将其转换为客户端可接受的表述形式。
更具体地讲,DispatcherServlet将会考虑到请求中Accept头部信息,并查找能够为客户端提供所需表述形式的消息转换器。

import org.springframework.http.converter.StringHttpMessageConverter
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
...

@Configuration
@EnableWebMvc
open class ServletConfig : WebMvcConfigurer {
    override fun configureContentNegotiation(configurer: ContentNegotiationConfigurer) {
        configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8)
    }

    override fun configureMessageConverters(converters: MutableList>) {
        val stringmc = StringHttpMessageConverter(Charsets.UTF_8)
        stringmc.setWriteAcceptCharset(false)
        converters.add(stringmc)
        
        val jsonmc = MappingJackson2HttpMessageConverter()
        converters.add(jsonmc)
        global.log("消息转换器就绪")
    }
}

/*
Spring共加载了 2 个消息转换器对象:
org.springframework.http.converter.StringHttpMessageConverter
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
*/

你可能感兴趣的:(内容协商 & 消息转换)