一、Spring MVC 是什么
Spring MVC 全稱 “Spring Web MVC” 是一個(gè) 基于 Servlet API 構(gòu)建的原始 Web 框架 ,從一開始就包含在 Spring 框架中
Web 框架
在之前學(xué)習(xí) Servlet 的時(shí)候就已經(jīng)接觸到 Web 。所謂的 Web 框架,就是當(dāng)用戶輸入一個(gè) URL 地址后,將 URL 地址和程序進(jìn)行映射,然后通過程序獲取到用戶的請(qǐng)求,經(jīng)過請(qǐng)求的處理后,服務(wù)器發(fā)送的響應(yīng)能夠返回到客戶端,將結(jié)果展示給用戶
Servlet API
有關(guān) Servlet API 的介紹文章
MVC 含義
MVC 是一種軟件工程中的一種軟件架構(gòu)模式,將軟件系統(tǒng)分成了模型、視圖、控制器三部分
M(Model) :指的是 模型 ,用于處理應(yīng)用程序數(shù)據(jù)邏輯部分
V(View) :指的是 視圖 ,用于處理數(shù)據(jù)顯示部分
C(Controller) :指的是 控制器 ,用于處理用戶交互的部分
解釋
用戶通過瀏覽器去訪問程序的時(shí)候,請(qǐng)求會(huì)先到 Controller(控制層),控制層驗(yàn)證參數(shù)的合法性,如果沒有問題的話,就會(huì)將請(qǐng)求轉(zhuǎn)發(fā)給 Model(模型)進(jìn)行業(yè)務(wù)的處理,然后將結(jié)果(業(yè)務(wù)數(shù)據(jù))響應(yīng)給控制層,然后控制層再將數(shù)據(jù)發(fā)送給 View(視圖),視圖最后做合并和整理工作,組裝成了一個(gè) HTML 頁面,最后將頁面響應(yīng)給用戶
總的來說, MVC 就是一種思想, Spring MVC 就是對(duì) MVC 這是一種思想的具體實(shí)現(xiàn)
二、Spring MVC 具體使用
2.1 Spring MVC 創(chuàng)建
Spring MVC 使用 Spring Boot 的方式創(chuàng)建的,創(chuàng)建的 Spring Boot 項(xiàng)目過程中有勾選依賴這一環(huán)節(jié),勾選的 Spring Web 框架 就是 Spring MVC 框架,將該依賴給勾選上了,其余的就是正常的創(chuàng)建 Spring Boot 項(xiàng)目的步驟
2.2 Spring MVC 連接
Spring MVC 連接即將用戶和 Java 程序進(jìn)行連接,用戶通過一個(gè)地址就可以調(diào)用到 Spring 程序
@RequestMapping 注解
在 Spring MVC 中常常使用 @RequestMapping 注解實(shí)現(xiàn)路由映射
路由映射就是用戶訪問 URL 時(shí),能夠?qū)⒂脩舻恼?qǐng)求和程序中的某個(gè)類中的某個(gè)方法對(duì)應(yīng)起來
@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(“/hello”) public String func() { return “
Hello Spring MVC
“; }}
解釋
顯示指定方法
@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(value = “/hello”,method = RequestMethod.POST) public String func() { return “
Hello Spring MVC
“; }}
通過 method 參數(shù) 內(nèi)容就可以指定具體的接收方法,此時(shí)該方法只能接收 POST 請(qǐng)求
@GetMapping 和 @PostMapping
除了在 @RequestMapping 注解中指定接收的方法之外,也可以直接使用 @GetMapping 和 @PostMapping 注解,前者使得方法只能接收 GET 請(qǐng)求,后者使得方法只能接受 POST 請(qǐng)求
2.3 如何獲取參數(shù)
2.3.1 通過 URL 傳遞參數(shù)
例如URL:http://127.0.0.1:8080/index/getUser?userName=peter&passWord=123
想要獲取 userName 和 passWord 對(duì)應(yīng)的內(nèi)容,可以直接使用方法中的參數(shù)來實(shí)現(xiàn)傳參
代碼展示
@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(“/getUser”) public String getUser(String userName,String passWord) { return “userName->”+ userName + ” | passWord->” + passWord; }}
結(jié)果顯示
注意
2.3.2 通過表單傳遞參數(shù)
通過表單進(jìn)行參數(shù)的傳遞方法也是和上面差不多的
代碼同上面的代碼展示,通過 PostMan 進(jìn)行提交 form 表單,也需要注意參數(shù)的對(duì)應(yīng)
結(jié)果展示
2.3.3 傳遞對(duì)象
在參數(shù)較少的情況下,會(huì)使用直接傳參的方式,如果參數(shù)較多時(shí),使用對(duì)象進(jìn)行傳參會(huì)更好
代碼展示
@Datapublic class User { private String userName; private String passWord;}@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(“/getUser1”) public String gerUser1(User user) { String name = user.getUserName(); String word = user.getPassWord(); return “對(duì)象中的userName:” + name + ” | 對(duì)象中的passWord:” + word; }}
結(jié)果顯示
代碼參數(shù)是一個(gè) User 對(duì)象,說明待會(huì)需要接收的就是一個(gè)對(duì)象,然后就會(huì)拿著這個(gè)對(duì)象中的所有屬性,在請(qǐng)求中匹配參數(shù)
2.3.4 補(bǔ)充
后端參數(shù)的重命名
后端參數(shù)名未必一定要和前端參數(shù)名一模一樣,可以通過 @RequestParam 注解來 重命名前后端的參數(shù)值
@RequestMapping(“/getUser”)public String getUser(@RequestParam(“userName”) String name,String passWord) { return “userName->”+ name + ” | passWord->” + passWord;}
前端的參數(shù) key 是 userName 和 passWord ,后端的參數(shù) key 是 name 和 passWord
設(shè)置參數(shù)必傳/非必傳
同樣是上面的代碼,如果參數(shù)中只傳了 userName 參數(shù)會(huì)怎樣,只傳了 passWord 參數(shù)會(huì)怎樣
結(jié)果顯示
如果沒有傳遞 passWord 參數(shù),影響不大
如果沒有傳遞 userName 參數(shù),就會(huì)報(bào) 400 錯(cuò)誤
原因就是 @RequestParam 中的 required 參數(shù)默認(rèn)值為 true ,表示 為必傳參數(shù)
如果有參數(shù)需要使用 @RequestParam 注解且該參數(shù)是非必傳參數(shù),就需要將 required 參數(shù)值設(shè)置為 false
@RequestMapping(“/getUser”)public String getUser(@RequestParam(value = “userName”,required = false) String name,String passWord) { return “userName->”+ name + ” | passWord->” + passWord;}
2.3.5 接收 JSON 對(duì)象
使用 @RequestBody 來接收 JSON 對(duì)象
代碼展示
@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(“/loginByJson”) public String loginByJson(@RequestBody User user) { return “userName:” + user.getUserName() + ” | passWord:” + user.getPassWord(); }}
結(jié)果顯示
2.3.6 獲取 URL 中的參數(shù)
一般來說,獲取 URL 中的參數(shù)一般是指獲取 query String 中的參數(shù)值,但還有一種特殊的,就是從 URL 的 PATH 中獲取參數(shù)
需要通過 @PathVariable 注解
代碼展示
@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(“/loginByPath/{userName}/{passWord}”) public String loginByPath(@PathVariable(“userName”) String name, @PathVariable String passWord) { return “userName:” + name + ” |passWord:” + passWord; }}
注意
結(jié)果顯示
2.3.7 文件上傳
使用 @RequestPart 注解上傳圖片
代碼展示
@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(“/upLoad”) public String upLoadFile(String userName, @RequestPart(“picture”)MultipartFile file) throws IOException { //獲取文件后綴 String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(“.”)); //文件路徑 String filePath = System.getProperty(“user.dir”)+ “/src/main/resources/picture/” + UUID.randomUUID().toString(); //拼接路徑 String finallyPath = filePath + suffix; file.transferTo(new File(finallyPath)); return userName + “上傳了一張圖片”; }}
注意
結(jié)果顯示
2.3.8 獲取 Cookie/Session/header
獲取 Cookie
通過 @CookieValue 注解
@RequestMapping(“/getCookie”)public String getCookie(@CookieValue(“newCookie”) String value) { return “cookie:” + value;}
最一開始訪問該方法時(shí)結(jié)果為 404 ,因?yàn)榇藭r(shí)沒有 key 為 newCookie 這樣的 Cookie
通過瀏覽器端模擬該 Cookie 后,就可以獲取到 Cookie 的值
獲取 Header
通過 @RequestHeader 注解
@RequestMapping(“/getHeader”)public String getHeader(@RequestHeader(“User-Agent”) String content) { return “User-Agent:” + content;}
獲取 Session
通過 @SessionAttribute 注解
按照以前的方法來創(chuàng)建 Session
@RequestMapping(“/setSession”)public String setSession(HttpServletRequest req) { HttpSession session = req.getSession(true); if(session != null) { session.setAttribute(“userName”,”Spring MVC”); } return “session 設(shè)置完成”;}
獲取 Session 對(duì)象中的 key 為 userName 的值
@RequestMapping(“/getSession”)public String getSession(@SessionAttribute(value = “userName”,required = false) String userName) { return “userName:” + userName;}
2.4 如何返回參數(shù)
2.4.1 返回靜態(tài)頁面
默認(rèn)請(qǐng)求下,Spring Boot 返回的是靜態(tài)頁面
代碼展示
@Controller@RequestMapping(“/index”)public class UserController { @RequestMapping(“/getView”) public String getView() { return “/index.html”; }}
index.html 中主要內(nèi)容為 Hello Spring MVC~
2.4.2 返回 text/html
在之前的各種例子中都是返回 text/html 類型,當(dāng)方法 返回值為 String 時(shí) ,并且有加上 @ResponseBody 注解,返回的就是 text/html 類型
實(shí)例:計(jì)算機(jī)加法實(shí)現(xiàn)
前端代碼展示
計(jì)算機(jī) 數(shù)字1: 數(shù)字2:
后端代碼展示
@RestControllerpublic class CalcController { @RequestMapping(“/calc”) public String calc(Integer one, Integer two) { if(one == null || two == null) return “不可為空”; return String.format(“%d 加上 %d 等于 %d”,one,two,one+two); }}
結(jié)果顯示
2.4.3 返回 JSON
通過 HashMap 返回?cái)?shù)據(jù)或者返回一個(gè) 對(duì)象 ,返回的數(shù)據(jù)類型就是 JSON
代碼展示(Map)
@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(“/getUserByJson”) public HashMap getUserByJson(String userName,String passWord) { HashMap map = new HashMap(); map.put(“userName”,userName); map.put(“passWord”,passWord); return map; }}
結(jié)果顯示(Map)
代碼展示(對(duì)象)
@RestController@RequestMapping(“/index”)public class UserController { @RequestMapping(“/getUserByJson1”) public User getUserByJson1(String userName,String passWord) { User user = new User(); user.setUserName(userName); user.setPassWord(passWord); return user; }}
結(jié)果顯示(對(duì)象)
實(shí)例:實(shí)現(xiàn)登錄操作
要求:
前端代碼展示
用戶登錄
登錄
用戶姓名: 用戶密碼:
后端代碼展示
@RestControllerpublic class LoginController { @RequestMapping(“/login”) public HashMap login(@RequestBody User user) { HashMap map = new HashMap(); String message = “”; //用戶名和密碼判斷,不得為null或”” if (StringUtils.hasLength(user.getUserName())&& StringUtils.hasLength(user.getPassWord())) { if (user.getUserName().equals(“Json”)&&user.getPassWord().equals(“123”)) { message = “”; }else { message = “用戶名或者密碼有誤,登錄失敗”; } }else { message = “請(qǐng)將信息填寫完整”; } map.put(“succ”,200); map.put(“message”,message); return map; }}
結(jié)果展示
2.4.4 請(qǐng)求轉(zhuǎn)發(fā)/請(qǐng)求重定向
forward(請(qǐng)求轉(zhuǎn)發(fā))
- 服務(wù)器進(jìn)行轉(zhuǎn)發(fā);
- 請(qǐng)求轉(zhuǎn)發(fā)地址不會(huì)發(fā)生變化;
- 請(qǐng)求轉(zhuǎn)發(fā)由于是服務(wù)器轉(zhuǎn)發(fā)的原來的外部資源可能訪問不到
redirect(請(qǐng)求重定向)
- 請(qǐng)求重新定位到資源;
- 請(qǐng)求的地址發(fā)生變化;
- 請(qǐng)求重定向和直接訪問新地址效果是一樣的,原來的外部資源可以順利訪問到
代碼展示
前端代碼展示
Document
Hello Spring MVC~
CSS代碼展示
h1 { color: red;}
后端代碼展示
@Controllerpublic class UserController { //請(qǐng)求轉(zhuǎn)發(fā)@RequestMapping(“/forward”) public String forward() { return “forward:/index.html”; } //請(qǐng)求重定向 @RequestMapping(“/redirect”) public String redirect() { return “redirect:/index.html”; }}
結(jié)果顯示
可以看出轉(zhuǎn)發(fā)的 URL 是不變的,重定向的 URL 是會(huì)變的
如果在類上也添加路由映射會(huì)發(fā)現(xiàn)請(qǐng)求轉(zhuǎn)發(fā)獲取不到資源了
后端代碼展示
@Controller@RequestMapping(“/index”)public class UserController { //請(qǐng)求轉(zhuǎn)發(fā)@RequestMapping(“/forward”) public String forward() { return “forward:/index.html”; } //請(qǐng)求重定向 @RequestMapping(“/redirect”) public String redirect() { return “redirect:/index.html”; }}
結(jié)果展示
此時(shí)轉(zhuǎn)發(fā)的頁面路徑多了 index, 和資源沒有在同一級(jí)目錄下,導(dǎo)致資源獲取的失敗
原文 https://blog.csdn.net/weixin_46103589/article/details/125430579