美文网首页
SpringMVC-ContentNegotiatingView

SpringMVC-ContentNegotiatingView

作者: 张明学 | 来源:发表于2020-07-18 23:37 被阅读0次

内容协商器(ContentNegotiatingViewResolver与contentNegotiationManager)是根据客户端的请求配置,响应不同格式的数据,这非常符合RESTful规范。

常见的配置


随着现在前后端分离的项目越来越多,Controller层现在通常返回JSON格式的数据,通用使用jackson或fastjson。在Controller的返回值上添加@ResponseBody,再配置对JSON格式的数据转换器即可,常用配置如下

message-converters

<mvc:annotation-driven>
    <mvc:message-converters>
        <ref bean="stringHttpMessageConverter"/>
        <!-- jackson -->
        <ref bean="jacksonHttpMessageConverter"/>
        <!-- fastjson -->
        <!-- <ref bean="fastJsonHttpMessageConverter"/> -->
    </mvc:message-converters>
</mvc:annotation-driven>

字符串的消息转换

<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
    <!-- 避免出现乱码 -->
    <constructor-arg value="UTF-8" index="0"/>
    <property name="supportedMediaTypes">
        <list>
            <value>text/plain;charset=UTF-8</value>
            <value>application/json;charset=UTF-8</value>
        </list>
    </property>
</bean>

使用jackson配置,参见:SpringMVC-Jackson

<!-- 使用jackson处理JSON的MessageConverter -->
    <bean id="jacksonHttpMessageConverter"
          class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
        <!-- 自定义Jackson的objectMapper -->
        <property name="objectMapper" ref="customObjectMapper"/>
        <property name="supportedMediaTypes">
            <list>
                <value>text/plain;charset=UTF-8</value>
                <value>application/json;charset=UTF-8</value>
            </list>
        </property>
    </bean>
        <!-- 对jackson的配置 -->
    <bean id="customObjectMapper" class="com.zmx.config.CustomObjectMapper"/>

使用fastJson配置,参见:SpringMVC集成fastjson

<bean id="fastJsonHttpMessageConverter" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
    <property name="supportedMediaTypes">
        <list>
            <value>application/json;charset=UTF-8</value>
            <!-- 避免IE出现下载JSON文件的情况 -->
            <value>text/html;charset=UTF-8</value>
        </list>
    </property>
    <property name="fastJsonConfig" ref="fastJsonConfig"></property>
</bean>
<!-- fastJson的配置 -->
<bean id="fastJsonConfig" class="com.alibaba.fastjson.support.config.FastJsonConfig">
    <property name="serializerFeatures">
        <list>
            <value>DisableCircularReferenceDetect</value>
            <value>SortField</value>
        </list>
    </property>
    <property name="charset" value="UTF-8"></property>
    <property name="dateFormat" value="yyyy-MM-dd HH:mm:ss"></property>
</bean>

以上配置可以配合@ResponseBody用来响应JSON格式数据

内容协商器配置


contentNegotiationManager

就是同一资源,可以有多种表现形式,比如xml、json等,具体使用哪种表现形式,是可以协商的。这是RESTfull的一个重要特性,Spring Web MVC也支持这个功能。至于如何决定采用何种方式(视图)来展示内容呢,是根据客户端的参数决定?

  • 后缀(xx/a.json返回JSON,xx/a.xml返回xml)
  • request参数识别(xx/a?format=json,xx/a?format=xml)
  • parameterName参数(xx/a?mediaType=json,xx/a?mediaType=xml)
  • http请求头accept参数(Accept: application/xml 将返回xml格式数据,Accept: application/json 将返回json格式数据)RESTful规范
<!-- 配置使用内容协商器 -->
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <!-- favorPathExtension参数表示是否开启后缀,默认true。(使用形如/xx/a.json、/xx/a.xml的方式)-->
    <property name="favorPathExtension" value="true"/>
    <!-- favorParameter参数表示是否开启request参数识别,默认false。(使用形如/xx/a?format=json、/xx/a?format=xml的方式) -->
    <property name="favorParameter" value="true"/>
    <!-- parameterName参数表示使用参数的名字,默认format,如果配置为mediaType,则请求格式变为/xx/a?mediaType=json -->
    <property name="parameterName" value="mediaType"/>
    <!-- ignoreAcceptHeader表示是否关闭accept头识别,默认false,即默认开启accept头识别。-->
    <property name="ignoreAcceptHeader" value="true"/>
    <!-- defaultContentType表示服务器默认的MediaType类型,不指定默认返回html页面 -->
    <property name="defaultContentType" value="text/html"/>
    <!-- mediaTypes里的entry中的key做为文件名/URL后缀/参数,其内容类型就是entry对应的value值。-->
    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json"/>
            <entry key="xml" value="application/xml"/>
        </map>
    </property>
</bean>

defaultContentType根据实际情况来,如果前后端分离的项目,可以配置成“application/json”,如果不是前后端分离,可以配置text/html,否则页面的url都要加入资源类型的标识信息(用后缀、request参数识别等等)太繁琐

ContentNegotiatingViewResolver

<!-- 内容协商视图解析器,根据contentNegotiationManager使用的不同mediaTypes决定不同的view进行响应 默认使用json-->
<bean id="contentNegotiatingViewResolver"
      class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="order" value="0"/>
    <!-- 内容协商管理器, 如已配置过管理器,这里可以不配置 -->
    <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
</bean>

html或jsp的视图

<!-- 返回资源型(html,jsp)的视图 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

JSON的视图

<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>

XML的视图

<bean id="xmlView" class="org.springframework.web.servlet.view.xml.MarshallingView">
    <constructor-arg>
        <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
            <property name="marshallerProperties">
                <map>
                    <entry key="jaxb.encoding" value="UTF-8"></entry>
                    <!-- 放置xml自动缩进属性 -->
                    <entry key="jaxb.formatted.output" value="true"></entry>
                </map>
            </property>
            <property name="packagesToScan" value="com.zmx.model"/>
            <!--<property name="classesToBeBound">-->
            <!--<list>-->
            <!--<value>com.zmx.model.vo.EmployeeVo</value>-->
            <!--</list>-->
            <!--</property>-->
        </bean>
    </constructor-arg>
</bean>

Controller处理

@RequestMapping(value = "/employee/{id}", method = RequestMethod.GET)
@ResponseBody
public EmployeeVo getEmployeeVo(@PathVariable("id") Long argId) {
    EmployeeVo result = new EmployeeVo();
    result.setId(argId);
    result.setName("test");
    result.setTelephone("021-10086");
    result.setSex(new Short("0"));
    result.setSalary(new BigDecimal(20356));
    result.setIsOfficial(true);
    result.setHobby("测试信息");
    result.setBirthday(new DateTime().minusYears(20).toDate());
    return result;
}

@RequestMapping(value = "/employee/{id}/info", method = RequestMethod.GET)
public String getEmployeJSP(@PathVariable("id") Long argId, Model model) {
    model.addAttribute("username","test");
    return "emp/info";
}

以上配置就可以处理:

http://localhost:8080/employee/123.json 返回JSON数据
http://localhost:8080/employee/123.xml 返回xml数据
http://localhost:8080/employee/123/infohttp://localhost:8080/employee/123/info.html 返回页面

相关文章

网友评论

      本文标题:SpringMVC-ContentNegotiatingView

      本文链接:https://www.haomeiwen.com/subject/dfpqkktx.html