Spring MVC数据绑定和响应——复杂数据绑定(四)JSON数据绑定

一、消息转换器---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来处理静态资源文件的访问。

相关推荐
陌上 烟雨齐17 分钟前
Kafka数据生产和发送
java·分布式·kafka
Jinkxs25 分钟前
高级15-Java构建工具:Maven vs Gradle深度对比
java·开发语言·maven
有梦想的攻城狮26 分钟前
spring中的ApplicationRunner接口详解
java·后端·spring·runner·application
程序视点27 分钟前
设计模式之原型模式!附Java代码示例!
java·后端·设计模式
振鹏Dong2 小时前
微服务架构及常见微服务技术栈
java·后端
丶小鱼丶2 小时前
二叉树算法之【中序遍历】
java·算法
摇滚侠3 小时前
Oracle 关闭 impdp任务
java
编程爱好者熊浪4 小时前
RedisBloom使用
java
苇柠4 小时前
Spring框架基础(1)
java·后端·spring
yics.4 小时前
数据结构——栈和队列
java·数据结构