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来处理静态资源文件的访问。

相关推荐
Theodore_102212 分钟前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
冰帝海岸1 小时前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象2 小时前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了2 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
小二·2 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic3 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王3 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康3 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神3 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
qq_327342734 小时前
Java实现离线身份证号码OCR识别
java·开发语言