【后端開發】初識Spring IoC與SpringDI、圖書管理系統

文章目錄

  • 圖書管理系統
    • 用戶登錄
      • 需求分析
      • 接口定義
      • 前端頁面代碼
      • 服務器代碼
    • 圖書列表展示
      • 需求分析
      • 接口定義
      • 前端頁面部分代碼
      • 服務器代碼
        • Controller層
        • service層
        • Dao層
        • modle層
  • Spring IoC
    • 定義
    • 傳統程序開發
    • 解決方案
    • IoC優勢
  • Spring DI
    • IoC &DI使用
    • 主要注解
  • Spring IoC詳解
    • bean的存儲
      • 五大注解
        • @Controller(控制器存儲)
          • getBean()方法
          • 面試:ApplicationContext VS BeanFactory
        • 為什么要這么多類注解
        • 五大注解是否可以混用
        • 程序被Spring管理的條件
    • 方法注解--@Bean
    • 掃描路徑
  • Spring DI詳解
    • 屬性注入
    • 構造方法注入
    • Setter注入
    • 優缺點
    • @Autowired存在的問題
      • @Primary
      • @Qualifier
      • @Resource
    • 面試--@Autowird 與 @Resource的區別

圖書管理系統

用戶登錄

需求分析

賬號密碼校驗接口:根據輸入用戶名和密碼校驗登錄是否通過。

接口定義

  • url:/user/login
  • type:post
  • 請求參數:name=admin&password=admin
  • 返回:true //賬號密碼驗證成功,false//賬號密碼驗證失敗

前端頁面代碼

<body><div class="container-login"><div class="container-pic"><img src="pic/computer.png" width="350px"></div><div class="login-dialog"><h3>登陸</h3><div class="row"><span>用戶名</span><input type="text" name="userName" id="userName" class="form-control"></div><div class="row"><span>密碼</span><input type="password" name="password" id="password" class="form-control"></div><div class="row"><button type="button" class="btn btn-info btn-lg" onclick="login()">登錄</button></div></div></div><script src="js/jquery.min.js"></script><script>function login() {$.ajax({url: "/user/login",type: "post",data: {userName: $("#userName").val(),password: $("#password").val()},success: function (result) {if (result == "") {location.href = "book_list.html";} else {alert(result)}}})}</script>
</body>

服務器代碼

@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/login")public String login(String userName, String password, HttpSession session) {//1.校驗參數//2.驗證密碼是否正確//3.返回結果if (!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)) {return "用戶名或密碼為空";}//理論上應該從數據庫中讀取,暫時先不用//一般正確情況下,會有后續的操作,因此建議將后續操作比較多的情況下放在括號外面if (!"admin".equals(userName) || !"admin".equals(password)) {return "密碼錯誤";}session.setAttribute("userName", userName);return "";}
}

圖書列表展示

需求分析

圖書列表:提供圖書列表信息

接口定義

  • url:/user/login
  • type:post
  • 請求參數:無
  • 返回:
    [{“id”: 1,
    “bookName”:“book1”,
    “author” :“author1”,
    “count”:270,
    “price”: 20”,
    publish":“publish1”,
    “status”: 1,
    “statusCN”:“可借閱”}…]

前端頁面部分代碼

		<script>//這里需要直接訪問到后端的圖書列表信息,直接需要訪問到后端,所以直接開始就使用ajax,但是為了代碼的可讀性,將其封裝到一個方法里面先getBookList();function getBookList() {$.ajax({url:"/book/getBookList",type:"get",success:function(books){var finalHtml = "";//下面使用單引號的原因是因為html中也有雙引號,可能會造成出錯for(var book of books){finalHtml += '<tr>';finalHtml += '<td><input type="checkbox" name="selectBook" value="'+book.id+'" id="selectBook" class="book-select"></td>';finalHtml += '<td>'+book.id+'</td>';finalHtml += '<td>'+book.bookName+'</td>';finalHtml += '<td>'+book.author+'</td>';finalHtml += '<td>'+book.num+'</td>';finalHtml += '<td>'+book.price+'</td>';finalHtml += '<td>'+book.publishName+'</td>';finalHtml += '<td>'+book.statusCN+'</td>';finalHtml += '<td>';finalHtml += ' <div class="op">';finalHtml += '<a href="book_update.html?bookId='+book.id+'">修改</a>';finalHtml += '<a href="javascript:void(0)" onclick="deleteBook('+book.id+')">刪除</a>';finalHtml += '</div></td></tr>';}$("tbody").html(finalHtml);}})}

服務器代碼

Controller層
@RequestMapping("/book")
@RestController
public class BookController {@Autowiredprivate BookService bookService;@RequestMapping("/getBookList")public List<BookInfo> getBookList() {
//        BookService bookService = new BookService();return bookService.getBookList();}
}
service層
@Component
public class BookService {@Autowiredprivate BookDao bookDao;public List<BookInfo> getBookList(){
//        BookDao bookDao = new BookDao();List<BookInfo> bookInfos = bookDao.mockData();for (BookInfo bookInfo : bookInfos) {if (bookInfo.getStatus() == 2){bookInfo.setStatusCN("不可借閱");}else {bookInfo.setStatusCN("可借閱");}}return bookInfos;}
}
Dao層
@Component
public class BookDao {//理論上該方法應該從數據庫中獲取,當前采用mock方式public List<BookInfo> mockData(){List<BookInfo> bookInfos = new ArrayList<BookInfo>();//mock數據,也就是測試時候所有的模擬數據for (int i = 1; i <= 15; i++) {BookInfo bookInfo = new BookInfo();bookInfo.setId(i);bookInfo.setAuthor("作者" + i);bookInfo.setBookName("圖書" + i);bookInfo.setNum(i * 2 + 1);bookInfo.setPrice(new BigDecimal(i*3));bookInfo.setPublishName("出版社" + i);if (i % 5 == 0){bookInfo.setStatus(2);
//                bookInfo.setStatusCN("不可借閱");}else {bookInfo.setStatus(1);
//                bookInfo.setStatusCN("可借閱");}bookInfos.add(bookInfo);}return bookInfos;}
}
modle層
@Data
public class BookInfo {private Integer id;private String bookName;private String author;private Integer num;private BigDecimal price;private String publishName;private Integer status;//1-可借閱  0-不可借閱  這里的數據都是要存放到數據庫中的,盡量減少往數據庫中存放文字信息private String statusCN;//這個字段不用網數據庫中存儲,僅是為了與status進行文字與數字的轉換
}

Spring IoC

Spring的抽象概念:Spring是包含了眾多?具?法的IoC容器。

定義

IoC 是Spring的核心思想,之前項目在類上添加 @Restcontroller 和@Controller 注解,就是把這個對象交給Spring管理,Spring框架啟動時就會加載該類,把對象交給Spring管理,就是loC思想。

loC:Inversion of Control(控制反轉),也就是說 Spring是一個"控制反轉"的容器。
什么是控制反轉呢?也就是控制權反轉,什么的控制權發生了反轉?
獲得依賴對象的過程被反轉了也就是說,當需要某個對象時,傳統開發模式中需要自己通過 new 創建對象,現在不需要再進行創建,把創建對象的任務交給容器,程序中只需要依賴注入(DependencyInjection, Dl)就可以了這個容器稱為:loC容器,Spring是一個loC容器,所以有時Spring 也稱為Spring 容器。

傳統程序開發

比如開發一個汽車,傳統的設計思路為:
先設計輪子(Tire),然后根據輪子的大小設計底盤(Bottom),接著根據底盤設計車身(Framework),后根據車身設計好整個汽車(Car)。

這里就出現了一個"依賴"關系:汽車依賴車身,車身依賴底盤,底盤依賴輪子。
也就是Car類依賴Framework類,Framework類依賴Bottom類,Bottom類依賴Tire類。

這樣的設計看起來沒問題,但是可維護性卻很低,接下來需求有了變更:隨著對的車的需求量越來越大,個性化需求也會越來越多,我們需要加工多種尺寸的輪胎。

此時,開發一個汽車需要依賴再依賴,直至依賴到輪胎的尺寸,也就是下面的改法。

    public static void main(String[] args) {public static void main(String[] args) {Car car = new Car(20);car.run();}}public class Car {private Framework framework;public Car(int size) {framework = new Framework(size);System.out.println("Car init....");}public void run() {System.out.println("Car run...");}
}public class Framework {private Bottom bottom;public Framework(int size) {bottom = new Bottom(size);System.out.println("Framework init...");}
}public class Bottom {private Tire tire;public Bottom(int size) {this.tire = new Tire(size);System.out.println("Bottom init...");}
}public class Tire {private int size;public Tire(int size) {this.size = size;System.out.println("輪胎尺?: " + size);}
}

以上代碼可以看出,以上程序的問題是:當最底層代碼改動之后,整個調用鏈上的所有代碼都需要修改,程序的耦合度非常高(修改一處代碼,影響其他處的代碼修改)。

解決方案

我們嘗試換一種思路,先設計汽車的大概樣子,然后根據汽車的樣子來設計車身,根據車身來設計底盤,最后根據底盤來設計輪子。這時候,依賴關系就倒置過來了:輪子依賴底盤,底盤依賴車身,車身依賴汽車。
在這里插入圖片描述
可以嘗試不在每個類中創建下級類,如果創建下級類就會出現當下級類發生改變操作,自己也要跟著修改。
此時,只需要將原來由自己創建的下級類,改為傳遞的方式(也就是注入的方式),因為我們不需要在當前類中創建下級類了,所以下級類即使發生變化(創建或減少參數),當前類本身也無需修改任何代碼,這樣就完成了程序的解耦。

public class Main {public static void main(String[] args) {Tire tire = new Tire(20);Bottom bottom = new Bottom(tire);Framework framework = new Framework(bottom);Car car = new Car(framework);car.run();}
}public class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;System.out.println("Car init....");}public void run() {System.out.println("Car run...");}
}public class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;System.out.println("Car init....");}public void run() {System.out.println("Car run...");}
}public class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;System.out.println("Framework init...");}
}public class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;System.out.println("Bottom init...");}
}public class Tire {private int size;public Tire(int size) {this.size = size;System.out.println("輪胎尺?: " + size);}
}

代碼經過以上調整,無論底層類如何變化,整個調用鏈是不用做任何改變的,這樣就完成了代碼之間的解耦,從而實現了更加靈活、通用的程序設計了。

IoC優勢

在傳統的代碼中對象創建順序是:Car>Framework->Bottom->Tire
改進之后解耦的代碼的對象創建順序是:Tire->Bottom->Framework ->Car

改進之后的控制權發生的反轉,不再是使用方對象創建并控制依賴對象了,而是把依賴對象注入將當前對象中,依賴對象的控制權不再由當前類控制了。
這樣的話,即使依賴類發生任何改變,當前類都是不受影響的,這就是典型的控制反轉,也就是IoC的實現思想。
在這里插入圖片描述

loC容器具備以下優點

  1. 資源集中管理:loC容器會幫助管理一些資源(對象等),需要使用時,只需要從loC容器中去取就可以了。
  2. 解耦合:在創建實例的時候不需要了解其中的細節,降低了使用資源雙方的依賴程度,也就是耦合度。

Spring 就是一種loC容器,幫助我們來做了這些資源管理。

Spring DI

Dl:DependencyInjection(依賴注入),容器在運行期間,動態的為應用程序提供運行時所依賴的資源,稱之為依賴注入。

程序運行時需要某個資源,此時容器就為其提供這個資源。
從這點來看,依賴注入(DI)和控制反轉(l0C)是從不同的角度的描述的同一件事情,就是指通過引入loC容器,利用依賴關系注入的方式,實現對象之間的解耦。

上述代碼通過構造函數的方式,把依賴對象注入到需要使用的對象中。

IoC是一種思想,也是"目標",而思想只是一種指導原則,最終還是要有可行的落地方案,而 DI 就屬于具體的實現。
所以也可以說,DI是loC的一種實現。

IoC &DI使用

既然 Spring 是一個 loC(控制反轉)容器,作為容器,那么它就具備兩個最基礎的功能:存、取。

Spring 容器管理的主要是對象,這些對象,我們稱之為"Bean"。把這些對象交由Spring管理,由Spring來負責對象的創建和銷毀,程序只需要告訴Spring,哪些需要存,以及如何從Spring中取出對象。

主要注解

@Component:交給Spring管理
@Autowired:注入運行時依賴的對象

@Component
public class BookService {@Autowiredprivate BookDao bookDao;public List<BookInfo> getBookList(){
//        BookDao bookDao = new BookDao();List<BookInfo> bookInfos = bookDao.mockData();for (BookInfo bookInfo : bookInfos) {if (bookInfo.getStatus() == 2){bookInfo.setStatusCN("不可借閱");}else {bookInfo.setStatusCN("可借閱");}}return bookInfos;}
}

Spring IoC詳解

前?提到IoC控制反轉,就是將對象的控制權交給Spring的IOC容器,由IOC容器創建及管理對象,也就是bean的存儲。

bean的存儲

五大注解

  • 五大類注解:@Controller、@Service、@Repository、@Component、@Configuration 。
  • bean對象:在spring容器中存放的對象。
  • ApplicationContext: 翻譯為Spring上下文,指的就是當前的運行環境,也可以看作是?個容器。故ApplicationContext的對象中存放了所有與當前的運行環境有關的內容,比如 spring容器中存放的bean對象。
@Controller(控制器存儲)

這里僅展示@Controller,其他四個注解與@Controller類似。
將UserControllerTest類用@Controller注解存放到IoC容器中。

@Controller
public class UserControllerTest {public void say(){System.out.println("hello, UserControllerTest");}
}
getBean()方法

這里分別使用三種getBean()方法來獲取UserController對象,進行打印測試
在這里插入圖片描述

@SpringBootApplication
public class LibraryApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(LibraryApplication.class, args);UserControllerTest bean = context.getBean(UserControllerTest.class);bean.say();System.out.println(bean);UserControllerTest userControllerTest = (UserControllerTest) context.getBean("userControllerTest");userControllerTest.say();System.out.println(userControllerTest);UserControllerTest userControllerTest1 = context.getBean("userControllerTest", UserControllerTest.class);userControllerTest1.say();System.out.println(userControllerTest1);}
}

在這里插入圖片描述
結果成功輸出也就是獲取到了UserControllerTest對象,并且地址一樣,說明是一個對象。
獲取對象的功能是Application的父類BeanFactory的功能。

面試:ApplicationContext VS BeanFactory

繼承關系和功能方面來說:Spring 容器有兩個頂級的接口BeanFactory和ApplicationContext。
其中 BeanFactory 提供了基礎的訪問容器的能力,而ApplicationContext 屬于 BeanFactony 的子類,它除了繼承了 BeanFactory 的所有功能之外,它還擁有獨特的特性,還添加了環境管理支持、資源訪問支持、以及事件傳播等方面的支持。
從性能方面來說:ApplicationContext 是一次性加載并初始化所有的 Bean 對象,而BeanFactory 是需要那個才去加載那個,因此更加輕量(空間換時間)。

為什么要這么多類注解

與應用分層呼應,讓程序員看到類注解之后,就能直接了解當前類的用途。

  • @Controller:控制層,接收請求,對請求進行處理,并進行響應
  • @Servie:業務邏輯層,處理具體的業務邏輯
  • @Repository:數據訪問層,也稱為持久層,負責數據訪問操作
  • @Configuration:配置層,處理項目中的一些配置信息
  • @Component:是一個元注解,也就是說可以注解其他類注解@Controller,@Service,@Repository,@Confiquraion,這些注解被稱為@Component 的行生注解,因為這些注解源代碼里面都有一個注解@Component。
五大注解是否可以混用

功能上:@Service @Repository @Configuration @Component 可以完全混用,@Controller有自己的特殊性。
規范上:不可以混用。因為我們想要與應用分層呼應。
在這里插入圖片描述

程序被Spring管理的條件
  1. 程序要被spring掃描到(默認路徑是啟動類所在的目錄以及子目錄),手動設置:@ComponentScan(basePackages = “~”)
  2. 程序需要配置五大注解和@Bean

方法注解–@Bean

@Bean要搭配類注解使用

類注解是添加到某個類上的,但是存在兩個問題:

  1. 使用外部包里的類,沒辦法添加類注解
  2. 一個類,需要多個對象,比如多個數據源

示例1,@Bean要搭配類注解使用

@Configuration
public class UserConfig {public void say(){System.out.println("hi,UserConfig");}@Beanpublic User user(){return new User("張三");}
}

示例2:定義多個對象,使用類的類型掃描

@Service
public class UserService {public void say(){System.out.println("hello, UserService");}@Beanpublic BookInfo user(){return new BookInfo();}@Beanpublic BookInfo user1(){return new BookInfo();}
}@SpringBootApplication
public class LibraryApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(LibraryApplication.class, args);BookInfo bean = context.getBean(BookInfo.class);System.out.println(bean);}
}

通過類的類型掃描,這里出現了報錯,通過類的類型掃描,此時容器中有兩個User對象,根據類型獲取對象,此時Spring不知道要獲取哪個對象,所以報錯了。
在這里插入圖片描述
解決辦法:用類的名字掃描。

@SpringBootApplication
public class LibraryApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(LibraryApplication.class, args);BookInfo bean1 = (BookInfo) context.getBean("user");System.out.println(bean1);BookInfo bean2 = (BookInfo) context.getBean("user1");System.out.println(bean2);}
}

在這里插入圖片描述

掃描路徑

把啟動類放到其他的目錄下面,再次啟動程序,會出錯。
在這里插入圖片描述
就是因為沒有找到對應的bean對象,使用五大注解聲明的bean,要想生效,還需要配置掃描路徑,讓Spring掃描到這些注解也就是通過 @ComponentScan 來配置掃描路徑。

@ComponentScan({"com.example.library"})
@SpringBootApplication
public class LibraryApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(LibraryApplication.class, args);}
}

Spring DI詳解

DI(依賴注入):依賴注入是一個過程,是指loC容器在創建Bean時,去提供運行時所依賴的資源,而資源指的就是對象在上面程序案例中,我們使用了 @Autowired 這個注解,完成了依賴注入的操作簡單來說,就是把對象取出來放到某個類的屬性中。

在一些文章中,依賴注入也被稱之為"對象注入”、"屬性裝配”,具體含義需要結合文章的上下文來理解。

關于依賴注入, Spring也給我們提供了三種方式:
屬性注入(Field Injection)
構造?法注入(Constructor Injection)
Setter 注入(Setter Injection)

屬性注入

@Controller
public class UserControllerTest {@Autowiredprivate UserService userService;//屬性注入public void say(){System.out.println("hello, UserControllerTest");}
}

構造方法注入

只有一個構造方法的時候即使不加@Autowired也可以獲取數據,但是要是加一個空的構造方法,會報出空指針異常。
因為程序啟動的時候會首先調用無參數的構造方法,如果沒有會調用我們寫的,但是兩個都有的話就會調用無參數的,此時并沒有真正new對象,去調用say()方法就會出現空指針異常。
解決辦法:就是在想要注入的構造方法中添加@Autowired注解

@Controller
public class UserControllerTest {private UserService userService;@Autowiredpublic UserService(UserService service){this.userService = service;}public void say(){System.out.println("hello, UserControllerTest");}
}

Setter注入

@Controller
public class UserControllerTest {private UserService userService;@Autowiredpublic void setUserService(UserService service){this.userService = service;}public void say(){System.out.println("hello, UserControllerTest");}
}

優缺點

  • 屬性注入
    優點:簡潔,使用方便
    缺點:只能用于 loC 容器,如果是非 loC 容器不可用,并且只有在使用的時候才會出現 NPE(空指針異常);不能注入一個Final修飾的屬性。
  • 構造函數注入(Spring4.x推薦)
    優點:可以注入final修飾的屬性;注入的對象不會被修改依賴對象;在使用前一定會被完全初始化,因為依賴是在類的構造方法中執行的,而構造方法是在類加載階段就會執行的方法;通用性好,構造方法是JDK支持的,所以更換任何框架都是適用的。
    缺點:注入多個對象時,代碼會比較繁瑣。
  • Setter注入
    優點:方便在類實例之后,重新對該對象進行配置或者注入。
    缺點:不能注入一個Final修飾的屬性;注入對象可能會被改變,因為setter方法可能會被多次調用,就有被修改的風險。

@Autowired存在的問題

Student 實體類

@Data
public class Student {private String name;private Integer id;public Student() {}public Student(String name) {this.name = name;}public Student(String name, Integer id) {this.name = name;this.id = id;}

BeanConfig類

@Configuration
public class BeanConfig {@Beanpublic Student StudentInfo() {return new Student("wh",01);}@Beanpublic Student StudentInfo2() {return new Student("Bob",02);}
}

DomeController類

@Controller
public class DomeController {@Autowiredprivate Student student;public void say(){System.out.println(student);}
}

啟動類

@SpringBootApplication
public class SpringIocApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(SpringIocApplication.class, args);DomeController bean = context.getBean(DomeController.class);bean.say();}
}

運行
在這里插入圖片描述

報錯的原因是,非唯一的 Bean 對象
解釋:@Autowired是先按照類型去注入,匹配到多個對象時,再按照名稱去注入。

如果明確注入對象的名稱,則可以正確打印該學生信息。

@Controller
public class DomeController {@Autowiredprivate Student StudentInfo2;public void say(){System.out.println(StudentInfo2);}
}

那當沒有明確注入對象的名稱,又想得到正確結果我們可以怎么做?
有以下幾種解決方案:

@Primary
@Qualifier
@Resource

@Primary

使用@Primary注解:當存在多個相同類型的Bean注入時,加上@Primary注解,來確定默認的實現。
直接加到Bean注入的方法上。

@Primary
@Bean
public Student StudentInfo() {return new Student("wh", 01);
}

@Qualifier

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

@Controller
public class DomeController {@Qualifier("StudentInfo2")@Autowiredprivate Student student;public void say(){System.out.println(student);}
}

@Resource

本身就是依賴注入注解,是按照bean的名稱進行注入。

@Controller
public class DomeController {@Resource(name = "StudentInfo")private Student student;public void say(){System.out.println(student);}
}

面試–@Autowird 與 @Resource的區別

  1. @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解。
  2. @Autowired 默認是按照類型注入,而@Resource是按照名稱注入,相比于 @Autowired 來說, @Resource ?持更多的參數設置,例如 name 設置,根據名稱獲取 Bean。

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

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

相關文章

通付盾風控智能體(RiskAgent): 神煩狗(DOGE)

在數字化業務高速發展的今天&#xff0c;風控系統已成為企業抵御黑產、欺詐、保障交易安全的核心防線。然而傳統風控面臨人力依賴高與策略滯后性等挑戰&#xff0c;數據分析師需每日從海量數據中手動提煉風險特征、設計防護規則&#xff0c;耗時費力&#xff1b;新策略從發現到…

大模型論文:Language Models are Unsupervised Multitask Learners(GPT2)

大模型論文&#xff1a;Language Models are Unsupervised Multitask Learners(GPT2) 文章地址&#xff1a;https://storage.prod.researchhub.com/uploads/papers/2020/06/01/language-models.pdf 摘要 自然語言處理任務&#xff0c;例如問答、機器翻譯、閱讀理解和摘要&am…

分布式ID生成方案的深度解析與Java實現

在分布式系統中&#xff0c;生成全局唯一的ID是一項核心需求&#xff0c;廣泛應用于訂單編號、用戶信息、日志追蹤等場景。分布式ID不僅需要保證全局唯一性&#xff0c;還要滿足高性能、高可用性以及一定的可讀性要求。本文將深入探討分布式ID的概念、設計要點、常見生成方案&a…

記 etcd 無法在docker-compose.yml啟動后無法映射數據庫目錄的問題

1、將etcd 單獨提取 Dockerfile&#xff0c;指定配置文件和數據目錄 #鏡像 FROM bitnami/etcd:3.5.11 #名稱 ENV name"etcd" #重啟 ENV restart"always" #運行無權限 ENV ALLOW_NONE_AUTHENTICATION"yes" #端口 EXPOSE 2379 2380 #管理員權限才…

怎樣才不算干擾球·棒球1號位

在棒球運動中&#xff0c;"干擾球"&#xff08;Interference&#xff09;是指球員或場外人員非法影響了比賽的正常進行。以下情況通常 不構成干擾&#xff0c;屬于合法行為或無需判罰&#xff1a; 1. 擊跑員&#xff08;Batter-Runner&#xff09;合法跑壘 跑壘限制…

PyTorch實現多輸入輸出通道的卷積操作

本文通過代碼示例詳細講解如何在PyTorch中實現多輸入通道和多輸出通道的卷積運算&#xff0c;并對比傳統卷積與1x1卷積的實現差異。 1. 多輸入通道互相關運算 當輸入包含多個通道時&#xff0c;卷積核需要對每個通道分別進行互相關運算&#xff0c;最后將結果相加。以下是實現…

深入解析 MySQL 中的日期時間函數:DATE_FORMAT 與時間查詢優化、DATE_ADD、CONCAT

深入解析 MySQL 中的日期時間函數&#xff1a;DATE_FORMAT 與時間查詢優化 在數據庫管理和應用開發中&#xff0c;日期和時間的處理是不可或缺的一部分。MySQL 提供了多種日期和時間函數來滿足不同的需求&#xff0c;其中DATE_FORMAT函數以其強大的日期格式化能力&#xff0c;…

SSH配置優化:提升本地內網Linux服務器遠程連接速度與穩定性

文章目錄 引言一. 理解SSH連接過程與影響因素二. 服務器端SSH配置優化三. 客戶端SSH配置優化四. 高級技巧五. 內網穿透突破公網IP限制總結 引言 SSH (Secure Shell) 是一種網絡協議&#xff0c;用于加密的網絡服務&#xff0c;常用于遠程登錄和管理Linux服務器。對于本地內網的…

BERT - MLM 和 NSP

本節代碼將實現BERT模型的兩個主要預訓練任務&#xff1a;掩碼語言模型&#xff08;Masked Language Model, MLM&#xff09; 和 下一句預測&#xff08;Next Sentence Prediction, NSP&#xff09;。 1. create_nsp_dataset 函數 這個函數用于生成NSP任務的數據集。 def cr…

“實時滾動”插件:一個簡單的基于vue.js的無縫滾動

1、參考連接&#xff1a; 安裝 | vue-seamless-scroll 2、使用步驟&#xff1a; 第一步&#xff1a;安裝 yarn add vue-seamless-scroll 第二步&#xff1a;引入 import vueSeamlessScroll from vue-seamless-scroll/src 第三步&#xff1a;注冊 components: { vueSeamless…

【藍橋杯】賽前練習

1. 排序 import os import sysn=int(input()) data=list(map(int,input().split(" "))) data.sort() for d in data:print(d,end=" ") print() for d in data[::-1]:print(d,end=" ")2. 走迷宮BFS import os import sys from collections import…

pyTorch-遷移學習-學習率衰減-四種天氣圖片多分類問題

目錄 1.導包 2.加載數據、拼接訓練、測試數據的文件夾路徑 3.數據預處理 3.1 transforms.Compose數據轉化 3.2分類存儲的圖片數據創建dataloader torchvision.datasets.ImageFolder torch.utils.data.DataLoader 4.加載預訓練好的模型(遷移學習) 4.1固定、修改預訓練…

第十四屆藍橋杯大賽軟件賽國賽Python大學B組題解

文章目錄 彈珠堆放劃分偶串交易賬本背包問題翻轉最大階梯最長回文前后綴貿易航線困局 彈珠堆放 遞推式 a i a i ? 1 i a_ia_{i-1}i ai?ai?1?i&#xff0c; n 20230610 n20230610 n20230610非常小&#xff0c;直接模擬 答案等于 494 494 494 劃分 因為總和為 1 e 6 1e6…

Python 和 JavaScript兩種語言的相似部分-由DeepSeek產生

Python 和 JavaScript 作為兩種流行的編程語言&#xff0c;雖然在設計目標和應用場景上有差異&#xff08;Python 偏向后端和腳本&#xff0c;JavaScript 偏向前端和動態交互&#xff09;&#xff0c;但它們的語法存在許多相似之處。以下是兩者在語法上的主要共同點及對比&…

改善 Maven 的依賴性

大家好&#xff0c;這里是架構資源棧&#xff01;點擊上方關注&#xff0c;添加“星標”&#xff0c;一起學習大廠前沿架構&#xff01; 建議使用mvn dependency:analyze命令來擺脫已聲明但未使用的依賴項&#xff1a; 還有另一個用例&#xff0c; mvn dependency:analyze 它可…

【SQL】子查詢詳解(附例題)

子查詢 子查詢的表示形式為&#xff1a;(SELECT 語句)&#xff0c;它是IN、EXISTS等運算符的運算數&#xff0c;它也出現于FROM子句和VALUES子句。包含子查詢的查詢叫做嵌套查詢。嵌套查詢分為相關嵌套查詢和不想關嵌套查詢 WHERE子句中的子查詢 比較運算符 子查詢的結果是…

Stable Diffusion 擴展知識實操整合

本文的例子都是基于秋葉整合包打開的webui實現的 一、ADetailer——改善人臉扭曲、惡心 After detailer插件可以自動檢測生成圖片的人臉&#xff0c;針對人臉自動上蒙版&#xff0c;自動進行重繪&#xff0c;整個流程一氣呵成&#xff0c;因此可以避免許多重復的操作。除此之…

freertos內存管理簡要概述

概述 內存管理的重要性 在嵌入式系統中&#xff0c;內存資源通常是有限的。合理的內存管理可以確保系統高效、穩定地運行&#xff0c;避免因內存泄漏、碎片化等問題導致系統崩潰或性能下降。FreeRTOS 的內存管理機制有助于開發者靈活地分配和釋放內存&#xff0c;提高內存利用…

按規則批量修改文件擴展名、刪除擴展名或添加擴展名

文件的擴展名是多種多樣的&#xff0c;有些不同文件的擴展名之間相互是可以直接轉換的。我們工作當中最常見的就是 doc 與 docx、xls 與 xlsx、jpg 與 jpeg、html 與 htm 等等&#xff0c;這些格式在大部分場景下都是可以相互轉換 能直接兼容的。我們今天要介紹的就是如何按照一…

熱門面試題第15天|最大二叉樹 合并二叉樹 驗證二叉搜索樹 二叉搜索樹中的搜索

654.最大二叉樹 力扣題目地址(opens new window) 給定一個不含重復元素的整數數組。一個以此數組構建的最大二叉樹定義如下&#xff1a; 二叉樹的根是數組中的最大元素。左子樹是通過數組中最大值左邊部分構造出的最大二叉樹。右子樹是通過數組中最大值右邊部分構造出的最大…