SpringMVC介紹-01 1.離線文檔 解壓 spring-5.3.8-dist.zip文件。 位置:spring-framework-5.3.8/docs/reference/html/web.html#spring-web 2.SpringMVC基本介紹 2.1SpringMVC特點&概述 ...
SpringMVC介紹-01
1.離線文檔
解壓 spring-5.3.8-dist.zip文件。
位置:spring-framework-5.3.8/docs/reference/html/web.html#spring-web
2.SpringMVC基本介紹
2.1SpringMVC特點&概述
-
SpringMVC 從易用性,效率上都比曾經流行的 Struts2 更好
-
SpringMVC 是 WEB 層框架:SpringMVC接管了 web層組件,比如控制器,視圖,視圖解析,返回給用戶的數據格式,同時支持 MVC 的開發模式/開發架構
-
SpringMVC 通過註解,讓 POJO 成為控制器,不需要繼承類或者實現介面
-
SpringMVC 採用低耦合的組件設計方式,具有更好的拓展和靈活性
-
支持 REST 格式的 URL 請求
-
SpringMVC 是基於 Spring 的,它的核心包為 spring-webmvc-xxx.jar 和 spring-web-xxx.jar
2.2Spring SpringMVC SpringBoot的關係
- SpringMVC 只是 Spring 處理 WEB 層的一個模塊/組件,SpringMVC 的基石是 Servlet
- SpringBoot 是為了簡化開發者的使用而推出的一個框架(約定優於配置,簡化了Spring的配置流程),它包含很多組件/框架,Spring 就是最核心的內容之一,也包含了 SpringMVC
- 三者之間的關係是:Spring Boot > Spring > SpringMVC
3.SpringMVC的快速入門
3.1需求說明
需求說明:使用SpringMVC,完成一個最基本的測試案例——登錄案例
3.2SpringMVC登錄流程分析
3.3代碼實現
-
創建Java項目,添加 web支持並配置 tomcat
-
導入SpringMVC 開發需要的jar包
-
src目錄下創建spring的容器文件applicationContext-mvc.xml(名稱隨意)
-
在WEB-INF/web.xml文件中配置前端控制器(中央控制器)
<!--配置前端控制器/中央控制器/分發控制器,負責處理所有的應用請求--> <servlet> <servlet-name>springDispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--配置屬性 contextConfigLocation,指定 DispatcherServlet 去操作的 spring容器配置文件--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-mvc.xml</param-value> </init-param> <!--在web項目啟動時,就自動的載入 DispatcherServlet實例,1表示載入的順序號--> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springDispatcherServlet</servlet-name> <!--1.配置的url-pattern為 /,表示用戶的請求都經過 DispatcherServlet 2.這樣配置也支持 rest 風格的url請求--> <url-pattern>/</url-pattern> </servlet-mapping>
-
web目錄下創建login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登錄</title> </head> <body> <h3>登錄頁面</h3> <%-- action="login": 這樣寫實際上是相對路徑,而相對路徑是以當前的瀏覽器地址欄而言。 因此實際上這裡表示的 url 是 http://localhost:8080/web工程路徑/login --%> <form action="login"> u:<input name="username" type="text"/> <br/> p:<input name="password" type="password"/> <br/> <input type="submit" value="登錄"/> </form> </body> </html>
關於web工程路徑,詳見 Javaweb--day18-web工程路徑
-
創建 src/com/li/web/UserServlet.java
package com.li.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author 李 * @version 1.0 * 1.如果我們使用了SpringMVC,在一個類上標識 @Controller * 2.表示將該類視為一個控制器,註入到容器 * 3.比原生的 servlet方便很多 */ @Controller public class UserServlet { /** * 編寫login方法,響應用戶請求 * 1.login()方法用於響應用戶的登錄請求 * 2.@RequestMapping(value = "/login") * 類似於我們原生的Servlet配置的url-pattern,不同的是這裡是給方法配置url映射 * 3.當用戶在瀏覽器地址欄輸入 http://localhost:8080/web工程路徑/login * 就能夠訪問當到 login()方法 * 4.return "login_ok"; 表示返回結果給視圖解析器(InternalResourceViewResolver), * 視圖解析器會根據配置,來決定提交到哪一個頁面,如: * <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> * <property name="prefix" value="/WEB-INF/pages/"/> * <property name="suffix" value=".jsp"/> * </bean> * 根據上面的配置,return "login_ok"; 就是轉發到 /WEB-INF/pages/login_ok.jsp * * @return */ @RequestMapping(value = "/login") public String login() { System.out.println("login ok..."); return "login_ok"; } }
-
創建web/WEB-INF/pages/login_ok.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登錄成功</title> </head> <body> <h1>恭喜,登錄成功!</h1> </body> </html>
-
配置容器文件applicationContext-mvc.xml
<!--指定掃描的包--> <context:component-scan base-package="com.li.web"/> <!--配置視圖解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!--配置屬性 suffix(尾碼) 和 prefix(首碼)--> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean>
-
整體的文件位置如下:
-
啟動tomcat,訪問
http://localhost:8080/springmvc/login.jsp
,訪問成功: -
點擊登錄,成功訪問到login_ok.jsp
3.4註意事項和細節說明
-
這裡的UserServlet 需要註解成一個@Controller,我們稱之為一個Handler處理器
-
在UserServlet 指定 url 時,value 可以省略(註意是省略“value”字元,不是省略值)
-
關於SpringMVC 的 DispatcherServlet 的配置文件,如果不在web.xml中指定spring配置文件,則預設在
/WEB-INF/
目錄下找名為springDispatcherServlet-servlet.xml
的spring配置文件。因此,我們將之前的spring容器文件移動到/web-INF/目錄下,並註釋掉web.xml配置的
<init-param>
,然後將容器文件重命名為 springDispatcherServlet-servlet.xml,重啟tomcat,依然可以成功運行。
4.SpringMVC執行流程
5.@RequestMapping
5.1基本使用
@RequestMapping註解可以指定 控制器(處理器) 的某個方法的請求url
5.2@RequestMapping其他使用方式
5.2.1修飾方法和類
@RequestMapping註解可以修飾方法,還可以修飾類。
當同時修飾類和方法時,請求的url就是組合形式:/類請求值/方法請求值
例子
(1)UserHandler.java:
package com.li.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* @author 李
* @version 1.0
*/
@RequestMapping(value = "/user")
@Controller //UserHandler就是一個處理器/控制器,註入到spring容器
public class UserHandler {
/**
* 1.method = RequestMethod.POST 表示請求buy方法必須是post請求
* 2.RequestMethod 四個常用的選項 :GET, POST, PUT, DELETE
* 3.如果沒有配置 RequestMethod,SpringMVC控制器預設支持 get和 post兩種方式
* 4.buy()方法對應的完整請求url = http://ip:port/web工程路徑/user/buy
* @return
*/
@RequestMapping(value = "/buy", method = RequestMethod.POST)
public String buy() {
System.out.println("購買商品");
return "success";
}
}
(2)request.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>購買商品</title>
</head>
<body>
<h1>購買商品</h1>
<%--
buy()方法對應的完整請求 url = http://ip:port/web工程路徑/user/buy
--%>
<form action="user/buy" method="post">
購買人:<input type="text" name="username"/><br/>
購買量:<input type="text" name="nums"/><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
(3)success.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>操作成功</title>
</head>
<body>
<h1>恭喜,操作成功!</h1>
</body>
</html>
在瀏覽器中訪問 http://localhost:8080/springmvc/request.jsp
,點擊提交按鈕,結果如下:
5.2.2指定請求方式
-
@RequestMapping 可以指定請求的方式(post/get/put/delete...),請求方式要和指定方式一致,否則報錯:
-
SpringMVC 控制器預設支持get 和 post兩種請求方式,即如果沒有指定 method,可以接收 get 和 post請求
5.2.3指定params和headers,支持簡單表達式
param1
:表示請求必須包含名為 param1 的請求參數!param1
:表示請求不能包含名為 param1 的請求參數param1 != value1
:表示請求包含名為 param1 的請求參數,但其值不能為 value1{"param1 = value1", "param2"}
:請求必須包含名為 param1 和 param2 的兩個請求參數,且 param1的值必須為 value1
應用實例
(1)修改UserHandler.java,增加方法
//...
@RequestMapping(value = "/user")
@Controller
public class UserHandler {
//...
/**
* 1.params = "bookId" 表示請求該方式時,必須給一個名為 bookId的參數
* 2.search(String bookId){} 表示請求目標方法時,
* 攜帶的 bookId參數的值會被填充到目標方法的同名形參中
* @param bookId
* @return
*/
@RequestMapping(value = "/find", params = "bookId", method = RequestMethod.GET)
public String search(String bookId) {
System.out.println("查詢書籍 bookId=" + bookId);
return "success";
}
}
(2)request.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>購買商品</title>
</head>
<body>
<h1>演示params的使用</h1>
<a href="user/find?bookId=100">查詢書籍</a>
</body>
</html>
(3) success.jsp 不變。
(4)redeployTomcat,在瀏覽器地址欄訪問:http://localhost:8080/springmvc/request.jsp
,點擊查詢書籍超鏈接,結果如下:
(5)修改UserHandler.java,指定參數的值=100。
(6)修改request.jsp,修改發送的值為200.
(7)redeployTomcat,重新範文request.jsp,點擊超鏈接,這裡可以看到出現異常,因為發送的值和方法指定的值不一樣。
5.2.4支持Ant 風格資源地址
?
:匹配文件名中的一個字元*
:匹配文件名中的任意字元,長度任意**
:匹配多層路徑- Ant 風格的 url 地址舉例:
/user/*/createUser
:匹配 /user/aaa/createUser、/user/bbb/createUser 等 URL/user/**/createUser
:匹配 /user/createUser、/user/aaa/bbb/createUser 等 URL/user/createUser??
: 匹配 /user/createUserab、/user/createUsercd 等 URL
應用實例
(1)修改UserHandler.java,增加方法:
//...
@RequestMapping(value = "/user")
@Controller
public class UserHandler {
//...
/**
* 要求:可以匹配 /user/message/aa, /user/message/aa/bb/cc
* @RequestMapping(value = "/message/**")
* 表示可以匹配多層的路徑
* @return
*/
@RequestMapping(value = "/message/**")
public String im(){
System.out.println("發送消息");
return "success";
}
}
(2)修改request.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>購買商品</title>
</head>
<body>
<h1>演示 Ant 風格的請求資源方式</h1>
<a href="user/message/aa">發送消息 1</a><br>
<a href="user/message/aa/bb/cc">發送消息 2</a><br>
</body>
</html>
(3) success.jsp 不變。
(4)redeployTomcat,在瀏覽器地址欄訪問:http://localhost:8080/springmvc/request.jsp
,分別點擊兩個超鏈接,都能成功訪問方法,並跳轉到success.jsp
5.2.5可配合@PathVariable映射URL綁定的占位符
- @RequestMapping 還可以配合 @PathVariable(路徑變數) 映射 URL 綁定的占位符
- 這樣就不需要在url地址欄上帶參數名了,更加簡潔明瞭
例子
request.jsp頁面如下,其中 kristina 和 300 皆為參數值
<h1>占位符的演示</h1>
<a href="user/reg/kristina/300">占位符的演示</a>
(1)修改UserHandler.java,增加方法,註意@PathVariable("username") 不能少
//...
@RequestMapping(value = "/user")
@Controller
public class UserHandler {
/**
* 我們希望目標方法獲取到username和 userid
* 前端頁面為:<a href="user/reg/kristina/300">占位符的演示</a>
* 1. value = "/reg/{username}/{userid}"
* 表示 kristina=>{username} ,300=>{userid}
* 2.通過 @PathVariable 將變數賦給對應的形參
*/
@RequestMapping(value = "/reg/{username}/{userid}")
public String register(@PathVariable("username") String name,
@PathVariable("userid") int id) {
System.out.println("接收到的參數--username=" + name + "--userid=" + id);
return "success";
}
}
(2)success.jsp不變
(3)redeployTomcat,訪問 http://localhost:8080/springmvc/request.jsp
,點擊超鏈接,成功訪問到success.jsp,後臺輸出如下:
5.2.6註意事項和使用細節
-
映射的URL不能重覆,否則報錯:
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'userHandler' method com.li.web.UserHandler#buy() to {POST [/user/buy]}: There is already 'userHandler' bean method
-
各種請求的簡寫形式
@RequestMapping(value="/buy",method=RequestMethod.POST)
等價於@PostMapping(value="buy")
以此類推,還有
@GetMapping
,@PostMapping
,@PutMapping
,@DeleteMapping
-
如果我們確定表單或者超鏈接會提交某個欄位數據,比如email,要求提交的參數名和目標方法的參數名保持一致。
例如:
/** * hello3(String email){} 如果請求參數有email=xx,就會將傳遞的參數值賦給String email * 但是要求名稱保持一致!如果不一致,那麼接收不到數據,而是null * @param email * @return */ @GetMapping(value = "/hello3") public String hello3(String email) { System.out.println("hello3= " + email); return "success"; }
5.2.7練習
編寫一個表單,以Post方式提交表單信息,後端編寫ComputerHandler,可以接收到表單信息
computer.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>hw-電腦信息</title>
</head>
<body>
<h1>電腦信息</h1>
<form action="computer/info" method="post">
品牌:<input type="text" name="brand"/><br/>
價格:<input type="text" name="price"/><br/>
數量:<input type="text" name="nums"/><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
ComputerHandler:
package com.li.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 李
* @version 1.0
*/
@RequestMapping("/computer")
@Controller
public class ComputerHandler {
//註意接收的參數名要和info方法的形參名一致
@PostMapping("/info")
public String info(String brand, String price, String nums) {
System.out.println("brand=" + brand +
" price=" + price + " nums=" + nums);
return "success";
}
}
redeployTomcat,訪問:http://localhost:8080/springmvc/computer.jsp
,輸入信息,點擊提交表單。
後臺輸出: