簡單地聊一聊Spring Boot的構架

本文由葡萄城技術團隊發佈。轉載請註明出處:葡萄城官網,葡萄城爲開發者提供專業的開發工具、解決方案和服務,賦能開發者。

前言

本文小編將詳細解析Spring Boot框架,並通過代碼舉例說明每個層的作用。我們將深入探討Spring Boot的整體架構,包括展示層、業務邏輯層和數據訪問層。通過這些例子,讀者將更加清晰地瞭解每個層在應用程序中的具體作用。通過代碼實例,我們將幫助讀者更好地理解和應用Spring Boot框架,從而提高應用程序的可維護性和可擴展性。

什麼是Spring Boot

在介紹Spring Boot框架的分層之前,小編先爲大家介紹一下什麼是Spring Boot:

Spring Boot是一個基於Spring框架的開發框架,旨在簡化Spring應用程序的搭建和開發。Spring Boot提供了很多自動化配置的功能,可以快速地搭建一個基於Spring的Web應用程序,而不需要手動進行繁瑣的配置。

Spring Boot可以幫助開發人員快速構建各種類型的應用程序,包括Web應用程序、RESTful服務、批處理應用程序和基於消息的應用程序等。它採用Java編程語言,並且可以與各種其他技術集成,例如Thymeleaf、MongoDB、Redis等。

Spring Boot還提供了很多有用的工具和插件,例如Spring Boot CLI(命令行界面),可以幫助開發人員更加便捷地創建、運行和測試Spring Boot應用程序。此外,Spring Boot還支持各種構建工具,例如Maven和Gradle,以及各種開發環境,例如Eclipse和IntelliJ IDEA。

Spring Boot分層:

Spring Boot主要分爲4層:Controller層、Service層、Repository/DAO層和Model層。

1. Controller層

在SpringBoot中,Controller層是MVC(Model-View-Controller)模式中的控制器部分,負責處理來自用戶發起的HTTP請求,並返回相應的響應結果。Controller層接收到請求後,通常會調用Service層進行業務邏輯處理,最後再將處理結果封裝成響應對象並返回給前端。

一個Controller類通常包含多個方法,每個方法對應一個不同的HTTP請求路徑,並使用特定的註解來標識。例如,使用@GetMapping註解表示該方法處理GET請求,@PostMapping表示該方法處理POST請求。同時,通過@RequestParam註解可以獲取請求參數,@PathVariable註解可以獲取URL路徑參數,@RequestBody註解可以獲取請求體中的數據。

2. Service層

在Spring Boot中,Service層是應用程序的一部分,負責處理業務邏輯和協調不同的組件。它是控制器(Controller)和數據訪問層(Repository)之間的中間層,用於將業務邏輯與數據操作解耦。

Service層的主要職責可以總結如下:

  1. 執行業務邏輯:Service層負責實現應用程序的業務邏輯。它包含了具體的業務規則和操作流程,以滿足需求和業務規定。例如,對於電子商務應用程序,Service層可能會包含創建訂單、處理支付、驗證庫存等業務邏輯的實現。
  2. 協調數據訪問:Service層充當控制器和數據訪問層之間的橋樑。它通過調用相應的Repository接口來執行數據操作,如查詢數據庫、保存數據、更新數據等。Service層可以組織和協調多個Repository操作,以完成複雜的業務需求。
  3. 提供業務接口:Service層可以定義一些公共接口或方法,供其他組件(如控制器、其他Service等)使用。這樣可以封裝底層的業務邏輯實現,使其對外提供統一的接口。這種封裝有助於提高代碼的可維護性和重用性。
  4. 處理事務管理:Service層通常涉及到數據庫的讀寫操作,需要保證數據的一致性和完整性。通過使用Spring框架提供的事務管理機制,Service層可以確保多個數據庫操作在一個事務中執行。它可以定義事務的邊界、隔離級別、回滾策略等,以確保數據操作的正確性和可靠性。
  5. 實現業務規則和驗證:Service層可以包含對傳入數據的驗證和處理邏輯。例如,對於用戶註冊操作,Service層可能會對輸入的用戶名進行唯一性檢查,對密碼進行加密等。這樣可以保證應用程序的安全性和數據的有效性。

3. Repository/DAO層

DAO全稱是Data Access Object,其主要目標是從數據庫高效獲取(查詢)數據,併爲service層提供服務。

Repository/DAO層的主要職責可以總結如下:

  1. 定義數據訪問接口:Repository或DAO層定義了訪問數據庫的接口,它們通常包括各種讀、寫、更新、刪除等操作。這些操作通過方法調用來實現,使得業務邏輯可以輕鬆地使用這些操作。
  2. 提供數據映射:Repository或DAO層負責將數據庫中的數據映射到Java類或對象中。這種映射可以是簡單的一對一關係,也可以是複雜的關聯關係。通常情況下,開發人員會使用ORM框架(如Hibernate)來自動完成數據映射。
  3. 處理數據訪問異常:Repository或DAO層負責處理與數據訪問相關的異常情況,例如數據庫連接失敗、SQL語句執行錯誤等。它們可以捕獲這些異常並進行相應的處理,以保證應用程序的穩定性和可靠性。
  4. 支持數據源配置:Repository或DAO層支持不同類型的數據源配置,例如關係型數據庫、NoSQL數據庫、文件系統等。它們可以根據不同的數據源類型,提供相應的數據訪問接口和數據映射策略。
  5. 提供數據緩存:Repository或DAO層可以緩存已經讀取的數據,以提高應用程序的性能。它們可以使用內存緩存、分佈式緩存等不同類型的緩存機制,根據業務需求進行選擇。

4. Model層

在Spring Boot中,Model層對象是用於封裝和傳遞數據的Java對象。它表示應用程序中的業務數據,並負責處理數據的獲取、保存和修改等操作。Model層對象通常具有以下特點:

  1. 實體類(Entity Class):Model層對象通常是實體類或POJO(Plain Old Java Object),用於表示業務數據的結構。實體類的屬性對應數據庫表的字段,通過ORM(Object-Relational Mapping)框架可以將實體類與數據庫進行映射。
  2. 數據傳輸對象(Data Transfer Object,DTO):在一些場景下,爲了滿足特定的需求,可能需要使用DTO來封裝數據。DTO是一個簡單的Java對象,用於在不同的層之間傳輸數據。DTO通常只包含必要的屬性,以減少數據傳輸的大小和複雜性。
  3. 數據校驗(Data Validation):Model層對象可以用於數據校驗,確保傳入的數據符合特定的規則和要求。可以使用註解(如javax.validation.constraints)或其他驗證框架(如Hibernate Validator)對屬性進行校驗。
  4. 業務邏輯(Business Logic):Model層對象可以包含一些業務邏輯的方法,用於處理數據的計算、轉換和操作等。這些方法可以在Model層對象中定義,或者在服務層(Service Layer)中進行實現。

代碼示例:

1.Controller層:

ProjectController.java

package com.example.Controller;
//import statements goes here
@RestController
public class UserController {
   
    //List all the available projects
    @GetMapping(path = "/projects", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<List<Project>> getProjects() {
     
    // perform validation checks
    // return the services provided by service layer
    }
    //Apply for the project
    @PostMapping(path = "/apply-project", consumes = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<HttpStatus> applyProject(@RequestBody Map<String,String> json) {
    // perform validation checks
    // return the services provided by service layer
    }
    
    //Upload resume
    @PostMapping(path = "/upload-resume/{usn}")
    public ResponseEntity<List<Object>> uploadToDB(@RequestParam("file") MultipartFile[] file,@PathVariable String usn) {
    
    // perform validation checks
    // return the services provided by service layer
    }
    //Download resume
    @GetMapping("/files/download/{fileName:.+}")
    public ResponseEntity downloadFromDB(@PathVariable String fileName) {
    // perform validation checks
    // return the services provided by service layer
    }
}

上面例子使用了@GetMapping和@PostMapping:

@GetMapping註解用於將一個方法映射到指定的HTTP GET請求。它可以用於處理瀏覽器直接訪問某個URL或者其他應用程序發起GET請求的情況。通過在方法上添加@GetMapping,我們可以定義一個處理該請求的方法,並在方法中編寫相應的業務邏輯。

@PostMapping註解用於將一個方法映射到指定的HTTP POST請求。它可以用於處理表單提交、客戶端數據上傳等操作。通過在方法上添加@PostMapping,我們可以定義一個處理該請求的方法,並在方法中編寫相應的業務邏輯。

2.Service層:

下面這段定義了項目相關的服務方法,並規定這些方法的輸入參數和返回值。

在代碼示例中,ProjectService 接口聲明瞭三個方法:

  1. getProjects() 方法返回一個 List<Project> 對象作爲響應體(ResponseEntity),用於獲取所有項目信息。
  2. applyProject(String USN,int project_id) 方法返回 HttpStatus 枚舉值,表示申請參與某個項目的狀態。
  3. uploadProjectDocument(MultipartFile[] files,int project_id) 方法返回 List<Object> 對象作爲響應體,用於上傳項目文檔。

ProjectService.java

package com.example.Service;

// import statements

public interface ProjectService {

    ResponseEntity<List<Project>> getProjects();

    HttpStatus applyProject(String USN,int project_id);

    ResponseEntity<List<Object>> uploadProjectDocument(MultipartFile[] files,int project_id);

}

ProjectServiceImpl.java

package com.example.Service;

//import statements
@Service
public class ProjectServiceImpl implements ProjectService {
//dependency injection of DAO to be gone here (Autowire)
  
    @Override
    public ResponseEntity<List<Project>> getProjects() {
        try {
           //Business logic implementation using DAO services
        } catch (Exception e) {
            return new ResponseEntity<>(null,HttpStatus.INTERNAL_SERVER_ERROR) ;
        }
    }
   
    @Override
    public HttpStatus applyProject(String USN, int project_id) {
   
    //Business logic implementation using DAO services
    }
  
   //helper functions
    public ResponseEntity uploadToLocalFileSystem(MultipartFile file,int project_id) {
     
    }
    @Override
    public ResponseEntity<List<Object>> uploadProjectDocument(MultipartFile[] files,int project_id) {
       //Business logic implementation using DAO services
    }

}

3.Repository/DAO層:

下面的這段代碼是一個接口類,屬於包名爲"com.example.Dao"的項目數據訪問對象(DAO)。它擴展了 JpaRepository<Project, Integer> 接口,該接口提供了基本的CRUD(創建、讀取、更新、刪除)操作方法,用於對數據庫中的 "Project" 實體進行操作。

ProjectDAO.java

package com.example.Dao;

//import statements

public interface ProjectDao extends JpaRepository<Project,Integer> {

//You can also include native queries on top of CRUD operations provided by JPA
// Add queries here using @Query annotations and corresponding functions

    @Query(value = "Your SQL query ",nativeQuery = true)
    public List<Project> getProjects();

}

}

4.Model層:

下面這段代碼定義了一個名爲 "Project" 的實體類,表示一個項目。它包含了項目的各個屬性(如項目ID、公司名稱、描述、要求等),並與其他實體類(如員工、學生、文檔、資金等)之間建立了關聯關係。通過使用 JPA 註解,該類可以方便地進行數據庫操作和查詢。

代碼中的各個部分的含義如下:

  1. @Entity 註解表示該類是一個實體類,與數據庫中的表進行映射。
  2. @Table(name = "project") 註解指定了對應的數據庫表名爲 "project"。
  3. @Id 註解表示該字段是主鍵。
  4. @GeneratedValue(strategy = GenerationType.IDENTITY) 註解指定了主鍵的生成策略爲自增長。
  5. @Column 註解用於指定該屬性與數據庫表中的列的映射關係,其中 nullable 屬性表示該列是否允許爲空,name 屬性指定了對應的數據庫列名。
  6. @JsonIgnore 註解用於忽略該屬性在序列化和反序列化過程中的處理。
  7. @ManyToMany(mappedBy="funded_projects") 註解表示當前實體與另一個實體 Fund 之間存在多對多的關聯關係,通過 mappedBy 屬性指定了在 Fund 實體中維護關聯關係的屬性名爲 "funded_projects"。
  8. Set<Staff>, Set<Student>, Set<Document>, Set<Fund> 表示與其他實體之間的關聯關係,通過集合類型的屬性來表示多對多關係或一對多關係。

Project.java

package com.example.Entity;

//import statements

@Entity
@Table(name = "project")
public class Project {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int project_id;
    @Column(nullable = false, name = "company_name")
    private String company_name;

    @Column(nullable = false, name = "description")
    private String description;

    @Column(nullable = false, name = "requirements")
    private String requirements;

    @Column(nullable = false, name = "manager")
    private String manager;
    @Column(nullable = false, name = "start_date")
    private Date start_date = new Date();

    @Column( name = "end_date")
    private Date end_date = new Date();
    @Column(nullable = false,name = "opening")
    private int opening;
    @Column(name = "resources")
    private String resources;
    public Set<Staff> getStaff_incharge() {
        return staff_incharge;
    }
    public void setStaff_incharge(Set<Staff> staff_incharge) {
        this.staff_incharge = staff_incharge;
    }
    public Set<Student> getApplied_students() {
        return applied_students;
    }
    public Set<Document> getDocuments() {
        return documents;
    }
    public void setDocuments(Set<Document> documents) {
        this.documents = documents;
    }
    @JsonIgnore
    @ManyToMany(mappedBy="funded_projects")
    private Set<Fund> funds;
    public Set<Fund> getFunds() {
        return funds;
    }
    public void setFunds(Set<Fund> funds) {
        this.funds = funds;
    }
    public void setApplied_students(Set<Student> applied_students) {
        this.applied_students = applied_students;
    }
    public Set<Student> getWorking_students() {
        return working_students;
    }
    public void setWorking_students(Set<Student> working_students) {
        this.working_students = working_students;
    }
//constructors
    public Project() {
        super();
    }
    public Project(int project_id, String company_name, String description, String requirements, String manager, Date start_date, Date end_date, int opening, String resources) {
        super();
        this.project_id = project_id;
        this.company_name = company_name;
        this.description = description;
        this.requirements = requirements;
        this.manager = manager;
        this.start_date = start_date;
        this.end_date = end_date;
        this.opening = opening;
        this.resources = resources;
    }
    public int getProject_id() {
        return project_id;
    }
    public void setProject_id(int project_id) {
        this.project_id = project_id;
    }
    public String getCompany_name() {
        return company_name;
    }
    public void setCompany_name(String company_name) {
        this.company_name = company_name;
    }

    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getRequirements() {
        return requirements;
    }
    public void setRequirements(String requirements) {
        this.requirements = requirements;
    }
    public String getManager() {
        return manager;
    }
    public void setManager(String manager) {
        this.manager = manager;
    }
    public Date getStart_date() {
        return start_date;
    }
    public void setStart_date(Date start_date) {
        this.start_date = start_date;
    }
    public Date getEnd_date() {
        return end_date;
    }
    public void setEnd_date(Date end_date) {
        this.end_date = end_date;
    }
    public int getOpening() {
        return opening;
    }
    public void setOpening(int opening) {
        this.opening = opening;
    }
    public String getResources() {
        return resources;
    }
    public void setResources(String resources) {
        this.resources = resources;
    }
    @Override
    public String toString() {
        return "Project{" +
                "project_id=" + project_id +
                ", company_name='" + company_name + '\'' +
                ", description='" + description + '\'' +
                ", requirements='" + requirements + '\'' +
                ", manager='" + manager + '\'' +
                ", start_date=" + start_date +
                ", end_date=" + end_date +
                ", opening=" + opening +
                ", resources='" + resources + '\'' +
                '}';
    }
}

總結

本文爲讀者詳細介紹了Spring Boot框架的四層構架,以及如何使用各種技術和工具來進行開發。通過閱讀本文,希望可以幫助讀者可以更好地理解Spring Boot框架的工作原理和應用場景,並能夠利用所學知識來實現自己的項目。

參考資料:《Understanding Spring Boot Architecture》

擴展鏈接:

Redis從入門到實踐

一節課帶你搞懂數據庫事務!

Chrome開發者工具使用教程

從表單驅動到模型驅動,解讀低代碼開發平臺的發展趨勢

低代碼開發平臺是什麼?

基於分支的版本管理,幫助低代碼從項目交付走向定製化產品開發

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章