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

发布于:2024-07-03 ⋅ 阅读:(12) ⋅ 点赞:(0)

一、消息转换器—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的依赖。

    <!--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的部分代码如下所示。

<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()方法,分别用于获取客户端提交的单个商品信息和多个商品信息。

<%@ 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配置文件的部分配置代码如下所示。

<!-- 配置要扫描的包 -->
    <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()方法中。提交单个商品时控制台打印信息如图所示。

获取到的Id为1名称为三文鱼的商品

        从图中所示的打印信息可以得出,客户端异步提交的JSON数据,按照形参product属性的格式进行关联映射,并赋值给product对应的属性,完成了JSON数据的绑定。

        8、在product.jsp的显示效果图所示的页面中,单击“提交多个商品”按钮,product.jsp表单中的2个商品信息以JSON格式异步发送到服务器端getProductList()方法中。提交多个商品时控制台打印信息如图所示。

获取到的Id为1名称为三文鱼的商品
获取到的Id为2名称为红牛的商品

        从图中所示的打印信息可以得出,客户端异步提交的JSON数据,按照形参products的存储结构进行关联映射,并赋值给products中对象的对应属性,完成了JSON数据的绑定。

四、JSON转换器配置和静态资源访问配置

        JSON转换器配置和静态资源访问配置,除了之前讲解的配置方案之外,还可以通过其他方式完成,下面讲解两种配置方式,使用<bean>元素配置JSON转换器和静态资源访问的配置方式。

(一)使用<bean>元素配置JSON转换器

        在配置JSON转换器时,除了常用的<mvc:annotation-driven />元素,还可以使用<bean>元素进行显示的配置,<bean>元素配置JSON转换器方式具体如下所示。

<!-- 使用<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>元素配置静态资源,也可以实现对静态资源的访问。配置静态资源的具体代码如下:

<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配置代码如下所示:

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