認識 Spring MVC
什么是 Spring MVC
Spring MVC(正式名稱:Spring Web MVC) 是基于 Servlet API 構(gòu)建的原始 Web 框架,從?開始就包含在 Spring 框架中。
- Spring MVC 是?個 Web 框架
- Spring MVC 是基于 Servlet API 構(gòu)建的
MVC 的定義
MVC 是 Model View Controller 的縮寫,它是軟件?程中的?種軟件架構(gòu)模式,它把軟件系統(tǒng)分為模型、視圖和控制器三個基本部分。
MVC 執(zhí)行流程:
- 用戶的請求首先到 Controller
- Controller 將請求轉(zhuǎn)發(fā)給 Model
- Model 處理業(yè)務(wù)并將數(shù)據(jù)結(jié)果返回給 Controller
- Controller 將處理的數(shù)據(jù)發(fā)給 View
- View 將數(shù)據(jù)轉(zhuǎn)換成頁面發(fā)送給用戶
MVC 是?種思想,? Spring MVC 是對 MVC 思想的具體實現(xiàn)。
總結(jié)來說,Spring MVC 是?個實現(xiàn)了 MVC 模式,并繼承了 Servlet API 的 Web 框架。既然是 Web框架,那么當?戶在瀏覽器中輸?了 url 之后,我們的 Spring MVC 項?就可以感知到?戶的請求.
在創(chuàng)建 Spring Boot 項?時,我們勾選的 Spring Web 框架其實就是 Spring MVC 框架。
Spring MVC 注解的運用
- 連接的功能:將?戶(瀏覽器)和 Java 程序連接起來,也就是訪問?個地址能夠調(diào)?到我們的 Spring 程序。
- 獲取參數(shù)的功能:?戶訪問的時候會帶?些參數(shù),在程序中要想辦法獲取到參數(shù)。
- 輸出數(shù)據(jù)的功能:執(zhí)?了業(yè)務(wù)邏輯之后,要把程序執(zhí)?的結(jié)果返回給?戶
1. Spring MVC 的連接
首先創(chuàng)建一個 TestController 類,來實現(xiàn)用戶與 Spring 程序的交互:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller //讓該類隨著 Spring 框架啟動而加載
@ResponseBody //返回非頁面數(shù)據(jù)(這個注解在返回數(shù)據(jù)中講解)
//@RestController 相當于@Controller + @ResponseBody
@RequestMapping("/test") //路由器規(guī)則注冊(一級路由)
public class TestController {
@RequestMapping("/hi") //路由器規(guī)則注冊(二級路由)
public String sayHi() {
System.out.println("hi Spring MVC");
return "<h1> 你好 Spring MVC <h1>";
}
}
通過瀏覽器地址訪問,來與程序交互:
可以看到,通過我們訪問地址 http://localhost:8080/test/hi 就可以執(zhí)行sayHi 方法,并返回字符串到頁面上了。
這里注意:
spring mvc 項目默認掃描路徑是啟動類所在的包下所有的子包,也就是說:我們新建的的類要想放入 IoC 中,就得在該包下創(chuàng)建類。(默認啟動類是在 demo 包下)
@RequestMapping 注解
@RequestMapping 是 Spring Web 應(yīng)?程序中最常被?到的注解之?,它是?來注冊接?的路由映射的。
路由映射:所謂的路由映射指的是,當?戶訪問?個 url 時,將?戶的請求對應(yīng)到程序中某個類的某個?法的過程就叫路由映射。
@RequestMapping 即可修飾類,也可以修飾?法,當修飾類和?法時,訪問的地址是類 + ?法。
@RequestMapping 也可以直接修飾?法,代碼實現(xiàn)如下:
默認情況下,@RequestMapping 是支持 post 和 get 請求的,我們用 Postman 來驗證一下:
get 請求:
post 請求:
在有些情況下,我們可能要該注解只支持其中一種請求,那要怎么實現(xiàn)呢?
- 只支持 get 請求的注解方式
@RestController
@RequestMapping("/test")
public class TestController {
//方式一
//下面 value 也可以改為 path
@RequestMapping(value = "/hi",method = RequestMethod.GET)
public String sayHi() {
System.out.println("hi Spring MVC");
return "<h1> 你好 Spring MVC <h1>";
}
//方式二
@GetMapping("/hhh")
public String hhh() {
return "hello world";
}
}
這里就只演示一下方式一:
注意,瀏覽器通過 url 來訪問地址, 默認是 get 請求。
再通過 Postman 來構(gòu)造一下 post 請求:
2. 只支持 post 請求的注解方式
@RestController
@RequestMapping("/test2")
public class Test2Controller {
//方式一
@RequestMapping(path = "/hi",method = RequestMethod.POST)
public String sayHi() {
return "你好";
}
//方式二
@PostMapping("/hhh")
public String hhh() {
return "你好,世界!";
}
}
這里通過瀏覽器直接訪問就報錯了:
通過 Postman 構(gòu)建 post 請求:
2. 獲取參數(shù)
獲取單個參數(shù)
學習 servlet 時獲取參數(shù)的寫法:
@RestController
@RequestMapping("/user")
public class UserController {
//傳統(tǒng)寫法獲取請求中的參數(shù)
@RequestMapping("/getname") //這里不建議使用大小寫, 可以用下劃線來區(qū)分
public String getName(HttpServletRequest request) {
return "Name : " + request.getParameter("name");
}
}
通過 url 傳遞參數(shù):
通過注解獲?。?/p>
@RestController
@RequestMapping("/user")
public class UserController {
//直接獲取 url 中的參數(shù)
//當該路由被觸發(fā)后,執(zhí)行到方法時
//就會對 name 進行匹配,直接對 name 進行賦值
@RequestMapping("/getname2")
public String getName2(String name) {
return "Name : " + name;
}
}
獲取多個參數(shù)
其實獲取多個參數(shù)和獲取單個參數(shù)差不多:
@RestController
@RequestMapping("/user")
public class UserController {
//在傳參時,注意參數(shù)的命名與要獲取的參數(shù)名一致
@RequestMapping("/getname3")
public String getName3(String name, Integer age) {
return "Name : " + name + "age : " + age;
}
}
不傳參數(shù)就默認為 null
傳遞對象
顧名思義,就是將參數(shù)當做一個對象的部分屬性來接收,在接收時我們新建一個 model 層,來存放所需要的對象:
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/add")
public User add(User user) {
return user; //將得到的對象返回回去
}
}
@Data 注解是個組合注解,它等于:@Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @NoArgsConstructor
添加了它就不需要我們自己寫 Getter 和 Setter 方法了,減少重復(fù)工作。
當后端進行接收數(shù)據(jù)時,就會將參數(shù)和 user 里的屬性進行對比,發(fā)現(xiàn)屬性名稱與參數(shù)的 key 相同就會進行賦值。
當對象返回前端時,因為前端是用 json 來表示對象的,所以返回的對象就轉(zhuǎn)化為 json 格式 :
表單傳參
其實表單傳參和 url 傳參區(qū)別就是傳遞參數(shù)的位置不一樣,對于后端來說都一樣,我們可以用 Postman 來構(gòu)造請求:
后端參數(shù)重命名
有時候前端傳遞的 key 你覺得不合理,想改個順眼的名字,就可以對傳遞過來的參數(shù)重命名,當然前端的參數(shù)是不變的。(注意: 對象不能重命名)
@RestController
@RequestMapping("/user")
public class UserController {
//將前端參數(shù) y 改為 name,并由 name 接收
@RequestMapping("/name")
public String name(@RequestParam("y") String name) {
return name;
}
}
這里就有一個問題,如果我不傳這個 y 就會報錯:
在 @RequestParam 中,參數(shù)默認是必傳的:
如果我們需求是參數(shù)非必傳則可以進行如下修改:
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/name")
public String name(@RequestParam(value = "y",required = false) String name) {
return name;
}
}
這樣就不會報錯了:
@RequestBody 接收 JSON 對象
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/get_json")
public User getJson(@RequestBody User user) {
return user;
}
}
使用 Postman 構(gòu)造對象并發(fā)送 :
@PathVariable 獲取 URL 中的參數(shù)
@RestController
@RequestMapping("/user")
public class UserController {
//{aid} 中的 aid 是用來接收參數(shù)的
@RequestMapping("/get_url/{aid}")
//下面的 "aid" 是將參數(shù)名為 aid 的參數(shù)賦值給后面的 aid
//這里兩個 aid 名字相同,可以省略參數(shù)名("aid")不寫
public Integer getUrl(@PathVariable("aid") Integer aid) {
return aid;
}
}
當然了, 還可以傳遞多個參數(shù) :
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/get_url2/{aid}/{name}")
public String getUrl2(@PathVariable() Integer aid, @PathVariable String name) {
return "aid: " + aid + " name: " + name;
}
}
上傳文件 @RequestPart
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/upload")
//myfile 是接收的參數(shù)名, 賦值給 file
public String upload(@RequestPart("myfile") MultipartFile file) throws IOException {
String path = "E:\\image\\img.png";
//保存文件
file.transferTo(new File(path));
return path;
}
}
該路徑下確實保存了 img.png 圖片
上面的代碼寫法是有問題的, 如果有很多用戶都要保存文件, 那文件名就不能寫死了, 必須保證每次保存的文件名都不一樣, 可以使用 UUID :
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/upload")
public String upload(@RequestPart("myfile") MultipartFile file) throws IOException {
//得到 UUID 并去掉 "-"
String name = UUID.randomUUID().toString().replace("-","");
//file.getOriginalFilename() 得到文件名
//file.getOriginalFilename().lastIndexOf(".") 得到最后一個"."的下標
//整個就是 name 拼接上 .后綴名
name += file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
String path = "E:\\image\\" + name;
//保存文件
file.transferTo(new File(path));
return path;
}
}
多次提交得到的文件 :
獲取 Cookie/Session/Header
- 獲取 Cookie
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/get_cookie")
public String getCookie(@CookieValue(value = "myCookie", required = false) String ck) {
return ck;
}
}
沒有輸出 :
通過前端構(gòu)建一個 key 為 myCookie 的 cookie :
- 獲取 Session
要想獲取 Session 首先要有 Session, 我們可以上傳一個 Session :
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/set_session")
public String setSession(HttpServletRequest request) {
HttpSession session = request.getSession();
if(session != null) {
session.setAttribute("SESSION_KEY","張三");
return "session set success";
}
return "session set fail";
}
@RequestMapping("/get_session")
public String getSession(@SessionAttribute(required = false, value = "SESSION_KEY") String name) {
return name;
}
}
3. 獲取 Header
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/get_header")
public String getHeader(@RequestHeader("User-Agent") String userAgent) {
return "UserAgent : " + userAgent;
}
}
可以通過 fiddler 來抓包驗證一下 :
3. 返回數(shù)據(jù)
默認請求下?論是 Spring MVC 或者是 Spring Boot 返回的都是 html 格式,如果需要返回非 html 格式數(shù)據(jù), 就得使用 @ResponseBody 注解了, 我們之前一直使用的 @RestController 便是 @ResponseBody + @Controller 注解.
驗證返回數(shù)據(jù)的默認格式 :
@Controller
public class Test {
@RequestMapping("/b")
public String t() {
return "hello.html";
}
}
因為沒有這個前端頁面, 所以返回出錯 :
抓包(返回的是 html 格式) :
在靜態(tài)文件中加入 hello.html 文件 :
再次訪問 :
使用 @ResponseBody 返回字符串 :文章來源:http://www.zghlxwxcb.cn/news/detail-653534.html
@Controller
public class Test {
@ResponseBody
@RequestMapping("/a")
public String t2() {
return "hello.html";
}
}
或者使用 @RestController 也可以.文章來源地址http://www.zghlxwxcb.cn/news/detail-653534.html
到了這里,關(guān)于Spring MVC 中的常見注解的用法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!