SpringMVC框架是SSM框架中繼Spring另一個重要的框架,那麼什麼是SpringMVC,如何用SpringMVC來整合SSM框架呢?下面讓我們詳細的瞭解一下.
注:在學習SpringMVC之前最好有JavaWeb的基礎,這樣才能更好的理解SpringMVC,如果不瞭解JavaWeb可以參考這篇文章JavaWeb基礎入門到上手專案,本篇文章參照於B站狂神說老師的SpringMVC視訊編寫,視訊原地址為【狂神說Java】SpringMVC最新教學IDEA版通俗易懂 ,大家記得一鍵三連啊!!!
Model(模型):資料模型,提供要展示的資料,因此包含資料和行為,可以認為是領域模型或JavaBean元件(包含資料和行為),不過現在一般都分離開來:Value Object(資料Dao) 和 服務層(行為Service)。也就是模型提供了模型資料查詢和模型資料的狀態更新等功能,包括資料和業務。
View(檢視):負責進行模型的展示,一般就是我們見到的使用者介面,客戶想看到的東西。
Controller(控制器):接收使用者請求,委託給模型進行處理(狀態改變),處理完畢後把返回的模型資料返回給檢視,由檢視負責展示。也就是說控制器做了個排程員的工作。
最典型的MVC就是JSP + servlet + javabean的模式。
在web早期的開發中,通常採用的都是Model1。
Model1中,主要分為兩層,檢視層和模型層。
Model1優點:架構簡單,比較適合小型專案開發;
Model1缺點:JSP職責不單一,職責過重,不便於維護;
Model2把一個專案分成三部分,包括檢視、控制、模型。
使用者發請求
Servlet接收請求資料,並呼叫對應的業務邏輯方法
業務處理完畢,返回更新後的資料給servlet
servlet轉向到JSP,由JSP來渲染頁面
響應給前端更新後的頁面
職責分析:
Controller:控制器
Model:模型
View:檢視
Model2這樣不僅提高的程式碼的複用率與專案的擴充套件性,且大大降低了專案的維護成本。Model 1模式的實現比較簡單,適用於快速開發小規模專案,Model1中JSP頁面身兼View和Controller兩種角色,將控制邏輯和表現邏輯混雜在一起,從而導致程式碼的重用性非常低,增加了應用的擴充套件性和維護的難度。Model2消除了Model1的缺點。
1.新建一個Maven工程當做父工程!pom依賴!
<!--匯入相應的依賴-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
2.建立一個Moudle:springmvc-01-servlet , 新增Web app的支援!
3.匯入servlet 和 jsp 的 jar 依賴
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
4.編寫一個Servlet類,用來處理使用者的請求
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.獲取前端引數
String method = req.getParameter("method");
if (method.equals("add")){
req.getSession().setAttribute("msg","執行了add方法");
}
if (method.equals("delete")){
req.getSession().setAttribute("msg","執行了delete方法");
}
//2.呼叫業務層
//3.檢視轉發或者重定向
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5.編寫Hello.jsp,在WEB-INF目錄下新建一個jsp的資料夾,新建hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
6.在web.xml中註冊Servlet
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.qjd.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
7.設定Tomcat,並啟動測試
localhost:8080/user?method=add
localhost:8080/user?method=delete
MVC框架要做哪些事情
將url對映到java類或java類的方法 .
封裝使用者提交的資料 .
處理請求–呼叫相關的業務處理–封裝響應資料 .
將響應的資料進行渲染 . jsp / html 等表示層資料 .
說明:
常見的伺服器端MVC框架有:Struts、Spring MVC、ASP.NET MVC、Zend Framework、JSF;常見前端MVC框架:vue、angularjs、react、backbone;由MVC演化出了另外一些模式如:MVP、MVVM 等等…
Spring MVC是Spring Framework的一部分,是基於Java實現MVC的輕量級Web框架。
檢視官方檔案:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html
我們為什麼要學習SpringMVC呢?
Spring:大雜燴,我們可以將SpringMVC中所有要用到的bean註冊到Spring中
Spring MVC的特點:
輕量級,簡單易學
高效 , 基於請求響應的MVC框架
與Spring相容性好,無縫結合
約定優於設定
功能強大:RESTful、資料驗證、格式化、在地化、主題等
簡潔靈活
Spring的web框架圍繞DispatcherServlet [ 排程Servlet ] 設計。
DispatcherServlet的作用是將請求分發到不同的處理器。從Spring 2.5開始,使用Java 5或者以上版本的使用者可以採用基於註解形式進行開發,十分簡潔;
正因為SpringMVC好 , 簡單 , 便捷 , 易學 , 天生和Spring無縫整合(使用SpringIoC和Aop) , 使用約定優於設定 . 能夠進行簡單的junit測試 . 支援Restful風格 .例外處理 , 在地化 , 國際化 , 資料驗證 , 型別轉換 , 攔截器 等等…所以我們要學習 .
最重要的一點還是用的人多 , 使用的公司多 .
Spring的web框架圍繞DispatcherServlet設計。
DispatcherServlet的作用是將請求分發到不同的處理器。
從Spring 2.5開始,使用Java 5或者以上版本的使用者可以採用基於註解的controller宣告方式。
Spring MVC框架像許多其他MVC框架一樣, 以請求為驅動 , 圍繞一箇中心Servlet分派請求及提供其他功能,DispatcherServlet是一個實際的Servlet (它繼承自HttpServlet 基礎類別)。
(DispatcherServlet本質上還是Servlet)
SpringMVC的原理如下圖所示:
當發起請求時被前置的控制器攔截到請求,根據請求引數生成代理請求,找到請求對應的實際控制器,控制器處理請求,建立資料模型,存取資料庫,將模型響應給中心控制器,控制器使用模型與檢視渲染檢視結果,將結果返回給中心控制器,再將結果返回給請求者
原圖:
中文圖:
圖為SpringMVC的一個較完整的流程圖,實線表示SpringMVC框架提供的技術,不需要開發者實現,虛線表示需要開發者實現。
DispatcherServlet表示前置控制器,是整個SpringMVC的控制中心
簡要分析執行流程
234:適配收到的請求到底是幹什麼的(根據hello找到處理器Handler)
5678:這個請求具體做什麼(找HelloController執行)
91011:檢視解析
1、DispatcherServlet表示前置控制器,是整個SpringMVC的控制中心。使用者發出請求,DispatcherServlet接收請求並攔截請求。
我們假設請求的url為 : http://localhost:8080/SpringMVC/hello
如上url拆分成三部分:
http://localhost:8080 ------> 伺服器域名
SpringMVC ------> 部署在伺服器上的web站點
hello ------> 表示控制器
通過分析,如上url表示為:請求位於伺服器localhost:8080上的SpringMVC站點的hello控制器。
2、HandlerMapping為處理器對映。DispatcherServlet呼叫HandlerMapping,HandlerMapping根據請求url查詢Handler。
3、HandlerExecution表示具體的Handler,其主要作用是根據url查詢控制器,如上url被查詢控制器為:hello。
4、HandlerExecution將解析後的資訊傳遞給DispatcherServlet,如解析控制器對映等。
5、HandlerAdapter表示處理器介面卡,其按照特定的規則去執行Handler。
6、Handler讓具體的Controller執行。
7、Controller將具體的執行資訊返回給HandlerAdapter,如ModelAndView。
8、HandlerAdapter將檢視邏輯名或模型傳遞給DispatcherServlet。
9、DispatcherServlet呼叫檢視解析器(ViewResolver)來解析HandlerAdapter傳遞的邏輯檢視名。
10、檢視解析器將解析的邏輯檢視名傳給DispatcherServlet。
11、DispatcherServlet根據檢視解析器解析的檢視結果,呼叫具體的檢視。
12、最終檢視呈現給使用者。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.註冊DispatcherServlet-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--關聯一個springmvc的組態檔:【servlet-name】-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!--啟動級別-1-->
<load-on-startup>1</load-on-startup>
</servlet>
<!--/ 匹配所有的請求;(不包括.jsp)-->
<!--/* 匹配所有的請求;(包括.jsp)-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
4.編寫SpringMVC 的 組態檔!名稱:springmvc-servlet.xml : [servletname]-servlet.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 新增 處理對映器(可省略)-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--新增 處理器介面卡(可省略)-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--檢視解析器:DispatcherServlet給他的ModelAndView
1.獲取了ModelAndView資料
2.解析ModelAndView的檢視名字
3.拼接檢視名字,找到對應的檢視
4.將資料渲染到這個檢視上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--字首-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--字尾-->
<property name="suffix" value=".jsp"/>
</bean>
<!--Handler-->
<bean id="/hello" class="com.qjd.controller.HelloController"/>
</beans>
5.編寫我們要操作業務Controller ,要麼實現Controller介面,要麼增加註解;需要返回一個ModelAndView,裝資料,封檢視;
//注意:這裡我們先匯入Controller介面
public class HelloController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
//ModelAndView 模型和檢視
ModelAndView mv = new ModelAndView();
//封裝物件,放在ModelAndView中。Model
mv.addObject("msg","HelloSpringMVC!");
//封裝要跳轉的檢視,放在ModelAndView中
mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
return mv;
}
}
6.將自己的類交給SpringIOC容器,註冊bean
<!--Handler-->
<bean id="/hello" class="com.qjd.controller.HelloController"/>
7.寫要跳轉的jsp頁面,顯示ModelandView存放的資料,以及我們的正常頁面;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
8.設定Tomcat 啟動測試!
9.測試結果
可能遇到的問題:存取出現404,排查步驟:
檢視控制檯輸出,看一下是不是缺少了什麼jar包。
如果jar包存在,顯示無法輸出,就在IDEA的專案發布中,新增lib依賴!
重啟Tomcat 即可解決!
新建一個Moudle,springmvc-03-hello-annotation 。新增web支援!
由於Maven可能存在資源過濾的問題,我們將設定完善
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
在pom.xml檔案引入相關的依賴:主要有Spring框架核心庫、Spring MVC、servlet , JSTL等。我們在父依賴中已經引入了!
設定web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.註冊servlet-->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--通過初始化引數指定SpringMVC組態檔的位置,進行關聯-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 啟動順序,數位越小,啟動越早 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!--所有請求都會被springmvc攔截 -->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
/ 和 /* 的區別:
< url-pattern > / </ url-pattern > 不會匹配到.jsp, 只針對我們編寫的請求;即:.jsp 不會進入spring的 DispatcherServlet類 。
< url-pattern > /* </ url-pattern > 會匹配 *.jsp,會出現返回 jsp檢視 時再次進入spring的DispatcherServlet 類,導致找不到對應的controller所以報404錯。
新增Spring MVC組態檔
在resource目錄下新增springmvc-servlet.xml組態檔,設定的形式與Spring容器設定基本類似,為了支援基於註解的IOC,設定了自動掃描包的功能,具體設定資訊如下:
<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自動掃描包,讓指定包下的註解生效,由IOC容器統一管理 -->
<context:component-scan base-package="com.qjd.controller"/>
<!-- 讓Spring MVC不處理靜態資源 .css .js .html ... -->
<mvc:default-servlet-handler />
<!--
支援mvc註解驅動
在spring中一般採用@RequestMapping註解來完成對映關係
要想使@RequestMapping註解生效
必須向上下文中註冊DefaultAnnotationHandlerMapping
和一個AnnotationMethodHandlerAdapter範例
這兩個範例分別在類級別和方法級別處理。
而annotation-driven設定幫助我們自動完成上述兩個範例的注入。
-->
<mvc:annotation-driven />
<!-- 檢視解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 字首 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 字尾 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
在檢視解析器中我們把所有的檢視都存放在/WEB-INF/目錄下,這樣可以保證檢視安全,因為這個目錄下的檔案,使用者端不能直接存取。
建立Controller
package com.qjd.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/HelloController")
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model) {
//真實存取地址 : 專案名/HelloController/hello
//封裝資料,向模型中新增屬性msg與值,可以在JSP頁面中取出並渲染
model.addAttribute("msg","hello,springmvc annotation!");
//會被檢視解析器處理,web-inf/jsp/hello.jsp
return "hello";
}
}
@Controller是為了讓Spring IOC容器初始化時自動掃描到;
@RequestMapping是為了對映請求路徑,這裡因為類與方法上都有對映所以存取時應該是/HelloController/hello;
方法中宣告Model型別的引數是為了把Action中的資料帶到檢視中;
方法返回的結果是檢視的名稱hello,加上組態檔中的前字尾變成WEB-INF/jsp/hello.jsp
建立檢視層
在WEB-INF/ jsp目錄中建立hello.jsp , 檢視可以直接取出並展示從Controller帶回的資訊;
可以通過EL表示取出Model中存放的值,或者物件;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
${msg}
</body>
</html>
設定Tomcat執行
小結:
實現步驟其實非常的簡單:
新建一個web專案
匯入相關jar包
編寫web.xml , 註冊DispatcherServlet
編寫springmvc組態檔
接下來就是去建立對應的控制類 , controller
最後完善前端檢視和controller之間的對應
測試執行偵錯.
使用springMVC必須設定的三大件:
處理器對映器、處理器介面卡、檢視解析器
通常,我們只需要手動設定檢視解析器,而處理器對映器和處理器介面卡只需要開啟註解驅動即可,而省去了大段的xml設定
控制器複雜提供存取應用程式的行為,通常通過介面定義或註解定義兩種方法實現。
控制器負責解析使用者的請求並將其轉換為一個模型。
在Spring MVC中一個控制器類可以包含多個方法
在Spring MVC中,對於Controller的設定方式有很多種
Controller是一個介面,在org.springframework.web.servlet.mvc包下,介面中只有一個方法;
//實現該介面的類獲得控制器功能
public interface Controller {
//處理請求且返回一個模型與檢視物件
ModelAndView handleRequest(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}
測試
新建一個Moudle,springmvc-04-controller!
springmvc-02-hellomvc中mvc的組態檔只留下 檢視解析器!
編寫一個Controller類,ControllerTest1
//只要是實現了Controller介面的類,就說明這是一個控制器了
public class ControllerTest1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest01");
mv.setViewName("test");//跳轉到test.jsp
return mv;
}
}
編寫完畢後,去Spring組態檔中註冊請求的bean;name對應請求路徑,class對應處理請求的類
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自動掃描包,讓指定包下的註解生效,由IOC容器統一管理 -->
<context:component-scan base-package="com.qjd.controller"/>
<!-- 讓Spring MVC不處理靜態資源 .css .js .html ... -->
<mvc:default-servlet-handler />
<!--
支援mvc註解驅動
在spring中一般採用@RequestMapping註解來完成對映關係
要想使@RequestMapping註解生效
必須向上下文中註冊DefaultAnnotationHandlerMapping
和一個AnnotationMethodHandlerAdapter範例
這兩個範例分別在類級別和方法級別處理。
而annotation-driven設定幫助我們自動完成上述兩個範例的注入。
-->
<mvc:annotation-driven />
<!-- 以上可以省略,是預設設定 -->
<!--檢視解析器:DispatcherServlet給他的ModelAndView
1.獲取了ModelAndView資料
2.解析ModelAndView的檢視名字
3.拼接檢視名字,找到對應的檢視
4.將資料渲染到這個檢視上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--字首-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--字尾-->
<property name="suffix" value=".jsp"/>
</bean>
<bean name="/t1" class="com.qjd.controller.ControllerTest1"/>
</beans>
寫前端test.jsp,注意在WEB-INF/jsp目錄下編寫,對應我們的檢視解析器
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
$END$
</body>
</html>
設定Tomcat執行測試
說明:
不需要在springmvc-servlet.xml中註冊bean
@Controller註解型別用於宣告Spring類的範例是一個控制器(在講IOC時還提到了另外3個註解);
Spring可以使用掃描機制來找到應用程式中所有基於註解的控制器類,為了保證Spring能找到你的控制器,需要在組態檔中宣告元件掃描。
<!-- 自動掃描指定的包,下面所有註解類交給IOC容器管理 -->
<context:component-scan base-package="com.qjd.controller"/>
增加一個ControllerTest2類,使用註解實現;
@Controller
//代表這個類會被Spring接管,自動註冊,被這個註解的類中的所有的方法,如果返回值是String,並且有具體頁面可以跳轉,那麼就會被檢視解析器解析
public class ControllerTest2 {
//對映存取路徑
@RequestMapping("/t2")
public String index(Model model){
//Spring MVC會自動範例化一個Model物件用於向檢視中傳值
model.addAttribute("msg", "ControllerTest2");
//返回檢視位置
return "test";
}
@RequestMapping("/t3")
public String index2(Model model){
//Spring MVC會自動範例化一個Model物件用於向檢視中傳值
model.addAttribute("msg", "ControllerTest3");
//返回檢視位置
return "test";
}
}
執行tomcat測試
可以發現,我們的兩個請求都可以指向一個檢視(test),但是頁面結果的結果是不一樣的,從這裡可以看出檢視是被複用的,而控制器與檢視之間是弱偶合關係。
註解方式是平時使用的最多的方式!
@RequestMapping
@RequestMapping註解用於對映url到控制器類或一個特定的處理程式方法。可用於類或方法上。用於類上,表示類中的所有響應請求的方法都是以該地址作為父路徑。
@Controller
@RequestMapping("/c3")
public class ControllerTest3 {
@RequestMapping("/t1")
public String test1(Model model){
model.addAttribute("msg","Hello");
return "test";
}
}
//http://localhost:8080/c3/t1
//等價為類上的@RequestMapping不寫,方法上的@RequestMapping為 @RequestMapping("/c3/t1")
概念:
Restful就是一個資源定位及資源操作的風格。不是標準也不是協定,只是一種風格。基於這個風格設計的軟體可以更簡潔,更有層次,更易於實現快取等機制。
特點:簡潔、高效、安全
功能
資源:網際網路所有的事物都可以被抽象為資源
資源操作:使用POST、DELETE、PUT、GET,使用不同方法對資源進行操作。
分別對應 新增、 刪除、修改、查詢。
傳統方式操作資源 :通過不同的引數來實現不同的效果!方法單一,post 和 get
http://127.0.0.1/item/deleteItem.action?id=1 刪除,GET或POST
使用RESTful操作資源 :可以通過不同的請求方式來實現不同的效果!如下:請求地址一樣,但是功能可以不同!
http://127.0.0.1/item/1 查詢,GET
http://127.0.0.1/item 新增,POST
http://127.0.0.1/item 更新,PUT
http://127.0.0.1/item/1 刪除,DELETE
學習測試
在新建一個類 RestFulController
在Spring MVC中可以使用 @PathVariable 註解,讓方法引數的值對應繫結到一個URI模板變數上。
@Controller
public class RestFulController {
//原來:http://localhost:8080/add?a=1&b=2
//RestFul:http://localhost:8080/add/a/b
//@RequestMapping(name = "/add/{a}/{b}",method = RequestMethod.GET)
@GetMapping("/add/{a}/{b}")
public String test1(@PathVariable int a, @PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg","結果1為"+res);
return "test";
}
@PostMapping("/add/{a}/{b}")
public String test2(@PathVariable int a, @PathVariable int b, Model model){
int res = a + b;
model.addAttribute("msg","結果2為"+res);
return "test";
}
}
思考:使用路徑變數的好處?
使用method屬性指定請求型別
小結:
Spring MVC 的 @RequestMapping 註解能夠處理 HTTP 請求的方法, 比如 GET, PUT, POST, DELETE 以及 PATCH。
所有的位址列請求預設都會是 HTTP GET 型別的。
方法級別的註解變體有如下幾個:組合註解
@GetMapping 是一個組合註解,平時使用的會比較多!
它所扮演的是 @RequestMapping(method =RequestMethod.GET) 的一個快捷方式。
設定ModelAndView物件 , 根據view的名稱 , 和檢視解析器跳到指定的頁面 .
頁面 : {檢視解析器字首} + viewName +{檢視解析器字尾}
<!--檢視解析器:DispatcherServlet給他的ModelAndView
1.獲取了ModelAndView資料
2.解析ModelAndView的檢視名字
3.拼接檢視名字,找到對應的檢視
4.將資料渲染到這個檢視上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
<!--字首-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--字尾-->
<property name="suffix" value=".jsp"/>
</bean>
對應的controller類
public class ControllerTest1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest01");
mv.setViewName("test");//跳轉到test.jsp
return mv;
}
}
ServletAPI
通過設定ServletAPI , 不需要檢視解析器(不建議使用,瞭解即可) .
@Controller
public class ResultGo {
@RequestMapping("/result/t1")
public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.getWriter().println("Hello,Spring BY servlet API");
}
@RequestMapping("/result/t2")
public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
rsp.sendRedirect("/index.jsp");
}
@RequestMapping("/result/t3")
public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
//轉發
req.setAttribute("msg","/result/t3");
req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
}
}
(1)通過SpringMVC來實現轉發和重定向 - 無需檢視解析器;
測試前,需要將檢視解析器註釋掉
預設為forward轉發(也可以加上)
redirect轉發需特別加
@Controller
public class ResultSpringMVC {
@RequestMapping("/rsm/t1")
public String test1(){
//轉發
return "/index.jsp";
}
@RequestMapping("/rsm/t2")
public String test2(){
//轉發二
return "forward:/index.jsp";
}
@RequestMapping("/rsm/t3")
public String test3(){
//重定向
return "redirect:/index.jsp";
}
}
(2)通過SpringMVC來實現轉發和重定向 - 有檢視解析器;
重定向 , 不需要檢視解析器 , 本質就是重新請求一個新地方嘛 , 所以注意路徑問題.
可以重定向到另外一個請求實現 .
@Controller
public class ResultSpringMVC2 {
@RequestMapping("/rsm2/t1")
public String test1(){
//轉發
return "test";
}
@RequestMapping("/rsm2/t2")
public String test2(){
//重定向
return "redirect:/index.jsp";
//return "redirect:hello.do"; //hello.do為另一個請求/
}
}
1、提交的域名稱和處理方法的引數名一致
@Controller
@RequestMapping("/user")
public class UserController {
@GetMapping("/t1")
public String test1(String name, Model model){
//1.接收前端引數
System.out.println("接收到前端的引數為"+name);
//2.將返回的結果傳遞給前端,Model
model.addAttribute("msg",name);
//3.檢視跳轉
return "test";
}
}
2、提交的域名稱和處理方法的引數名不一致
@Controller
@RequestMapping("/user")
public class UserController {
@GetMapping("/t1")
public String test1(@RequestParam("username") String name, Model model){
//1.接收前端引數
System.out.println("接收到前端的引數為"+name);
//2.將返回的結果傳遞給前端,Model
model.addAttribute("msg",name);
//3.檢視跳轉
return "test";
}
}
3、提交的是一個物件
要求提交的表單域和物件的屬性名一致 , 引數使用物件即可
實體類:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private int age;
}
UserController:
//前端接收的是一個物件 : id,name,age
@GetMapping("/t2")
public String test2(User user,Model model){
System.out.println(user);
model.addAttribute("msg",user);
return "test";
}
說明:如果使用物件的話,前端傳遞的引數名和物件名必須一致,否則就是null。
第一種 : 通過ModelAndView
我們之前用的就是這種方式,這裡就不再過多贅述
public class ControllerTest1 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//返回一個模型檢視物件
ModelAndView mv = new ModelAndView();
mv.addObject("msg","ControllerTest1");
mv.setViewName("test");
return mv;
}
}
第二種 : 通過ModelMap
ModelMap
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap modelMap){
//封裝要顯示到檢視中的資料
//相當於req.setAttribute("name",name);
modelMap.addAttribute("name",name);
System.out.println(name);
return "hello";
}
第三種 : 通過Model
Model
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
//封裝要顯示到檢視中的資料
//相當於req.setAttribute("name",name);
model.addAttribute("msg",name);
System.out.println(name);
return "test";
}
就對於新手而言簡單來說使用區別就是:
Model 只有寥寥幾個方法只適合用於儲存資料,簡化了新手對於Model物件的操作和理解;
ModelMap 繼承了 LinkedMap ,除了實現了自身的一些方法,同樣的繼承 LinkedMap 的方法和特性;
ModelAndView 可以在儲存資料的同時,可以進行設定返回的邏輯檢視,進行控制展示層的跳轉。
我們更多的時候都是使用Model
測試步驟:
我們可以在首頁編寫一個提交的表單
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/e/t1" method="post">
<input type="text" name="name">
<input type="submit">
</form>
</body>
</html>
後臺編寫對應的處理類
@Controller
public class EncodingController {
@PostMapping("/e/t1")
public String test1(String name, Model model){
model.addAttribute("msg",name);
return "test";
}
}
輸入中文測試會發現亂碼
以前亂碼問題通過過濾器解決 , 而SpringMVC給我們提供了一個過濾器 , 可以在web.xml中設定 .
修改了xml檔案需要重啟伺服器!
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意:這裡寫/*,寫/的話過濾不了jsp頁面,不能解決亂碼
但是我們發現 , 有些極端情況下.這個過濾器對get的支援不好 .
處理方法 :
修改tomcat組態檔 :設定編碼!
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
自定義過濾器(萬能解決)
package com.kuang.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
/**
* 解決get和post請求 全部亂碼的過濾器
*/
public class GenericEncodingFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//處理response的字元編碼
HttpServletResponse myResponse=(HttpServletResponse) response;
myResponse.setContentType("text/html;charset=UTF-8");
// 轉型為與協定相關物件
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
// 對request包裝增強
HttpServletRequest myrequest = new MyRequest(httpServletRequest);
chain.doFilter(myrequest, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
//自定義request物件,HttpServletRequest的包裝類
class MyRequest extends HttpServletRequestWrapper {
private HttpServletRequest request;
//是否編碼的標記
private boolean hasEncode;
//定義一個可以傳入HttpServletRequest物件的建構函式,以便對其進行裝飾
public MyRequest(HttpServletRequest request) {
super(request);// super必須寫
this.request = request;
}
// 對需要增強方法 進行覆蓋
@Override
public Map getParameterMap() {
// 先獲得請求方式
String method = request.getMethod();
if (method.equalsIgnoreCase("post")) {
// post請求
try {
// 處理post亂碼
request.setCharacterEncoding("utf-8");
return request.getParameterMap();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else if (method.equalsIgnoreCase("get")) {
// get請求
Map<String, String[]> parameterMap = request.getParameterMap();
if (!hasEncode) { // 確保get手動編碼邏輯只執行一次
for (String parameterName : parameterMap.keySet()) {
String[] values = parameterMap.get(parameterName);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
// 處理get亂碼
values[i] = new String(values[i]
.getBytes("ISO-8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
}
hasEncode = true;
}
return parameterMap;
}
return super.getParameterMap();
}
//取一個值
@Override
public String getParameter(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
if (values == null) {
return null;
}
return values[0]; // 取回引數的第一個值
}
//取所有值
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> parameterMap = getParameterMap();
String[] values = parameterMap.get(name);
return values;
}
}
一般情況下,SpringMVC預設的亂碼處理就已經能夠很好的解決了!
然後在web.xml中設定這個過濾器即可!
亂碼問題,需要平時多注意,在儘可能能設定編碼的地方,都設定為統一編碼 UTF-8!
在 JavaScript 語言中,一切都是物件。因此,任何JavaScript 支援的型別都可以通過 JSON 來表示,例如字串、數位、物件、陣列等。看看他的要求和語法格式:
物件表示為鍵值對,資料由逗號分隔
花括號儲存物件
方括號儲存陣列
JSON 鍵值對是用來儲存 JavaScript 物件的一種方式,和 JavaScript 物件的寫法也大同小異,鍵/值對組合中的鍵名寫在前面並用雙引號 「」 包裹,使用冒號 : 分隔,然後緊接著值:
{"name": "QinJiang"}
{"age": "3"}
{"sex": "男"}
很多人搞不清楚 JSON 和 JavaScript 物件的關係,甚至連誰是誰都不清楚。其實,可以這麼理解:
JSON 是 JavaScript 物件的字串表示法,它使用文字表示一個 JS 物件的資訊,本質是一個字串。
var obj = {a: 'Hello', b: 'World'}; //這是一個物件,注意鍵名也是可以使用引號包裹的
var json = '{"a": "Hello", "b": "World"}'; //這是一個 JSON 字串,本質是一個字串
var obj = JSON.parse('{"a": "Hello", "b": "World"}');
//結果是 {a: 'Hello', b: 'World'}
var json = JSON.stringify({a: 'Hello', b: 'World'});
//結果是 '{"a": "Hello", "b": "World"}'
程式碼測試
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//編寫一個JavaScript物件
var user = {
name : '坤坤',
age : 18,
sex : '男'
};
//將js物件轉換為json物件
let json = JSON.stringify(user);
//將json物件轉換為js物件
let obj = JSON.parse(json);
//console.log(user);
console.log(json);
console.log(obj);
</script>
</head>
<body>
</body>
</html>
測試結果
Jackson應該是目前比較好的json解析工具了
當然工具不止這一個,比如還有阿里巴巴的 fastjson 等等。
我們這裡使用Jackson,使用它需要匯入它的jar包;
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
設定SpringMVC需要的設定
(web.xml)
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.註冊DispatcherServlet:這個是springmvc的核心;請求分發器,前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 設定SpringMVC的亂碼過濾 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
springmvc-servlet.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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自動掃描包,讓指定包下的註解生效,由IOC容器統一管理 -->
<context:component-scan base-package="com.qjd.controller"/>
<!-- 讓Spring MVC不處理靜態資源 .css .js .html ... -->
<mvc:default-servlet-handler />
<!--
支援mvc註解驅動
在spring中一般採用@RequestMapping註解來完成對映關係
要想使@RequestMapping註解生效
必須向上下文中註冊DefaultAnnotationHandlerMapping
和一個AnnotationMethodHandlerAdapter範例
這兩個範例分別在類級別和方法級別處理。
而annotation-driven設定幫助我們自動完成上述兩個範例的注入。
-->
<mvc:annotation-driven />
<!-- 檢視解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 字首 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 字尾 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
我們隨便編寫一個User的實體類,然後我們去編寫我們的測試Controller;
//需要匯入lombok
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private int age;
}
這裡我們需要兩個新東西,一個是@ResponseBody,一個是ObjectMapper物件,我們看下具體的用法
編寫一個Controller;
@Controller
public class UserController {
@RequestMapping(value = "/j1",produces = "application/json;charset=utf-8")//produces解決亂碼
@ResponseBody //加上這個註解就不會走檢視解析器,會直接返回一個字串
public String json1() throws JsonProcessingException {
//jackson ObjectMapper
ObjectMapper mapper = new ObjectMapper();
//建立一個物件
User user = new User(1,"坤坤",18);
String str = mapper.writeValueAsString(user);
return str;
}
}
設定Tomcat , 啟動測試一下!
亂碼統一解決
上一種方法比較麻煩,如果專案中有許多請求則每一個都要新增,可以通過Spring設定統一指定,這樣就不用每次都去處理了!
我們可以在springmvc的組態檔上新增一段訊息StringHttpMessageConverter轉換設定!
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
測試結果
返回json字串統一解決
@ResponseBody解決(每個方法都得加,不建議使用)
@RequestMapping( "/j1")
@ResponseBody //加上這個註解就不會走檢視解析器,會直接返回一個字串
public String json1() throws JsonProcessingException {
//jackson ObjectMapper
ObjectMapper mapper = new ObjectMapper();
//建立一個物件
User user = new User(1,"坤坤",18);
String str = mapper.writeValueAsString(user);
return str;
}
@RestController(直接加到類上即可)
@RestController
public class UserController {
@RequestMapping(value = "/j1")
public String json1() throws JsonProcessingException {
//建立一個jackson的物件對映器,用來解析資料
ObjectMapper mapper = new ObjectMapper();
//建立一個物件
User user = new User(1, "秦疆一號", 12);
//將我們的物件解析成為json格式
String str = mapper.writeValueAsString(user);
return str;
}
}
增加一個新的方法
@RequestMapping("/j2")
@ResponseBody
public String json2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//建立一個集合
List<User> userList = new ArrayList<User>();
User user1 = new User(1,"坤坤1",18);
User user2 = new User(2,"坤坤2",18);
User user3 = new User(3,"坤坤3",18);
User user4 = new User(4,"坤坤4",18);
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
String str = mapper.writeValueAsString(userList);
return str;
}
增加一個新的方法
@RequestMapping("/j3")
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//建立時間一個物件,java.util.Date
Date date = new Date();
//將我們的物件解析成為json格式
String str = mapper.writeValueAsString(date);
return str;
}
執行結果 :是時間戳的形式
解決方案:取消timestamps形式 , 自定義時間格式
@RequestMapping("/j3")
@ResponseBody
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//使用ObjectMapper來格式化日期,false代表不使用時間戳的形式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mapper.setDateFormat(sdf);
Date date = new Date();
sdf.format(date);
//ObjectMapper,時間解析後的預設格式為:Timestamp,時間戳
String str = mapper.writeValueAsString(date);
return str;
}
執行結果:
進階使用
將公共部分提取出來封裝成工具類
public class JsonUtils {
public static String getJson(Object object){
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}
public static String getJson(Object object,String dateFormat){
ObjectMapper mapper = new ObjectMapper();
//使用ObjectMapper來格式化日期,false代表不使用時間戳的形式
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
mapper.setDateFormat(sdf);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
再輸出時間物件是即可簡化程式碼:
@RequestMapping("/j3")
public String json3(){
Date date = new Date();
return JsonUtils.getJson(date,"yyyy-MM-dd HH:mm:ss");
}
}
輸出集合物件:
@RequestMapping("/j2")
public String json2(){
//建立一個集合
List<User> userList = new ArrayList<User>();
User user1 = new User(1,"坤坤1",18);
User user2 = new User(2,"坤坤2",18);
User user3 = new User(3,"坤坤3",18);
User user4 = new User(4,"坤坤4",18);
userList.add(user1);
userList.add(user2);
userList.add(user3);
userList.add(user4);
return JsonUtils.getJson(userlist);
}
}
8.7、FastJson
fastjson.jar是阿里開發的一款專門用於Java開發的包,
實現json物件與JavaBean物件的轉換,
實現JavaBean物件與json字串的轉換,
實現json物件與json字串的轉換。
實現json的轉換方法很多,最後的實現結果都是一樣的。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.60</version>
</dependency>
@RequestMapping("/j4")
@ResponseBody
//@ResponseBody//他就不會走檢視解析器,會直接返回一個 字串
public String json4(){
User user1 = new User(1, "秦疆1號", 12);
User user2 = new User(2, "秦疆2號", 12);
User user3 = new User(3, "秦疆3號", 12);
User user4 = new User(4, "秦疆4號", 12);
User user5 = new User(5, "秦疆5號", 12);
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
list.add(user5);
System.out.println("*******Java物件 轉 JSON字串*******");
String str1 = JSON.toJSONString(list);
System.out.println("JSON.toJSONString(list)==>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)==>"+str2);
System.out.println("\n****** JSON字串 轉 Java物件*******");
User jp_user1=JSON.parseObject(str2,User.class);
System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
System.out.println("\n****** Java物件 轉 JSON物件 ******");
JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));
System.out.println("\n****** JSON物件 轉 Java物件 ******");
User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
return JSON.toJSONString(list);
}
AJAX 工作原理:
我們可以使用前端的一個標籤來偽造一個ajax的樣子。iframe標籤
新建一個module :sspringmvc-06-ajax , 匯入web支援!
編寫一個 ajax-frame.html 使用 iframe 測試,感受下效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>iframe體驗頁面無重新整理</title>
</head>
<body>
<script type="text/javascript">
window.onload = function f() {
var myDate = new Date();
document.getElementById('currentTime').innerText = myDate.getTime();
}
function loadPage() {
var targetURL = document.getElementById('url').value;
console.log(targetURL);
document.getElementById('iframePosition').src = targetURL;
}
</script>
<div>
<p>顯示時間(1970毫秒):<span id="currentTime"></span></p>
<p>請輸入要載入的地址:</p>
<p>
<input type="text" id="url" value="https://www.bilibili.com/">
<input type="button" value="提交" onclick="loadPage()">
</p>
</div>
<div>
<h3>
載入頁面的位置
</h3>
<iframe style="width: 100%;height: 500px" id="iframePosition">
</iframe>
</div>
</body>
</html>
測試結果:
利用AJAX可以做:
Ajax的核心是xhr,xhr為向伺服器傳送請求和解析伺服器響應提供了介面,能夠以非同步的方式從伺服器獲取新資料
jQuery提供多個與AJAX有關的方法:
通過jQuery AJAX方法,您能夠使用HTTP Get和HTTP Post從遠端伺服器上請求文字、HTML、XML或JSON一同時您能夠把這些外部資料直接載入網頁的被選元素中。
Query Ajax-本質就是XMLHttpRequest,對他進行了封裝,方便呼叫!
jQuery.ajax(...)
部分引數:
url:請求地址
data:要傳送的資料
success:成功之後執行的回撥函數(全域性)
error:失敗之後執行的回撥函數(全域性)
使用jQuery需要先匯入jQuery的js檔案
匯入jquery , 可以使用線上的CDN , 也可以下載匯入
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="${pageContext.request.contextPath}/statics/js/jquery-3.1.1.min.js"></script>
我們來個簡單的測試,使用最原始的HttpServletResponse處理 , .最簡單 , 最通用(滑鼠失去焦點的時候非同步重新整理)
設定web.xml 和 springmvc的組態檔【記得靜態資源過濾和註解驅動設定上】
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--1.註冊DispatcherServlet:這個是springmvc的核心;請求分發器,前端控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 設定SpringMVC的亂碼過濾 -->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
<?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
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自動掃描包,讓指定包下的註解生效,由IOC容器統一管理 -->
<context:component-scan base-package="com.qjd.controller"/>
<!-- 靜態資源過濾 -->
<mvc:default-servlet-handler/>
<!-- 註解支援 -->
<mvc:annotation-driven/>
<!-- 檢視解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 字首 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 字尾 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
編寫一個AjaxController
@RestController
public class AjaxController {
@RequestMapping("/t1")
public String test(){
return "hello";
}
@RequestMapping("/a1")
public void a1(String name, HttpServletResponse response) throws IOException {
System.out.println("a1:param=>"+name);
if("kunkun".equals(name)){
response.getWriter().println("true");
}else {
response.getWriter().println("false");
}
}
}
匯入jquery , 可以使用線上的CDN , 也可以下載匯入(注意這裡匯入不成功會出現400錯誤)
編寫index.jsp測試
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<!--jQuery引入-->
<%-- <script src="http://code.jquery.com/jquery-3.6.0.min.js"></script>--%>
<script src = "${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
function a(){
$.post({
url:"${pageContext.request.contextPath}/a1",
data:{"name":$("#username").val()},
success:function (data){
alert(data);
},
error:function (){
alert("error");
}
})
}
</script>
</head>
<body>
<%--失去焦點的時候,發起一個請求(攜帶資訊)到後臺 --%>
使用者名稱:<input type="text" id="username" onblur="a()">
</body>
</html>
啟動tomcat測試!開啟瀏覽器的控制檯,當我們滑鼠離開輸入框的時候,可以看到發出了一個ajax的請求!是後臺返回給我們的結果!測試成功!
Ajax把主動權交給了前端:
在頁面點選載入資料按鈕即可顯示出資料(XHR非同步請求)
實體類user(使用了lombok外掛,可以自己寫實現類方法)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private int age;
private String sex;
}
我們來獲取一個集合物件,展示到前端頁面
@RequestMapping("/a2")
public List<User> a2(){
List<User> userList = new ArrayList<>();
//新增資料
userList.add(new User("張三",10,"男"));
userList.add(new User("李四",12,"男"));
userList.add(new User("王五",13,"男"));
return userList;
}
前端頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<!--jQuery引入-->
<%-- <script src="http://code.jquery.com/jquery-3.6.0.min.js"></script>--%>
<script src = "${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
$(function (){
$("#btn").click(function (){
$.post({
url:"${pageContext.request.contextPath}/a2",
success:function(data){
//console.log(data);
let html = "";
for (let i = 0; i < data.length; i++) {
html += "<tr>" +
"<td>" + data[i].name + "</td>" +
"<td>" + data[i].age + "</td>" +
"<td>" + data[i].sex + "</td>" +
"</tr>"
}
$("#content").html(html);
}
});
})
});
</script>
</head>
<body>
<input type="button" value="載入資料" id="btn">
<table>
<tr>
<td>姓名</td>
<td>年齡</td>
<td>性別</td>
</tr>
<tbody id="content">
<%--資料:後臺 --%>
</tbody>
</table>
</body>
</html>
測試結果
我們寫一個Controller(請求處理)
@RequestMapping("/a3")
public String a3(String name,String pwd){
String msg = "";
if (name != null) {
//admin 這些資料應該在資料庫中查詢
if ("admin".equals(name)){
msg = "ok";
}else {
msg = "使用者名稱有誤";
}
}
if (pwd != null) {
//123456 這些資料應該在資料庫中查詢
if ("123456".equals(pwd)){
msg = "ok";
}else {
msg = "密碼有誤";
}
}
return msg;
}
前端頁面Login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<!--jQuery引入-->
<%-- <script src="http://code.jquery.com/jquery-3.6.0.min.js"></script>--%>
<script src = "${pageContext.request.contextPath}/statics/js/jquery-3.6.0.js"></script>
<script>
//失去焦點
function a1(){
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{"name":$("#name").val()},
success:function (data) {
if(data.toString() == "ok"){
$("#userInfo").css("color","green");
}else {
$("#userInfo").css("color","red");
}
$("#userInfo").html(data);
}
})
}
function a2(){
$.post({
url:"${pageContext.request.contextPath}/a3",
data:{"pwd":$("#pwd").val()},
success:function (data) {
if(data.toString() == "ok"){
$("#pwdInfo").css("color","green");
}else {
$("#pwdInfo").css("color","red");
}
$("#pwdInfo").html(data);
}
})
}
</script>
</head>
<body>
<p>
使用者名稱:<input type="text" id="name" onblur="a1()"/>
<span id="userInfo"></span>
</p>
<p>
密碼:<input type="text" id="pwd" onblur="a2()"/>
<span id="pwdInfo"></span>
</p>
</body>
</html>
處理亂碼問題
<mvc:annotation-driven>
<!--JSON亂碼問題設定 -->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
測試結果
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>JSONP百度搜尋</title>
<style>
#q{
width: 500px;
height: 30px;
border:1px solid #ddd;
line-height: 30px;
display: block;
margin: 0 auto;
padding: 0 10px;
font-size: 14px;
}
#ul{
width: 520px;
list-style: none;
margin: 0 auto;
padding: 0;
border:1px solid #ddd;
margin-top: -1px;
display: none;
}
#ul li{
line-height: 30px;
padding: 0 10px;
}
#ul li:hover{
background-color: #f60;
color: #fff;
}
</style>
<script>
// 2.步驟二
// 定義demo函數 (分析介面、資料)
function demo(data){
var Ul = document.getElementById('ul');
var html = '';
// 如果搜尋資料存在 把內容新增進去
if (data.s.length) {
// 隱藏掉的ul顯示出來
Ul.style.display = 'block';
// 搜尋到的資料迴圈追加到li裡
for(var i = 0;i<data.s.length;i++){
html += '<li>'+data.s[i]+'</li>';
}
// 迴圈的li寫入ul
Ul.innerHTML = html;
}
}
// 1.步驟一
window.onload = function(){
// 獲取輸入框和ul
var Q = document.getElementById('q');
var Ul = document.getElementById('ul');
// 事件滑鼠擡起時候
Q.onkeyup = function(){
// 如果輸入框不等於空
if (this.value != '') {
// ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆JSONPz重點☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
// 建立標籤
var script = document.createElement('script');
//給定要跨域的地址 賦值給src
//這裡是要請求的跨域的地址 我寫的是百度搜尋的跨域地址
script.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+this.value+'&cb=demo';
// 將組合好的帶src的script標籤追加到body裡
document.body.appendChild(script);
}
}
}
</script>
</head>
<body>
<input type="text" id="q" />
<ul id="ul">
</ul>
</body>
</html>
過濾器與攔截器的區別:攔截器是AOP思想的具體應用。
過濾器
servlet規範中的一部分,任何javaweb工程都可以使用
在url-pattern中設定了/*之後,可以對所有要存取的資源進行攔截
攔截器
攔截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
攔截器只會攔截存取的控制器方法, 如果存取的是jsp/html/css/image/js是不會進行攔截的(自帶靜態資源過濾)
新建一個Moudule , springmvc-Interceptor , 新增web支援
設定web.xml 和 springmvc-servlet.xml 檔案
編寫一個攔截器(必須實現 HandlerInterceptor 介面)
public class MyInterceptor implements HandlerInterceptor {
//return true; 執行下一個攔截器,放行
//return false; 不執行下一個攔截器,攔截(卡在攔截器,不能執行請求)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("===========處理前===========");
return true;
}
//紀錄檔
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("===========處理後===========");
}
//紀錄檔
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("===========清理===========");
}
}
在springmvc的組態檔中設定攔截器
<!--攔截器設定 -->
<mvc:interceptors>
<mvc:interceptor>
<!--包括這個請求下面的所有請求-->
<mvc:mapping path="/**"/>
<bean class="com.qjd.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
編寫一個Controller,接收請求
@RestController
public class TestController {
@RequestMapping("/t1")
public String test(){
System.out.println("TestController->test()執行了");
return "ok";
}
}
啟動tomcat 測試一下!(http://localhost:8888/t1)
實現思路:
有一個登陸頁面,需要寫一個controller存取頁面。
登陸頁面有一提交表單的動作。需要在controller中處理。判斷使用者名稱密碼是否正確。如果正確,向session中寫入使用者資訊。返回登陸成功。
攔截使用者請求,判斷使用者是否登陸。如果使用者已經登陸。放行, 如果使用者未登陸,跳轉到登陸頁面
測試:
編寫一個登陸頁面 login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%--在web-inf下面的所有頁面或者資源,只能通過controller或者Servlet進行存取--%>
<h1>登入頁面</h1>
<form action="${pageContext.request.contextPath}/user/login" method="post">
使用者名稱:<input type="text" name="username">
密碼:<input type="text" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>
編寫一個Controller處理請求
@Controller
@RequestMapping("/user")
public class LoginController {
@RequestMapping("/login")
public String login(String username, String password, HttpSession session, Model model){
//把使用者的資訊存在session中
session.setAttribute("userLoginInfo",username);
model.addAttribute("username",username);
return "main";
}
@RequestMapping("/goOut")
public String goOut(String username, String password, HttpSession session, Model model){
session.removeAttribute("userLoginInfo");
return "main";
}
@RequestMapping("/main")
public String main(){
return "main";
}
@RequestMapping("/goLogin")
public String login(){
return "login";
}
}
編寫一個登陸成功的頁面 main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>首頁</h1>
<p>
<span>${username}</span>
</p>
<p>
<a href="${pageContext.request.contextPath}/user/goOut">登出</a>
</p>
</body>
</html>
在 index 頁面上測試跳轉!啟動Tomcat 測試,未登入也可以進入主頁!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1><a href="${pageContext.request.contextPath}/user/goLogin">登入頁面</a></h1>
<h1><a href="${pageContext.request.contextPath}/user/main">首頁</a></h1>
</body>
</html>
編寫使用者登入攔截器
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
//放行:判斷什麼情況下登入
//登入頁面也會放行
if (request.getRequestURI().contains("goLogin")) {
return true;
}
if (request.getRequestURI().contains("login")) {
return true;
}
if (session.getAttribute("userLoginInfo") != null) {
return true;
}
//判斷什麼情況下沒有登入
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
在Springmvc的組態檔中註冊攔截器
<!--攔截器設定 -->
<mvc:interceptors>
<mvc:interceptor>
<!--包括這個請求下面的所有請求-->
<mvc:mapping path="/**"/>
<bean class="com.qjd.config.MyInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<!--包括這個請求下面的所有請求-->
<mvc:mapping path="/user/**"/>
<bean class="com.qjd.config.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
再次重啟Tomcat測試!
(1)
(2)
對錶單中的 enctype 屬性做個詳細的說明:
<%--enctype="multipart/form-data" 代表以二進位制流的形式提交 --%>
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>
一旦設定了enctype為multipart/form-data,瀏覽器即會採用二進位制流的方式來處理表單資料,而對於檔案上傳的處理則涉及在伺服器端解析原始的HTTP響應。在2003年,Apache Software Foundation釋出了開源的Commons FileUpload元件,其很快成為Servlet/JSP程式設計師上傳檔案的最佳選擇。
匯入檔案上傳的jar包,commons-fileupload , Maven會自動幫我們匯入他的依賴包 commons-io包;
<!--檔案上傳-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!--servlet-api匯入高版本的-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
設定bean:multipartResolver
<!--檔案上傳設定-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 請求的編碼格式,必須和jSP的pageEncoding屬性一致,以便正確讀取表單的內容,預設為ISO-8859-1 -->
<property name="defaultEncoding" value="utf-8"/>
<!-- 上傳檔案大小上限,單位為位元組(10485760=10M) -->
<property name="maxUploadSize" value="10485760"/>
<property name="maxInMemorySize" value="40960"/>
</bean>
CommonsMultipartFile 的 常用方法:
String getOriginalFilename():獲取上傳檔案的原名
InputStream getInputStream():獲取檔案流
void transferTo(File dest):將上傳檔案儲存到一個目錄檔案中
編寫前端頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%--enctype="multipart/form-data" 代表以二進位制流的形式提交 --%>
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file"/>
<input type="submit" value="upload">
</form>
<a href="${pageContext.request.contextPath}/statics/1.jpg">點選下載</a>
</body>
</html>
Controller
這個controller包含問價能上傳的兩種方法(fileUpload,fileUpload2),檔案下載的一種方法(downloads)
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
@RestController
public class FilerController {
//@RequestParam("file") 將name=file控制元件得到的檔案封裝成CommonsMultipartFile 物件
//批次上傳CommonsMultipartFile則為陣列即可
@RequestMapping("/upload")
public String fileUpload(@RequestParam("file") CommonsMultipartFile file , HttpServletRequest request) throws IOException {
//獲取檔名 : file.getOriginalFilename();
String uploadFileName = file.getOriginalFilename();
//如果檔名為空,直接回到首頁!
if ("".equals(uploadFileName)){
return "redirect:/index.jsp";
}
System.out.println("上傳檔名 : "+uploadFileName);
//上傳路徑儲存設定
String path = request.getServletContext().getRealPath("/upload");
//如果路徑不存在,建立一個
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
System.out.println("上傳檔案儲存地址:"+realPath);
InputStream is = file.getInputStream(); //檔案輸入流
OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //檔案輸出流
//讀取寫出
int len=0;
byte[] buffer = new byte[1024];
while ((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
os.flush();
}
os.close();
is.close();
return "redirect:/index.jsp";
}
/*
* 採用file.Transto 來儲存上傳的檔案
*/
@RequestMapping("/upload2")
public String fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
//上傳路徑儲存設定
String path = request.getServletContext().getRealPath("/upload");
File realPath = new File(path);
if (!realPath.exists()){
realPath.mkdir();
}
//上傳檔案地址
System.out.println("上傳檔案儲存地址:"+realPath);
//通過CommonsMultipartFile的方法直接寫檔案(注意這個時候)
file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));
return "redirect:/index.jsp";
}
@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
//要下載的圖片地址
String path = request.getServletContext().getRealPath("/upload");
String fileName = "1.jpg";
//1、設定response 響應頭
response.reset(); //設定頁面不快取,清空buffer
response.setCharacterEncoding("UTF-8"); //字元編碼
response.setContentType("multipart/form-data"); //二進位制傳輸資料
//設定響應頭
response.setHeader("Content-Disposition",
"attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));
File file = new File(path,fileName);
//2、 讀取檔案--輸入流
InputStream input=new FileInputStream(file);
//3、 寫出檔案--輸出流
OutputStream out = response.getOutputStream();
byte[] buff =new byte[1024];
int index=0;
//4、執行 寫出操作
while((index= input.read(buff))!= -1){
out.write(buff, 0, index);
out.flush();
}
out.close();
input.close();
return null;
}
}
測試結果
(1)檔案上傳
因為Controller使用的@RestController,所以返回的是字串
(2)檔案下載
輸入download下載檔案:
ok,下載成功!
到這裡關於SpringMVC的知識就結束了,並且SSM框架也結束了,如果任何文章有遺漏或錯誤歡迎大家提出,我會第一時間修改。關於SSM框架,大家如果想要深入理解SSM框架,就要多去看開源的專案,在專案中更深入理解SSM.
最後,關於SSM整合--簡易書籍管理系統大家可以看下面的文章:SSM框架整合---簡易書籍管理系統