一、消息转换器---HttpMessageConverter接口
客户端不同的请求,HttpServletRequest中数据的MediaType可能会不同,如果想将HttpServletRequest中的数据转换成指定对象,或者将对象转换成指定格式的数据,就需要使用对应的消息转换器来实现。Spring中提供了一个HttpMessageConverter接口作为消息转换器。因为数据的类型有多种,所以Spring中提供了多个HttpMessageConverter接口的实现类,其中MappingJackson2HttpMessageConverter是HttpMessageConverter接口的实现类之一,在处理请求时,可以将请求的JSON报文绑定到处理器的形参对象,在响应请求时,将处理器的返回值转换成JSON报文。
二、HttpMessageConverter与Converter类型转换器的区别
需要注意的是,HttpMessageConverter消息转换器和之前所学习的Converter类型转换器是有区别的。HttpMessageConverter消息转换器用于将请求消息中的报文数据转换成指定对象,或者将对象转换成指定格式的报文进行响应;Converter类型转换器用于对象之间的类型转换。
接下来通过一个异步提交商品信息案例,演示Spring MVC中的JSON数据绑定,案例具体实现步骤如下。
1、在项目的pom.xml文件中导入Jackson的依赖。
html
<!--Jackson转换核心包依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.2</version>
</dependency>
<!--Jackson转换的数据绑定包依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.2</version>
</dependency>
<!--Jackson JSON转换注解包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
2、在项目中导入jQuery文件
由于本次演示的是异步数据提交,需要使用jQuery,所以需要将jQuery文件导入到项目中,以便发送ajax请求。在项目的/webapp文件夹下创建名称为js的文件夹,在js文件夹中导入jQuery文件。
3、创建一个商品信息页面product.jsp,在product.jsp中创建一个表单用于填写商品信息,表单提交时,表单发送异步请求将表单的商品信息发送到处理器。product.jsp的部分代码如下所示。
javascript
<script type="text/javascript">
function sumbmitProduct() {
var proId = $("#proId").val(); var proName = $("#proName").val();
$.ajax({ url: "${pageContext.request.contextPath }/getProduct",
type: "post",
data: JSON.stringify({proId: proId, proName: proName}),
contentType: "application/json;charset=UTF-8",
dataType: "json",
success: function (response) {alert(response);} }); }
</script>
4、修改ProductController.java类,在ProductController类中新增getProduct()方法和getProductList()方法,分别用于获取客户端提交的单个商品信息和多个商品信息。
html
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head><title>异步提交商品</title>
<script type="text/javascript"
src="${pageContext.request.contextPath }/js/jquery-3.6.0.js"></script>
</head>
<body>
<form id="products">
<table border="1">
<tr>
<th>商品id</th>
<th>商品名称</th>
<th>提交</th>
</tr>
<tr>
<td>
<input name="proId" value="1" id="proId" type="text">
</td>
<td><input name="proName" value="三文鱼"
id="proName" type="text"></td>
<td><input type="button" value="提交单个商品"
onclick="sumbmitProduct()"></td>
</tr>
<tr>
<td><input name="proId" value="2" id="proId2"
type="text"></td>
<td><input name="proName" value="红牛"
id="proName2" type="text"></td>
<td><input type="button" value="提交多个商品"
onclick="submitProducts()"></td>
</tr>
</table>
</form>
<script type="text/javascript">
function sumbmitProduct() {
var proId = $("#proId").val();
var proName = $("#proName").val();
$.ajax({
url: "${pageContext.request.contextPath }/getProduct",
type: "post",
data: JSON.stringify({proId: proId, proName: proName}),
contentType: "application/json;charset=UTF-8",
dataType: "json",
success: function (response) {
alert(response);
}
});
}
function submitProducts() {
var pro1 = {proId: $("#proId").val(), proName: $("#proName").val()}
var pro2 = {proId: $("#proId2").val(), proName: $("#proName2").val()}
$.ajax({
url: "${pageContext.request.contextPath }/getProductList",
type: "post",
data: JSON.stringify([pro1, pro2]),
contentType: "application/json;charset=UTF-8",
dataType: "json",
success: function (response) {
alert(response);
}
});
}
</script>
</body>
</html>
5、在项目的web.xml文件中配置的DispatcherServlet会拦截所有URL,导致项目中的静态资源(如css、jsp、js等)也被DispatcherServlet拦截。如果想放行静态资源,可以在Spring MVC的配置文件中进行静态资源配置。Spring MVC配置文件的部分配置代码如下所示。
html
<!-- 配置要扫描的包 -->
<context:component-scan base-package="com.test.controller"/>
<!-- 配置视图解析器 --><bean class= "org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/></bean>
<!-- 配置注解驱动 --><mvc:annotation-driven />
<!--配置静态资源的访问映射,此配置中的文件,将不被前端控制器拦截 -->
<mvc:resources mapping="/js/**" location="/js/" />
三、<mvc:resources .../>的两个重要属性
|----------|----------------------------------------|
| 属性 | 说明 |
| location | 用于定位需要访问的本地静态资源文件路径,具体到某个文件夹 |
| mapping | 匹配静态资源全路径,其中"/**"表示文件夹及其子文件夹下的某个具体文件 |
6、启动chapter12项目,在浏览器中访问商品信息页面product.jsp,访问地址为http://localhost:8080/chapter12/product.jsp。
7、在product.jsp的显示效果图所示的页面中,单击右侧"提交单个商品"按钮,product.jsp表单中的单个商品信息以JSON格式异步发送到服务器端getProduct()方法中。提交单个商品时控制台打印信息如图所示。
java
获取到的Id为1名称为三文鱼的商品
从图中所示的打印信息可以得出,客户端异步提交的JSON数据,按照形参product属性的格式进行关联映射,并赋值给product对应的属性,完成了JSON数据的绑定。
8、在product.jsp的显示效果图所示的页面中,单击"提交多个商品"按钮,product.jsp表单中的2个商品信息以JSON格式异步发送到服务器端getProductList()方法中。提交多个商品时控制台打印信息如图所示。
java
获取到的Id为1名称为三文鱼的商品
获取到的Id为2名称为红牛的商品
从图中所示的打印信息可以得出,客户端异步提交的JSON数据,按照形参products的存储结构进行关联映射,并赋值给products中对象的对应属性,完成了JSON数据的绑定。
四、JSON转换器配置和静态资源访问配置
JSON转换器配置和静态资源访问配置,除了之前讲解的配置方案之外,还可以通过其他方式完成,下面讲解两种配置方式,使用<bean>元素配置JSON转换器和静态资源访问的配置方式。
(一)使用<bean>元素配置JSON转换器
在配置JSON转换器时,除了常用的<mvc:annotation-driven />元素,还可以使用<bean>元素进行显示的配置,<bean>元素配置JSON转换器方式具体如下所示。
html
<!-- 使用<bean>元素配置注解方式的处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method
.annotation.RequestMappingHandlerMapping" />
<!-- 使用<bean>元素配置注解方式的处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.method
.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters"><list><!-- 配置JSON转换器 -->
<bean class="org.springframework.http.converter.json
.MappingJackson2HttpMessageConverter"/></list></property>
</bean>
(二)静态资源访问的配置方式
除了使用<mvc:resources>元素实现对静态资源的访问外,Spring MVC还提供了另外2种静态资源访问的配置方式。
(1)使用<mvc:default-servlet-handler>配置静态资源
在Spring MVC的配置文件中,使用<mvc:default-servlet-handler>元素配置静态资源,也可以实现对静态资源的访问。配置静态资源的具体代码如下:
java
<mvc:default-servlet-handler />
在Spring MVC的配置文件中配置<mvc:default-servlet-handler />后,Spring MVC会在Spring MVC上下文中定义一个默认的Servlet请求处理器DefaultServletHttpRequestHandler,该处理器会对进入DispatcherServlet的URL进行筛查,如果发现是静态资源的请求,就将该请求转由Web服务器默认的Servlet处理,默认的Servlet会对静态资源放行;如果不是静态资源的请求,就由DispatcherServlet继续处理。
(2)激活Tomcat默认的Servlet来处理静态资源访问
在web.xml文件中激活Tomcat默认的Servlet去处理对应的静态资源,web.xml配置代码如下所示:
java
<servlet-mapping>
<servlet-name>default</servlet-name><url-pattern>*.js</url-pattern>
</servlet-mapping><servlet-mapping>
<servlet-name>default</servlet-name><url-pattern>*.css</url-pattern>
</servlet-mapping> ...
在上述代码中, <servlet-mapping>元素可以激活Tomcat默认的Servlet来处理静态文件。在配置时,可以根据需要继续追加<servlet-mapping>。此种配置方式和第(1)种方式本质上是一样的,都是使用Web服务器默认的Servlet来处理静态资源文件的访问。