一、消息轉換器—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來處理靜態資源文件的訪問。