SpringBoot快速上手
學(xué)習(xí)流程介紹:
- spring boot
- springmvc
- spring framework
- mybatis
- spring 源碼
Maven
項目管理工具,idea中將他嵌入進來了
- 項目構(gòu)建、打包
- 依賴管理
會出現(xiàn)的一個官方bug
就是當你創(chuàng)建maven項目的時候會卡死
那么怎么辦呢?
你只能先關(guān)閉原來項目,再重新去創(chuàng)建maven項目。
創(chuàng)建完項目之后
創(chuàng)建完maven項目之后,idea右邊會出現(xiàn)一個maven的框
那么右鍵選擇
就可以解決這個問題.
常用的的三個功能
clean
:清理class
文件(也就是清理緩存)
package
:打包
install
:在工作中常用于發(fā)布包到本地
依賴管理
通過poe.xml
依賴已經(jīng)進來了.
-
會將當前的依賴引入到當前項目里面
-
Maven Helper
插件,可以查看依賴之間的關(guān)系
Maven倉庫
倉庫:
- 本地倉庫
- 遠程倉庫
- 中央倉庫
- 私有倉庫
中央倉庫
中央倉庫
中央倉庫查詢會有一定的滯后性
本地倉庫
需要自己配置噢
國內(nèi)源配置
找到setting.xml
文件,在 mirrors 節(jié)點上,添加內(nèi)容如下:
<mirror>
<id>aliyunmaven</id>
<mirrorOf>central</mirrorOf>
<name>阿?云公共倉庫</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
然后再設(shè)置好新項目的setting
.建議找一個存儲空間大的盤,像我一樣設(shè)置(如上圖).因為隨著時間推移,外賣做的項目的數(shù)量變多,本地倉庫中的setting
文件的占用的內(nèi)存也會越來越多.
還有就是建議命名不要用中文!
私服
企業(yè)開發(fā)中一些代碼具有一定的私密性,所以企業(yè)會建立自己的私服(需要賬號密碼)
springboot項目創(chuàng)建
建議是申請教育版本的ideaa或者專業(yè)版的idea噢~
如果是社區(qū)版的idea,那么就需要你去下載spring
插件
別直接點擊Install
,除非你錢多~
插件地址
什么是spring
spring是一個非常好用的框架,快 簡單 安全
spring是一個家族產(chǎn)品,在面試中提到spring,大多是指spring家族.
而spring boot的誕生就是未來簡化spring程序開發(fā)的
spring boot項目的創(chuàng)建
-
需要注意的是現(xiàn)在idea2023創(chuàng)建spring項目的時候,只有
jdk17 jdk21
,可以選擇,這里我的解決辦法是替換項目的源頭,我們只知道IDEA頁面創(chuàng)建Spring項目,其實是訪問spring initializr去創(chuàng)建項目。故我們可以通過阿里云國服去間接創(chuàng)建Spring項目。將https://start.spring.io/或者http://start.springboot.io/替換為 https://start.aliyun.com/.即可解決這個問題. -
-
選擇springboot版本,選擇
2.X
版本,因為2.X
使用的是JDK8
,也不要選擇snapshot
版本.(不穩(wěn)定版本)snapshot 程序有問題的話,可以修改,重新發(fā)包
非 snapshot 是不能修改的,若需要修改,只能改版本號
-
-
-
此處的測試代碼,和測試人員無關(guān),是開發(fā)人員的測試代碼,
開發(fā)人員先進行簡單測試,測試完成之后再提交給測試人員.單元測試代碼
-
項目啟動
Hello World
創(chuàng)建HelloController
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello, SpringBoot";
}
}
然后再網(wǎng)頁中輸入localhost:8080/hello
web服務(wù)器
常?的Web服務(wù)器有: Apache,Nginx, IIS, Tomcat, Jboss
等
SpringBoot 內(nèi)置了Tomcat服務(wù)器, ?需配置即可直接運?
Tocmat默認端?號是8080, 所以我們程序訪問時的端?號也是8080
SpringMVC
本小節(jié)將會了解到的:
- 學(xué)習(xí)常見的
Spring MVC Web
注解 - 了解
SPring MVC
來完成基礎(chǔ)功能開發(fā) - 了解
MVC
和三層架構(gòu)的設(shè)計模式 - 掌握企業(yè)開發(fā)的命名規(guī)范
什么是SpringWebMVC
Spring Web MVC
是基于Servlet API
構(gòu)建的原始Web框架,從一開始就包含在Spring
框架中。它的正式名稱“Spring Web MVC”
來自其源模塊的名稱(Spring-webmvc)
,但它通常被稱為"SpringMVC
".
什么是MVC
Model
模型:是應(yīng)?程序的主體部分,?來處理程序中數(shù)據(jù)邏輯的部分
View
視圖:指在應(yīng)?程序中專??來與瀏覽器進?交互,展?數(shù)據(jù)的資源
Controller
控制器:可以理解為?個分發(fā)器,?來決定對于視圖發(fā)來的請求,需要?哪?個模型來處理,以及處理完后需要跳回到哪?個視圖。即?來連接視圖和模型
MVC
是一種思想,而Spring MVC
是MVC
的一種實現(xiàn)
SpringMVC
SpringMVC
項目的創(chuàng)建和上面創(chuàng)建SpringBoot
項目一樣.
不過目前推崇的前后端分離已經(jīng)不需要View
層了,于是乎:
學(xué)習(xí)Spring web mvc
- 建立連接
- 請求
- 響應(yīng)
建立連接
@RequestMapping
類注解、方法注解
作用范圍:
-
類
當一個類有多個注解的時候,這些注解沒有先后順序
類路徑+方法路徑
@RequestMapping("/user")// /可加可不加 但是我建議你加 @RestController public class UserController { @RequestMapping("/hello") public String hello() { return "hello"; } }
此時訪問路徑:
[127.0.0.1:8080/user/hello](http://127.0.0.1:8080/user/hello)
-
方法上
@RestController public class UserController { @RequestMapping("/hello") public String hello() { return "hello"; } }
請求方式是Get
還是Post
-
get
通過瀏覽器訪問的方式為get
post
請求
指定請求方式
@RequestMapping("/user")
@RestController
public class UserController {
@RequestMapping(value = "/hello",method = RequestMethod.GET)
// 注解里,雙引號的值會賦給"value"這個屬性
// 只有一個屬性的時候,且屬性名為value,可以省略
public String hello()
{
return "hello";
}
}
請求單個參數(shù)
@RequestMapping("/r1")
public String r1(String name){
return "接受到參數(shù) name:" + name;
}
@RequestMapping("/r2")
public String r2(int age){
return "接受到參數(shù) age:" + age;
}
請求多個參數(shù)
@RequestMapping("/r3")
public String r3(String name,Integer age){
return "name:"+name+" "+"age:"+age;
// 參數(shù)請求 順序先后不分
}
傳遞對象
// 創(chuàng)建userInfo
public class UserInfo {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "UserInfo{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
@RequestMapping("/r4")
public String r4(UserInfo user){
return user.toString();
}
參數(shù)重命名
@RequestParam
@RequestMapping("/r5")
public String r4(@RequestParam("name") String username, Integer age){
return "username: " + username+ ", age: " + age;
}
@RequestParam(“name”) 從請求中獲取 name 的參數(shù),并且賦值給 username 參數(shù) 且默認這個參數(shù)是必傳的
設(shè)置參數(shù)為非必傳的
我們先看一下RequestParam
public @interface RequestParam {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
boolean required() default true;
String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}
于是乎我們可以:將required
設(shè)置為false
@RequestMapping("/r5")
public String r5(@RequestParam(value = "name", required = false) String username, Integer age){
return "username: " + username+ ", age: " + age;
}
傳遞數(shù)組
@RequestMapping("/r7")
public String r7(String[]arr){
return Arrays.toString(arr);
}
傳遞集合
@RequestMapping("/r8")
public String r8(@RequestParam("list") List<String> list){
return list.toString();
}
在Spring MVC中,
@RequestParam
注解用于從請求中提取參數(shù)值。@RequestParam("list") List<String> list
表示從請求中獲取名為 “l(fā)ist” 的參數(shù),并將其綁定到一個List<String>
類型的變量list
上。這種方式常用于接收前端傳遞的多個相同類型的參數(shù),例如,前端通過 URL 或者表單提交將多個字符串參數(shù)傳遞給后端。通過將它們綁定到一個
List<String>
類型的參數(shù)上,你可以輕松地處理多個相同類型的參數(shù)。請求 URL 如下:
/r8?list=value1&list=value2&list=value3
通過上述的
@RequestParam("list") List<String> list
,Spring 將自動將這些值綁定到一個列表中,你可以在方法體內(nèi)使用這個list
參數(shù)來訪問傳遞的多個值。總的來說,這是一種方便的方式,用于處理請求中包含多個相同類型參數(shù)的場景。
在Web開發(fā)中,有時候我們需要從前端接收一組相同類型的參數(shù)。使用
List<String>
類型的參數(shù)綁定可以方便地處理這種情況,而不需要為每個參數(shù)定義一個獨立的變量。考慮以下情景:
表單提交: 當用戶通過表單提交多個相同類型的數(shù)據(jù)時,可以將這些數(shù)據(jù)綁定到一個
List<String>
中。例如,一個多選框(Checkbox)的多個選項。URL參數(shù): 當通過URL傳遞多個相同類型的參數(shù)時,使用
List<String>
可以更清晰地表達意圖。例如,/r8?list=value1&list=value2&list=value3
。RESTful風格的請求: 在RESTful風格的API中,有時需要從請求體或路徑中接收多個相同類型的數(shù)據(jù)。
綁定到
List<String>
的好處包括:
代碼簡潔: 不需要為每個參數(shù)定義一個變量,通過一個
List
就可以容納所有的值。可擴展性: 如果前端需要傳遞更多的相同類型的參數(shù),代碼不需要做太多修改。
清晰明了: 通過命名為
list
,表達了這是一組相同類型的數(shù)據(jù)。
傳遞JSON
數(shù)據(jù)
JSON與Javascript的關(guān)系
沒有關(guān)系, 只是語法相似, js開發(fā)者能更快的上??已, 但是他的語法本??較簡單, 所以也很好學(xué)
JSON 優(yōu)點
-
簡單易?: 語法簡單,易于理解和編寫,可以快速地進?數(shù)據(jù)交換
-
跨平臺?持: JSON可以被多種編程語?解析和?成, 可以在不同的平臺和語?之間進?數(shù)據(jù)交換和傳輸
-
輕量級: 相較于XML格式, JSON數(shù)據(jù)格式更加輕量級, 傳輸數(shù)據(jù)時占?帶寬較?, 可以提?數(shù)據(jù)傳輸速度
-
易于擴展: JSON的數(shù)據(jù)結(jié)構(gòu)靈活,?持嵌套對象和數(shù)組等復(fù)雜的數(shù)據(jù)結(jié)構(gòu),便于擴展和使?
-
安全性: JSON數(shù)據(jù)格式是?種純?本格式,不包含可執(zhí)?代碼, 不會執(zhí)?惡意代碼,因此具有較?的安全性
public class JSONUtils {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
UserInfo userInfo = new UserInfo();
userInfo.setName("zhangsan");
userInfo.setAge(18);
userInfo.setId(12);
// 對象轉(zhuǎn) JSON
String s = objectMapper.writeValueAsString(userInfo);
System.out.println(s);
// JSON 轉(zhuǎn)成 java 對象
UserInfo userInfo1 = objectMapper.readValue(s,UserInfo.class);
System.out.println(userInfo1);
}
}
@RequestMapping("/r9")
public String r9(@RequestBody UserInfo userInfo){
return userInfo.toString();
}
獲取URL中的參數(shù)
@PathVariable
@RequestMapping("/r10/{articleId}")
public String r10(@PathVariable Integer articleId){
return "articleId:"+articleId;
}
上傳文件
@RequestPart
@RequestMapping("/r11")
public String r11(@RequestPart MultipartFile file){
return "獲取上傳文件:" + file.getOriginalFilename();
}
@RequestMapping("/r11")
public String r11(@RequestPart MultipartFile file) throws IOException {
String fileName = file.getOriginalFilename();
file.transferTo(new File("D:/temp/"+fileName));
return "獲取上傳文件:" + file.getOriginalFilename();
}
這段代碼雖然也可以不加注解,但是建議還是將注解加上去
獲取Cookie/Session
Cookie
HTTP 協(xié)議??是屬于 “?狀態(tài)” 協(xié)議.
無狀態(tài)協(xié)議:
默認情況下 HTTP 協(xié)議的客?端和服務(wù)器之間的這次通信, 和下次通信之間沒有直接的聯(lián)系.
但是實際開發(fā)中, 我們很多時候是需要知道請求之間的關(guān)聯(lián)關(guān)系的.
例如登陸?站成功后, 第?次訪問的時候服務(wù)器就能知道該請求是否是已經(jīng)登陸過了.
Session
會話:對話的意思
在計算機領(lǐng)域, 會話是?個客?與服務(wù)器之間的不中斷的請求響應(yīng). 對客?的每個請求,服務(wù)器能夠識
別出請求來?于同?個客?. 當?個未知的客?向Web應(yīng)?程序發(fā)送第?個請求時就開始了?個會話.
當客?明確結(jié)束會話或服務(wù)器在?個時限內(nèi)沒有接受到客?的任何請求時,會話就結(jié)束了.
?如我們打客服電話
每次打客服電話, 是?個會話. 掛斷電話, 會話就結(jié)束了
下次再打客服電話, ?是?個新的會話.
如果我們?時間不說話, 沒有新的請求, 會話也會結(jié)束
服務(wù)器同?時刻收到的請求是很多的. 服務(wù)器需要清楚的區(qū)分每個請求是從屬于哪個??, 也就是屬于哪個會話, 就需要在服務(wù)器這邊記錄每個會話以及與??的信息的對應(yīng)關(guān)系.
Session
是服務(wù)器為了保存??信息?創(chuàng)建的?個特殊的對象.
Session的本質(zhì)就是?個 “哈希表”, 存儲了?些鍵值對結(jié)構(gòu). Key 就是SessionID, Value 就是??信息(??信息可以根據(jù)需求靈活設(shè)計).
SessionIsd
是由服務(wù)器生成的一個"唯一性字符串",從Session
機制的角度來看,這個唯一性字符串稱為"Sessionld"
.但是站在整個登錄流程中看待,也可以把這個唯一性字符串稱為"token".
上述例子中的令牌ID,就可以看做是Sessionld
,只不過令牌除了ID之外,還會帶一些其他信息,比如時間,簽名等.
-
當??登陸的時候, 服務(wù)器在 Session 中新增?個新記錄, 并把 sessionId返回給客?端. (通過HTTP 響應(yīng)中的 Set-Cookie 字段返回).
-
客?端后續(xù)再給服務(wù)器發(fā)送請求的時候, 需要在請求中帶上 sessionId. (通過 HTTP 請求中的Cookie 字段帶上).
-
服務(wù)器收到請求之后, 根據(jù)請求中的 sessionId在 Session 信息中獲取到對應(yīng)的??信息, 再進?后續(xù)操作.找不到則重新創(chuàng)建Session, 并把SessionID返回
Session默認是保存在內(nèi)存中的.如果重啟服務(wù)器則Session數(shù)據(jù)就會丟失.
Cookie和Session的區(qū)別
在此之前我們可以舉一個例子
學(xué)生入學(xué)
學(xué)校收集學(xué)生信息,姓名,班級,身份證號等等
那么學(xué)校該如何存儲呢?
Number Name Age Attribute 1 張三 18 CS 2 李四 17 CS 3 王五 20 CS 學(xué)校存儲信息之后,給學(xué)生發(fā)學(xué)生證
學(xué)生出入學(xué)校,使用學(xué)生證(就好比是
Cookie
)來證明身份但是,學(xué)生證可以造假,但是學(xué)校的教務(wù)系統(tǒng)的信息是造假不了的
于是乎:
Cookie
是可以造假的,但是Session
不行
-
用戶提供賬號和密碼,服務(wù)器進行驗證。
-
服務(wù)器驗證通過,會把信息存儲在
Session
中,把SessionId
返回給客戶端(通過Set-Cookie
的方式) -
客戶端收到響應(yīng),把
sessionID
存儲在Cookie
中 -
后續(xù)的請求中,客戶端帶著
SessionID
去請求(帶著Cookie
信息去請求)request.getSession
就是從Cookie
中獲取SessionID
,并且根據(jù)SessionID
獲取Session
信息
區(qū)別如下:
-
Cookie
是客戶端保存用戶信息的一種機制.Session
是服務(wù)器端保存用戶信息的一種機制: -
Cookie
和Session
之間主要是通過Sessionld
關(guān)聯(lián)起來的,Sessionld
是Cookie
和Session
之間的橋梁 -
Cookie
和Session
經(jīng)常會在一起配合使用.但是不是必須配合.- 完全可以用
Cookie
來保存一些數(shù)據(jù)在客戶端.這些數(shù)據(jù)不一定是用戶身份信息,也不一定是Sessionld
-
Session
中的sessionld
也不需要非得通過Cookie
/Set
-Cookie
傳遞,比如通過URL
傳遞
- 完全可以用
共同點:都是會話機制
Cookie
是客戶端機制
Session
是服務(wù)器機制
Cookie
存儲的信息由程序員而定
Session
也不一定必須存在Cookie
中
傳統(tǒng)方式獲取Cookie
@RestController
@RequestMapping("/request")
public class RequestController {
@RequestMapping("/getCookie")
public String getCookie(HttpServletRequest request) // 內(nèi)置對象,有需要就加上,沒需要就不加 需要幾個就加幾個
{
Cookie[] cookies = request.getCookies();
// Arrays.stream(cookies).forEach(x->{
// System.out.println(x.getName()+":"+x.getValue());
// });
// 等價于
if (cookies != null){
for(Cookie c:cookies){
System.out.println(c.getName()+":"+c.getValue());
}
return "獲取Cookies成功";
}
else
return "獲取Cookies不成功";
}
}
SpringBoot獲取Cookie
@RequestMapping("/getCookie2")
public String getCookie2(@CookieValue ("riyewuxiushi")String riyewuxiushi){
return "riyewuxiushi"+riyewuxiushi;
}
傳統(tǒng)方式獲取Session
@RequestMapping("/setSession")
public String setSession(HttpServletRequest request){
HttpSession session = request.getSession(); // 默認值為 true
session.setAttribute("userName","zhangsan");
return "設(shè)置session成功";
}
@RequestMapping("/getSession")
public String getSession(HttpServletRequest request){
HttpSession session = request.getSession();
String userName = (String) session.getAttribute("userName");
return "登錄用戶:"+ userName;
}
SpringBoot獲取Session
@RequestMapping("/getSession2")
public String getSession2(HttpSession session){ // 內(nèi)置對象
String userName = (String) session.getAttribute("userName");
return "登錄用戶:"+ userName;
}
@RequestMapping("/getSession3")
public String getSession3(@SessionAttribute(value = "userName",required = false) String userName){
return "登錄用戶:"+ userName;
}
獲取Header
傳統(tǒng)獲取Header
@RequestMapping("/getheader")
public String getheader(HttpServletRequest request){
String userAgent = request.getHeader("User-Agent");
return "userAgent"+userAgent;
}
springboot方式獲取Header
@RequestMapping("/getheader2")
public String getheader2(@RequestHeader("User-Agent")String userAgent){
return "userAgent"+userAgent;
}
響應(yīng)
返回靜態(tài)頁面
@RequestMapping("/return")
//@RestController
@Controller
// 多個注解的時候 注解不分先后順序
public class ReturnController {
@RequestMapping("/r1")
public String r1(){
return "/index.html";
}
}
@RestContraller
和 @Controller
的區(qū)別
@RestController
和 @Controller
是 Spring Framework 中用于標記類的注解,用于定義處理 HTTP 請求的控制器。它們之間有一些區(qū)別和聯(lián)系。
區(qū)別:
- 返回值處理:
@Controller
通常用于創(chuàng)建傳統(tǒng)的基于視圖的 Web 應(yīng)用程序,它的方法可以返回模型數(shù)據(jù)和視圖名稱,最終由視圖解析器解析為具體的視圖。而@RestController
則是用于創(chuàng)建 RESTful Web 服務(wù)的控制器,它的方法返回的是數(shù)據(jù)對象,會自動通過消息轉(zhuǎn)換器將數(shù)據(jù)轉(zhuǎn)為 JSON/XML 等格式,不會經(jīng)過視圖解析器。 - 默認行為:
@RestController
組合了@Controller
和@ResponseBody
注解的功能。@ResponseBody
注解表示方法的返回值將直接寫入 HTTP 響應(yīng)體中,而不是通過視圖解析器解析為視圖。因此,@RestController
類的每個方法都默認返回數(shù)據(jù)對象,而不是視圖。 - 使用場景:
@Controller
適用于傳統(tǒng)的基于視圖的 Web 應(yīng)用程序,例如使用 Thymeleaf、JSP 或者其他模板引擎渲染視圖。@RestController
適用于構(gòu)建 RESTful Web 服務(wù),響應(yīng) JSON 或 XML 格式的數(shù)據(jù)。
聯(lián)系:
- 標記作用:
@RestController
和@Controller
都是用于標記類的注解,將類聲明為 Spring Framework 的組件,用于處理 HTTP 請求。 - 注解繼承:
@RestController
是@Controller
注解的特殊化,可以認為是@Controller
的增強版本。@RestController
繼承了@Controller
的所有功能,同時還提供了自動將方法返回值轉(zhuǎn)換為數(shù)據(jù)格式的能力。
// @RestController 源碼
@Target({ElementType.TYPE}) // 表示注解的范圍
@Retention(RetentionPolicy.RUNTIME) // 注解的生命周期
@Documented //
// 上面三個是元注解:是可以注解到 其他注解 的注解
@Controller // ----> 這說明 RestContraller 是基于 Controller 實現(xiàn)的
@ResponseBody
public @interface RestController {
@AliasFor(
annotation = Controller.class
)
String value() default "";
}
@RestController = @Controller + @ResponseBody
@Controller
: 告訴Spring幫我們管理那些程序
@ResponseBody
:返回數(shù)據(jù)
路徑問題
-
servlet
路徑有項目名,是因為一個tomcat
下面可以部署多個項目,我們需要通過路徑來進行區(qū)分 -
spring
路徑不需要有項目名,是因為springboot
內(nèi)置了tomcat
,一個tomcat
下面就部署當前這一個項目 - 如果部署多個項目,就啟動多個
tomcat
一個項目部署多個服務(wù)
IDEA 2023.2新版如何將同一個項目開啟多個
返回數(shù)據(jù)@ResponseBody
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
}
即可以修飾類,又可以修飾方法
修飾類:表示該類所有的方法 返回的是數(shù)據(jù)
修飾方法:表示該方法返回的是數(shù)據(jù)
@RequestMapping("/r1")
public String r1(){
return "/index.html";
}
@ResponseBody
@RequestMapping("/r2")
public String r2(){
return "hello spring";
}
返回HTML片段
@ResponseBody
@RequestMapping("/r3")
public String r3(){
return "<h1>我是返回的片段</h1>";
}
-
get
可以被緩存 冪等 -
post
不可以被緩存
返回JSON
@ResponseBody
@RequestMapping("/r4")
public UserInfo r4(){
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setName("zhangsan");
userInfo.setAge(19);
return userInfo;
}
@ResponseBody
@RequestMapping("/r5")
public Map<String ,String> r5(){
HashMap map = new HashMap();
map.put("k1","v1");
map.put("k2","v2");
return map;
}
//@ResponseBody
@RequestMapping("/r6")
public String r6(){
return "/a.js";
}
@RequestMapping("/r7")
public String r7(){
return "/b.css";
}
設(shè)置狀態(tài)碼
@ResponseBody
@RequestMapping("/r8")
public String r8(HttpServletResponse response){
response.setStatus(401);
return "設(shè)置狀態(tài)碼成功";
}
狀態(tài)碼的設(shè)置不影響頁面的顯示
設(shè)置Header
設(shè)置Content-Type
我們通過設(shè)置 produces屬性的值, 設(shè)置響應(yīng)的報頭Content-Type
// @RequestMapping源碼
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
value
: 指定映射的URL
method
: 指定請求的method
類型, 如GET
,POST
等
consumes
: 指定處理請求(request
)的提交內(nèi)容類型(Content-Type
),例如application
/json
,text
/html
;
produces
: 指定返回的內(nèi)容類型,僅當request
請求頭中的(Accept
)類型中包含該指定類型才返回
Params
: 指定request
中必須包含某些參數(shù)值時,才讓該?法處理
headers
: 指定request
中必須包含某些指定的header
值,才能讓該?法處理請求
@ResponseBody
@RequestMapping("/r9")
public String r9(){
return "123333";
}
@ResponseBody
@RequestMapping(value = "/r9",produces = "application/json")
public String r9(){
return "123333";
}
設(shè)置其他Header
設(shè)置其他Header的話, 需要使?Spring MVC的內(nèi)置對象HttpServletResponse 提供的?法來進?設(shè)置
@ResponseBody
@RequestMapping(value = "/r10",produces = "application/json")
public String r10(HttpServletResponse response){
response.setHeader("myHeader","myHeaderValue");
return "設(shè)置Header成功";
}
void setHeader(String name, String value) 設(shè)置?個帶有給定的名稱和值的 header. 如果 name已經(jīng)存在, 則覆蓋舊的值
案例
學(xué)習(xí)建議:
最開始學(xué)習(xí)的時候:小步慢跑
每次寫少量的代碼,就進行測試
不要一次把代碼全部寫完,一次性進行測試
隨著對代碼的熟悉,可以逐漸加大步伐
加法計算器
前端代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="calc/sum" method="post">
<h1>計算器</h1>
數(shù)字1:<input name="num1" type="text"><br>
數(shù)字2:<input name="num2" type="text"><br>
<input type="submit" value=" 點擊相加 ">
</form>
</body>
</html>
后端接到需求的時候
- 需求評審
- 開發(fā)
- 接口的定義
- 開發(fā)
- 測試(自行測試,與測試人員無關(guān))
- 聯(lián)調(diào)(后端和前端聯(lián)調(diào))
- 提測(測試人員的工作)
- 上線
- 維護
- 下線
后端代碼
接口定義
兩個原則
- 看我需要什么(請求參數(shù))
- 看對方需要什么(響應(yīng)結(jié)果)
請求參數(shù):參與計算的兩個數(shù)字
響應(yīng)結(jié)果:計算結(jié)果
/calc/sum
參數(shù):
num1 , num2
返回結(jié)果:兩者計算的數(shù)據(jù)
請求路徑:calc/sum
請求?式:GET/POST
接?描述:計算兩個整數(shù)相加
請求參數(shù):
參數(shù)名 類型 是否必須 備注 num1 Integer 是 參與計算的第一個數(shù) num2 Integer 是 參與計算的第二個數(shù)
響應(yīng)數(shù)據(jù):
Content-Type : text/html
@RestController
@RequestMapping("/calc")
public class CalcController {
@RequestMapping("/sum")
public String sum(Integer num1, Integer num2){
Integer sum = num1 + num2;
return "<h1>計算機計算結(jié)果: "+sum+"</h1>";
}
}
問題可能出現(xiàn)的地方:
- 前端
- 后端
- 前后端交互
- 請求有沒有發(fā)出去
- 后端有沒有收到請求
用戶登錄
前端代碼
// login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
<h1>用戶登錄</h1>
用戶名:<input name="userName" type="text" id="userName"><br>
密碼:<input name="password" type="password" id="password"><br>
<input type="button" value="登錄" onclick="login()">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
function login() {
$.ajax({
type:"post",
url:"/login/check",
data:{
userName:$("#userName").val(),
password:$("#password").val()
},
success:function(result){
if (result == true){
// 用戶名和密碼正確
location.href = "/index.html";
// location.assign("index.html");
// location.replace("index.html");
}else{
alert("用戶名或密碼錯誤");
}
}
});
}
</script>
</body>
</html>
// index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>用戶登錄首頁</title>
</head>
<body>
登錄人: <span id="loginUser"></span>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
$.ajax({
url:"/login/index",
type:"get",
success:function (result) {
$("#loginUser").text(result);
}
});
</script>
</body>
</html>
后端代碼
用戶驗證:
/login/check
參數(shù):
userName
password
響應(yīng):
用戶和密碼是否正確
true
false
獲取登錄的用戶:
/login/index
參數(shù):
無
響應(yīng):
登錄的用戶
@RequestMapping("/login")
@RestController
public class LoginController {
@RequestMapping("/check")
public boolean check(String userName, String password, HttpSession session){
// 校驗賬號和密碼是否為空
// if (userName == null || "".equals(userName) || password == null || "".equals(password)){
// return false;
// }
if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
return false;
}
// 校驗賬號和密碼是否正確
// 模擬數(shù)據(jù)
if("zhangsan".equals(userName) && "123456".equals(password)){ // 防止空指針,養(yǎng)成習(xí)慣 常量寫在前面
session.setAttribute("userName",userName);
return true;
}
return false;
}
@RequestMapping("/index")
public String index(HttpSession session){
String userName = (String) session.getAttribute("userName");
return userName;
}
}
留言板
前端代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>留言板</title>
<style>
.container {
width: 350px;
height: 300px;
margin: 0 auto;
/* border: 1px black solid; */
text-align: center;
}
.grey {
color: grey;
}
.container .row {
width: 350px;
height: 40px;
display: flex;
justify-content: space-between;
align-items: center;
}
.container .row input {
width: 260px;
height: 30px;
}
#submit {
width: 350px;
height: 40px;
background-color: orange;
color: white;
border: none;
margin: 10px;
border-radius: 5px;
font-size: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>留言板</h1>
<p class="grey">輸入后點擊提交, 會將信息顯示下方空白處</p>
<div class="row">
<span>誰:</span> <input type="text" name="" id="from">
</div>
<div class="row">
<span>對誰:</span> <input type="text" name="" id="to">
</div>
<div class="row">
<span>說什么:</span> <input type="text" name="" id="say">
</div>
<input type="button" value="提交" id="submit" onclick="submit()">
<!-- <div>A 對 B 說: hello</div> -->
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
<script>
// 頁面加載時,顯示留言信息
// 從后端獲取留言信息,顯示在頁面上
$.ajax({
type:"get",
url:"/message/getList",
success:function (messages) {
for (var message of messages){
var html = "<div>"+message.from+"對"+message.to+"說:"+message.message+"</div>";
$(".container").append(html);
}
}
});
function submit(){
//1. 獲取留言的內(nèi)容
var from = $('#from').val();
var to = $('#to').val();
var say = $('#say').val();
if (from== '' || to == '' || say == '') {
return;
}
$.ajax({
type:"post",
url:"/message/publish",
data:{
from:from,
to:to,
message:say
},
success:function (result) {
if (result == true){
// 添加成功
//2. 構(gòu)造節(jié)點
var divE = "<div>"+from +"對" + to + "說:" + say+"</div>";
//3. 把節(jié)點添加到頁面上
$(".container").append(divE);
//4. 清空輸入框的值
$('#from').val("");
$('#to').val("");
$('#say').val("");
}else{
alert("發(fā)表失敗");
}
}
});
}
</script>
</body>
</html>
后端代碼
提交留言:用戶輸入留言信息的時候,后端需要將留言信息保存起來
URL:/message/publish
參數(shù)
from
:發(fā)表人to
:接收人message
:信息返回:提交成功/失敗
true、false
展示留言:頁面展示的時候,需要從后端獲取到所有的留言信息
URL:/message/getList
參數(shù)
無
返回:全部的留言信息
List<MessageInfo>
lombok工具包介紹
-
新項目
創(chuàng)建項目的時候直接加入依賴
-
老項目
在poe.xml中引入依賴,去maven中央倉庫找
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency>
@Data public class MessageInfo { private String from; private String to; private String message; }
@Data
會自動生成get、set
方法idea會自己進行反編譯
單獨使用可以@Getter @Setter
注解 作用 @Getter 自動添加getter方法 @Setter 自動添加setter方法 @ToString 自動添加toString方法 @EqualsAndHashCode ?動添加 equals 和 hashCode ?法 @NoArgsConstructor 自動添加無參構(gòu)造方法 @AllArgsConstructor 自動添加全屬性構(gòu)造方法,順序按照屬性的定義順序 @NonNull 屬性不能為null @RequiredArgsConstructor 自動添加必需屬性的構(gòu)造方法,final+@NonNull的屬性為必需 @Data = @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor
+ @NoArgsConstructor
-
更快地引入依賴
下載這個就好啦~然后重啟IDEA
使用方法:
package org.example.springmvc_demo;
import lombok.Data;
/**
* @author 日夜無休時
* @date 2024/1/29
*/
@Data
public class MessageInfo {
private String from;
private String to;
private String message;
// 換一個新工具 lombook @Data
// public String getFrom() {
// return from;
// }
//
// public void setFrom(String from) {
// this.from = from;
// }
//
// public String getTo() {
// return to;
// }
//
// public void setTo(String to) {
// this.to = to;
// }
//
// public String getMessage() {
// return message;
// }
//
// public void setMessage(String message) {
// this.message = message;
// }
}
package org.example.springmvc_demo;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* @author 日夜無休時
* @date 2024/1/29
*/
@RestController
@RequestMapping("/message")
public class MessageController {
private List<MessageInfo>messageInfos = new ArrayList<>();
@RequestMapping("/publish")
public boolean publishMessage(MessageInfo messageInfo){
if (!StringUtils.hasLength(messageInfo.getFrom())
|| !StringUtils.hasLength(messageInfo.getTo())
|| !StringUtils.hasLength((messageInfo.getMessage()))){
return false;
}
// 暫時存放在內(nèi)存中
messageInfos.add(messageInfo);
return true;
}
@RequestMapping("/getList")
public List<MessageInfo> getList(){
for (MessageInfo messageInfo : messageInfos){
}
return messageInfos;
}
}
圖書管理系統(tǒng)
定義接口
接口定義:
服務(wù)提供方:
提供什么服務(wù)
提供服務(wù)時,需要什么參數(shù)
處理之后,需要給對方什么響應(yīng)
客戶端角度:
- 我需要什么服務(wù)
- 服務(wù)端的參數(shù) 我是否有
- 對方給我提供的信息,能否滿足我的需求
-
登錄
URL: /user/login
參數(shù):用戶名和密碼
userName
password
返回:
true:用戶名和密碼正確
false:用戶名和密碼錯誤
-
圖書列表
URL:/book/getList
參數(shù):無
返回:圖書列表
List
MOCK
虛擬的、假的。開發(fā)的時候通常是幾個團隊并行開發(fā),開發(fā)后需要進行測試(自測),如果測試時,依賴方還沒完成開發(fā),調(diào)用方就采用mock的方式,先進行測試。
應(yīng)用分層
一種開發(fā)規(guī)范
三層架構(gòu)(軟件設(shè)計架構(gòu)方式)
- 表現(xiàn)層:就是展示數(shù)據(jù)結(jié)果和接受用戶指令的,是最靠近用戶的一層
- 業(yè)務(wù)邏輯層:負責處理業(yè)務(wù)邏輯,里面有復(fù)雜業(yè)務(wù)的具體實現(xiàn)
- 數(shù)據(jù)層:負責存儲和管理與應(yīng)用程序相關(guān)的數(shù)據(jù)
命名規(guī)范
- 類名 大駝峰
- 變量名 小駝峰
MVC和三層架構(gòu)之間的關(guān)系
共同點:
-
解耦(高內(nèi)聚,低耦合)
模塊內(nèi) 關(guān)系盡量緊密(高內(nèi)聚)
模塊間 關(guān)系盡量關(guān)聯(lián)低(低耦合)
比如說:公司與公司之間,關(guān)聯(lián)應(yīng)該越小越好,公司內(nèi)部,員工應(yīng)該團結(jié)
SpringMVC小結(jié)
什么是springmvc
spring web mvc
@RequestMapping
既是類注解,也是方法注解
訪問的URL路徑 = 類路徑 + 方法路徑
默認支持 get/post
,可以使用method
屬性來限制請求方式文章來源:http://www.zghlxwxcb.cn/news/detail-830395.html
請求
- 請求當個參數(shù)
- 請求多個參數(shù)
- 請求參數(shù)為對象
- 對參數(shù)重命名
@RequestParam 默認是必傳參數(shù),設(shè)置 required = false 就是非必傳
- 設(shè)置參數(shù)為非必傳
- 請求參數(shù)為
JSON
@RequestBody
Cookie & Session
- 傳遞數(shù)組
- 傳遞集合
@RequestParam
- 獲取Header
響應(yīng)
- 返回靜態(tài)頁面
- 返回數(shù)據(jù)
@ResponseBody
- 返回
HTML
片段 - 返回
JSON
- 設(shè)置響應(yīng)頭(狀態(tài)碼、編碼、其他
header
)
注解總結(jié)
- @RequestMapping: 路由映射
- @RequestParam: 后端參數(shù)重命名
- @RequestBody: 接收JSON類型的參數(shù)
- @PathVariable: 接收路徑參數(shù)
- @RequestPart: 上傳?件
- @ResponseBody: 返回數(shù)據(jù)
- @CookieValue: 從Cookie中獲取值
- @SessionAttribute: 從Session中獲取值
- @RequestHeader: 從Header中獲取值
- @Controller: 定義?個控制器, Spring 框架啟動時加載, 把這個對象交給Spring管理. 默認返回視圖.
- @RestController: @ResponseBody + @Controller 返回數(shù)據(jù)
Cookie和Session
Cookie 和Session都是會話機制, Cookie是客?端機制, Session是服務(wù)端機制. ?者通過SessionId來關(guān)聯(lián). Spring MVC內(nèi)置HttpServletRequest, HttpServletResponse兩個對象. 需要使?時, 直接在?法中添加對應(yīng)參數(shù)即可, Cookie和Session可以從HttpServletRequest中來獲取, 也可以直接使?HttpServletResponse設(shè)置Http響應(yīng)狀態(tài)碼.文章來源地址http://www.zghlxwxcb.cn/news/detail-830395.html
到了這里,關(guān)于【JavaEE】spring boot快速上手的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!