SpringBoot(二)--- SpringBoot基礎(http協議、分層解耦)

目錄

前言

一、SpringBoot入門

1.入門程序

2.解析

二、HTTP協議

1.HTTP概述

2.HTTP請求協議

2.1 GET方式的請求協議

2.2 POST方式的請求協議

2.3 兩者的區別

2.4 獲取請求數據

3.HTTP響應協議

三、分層解耦

1.三層架構

2.IOC&DI

2.1 入門

2.2 IOC詳解

2.3 DI詳解

2.4 注意事項


前言

我們可以通過HTML、CSS、JS這三項技術進行前端頁面的開發,最終,這些前端頁面,我們就可以部署在服務器上,然后打開瀏覽器就可以直接訪問服務器上部署的前端頁面了。而像這HTML、CSS、JS 以及圖片、音頻、視頻等這些資源,我們都稱為靜態資源。 所謂靜態資源,就是指在服務器上存儲的不會改變的數據,通常不會根據用戶的請求而變化。

與靜態資源相對的就是動態資源,即在服務器端進行存儲,會根據用戶請求和其他數據動態生成,內容可能會在每次請求時都發生變化。我們可以基于Spring框架來構建動態資源

對于java程序開發的動態資源來說,我們通常會將這些動態資源部署在Tomcat(Tomcat服務器),這樣的Web服務器中運行。 而瀏覽器與服務器在通信的時候,基本都是基于HTTP協議的。


一、SpringBoot入門

1.入門程序

在com.example.demo這個包下創建HelloController類

類中的代碼如下:

package com.example.demo;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController// 表明是個請求處理類
public class HelloController {@RequestMapping("/hello") // 標識請求路徑public String hello(String name) {System.out.println("HelloController...hello:" + name);return "Hello" + name;}
}

上面的hello方法中參數是前端給服務器提交的參數,return表示服務器給前端返回的數據。

運行SpringBoot自動生成的引導類 (標識有@SpringBootApplication注解的類)

打開瀏覽器,輸入http://localhost:8080/hello?name=xiaoming

可以發現,前端頁面在網址欄向服務器傳遞了xiaoming這個參數,然后服務器將這個參數重新相應給了前端頁面。

2.解析

我們發現運行SpringBoot自動生成的引導類就可以啟動整個服務,這是為什么呢?

因為我們在創建springboot項目的時候,選擇了web開發的起步依賴 spring-boot-starter-web。而spring-boot-starter-web依賴,又依賴了spring-boot-starter-tomcat,由于maven的依賴傳遞特性,那么在我們創建的springboot項目中也就已經有了tomcat的依賴,這個其實就springboot中內嵌的tomcat。

而運行引導類中的main方法,其實啟動的就是springboot中內嵌的Tomcat服務器。 而我們所開發的項目,也會自動的部署在該tomcat服務器中,并占用8080端口號 。

二、HTTP協議

1.HTTP概述

HTTP:Hyper Text Transfer Protocol(超文本傳輸協議),規定了瀏覽器與服務器之間數據傳輸的規則。

  • http是互聯網上應用最為廣泛的一種網絡協議

  • http協議要求:瀏覽器在向服務器發送請求數據時,或是服務器在向瀏覽器發送響應數據時,都必須按照固定的格式進行數據傳遞

HTTP協議

  • 基于TCP協議: 面向連接,安全。

  • 基于請求-響應模型: 一次請求對應一次響應(先請求后響應)。

  • HTTP協議是無狀態協議: 對于數據沒有記憶能力。每次請求-響應都是獨立的

????????無狀態指的是客戶端發送HTTP請求給服務端之后,服務端根據請求響應數據,響應完后,不會記錄任何信息。

2.HTTP請求協議

瀏覽器將數據以請求格式發送到服務器。包括:請求行、請求頭 、請求體。

2.1 GET方式的請求協議

  • 請求行(以上圖中紅色部分) :HTTP請求中的第一行數據。由:請求方式資源路徑協議/版本組成(之間使用空格分隔)

    • 請求方式:GET

    • 資源路徑:/brand/findAll?name=OPPO&status=1

      • 請求路徑:/brand/findAll

      • 請求參數:name=OPPO&status=1

        • 請求參數是以key=value形式出現

        • 多個請求參數之間使用&連接

      • 請求路徑和請求參數之間使用?連接

    • 協議/版本:HTTP/1.1

  • 請求頭(以上圖中黃色部分) :第二行開始,上圖黃色部分內容就是請求頭。格式為key: value形式

    • http是個無狀態的協議,所以在請求頭設置瀏覽器的一些自身信息和想要響應的形式。這樣服務器在收到信息后,就可以知道是誰,想干什么了

服務端可以根據請求頭中的內容來獲取客戶端的相關信息,有了這些信息服務端就可以處理不同的業務需求。

2.2 POST方式的請求協議

  • 請求行(以上圖中紅色部分):包含請求方式、資源路徑、協議/版本

    • 請求方式:POST

    • 資源路徑:/brand

    • 協議/版本:HTTP/1.1

  • 請求頭(以上圖中黃色部分)

  • 請求體(以上圖中綠色部分) :存儲請求參數

    • 請求體和請求頭之間是有一個空行隔開(作用:用于標記請求頭結束)

2.3 兩者的區別

2.4 獲取請求數據

web服務器對HTTP請求進行解析,并將其數據封裝到了HttpServletRequest類里面,并在調用Controller方法的時候傳遞給了該方法。

用HttpServletRequest類型 聲明一個形參(例如request),用request的方法操作具體數據。

@RestController
public class RequestController {/*** 請求路徑 http://localhost:8080/request?name=Tom&age=18* @param request* @return*/@RequestMapping("/request")public String request(HttpServletRequest request){//1.獲取請求參數 name, ageString name = request.getParameter("name"); // 請求數據以鍵值對形式存在String age = request.getParameter("age");System.out.println("name = " + name + ", age = " + age);//2.獲取請求路徑String uri = request.getRequestURI();String url = request.getRequestURL().toString();System.out.println("uri = " + uri);System.out.println("url = " + url);//3.獲取請求方式String method = request.getMethod();System.out.println("method = " + method);//4.獲取請求頭String header = request.getHeader("User-Agent");System.out.println("header = " + header);return "request success";}}

3.HTTP響應協議

服務器將數據以響應格式返回給瀏覽器。包括:響應行 、響應頭 、響應體

  • 響應行(以上圖中紅色部分):響應數據的第一行。響應行由協議及版本響應狀態碼狀態碼描述組成

    • 協議/版本:HTTP/1.1

    • 響應狀態碼:200

    • 狀態碼描述:OK

  • 響應頭(以上圖中黃色部分):響應數據的第二行開始。格式為key:value形式

    • http是個無狀態的協議,所以可以在請求頭和響應頭中設置一些信息和想要執行的動作,這樣,對方在收到信息后,就可以知道你是誰,你想干什么

  • 響應體(以上圖中綠色部分): 響應數據的最后一部分。存儲響應的數據

    • 響應體和響應頭之間有一個空行隔開(作用:用于標記響應頭結束)

關于響應狀態碼,我們主要有以下三個狀態碼:

  • 200 ok 客戶端請求成功

  • 404 Not Found 請求資源不存在

  • 500 Internal Server Error 服務端發生不可預期的錯誤

三、分層解耦

1.三層架構

我們進行程序設計以及程序開發時,盡可能讓每一個接口、類、方法的職責更單一些(單一職責原則)。盡量滿足高內聚、低耦合的要求。

我們在項目開發中,可以把代碼分為三層,如圖所示:

  • Controller:控制層。接收前端發送的請求,對請求進行處理,并響應數據。

  • Service:業務邏輯層。處理具體的業務邏輯。

  • Dao:數據訪問層(Data Access Object),也稱為持久層。負責數據訪問操作,包括數據的增、刪、改、查。這一層主要是進行數據庫的處理。

基于三層架構執行流程如圖所示:

  • 前端發起的請求,由Controller層接收(Controller響應數據給前端)

  • Controller層調用Service層來進行邏輯處理(Service層處理完后,把處理結果返回給Controller層)

  • Serivce層調用Dao層(邏輯處理過程中需要用到的一些數據要從Dao層獲取)

  • Dao層操作文件中的數據(Dao拿到的數據會返回給Service層)

2.IOC&DI

  • 控制反轉: Inversion Of Control,簡稱IOC對象的創建控制權由程序自身轉移到外部(容器),這種思想稱為控制反轉。對象的創建權由程序員主動創建轉移到容器(由容器創建、管理對象)。這個容器稱為:IOC容器或Spring容器。

  • 依賴注入: Dependency Injection,簡稱DI容器為應用程序提供運行時,所依賴的資源,稱之為依賴注入。程序運行時需要某個資源,此時容器就為其提供這個資源。

      • bean對象:IOC容器中創建、管理的對象,稱之為:bean對象。

      ?

      2.1 入門

      在實現類加上 @Component 注解,就代表把當前類產生的對象交給IOC容器管理。

      來看下面的代碼:

      A. UserDaoImpl

      @Component
      public class UserDaoImpl implements UserDao {@Overridepublic List<String> findAll() {InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());return lines;}
      }

      B. UserServiceImpl

      @Component
      public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;@Overridepublic List<User> findAll() {List<String> lines = userDao.findAll();List<User> userList = lines.stream().map(line -> {String[] parts = line.split(",");Integer id = Integer.parseInt(parts[0]);String username = parts[1];String password = parts[2];String name = parts[3];Integer age = Integer.parseInt(parts[4]);LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));return new User(id, username, password, name, age, updateTime);}).collect(Collectors.toList());return userList;}
      }

      發現UserServiceImpl這個類中聲明了接口UserDao,但是它并沒有創建接口的實現類對象,就是因為實現類UserDaoImpl加了@Component 注解,把當前類產生的對象交給了IOC容器管理。而在UserServiceImpl這個類中聲明的接口UserDao上有@Autowired注解,它可以自動從IOC容器中取出實現類的相關對象。

      2.2 IOC詳解

      IOC控制反轉,就是將對象的控制權交給Spring的IOC容器,由IOC容器創建及管理對象。IOC容器創建的對象稱為bean對象。

      而Spring框架為了更好的標識web應用程序開發當中,bean對象到底歸屬于哪一層,又提供了@Component的衍生注解:

      注意1:聲明bean的時候,可以通過注解的value屬性指定bean的名字,如果沒有指定,默認為類名首字母小寫。

      注意2:使用以上四個注解都可以聲明bean,但是在springboot集成web開發中,聲明控制器bean只能用@Controller。

      2.3 DI詳解

      依賴注入,是指IOC容器要為應用程序去提供運行時所依賴的資源,而資源指的就是對象。

      在入門代碼中,我們使用了@Autowired這個注解,完成了依賴注入的操作,而這個Autowired翻譯過來叫:自動裝配。@Autowired注解,默認是按照類型進行自動裝配的(去IOC容器中找某個類型的對象,然后完成注入操作)

      @Autowired 進行依賴注入,常見的方式,有如下三種:

      a) 屬性注入

      @RestController
      public class UserController {//方式一: 屬性注入@Autowiredprivate UserService userService;}

      b). 構造函數注入

      @RestController
      public class UserController {//方式二: 構造器注入private final UserService userService;@Autowired //如果當前類中只存在一個構造函數, @Autowired可以省略public UserController(UserService userService) {this.userService = userService;}}   

      3). setter注入

      /*** 用戶信息Controller*/
      @RestController
      public class UserController {//方式三: setter注入private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}}    

      第一種是最常用的,因為代碼最為簡潔。

      2.4 注意事項

      那如果在IOC容器中,存在多個相同類型的bean對象,會出現什么情況呢?

      在下面的例子中,準備了兩個UserService的實現類,并且都交給了IOC容器管理。 代碼如下:

      啟動項目之后,控制臺報錯了

      出現錯誤的原因是因為在Spring的容器中,UserService這個類型的bean存在兩個,框架不知道具體要注入哪個bean使用,所以就報錯了。

      對于上述問題,有以下解決方案:

      方案一:使用@Primary注解

      當存在多個相同類型的Bean注入時,加上@Primary注解,來確定默認的實現。

      @Primary
      @Service
      public class UserServiceImpl implements UserService {
      }

      方案二:使用@Qualifier注解

      指定當前要注入的bean對象。 在@Qualifier的value屬性中,指定注入的bean的名稱。 @Qualifier注解不能單獨使用,必須配合@Autowired使用。

      @RestController
      public class UserController {@Qualifier("userServiceImpl")@Autowiredprivate UserService userService;
      }

      方案三:使用@Resource注解

      @RestController
      public class UserController {@Resource(name = "userServiceImpl")private UserService userService;
      }

      @Autowird 與 @Resource有什么區別?

      • @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解

      • @Autowired 默認是按照類型注入,而@Resource是按照名稱注入

      本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
      如若轉載,請注明出處:http://www.pswp.cn/web/80588.shtml
      繁體地址,請注明出處:http://hk.pswp.cn/web/80588.shtml
      英文地址,請注明出處:http://en.pswp.cn/web/80588.shtml

      如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

      相關文章

      Please install it with pip install onnxruntime

      無論怎么安裝都是 Please install it with pip install onnxruntime 我python 版本是3.11 &#xff0c;我換成3.10 解決了

      【數據結構入門訓練DAY-35】棋盤問題

      本次訓練聚焦于使用深度優先搜索&#xff08;DFS&#xff09;算法解決棋盤上的棋子擺放問題。題目要求在一個可能不規則的nn棋盤上擺放k個棋子&#xff0c;且任意兩個棋子不能位于同一行或同一列。輸入包括棋盤大小n和棋子數k&#xff0c;以及棋盤的形狀&#xff08;用#表示可放…

      【日常筆記】wps如何將值轉換成東西南北等風向漢字

      在WPS表格中&#xff0c;若要將數值&#xff08;如角度值&#xff09;轉換成“東、南、西、北”等風向漢字&#xff0c;可通過以下步驟結合自定義函數或條件判斷實現&#xff1a; 一、wps如何將值轉換 方法一&#xff1a;使用LOOKUP函數&#xff08;簡化公式&#xff09;&…

      Web性能優化的未來:邊緣計算、AI與新型渲染架構

      一、邊緣計算與性能優化深度整合 1.1 邊緣節點計算卸載策略 ? 智能任務分割:將非關鍵路徑計算卸載到邊緣節點 // 客戶端代碼 const edgeTask = new EdgeTask(image-processing); edgeTask.postMessage(imageData, {transfer

      spring中的EnvironmentPostProcessor接口詳解

      前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到網站 EnvironmentPostProcessor 是 Spring Boot 提供的一個關鍵擴展接口&#xff0c;允許開發者在 Spring 應用環境初始化后、應用上下文創建前&…

      Vue3知識點梳理

      注&#xff1a;純手打&#xff0c;如有錯誤歡迎評論區交流&#xff01; 轉載請注明出處&#xff1a;https://blog.csdn.net/testleaf/article/details/148056625 編寫此文是為了更好地學習前端知識&#xff0c;如果損害了有關人的利益&#xff0c;請聯系刪除&#xff01; 本文章…

      C++23 新增的查找算法詳解:ranges::find_last 系列函數

      文章目錄 引言C Ranges 庫簡介ranges::find_last、ranges::find_last_if 和 ranges::find_last_if_not 概述ranges::find_last示例代碼代碼解釋 ranges::find_last_if函數簽名參數解釋示例代碼代碼解釋 ranges::find_last_if_not示例代碼代碼解釋 使用場景總結 引言 在 C 的發…

      DW_DMAC簡介

      基本概念&#xff1a; DMA&#xff1a;全稱direct memory access&#xff0c;即直接存儲器訪問。dma可以在中央處理器CPU不參與的情況下&#xff0c;實現外設和內存之間的數據直接傳輸&#xff0c;從而提高數據傳輸效率 外設與計算機內存之間的數據傳輸&#xff0c;一般可通過…

      信號量基礎入門:并發控制的核心概念

      問題的復雜性產生的根本原因在于&#xff0c;如 2.2 節所述&#xff0c;共享變量的訪問始終是“單向信息流”。也就是說&#xff0c;一個進程可以分配新值或檢查當前值&#xff0c;但這種檢查不會為其他進程留下任何痕跡。結果是&#xff0c;當一個進程想要對共享變量的當前值作…

      (十九)Java集合框架深度解析:從基礎到高級應用

      一、集合框架概述 1.1 什么是集合框架 Java集合框架(Java Collections Framework, JCF)是Java語言中用于表示和操作集合的一套標準化體系結構。它提供了一組接口、實現類和算法&#xff0c;用于存儲和操作對象組&#xff0c;解決了數組在存儲對象時的諸多限制。 集合框架的主…

      Blender cycles烘焙貼圖筆記

      下載了一些槍模型&#xff0c;一個模型有七八個材質&#xff0c;一個扳機、準星還有單獨的材質&#xff0c;用的貼圖只有一小部分有內容&#xff0c;對Draw Call非常不友好。不得不學一下怎么用Blender減材質。 找到了這個視頻如何在Blender中將多種材料多張貼圖烘焙成一張貼圖…

      mysql的高可用

      1. 環境準備 2臺MySQL服務器&#xff08;node1: 192.168.1.101&#xff0c;node2: 192.168.1.102&#xff09;2臺HAProxy Keepalived服務器&#xff08;haproxy1: 192.168.1.103&#xff0c;haproxy2: 192.168.1.104&#xff09;虛擬IP&#xff08;VIP: 192.168.1.100&#x…

      鴻蒙 系統-安全-程序訪問控制-應用權限管控

      Ability Kit 提供了一種允許應用訪問系統資源&#xff08;如&#xff1a;通訊錄等&#xff09;和系統能力&#xff08;如&#xff1a;訪問攝像頭、麥克風等&#xff09;的通用權限訪問方式&#xff0c;來保護系統數據&#xff08;包括用戶個人數據&#xff09;或功能&#xff0…

      算法-數對的使用

      1、數對可用于數組排序中&#xff0c;并且可記憶化排序前的元素下標 #include<iostream> #include<string> #include<bits/stdc.h> using namespace std; typedef long long ll; const int N 2e5 10; pair<int, int> a[N]; void solve() {ll n;cin …

      Linux基礎第四天

      系統之間文件共享 想要實現兩個不同的系統之間實現文件共享&#xff0c;最簡單的一種方案就是設置VMware軟件的共享文件夾&#xff0c;利用共享文件夾可以實現linux系統和windows系統之間的文件共享&#xff0c;這樣就可以實現在windows系統上編輯程序&#xff0c;然后在linux系…

      Docker 核心原理詳解:Namespaces 與 Cgroups 如何實現資源隔離與限制

      #Docker疑難雜癥解決指南# Docker 作為容器化技術的代名詞,徹底改變了軟件的開發、部署和管理方式。它憑借其輕量、快速、一致性強的特性,成為了現代云原生架構的基石。然而,Docker 容器的神奇之處并非“無中生有”,其背后是 Linux 內核的兩大核心技術——Namespaces(命名…

      GitHub 趨勢日報 (2025年05月14日)

      本日報由 TrendForge 系統生成 https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日整體趨勢 Top 10 排名項目名稱項目描述今日獲星總星數語言1xming521/WeClone&#x1f680;從聊天記錄創造數字分身的一站式解決方案&…

      【Go】從0開始學習Go

      文章目錄 從0開始學習Go0 與C對比1 代碼框架1.1 helloworld式代碼示例1.2 主體代碼元素&#xff08;核心三部分&#xff09;1.3 其他 2 與C/C區別3 有用的小工具4 注意事項 從0開始學習Go 0 與C對比 特性CGo編譯型語言需要編譯為機器碼直接編譯為二進制可執行文件靜態類型類型…

      簡單說一下 Webpack分包

      最近在看有關webpack分包的知識&#xff0c;搜索了很多資料&#xff0c;感覺這一塊很是迷惑&#xff0c;網上的資料講的也迷迷糊糊&#xff0c;這里簡單總結分享一下&#xff0c;也當個筆記。 如有錯誤請指出。 為什么需要分包 我們知道&#xff0c;webpack的作用&#xff0c…

      使用Python和FastAPI構建網站爬蟲:Oncolo醫療文章抓取實戰

      使用Python和FastAPI構建網站爬蟲&#xff1a;Oncolo醫療文章抓取實戰 前言項目概述技術棧代碼分析1. 導入必要的庫2. 初始化FastAPI應用3. 定義請求模型4. 核心爬蟲功能4.1 URL驗證和準備4.2 設置HTTP請求4.3 發送請求和解析HTML4.4 提取文章內容4.5 保存結果和返回數據 5. AP…