Java框架-SpringMVC的應用(json資料互動、控制器方法返回值、檔案上傳)
阿新 • • 發佈:2018-11-01
1. 搭建SpringMVC開發環境
1.1 建立專案,新增依賴
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
< modelVersion>4.0.0</modelVersion>
<groupId>com.azure</groupId>
<artifactId>day56project_SpringMVC_day2</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--匯入spring核心包-->
<dependency>
< groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--匯入springMVC支援包-->
<dependency>
<groupId>org.springframework</ groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--servlet支援包-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
<!--日誌包-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
1.2 web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--設定springMVC前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--載入springMVC配置檔案-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--設定攔截規則-->
<servlet-mapping>
<!--
攔截請求規則:
1. *.do:攔截作為.do字尾得請求
要求:請求路徑字尾必須以.do結尾;
缺點:不方便,每個請求都要寫上.do的字尾;不支援restful風格的請求
2./ 表示攔截所有的請求,但不包含jsp請求
注意:此時靜態資源(如html、css等)無法訪問。
-->
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
1.3 springMVC.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--1. 開啟註解掃描-->
<context:component-scan base-package="com.azure"></context:component-scan>
<!--2. 配置檢視解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--3. 開啟mvc註解-->
<mvc:annotation-driven></mvc:annotation-driven>
</beans>
1.4 測試頁面index.html
由於在web.xml中前端控制器的攔截規則是/
,動態資源(jsp)不會被攔截,而靜態資源(如html、css、js等)預設不能訪問。
1.4.1 攔截路徑設為/時靜態資源無法訪問的原因分析
-
tomcat伺服器訪問任何資源都是通過servlet把資源返回到瀏覽器客戶端。
-
而訪問靜態資源不是使用servlet程式,而是預設通過DefaultServlet(預設servlet)把靜態資源返回到客戶端中。該預設servlet在tomcat伺服器啟動時預設就建立:
-
而我們在專案中配置攔截的路徑是
/
,則所有的資源都會進入我們專案新建的dispatcherServlet,而不會經過DefaultServlet,從而導致靜態資源無法被返回。 -
所以解決方式有兩種:修改放行資源路徑,重新配置DefaultServlet.
1.4.2 指定放行路徑對靜態資源放行
- 將資源放入包中,然後在springMVC.xml中指定放行資源路徑
- 也可以單獨指定放行的資源,但是效率差
- 注意:
/pages/*
和/panges/**
兩種寫法的差別
1.4.2.1 springMVC.xml配置調整
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--1. 開啟註解掃描-->
<context:component-scan base-package="com.azure"></context:component-scan>
<!--2. 配置檢視解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--3. 開啟mvc註解-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--4. 設定放行的靜態資源-->
<!--使用mvc:resources標籤:
屬性:
mapping:指定對映路徑,即瀏覽器的訪問路徑
location:表示對映路徑對應的實際物理路徑
-->
<!--放行指定的單個資源-->
<mvc:resources mapping="/index.html" location="/index.html"/><!--表示放行根目錄下的index.html,之所以會報錯是idea不推薦這種配置方式-->
<!--放行指定目錄下的所有資源-->
<!--/pages/* : 表示pages目錄下的所有資源會被放行-->
<!--/pages/**: 表示pages目錄及其子目錄下的所有資源會被放行-->
<mvc:resources mapping="/pages/**" location="/pages/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/image/**" location="/image/"/>
</beans>
1.4.3 使用tomcat的DefaultServlet處理靜態資源
- 重新配置使用預設servlet處理靜態資源
1.4.3.1 web.xml配置調整
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!--設定springMVC前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--載入springMVC配置檔案-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!--設定攔截規則-->
<servlet-mapping>
<!--
攔截請求規則:
1. *.do:攔截作為.do字尾得請求
要求:請求路徑字尾必須以.do結尾;
缺點:不方便,每個請求都要寫上.do的字尾;不支援restful風格的請求
2./ 表示攔截所有的請求,但不包含jsp請求
注意:此時靜態資源(如html、css等)無法訪問。
-->
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--配置預設servlet處理指定靜態資源-->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
</web-app>
2. 往域中存放資料
2.1 Model和ModelMap型別
- 作用:作為方法引數時可以將資料儲存到request域中
- 使用方法:Model和ModelMap作為控制器方法的引數
2.1.1 示例程式碼
2.1.1.1 控制類
@Controller
public class ModelController {
/*Model作為方法引數*/
@RequestMapping("/model")
public String model(Model model) {
model.addAttribute("JoJo","StarPlatinum" );
return "success";
}
/*ModelMap作為方法引數*/
@RequestMapping("/modelMap")
public String modelMap(ModelMap modelMap) {
modelMap.addAttribute("Dio","TheWorld" );
return "success";
}
}
2.1.1.2 success.jsp頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>success</title>
</head>
<body>
<h3>success!!</h3>
${requestScope.JoJo}<%--從request域中獲取資料--%>
${requestScope.Dio}
</body>
</html>
2.1.2 Model和ModelMap的異同
相同點:
- 由於ModelMap的一個子類ExtendedModelMap實現Model介面,所以Model和ModelMap都是通過Model介面的子實現類BindingAwareModelMap實現儲存資料到域的功能;使用addAttribute方法時最終都是會呼叫
request.setAttribute()
方法; - 兩者從將資料儲存到request域中的角度上來看是一樣的。
不同點:
- Model是介面,而ModelMap是類。它們有各自的功能,只是儲存資料到request域的功能上一致
2.2 SessionAttributes註解
- 作用:自動把Model或ModelMap中的資料儲存到session域中,用於多次執行控制器方法間的引數共享。
- 屬性:
- names:用於存入Model或ModelMap中指定的屬性名稱的資料;
- type:用於存入Model或ModelMap中指定型別的資料。該型別的所有資料都會存入session中。如果是基本資料型別,要使用對應包裝類的位元組碼物件
2.2.1 控制類
/**
* 註解@SessionAttributes
* 1.自動把Model或者ModelMap中的資料放入session
* 2.屬性:
* names = {"JoJo","Dio"}, 把Model或者ModelMap中指定名稱的key的資料,自動放入session
* types = Integer.class 把Model或者ModelMap中指定型別的資料,自動放入session
*/
@Controller
@SessionAttributes(names = {"JoJo","Dio"},types = Integer.class)
public class SessionAttributesController {
@RequestMapping("/sessionModel")
public String sessionModel(Model model) {
model.addAttribute("JoJo","StarPlatinum");
model.addAttribute("Dio","TheWorld");
model.addAttribute("num1",831143);
model.addAttribute("num2","12345");//不滿足存入的條件,該條資料不會存入session
return "success";
}
@RequestMapping("/sessionModelMap")
public String sessionModelMap(ModelMap modelMap) {
modelMap.addAttribute("JoJo","StarPlatinum");
modelMap.addAttribute("Dio","TheWorld");
return "success";
}
/*清除session的資料
* 1.使用原始的session.setAttribute方法存入的,只能使用原始的方法清除;
* 2.使用springMVC提供的方法自動存入的(即上面程式碼),只能使用@SessionAttributes註解清除.
* 注意:方法的引數是SessionStatus,這個物件提供setComplete()方法清空自動存入session的資料,
* 而原始方法存入的不會被清除
*/
@RequestMapping("/del")
public String del(SessionStatus sessionStatus){
// 清空通過@SessionAttributes註解自動放入session中的資料
sessionStatus.setComplete();
return "success";
}
}
2.2.2 success.jsp頁面
<body>
<h3>success!!</h3>
<h4>從request域中獲取資料</h4>
${requestScope.JoJo}
${requestScope.Dio}
<h4>從session域中獲取資料</h4>
${sessionScope.JoJo}
${sessionScope.Dio}
${sessionScope.num1}
${sessionScope.num2}
</body>
3. json資料的互動
3.1 使用的註解
3.1.1 @RequestBody
- 作用:在處理器方法的形參上使用。把請求的json格式資料轉換為java物件
3.1.2 @ResponseBody
- 在處理器方法返回值上使用,或在方法上使用。需要jackson支援包
- 作用:將響應的java物件轉換為json格式的資料
3.2 新增依賴
- 需要在pom.xml中匯入jackson支援包
<!--jackson支援包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
3.3 引入jquery檔案,在springMVC.xml中配置
- 由於上面已經在springMVC中設定放行
/js/**
的資源
3.4 在pages目錄下新建測試用html頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajax</title>
<script src="../js/jquery-3.3.1.min.js" type="text/javascript"></script>
<script>
$(function(){
$("#ajaxPost").click(function(){
$.ajax({
// 請求型別,這裡必須為post,否則無法使用requestBody
type : "post",
// 請求地址
url : "/responseBodyJson",
// 傳送給後臺的ajax請求資料
data:'{"id":100,"name":"jack","money":9.9}',
dataType:"json",
// 請求格式與編碼,避免亂碼
contentType:"application/json;charset=utf-8",
success : function(jsn){
alert("jsn="+jsn+"; jsn.id="+jsn.id+"; jsn.name="+jsn.name+"; jsn.money="+jsn.money);
}
});
});
});
</script>
</head>
<body>
<h2>RequestBody獲取請求JSON格式資料 & ResponseBody自動把物件轉json並響應</h2>
<button id="ajaxPost">測試ajax請求json與響應json</button>
</body>
</html>
3.5 建立Account實體類用來封裝資料
public class Account {
private int id;
private String name;
private double money;
3.6 控制器類
@Controller
public class JsonController {
@RequestMapping("/responseBodyJson") //注意與頁面的ajax中的url保持一致
@ResponseBody //表示方法返回json格式(自動把返回物件轉json格式)