在我们实际的开发中,往往需要SpringMVC服务提供多种的格式的数据。如:JSON、XML、HTML
当然我们知道SpringMVC已经提供了很多种转换器,供我们使用将数据转换成我们想要的数据格式。但是服务者怎么知道使用者,想要使用哪种数据格式哪?这就使用到了SpringMVC中的内容协商。
既然是内容协商,那么使用者肯定会告诉服务者,你给我返回什么类型的数据。使用者可以通过如下方式通知服务者。
一、内容协商
1、使用参数
/userController/getUser?format=json /userController/getUser?format=xml
2、使用扩展名
/userController/getUser.html /userController/getUser.json /userController/getUser.xml
3、使用http的Request Headers中的Accpet
GET /userController/getUser HTTP/1.1 Accept: application/xml //将返回xml格式数据 GET /userController/getUser HTTP/1.1 Accept: application/json //将返回json格式数据
以上三种方式分析:
1、使用参数
现在很多open API是使用这种方式,但可能由于要编写的字符较多。
淘宝的开放平台就是使用的此种方式
2、使用扩展名称
丧失了同一url多种展现的方式,但现在这种在实际环境中是使用比较方便的。
3、使用Request Header中Accpet
这种方式是最理想的,但如果你的资源要给用户直接通过浏览器访问(即html展现),那么由于浏览器的差异,发送上来的Accept Header头将是不一样的. 将导致服务器不知要返回什么格式的数据给你. 下面是浏览器的Accept Header:
Chrome:
Firefox:
IE9:
我们使用第一种方式和第二种方式,在Spring中如何让配置
二、SpringMVC配置
现spring完成内容协商(content negotiation)的工作是由ContentNegotiatingViewResolver来完成的。
它的工作模式支持我上面讲的三种,ContentNegotiatingViewResolver是根据客户提交的MimeType(如 text/html,application/xml)来跟服务端的一组viewResover的MimeType相比较,如果符合,即返回viewResover的数据。
而 /userController/getUser.xml, ContentNegotiatingViewResolver会首先将 .xml 根据mediaTypes属性将其转换成 application/xml,然后完成前面所说的比较。
1、我们看下ContentNegotiatingViewResolver的配置:
<!-- 根据客户端的不同的请求决定不同的view进行响应, 如 /user/getUser.json /user/getUser.xml --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <!-- 设置为true以忽略对Accept Header的支持 --> <property name="ignoreAcceptHeader" value="true" /> <!-- 在没有扩展名时即: "/user/getUser" 时的默认展现形式 --> <property name="defaultContentType" value="text/html" /> <!-- 扩展名至mimeType的映射,即 /getUser.json => application/json --> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> <!-- 用于开启 /user/getUser?format=json 的支持 --> <property name="favorParameter" value="false" /> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/page/" /> <property name="suffix" value=".jsp"></property> </bean> </list> </property> <property name="defaultViews"> <list> <!-- for application/json --> <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> <!-- for application/xml --> <bean class="org.springframework.web.servlet.view.xml.MarshallingView"> <property name="marshaller"> <!-- xstream.XStreamMarshaller --> <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound" > <list> <value>com.wy.pojo.User</value> </list> </property> </bean> </property> </bean> </list> </property> </bean>
我们在创建User对象
@XmlRootElement(name = "User") public class User implements Serializable { private static final long serialVersionUID = 1L; private String username; private String password; private int age; private String sex; private String birthday; @XmlElement public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @XmlElement public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement public int getAge() { return age; } public void setAge(int age) { this.age = age; } @XmlElement public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @XmlElement public String getBirthday() { return birthday; } public void setBirthday(String birthday) { this.birthday = birthday; } @Override public String toString() { // TODO Auto-generated method stub return this.username + "#" + this.password + "#" + this.age + "#" + this.sex + "#" + this.birthday; } }
我们的控制层很简单的
@Controller @RequestMapping("/userController") public class UserController { @RequestMapping(value="getUser") public User getUser(){ User user = new User(); user.setUsername("wy"); user.setPassword("123"); user.setAge(123); user.setSex("male"); user.setBirthday("2013-09-10"); return user; } }
好,我们看下效果会是怎样子:
当我们在浏览器中输入:http://localhost:8080/SpringMVC/userController/getUser.json
结果:
{"user":{"username":"wy","password":"123","age":123,"sex":"male","birthday":"2013-09-10"}}
当我们在浏览器中输入:http://localhost:8080/SpringMVC/userController/getUser.xml
结果:
<User><age>123</age><birthday>2013-09-10</birthday><password>123</password><sex>male</sex><username>wy</username></User>
将配置文件中的
<!-- 用于开启 /user/getUser?format=json 的支持 --> <property name="favorParameter" value="false" />
中false修改为true
我们再次在浏览器中输入:http://localhost:8080/SpringMVC/userController/getUser?format=json
结果是:
{"user":{"username":"wy","password":"123","age":123,"sex":"male","birthday":"2013-09-10"}}
我们再次在浏览器中输入:http://localhost:8080/SpringMVC/userController/getUser?format=xml
结果是:
<User><age>123</age><birthday>2013-09-10</birthday><password>123</password><sex>male</sex><username>wy</username></User>
发现两次的请求结果是等效的。
下面是ContentNegotiatingViewResolver的完全配置:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd" > <!-- 默认的注解映射的支持 ,它会自动注册DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter--> <mvc:annotation-driven /> <!-- 自动扫描注解的Controller --> <context:component-scan base-package="com.wy.controller" /> <!-- 根据客户端的不同的请求决定不同的view进行响应, 如 /user/getUser.json /user/getUser.xml --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <!-- 设置为true以忽略对Accept Header的支持 --> <property name="ignoreAcceptHeader" value="true" /> <!-- 在没有扩展名时即: "/user/getUser" 时的默认展现形式 --> <property name="defaultContentType" value="text/html" /> <!-- 扩展名至mimeType的映射,即 /getUser.json => application/json --> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> </map> </property> <!-- 用于开启 /user/getUser?format=json 的支持 --> <property name="favorParameter" value="true" /> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/page/" /> <property name="suffix" value=".jsp"></property> </bean> </list> </property> <property name="defaultViews"> <list> <!-- for application/json --> <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> <!-- for application/xml --> <bean class="org.springframework.web.servlet.view.xml.MarshallingView"> <property name="marshaller"> <!-- xstream.XStreamMarshaller --> <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound" > <list> <value>com.wy.pojo.User</value> </list> </property> </bean> </property> </bean> </list> </property> </bean> </beans>
2、重载MappingJacksonJsonView
我们在返回JSON格式的数据时,发现并不是我们常见的json。 也就是我们期望的返回是{success:true,message:”return ok”}; 但实际返回的却是 {"jsonResult":{"success":true,"msg":"return ok"}}
原因是MappingJacksonJsonView中对返回值的处理未考虑modelMap中只有一个值的情况, 直接是按照mapName:{mapResult}的格式来返回数据的。
public class CustomJsonView extends MappingJacksonJsonView { protected Object filterModel(Map<String, Object> model) { Map<?, ?> result = (Map<?, ?>) super.filterModel(model); if (result.size() == 1) { return result.values().iterator().next(); } else { return result; } } }
3、我们将
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
替换为我们刚修改的
<bean class="com.wy.view.CustomJsonView"/>
再次浏览器中输入:http://localhost:8080/SpringMVC/userController/getUser.json
看到的结果这是我们期望的:
{"username":"wy","password":"123","age":123,"sex":"male","birthday":"2013-09-10"}
相关推荐
在Spring MVC框架中,开发人员经常需要处理JSON数据进行前后端交互。然而,在实际操作中,我们可能会遇到一个常见的问题,即HTTP状态码406(Not Acceptable)。这个错误通常意味着服务器生成了响应,但客户端无法...
并且基于Spring MVC提供了一个完整功能:实现了生成验证码图片,以及验证输入是否匹配的两个接口,接口为Rest风格,符合内容协商原则(同一资源,多种展现:xml,json,html)。 另外,演示了注解(Annotation)的用法,实现...
4. **内容协商**:这个特性允许服务器根据客户端的偏好返回不同的格式,比如 JSON 或 XML,可以通过 `@RequestMapping` 注解的 `produces` 和 `consumes` 属性来指定。 5. **MVC 视图解析**:Spring MVC 3.0 引入了...
4. **内容协商**:此版本引入了内容协商功能,允许服务器根据客户端的接受类型(如 Accept 头)返回不同的格式,如 JSON、XML 或 HTML,增强了服务的可复用性。 5. **RESTful 支持**:通过 `@RequestMapping` 注解...
5. **内容协商**: 允许服务器根据客户端的能力返回不同格式的数据,如JSON、XML等,通过`@RequestMapping`的produces属性实现。 6. **国际化支持**: `MessageSource`接口提供国际化消息管理,使应用能适应不同地区...
在SpringMVC环境中实现Ajax异步请求JSON格式数据是一项常见的任务,这有助于创建更高效、交互性更强的Web应用程序。以下是一份详细的步骤指南和关键知识点解析: 首先,环境搭建是基础。确保你已经设置了标准的...
RESTful服务应支持多种数据格式,如JSON、XML等。Spring MVC通过`produces`和`consumes`属性来指定控制器方法支持的媒体类型。 8. **安全性** 考虑到RESTful服务可能暴露给公众,安全性是重要的考虑因素。Spring ...
Spring 3.2版本新增了对Servlet 3异步请求处理的支持、改进了Spring MVC的测试框架、增强了内容协商功能、支持泛型的RestTemplate、对@RequestBody参数的支持,以及对日期和时间格式化的全球支持等。另外,Spring ...
- **内容协商**: 支持多种格式的响应,如 JSON、XML。 4. **CRUD 操作** - **Create**: 创建新记录,通常使用 POST 请求。 - **Read**: 获取记录,GET 请求用于查询。 - **Update**: 更新记录,PUT 请求用于...
通过这种方式,我们可以创建资源的CRUD操作,如GET、POST、PUT和DELETE,返回JSON或XML数据,使得客户端可以方便地进行交互。 6. **优化与最佳实践** - 避免过度使用`@ResponseBody`。对于复杂视图,使用视图解析...
1. **内容协商视图解析器(ContentNegotiatingViewResolver)** 和 **BeanNameViewResolver**:这两个视图解析器帮助Spring MVC根据请求的格式(如JSON、XML等)选择合适的视图来展示响应内容。BeanNameViewResolver...
在Jquery的$.ajax请求中,如果遇到部署在Tomcat上的Spring MVC应用返回HTTP 406错误,这通常是由于内容协商不成功导致的。本文将深入探讨这个问题,并提供解决方案。 首先,我们需要理解HTTP 406错误的含义。406 ...
Spring Boot 微服务应用 这个小的 Spring Boot 应用程序充当了典型微服务... java -jar target/swagger-springmvc-bug.1.1.8.RELEASE.jar ( mvn spring-boot:run有效但 index.html 中使用的资源过滤无效) http://loca
- **功能**: 内容协商视图解析器,根据请求头中的Accept类型选择合适的视图。 - **应用场景**: 实现响应不同格式的数据(如JSON或XML)。 **HandlerExceptionResolver** - **功能**: 异常处理程序,用于处理控制器...
- Spring 3.2版本中,支持Servlet 3异步请求处理基础,SpringMVC的测试框架得到增强,内容协商和@ControllerAdvice注释的改进。 - 引入了基于代码的Servlet 3+容器初始化抽象基类,以及...
输出XML和JSON 使用HttpEntity<T>/ResponseEntity<T> 目录 数据绑定机理 数据类型转换 PropertyEditor依然有效 强大的ConversionService,让很多梦想成真 基于ConversionService体系,定义自定义的类型转换器 格式化...