为了账号安全,请及时绑定邮箱和手机立即绑定

Springboot单体架构搭建学习:从入门到实践

标签:
SpringBoot

本文将指导你学习如何使用Spring Boot搭建单体架构,从快速搭建第一个Spring Boot项目开始,详细介绍如何构建基本的Spring Boot项目、实现服务拆分与管理,并最终部署到服务器。Spring Boot单体架构搭建学习涵盖了从基础到高级的各个方面,帮助开发者快速掌握这一技能,让你能够快速构建并部署稳定可靠的单体应用。

Spring Boot简介

什么是Spring Boot

Spring Boot 是Spring框架的一个子项目,旨在简化Spring应用的初始搭建及开发过程。它通过约定优于配置的方式,帮助开发者快速搭建Spring应用。Spring Boot的核心目标是简化Spring应用的开发,并且提供一套完整的默认配置,使得开发人员可以快速上手,专注于业务逻辑。

Spring Boot通过提供一系列默认配置,使得开发人员能够快速地创建独立的、生产级别的基于Spring的应用程序,无需大量的XML配置。它还支持嵌入式的Web服务器(如Tomcat、Jetty),可以将应用打包为单一的可执行的jar或者war文件,简化部署过程。

Spring Boot的优势和应用场景

优势

  1. 快速启动:通过默认配置,开发者可以快速启动并运行应用,减少配置时间。
  2. 无XML配置:尽可能地减少XML配置文件的使用,采用约定优于配置的模式,使得配置更加简洁。
  3. 自动配置:Spring Boot可以通过自动配置来减少配置文件的工作量,使得开发人员专注于业务逻辑。
  4. 嵌入式Web服务器:内置了Tomcat、Jetty等Web服务器,可以将应用打包为可执行的jar或war文件,简化部署过程。
  5. 模块化开发:提供各种starter依赖,使得开发人员可以快速地引入需要的功能模块,加快开发速度。
  6. 监控与日志管理:提供了Actuator(监控)和Logback(日志)等模块,便于监控应用状态和管理日志。
  7. 外部化配置:支持从外部属性文件或环境变量加载配置,提高应用的灵活性和可维护性。

应用场景

Spring Boot适用于各种类型的Java应用开发,特别是以下场景:

  1. Web应用:快速开发基于Web的应用,可以是RESTful服务、静态页面展示等。
  2. 微服务应用:虽然Spring Boot可以用于微服务,但更常见的是作为单体应用的基础架构,提供稳定可靠的服务。
  3. 独立应用:可以将应用打包为可执行的jar文件,独立启动运行,无需外部依赖。
  4. 快速原型开发:对于快速原型开发,Spring Boot提供了快速配置的功能,可以很快地搭建一个原型系统。
快速搭建第一个Spring Boot项目

创建Spring Boot项目

  1. 安装Spring Boot CLI:可以通过Maven或Gradle构建工具来安装Spring Boot CLI,或者使用IDE工具(如Spring Tool Suite、IntelliJ IDEA等)来创建Spring Boot项目。
  2. 使用Spring Boot CLI创建项目
    spring init --dependencies=web my-first-spring-boot-app
    cd my-first-spring-boot-app
    mvn spring-boot:run
  3. 使用IDE创建项目:使用Spring Initializr插件来创建一个新的Spring Boot项目,选择所需的依赖(如Web、Thymeleaf等),然后直接运行项目。

添加依赖和配置文件

  1. pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
  2. application.properties
    server.port=8080
    spring.application.name=my-first-spring-boot-app

项目结构

  • src/main/java:存放Java源代码,包括主类和业务逻辑类。
  • src/main/resources:存放资源文件,如配置文件、静态文件以及模板文件。
  • src/test/java:存放测试代码。
  • pom.xml:Maven构建文件,包含项目依赖和构建配置。

示例代码

主类(Application.java):

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

配置文件(application.properties):

server.port=8080
spring.application.name=my-first-spring-boot-app
构建基本的Spring Boot项目

创建项目

  1. 使用Spring Initializr创建项目:选择Web依赖,创建一个新的项目。
  2. 初始化项目
    • 创建一个新的Spring Boot项目,选择Web依赖。
    • 初始化项目后,运行项目以确保一切正常。

添加依赖和配置文件

  1. pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
  2. application.properties
    server.port=8080
    spring.application.name=my-basic-spring-boot-app

实现基本的RESTful服务

  1. 创建控制器

    package com.example.demo.controller;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HomeController {
    
        @GetMapping("/")
        public String home() {
            return "Hello, World!";
        }
    
    }
  2. 测试服务:启动应用后,访问http://localhost:8080/,应显示“Hello, World!”。
单体架构概述

什么是单体架构

单体架构(Monolithic Architecture)是一种传统的软件架构模式,将应用的所有功能模块(如用户管理、订单处理、产品展示等)都打包到一个单一的可执行文件中。在这种架构模式下,所有的业务逻辑都是紧密耦合在一起的,通常运行在同一个进程中,共享一个数据库。

单体架构的特点包括:

  1. 单一代码库:所有功能模块的代码集中在一个代码库中,易于管理和维护。
  2. 部署简单:整个应用作为一个整体部署,简化了部署流程。
  3. 易于监控:整个应用作为一个单独的进程运行,监控和调试相对简单。
  4. 灵活性较低:修改一处代码可能影响到其他模块,增加了开发的复杂性。

单体架构的优点与缺点

优点

  1. 开发简单:由于所有功能模块都在同一代码库中,开发简单直接。
  2. 部署方便:整个应用作为一个独立单元部署,简化了部署流程。
  3. 易于监控:单一进程运行,监控和调试相对简单。
  4. 易于调试:开发人员可以在同一个代码库中进行调试,不涉及复杂的模块间通信。

缺点

  1. 扩展性差:整个应用作为一个单一单元运行,扩展性差,不容易水平扩展。
  2. 维护成本高:代码紧密耦合,修改一处代码可能影响到其他模块。
  3. 部署复杂:当应用规模变大时,部署和升级变得更加复杂。
  4. 故障影响范围大:某个模块出现问题,可能导致整个应用不可用。
  5. 技术栈单一:使用单一的技术栈开发,限制了技术多样性。

单体架构适用场景

单体架构适用于以下场景:

  1. 小型应用:对于一些小型应用,单体架构可以快速搭建,开发和维护成本较低。
  2. 早期项目:对于初创项目或早期项目,单体架构可以帮助团队快速启动,减少复杂性。
  3. 单点服务:如果应用只需要提供有限的服务,单体架构可以很好地满足需求。
  4. 技术栈单一:如果团队熟悉单一的技术栈,可以高效地使用单体架构进行开发。
单体架构下的服务拆分与管理

实现基本的服务拆分

  1. 创建新的Java类

    package com.example.demo.service;
    
    public class ProductService {
    
        public String getProductDetails() {
            return "Product details";
        }
    
    }
  2. 注入服务到控制器

    package com.example.demo.controller;
    
    import com.example.demo.service.ProductService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HomeController {
    
        @Autowired
        private ProductService productService;
    
        @GetMapping("/products")
        public String products() {
            return productService.getProductDetails();
        }
    
    }

使用Spring Boot管理模块

  1. 创建新的Java类

    package com.example.demo.module;
    
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ModuleConfig {
    
        // 配置模块相关的bean
    
    }
  2. 注入模块配置到控制器

    package com.example.demo.controller;
    
    import com.example.demo.module.ModuleConfig;
    import com.example.demo.service.ProductService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HomeController {
    
        @Autowired
        private ModuleConfig moduleConfig;
    
        @Autowired
        private ProductService productService;
    
        @GetMapping("/products")
        public String products() {
            return productService.getProductDetails();
        }
    
    }

数据库设计与连接配置

  1. 设计数据库:根据应用需求设计数据库表结构。
  2. 配置数据库连接

    spring.datasource.url=jdbc:mysql://localhost:3306/mydb
    spring.datasource.username=root
    spring.datasource.password=root
    spring.jpa.hibernate.ddl-auto=update
  3. 使用JPA或MyBatis等持久化框架:使用Spring Data JPA或MyBatis等框架进行数据库操作。

  4. 创建实体类

    package com.example.demo.entity;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class Product {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        private String name;
    
        private double price;
    
        // getters and setters
    
    }
  5. 创建Repository接口

    package com.example.demo.repository;
    
    import com.example.demo.entity.Product;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface ProductRepository extends JpaRepository<Product, Long> {
    }
  6. 使用Repository接口

    package com.example.demo.service;
    
    import com.example.demo.entity.Product;
    import com.example.demo.repository.ProductRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class ProductService {
    
        @Autowired
        private ProductRepository productRepository;
    
        public List<Product> getAllProducts() {
            return productRepository.findAll();
        }
    
    }
单体架构的测试与部署

单元测试与集成测试

  1. 单元测试

    package com.example.demo.service;
    
    import com.example.demo.entity.Product;
    import com.example.demo.repository.ProductRepository;
    import org.junit.jupiter.api.Test;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.MockitoAnnotations;
    
    import static org.mockito.Mockito.when;
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    public class ProductServiceTest {
    
        @Mock
        private ProductRepository productRepository;
    
        @InjectMocks
        private ProductService productService;
    
        @Test
        public void testGetAllProducts() {
            MockitoAnnotations.initMocks(this);
    
            Product product1 = new Product();
            product1.setName("Product 1");
            product1.setPrice(10.0);
    
            Product product2 = new Product();
            product2.setName("Product 2");
            product2.setPrice(20.0);
    
            when(productRepository.findAll()).thenReturn(List.of(product1, product2));
    
            List<Product> products = productService.getAllProducts();
    
            assertEquals(2, products.size());
            assertEquals("Product 1", products.get(0).getName());
            assertEquals(10.0, products.get(0).getPrice());
        }
    
    }
  2. 集成测试

    package com.example.demo.controller;
    
    import com.example.demo.entity.Product;
    import com.example.demo.repository.ProductRepository;
    import com.example.demo.service.ProductService;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.junit.jupiter.MockitoExtension;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
    import org.springframework.boot.test.mock.mockito.MockBean;
    import org.springframework.test.context.junit.jupiter.SpringExtension;
    import org.springframework.test.web.servlet.MockMvc;
    
    import java.util.Arrays;
    
    import static org.mockito.Mockito.when;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
    
    @ExtendWith(SpringExtension.class)
    @WebMvcTest
    public class HomeControllerTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        @MockBean
        private ProductService productService;
    
        @Test
        public void shouldReturnProductList() throws Exception {
            Product product1 = new Product();
            product1.setName("Product 1");
            product1.setPrice(10.0);
    
            Product product2 = new Product();
            product2.setName("Product 2");
            product2.setPrice(20.0);
    
            when(productService.getAllProducts()).thenReturn(Arrays.asList(product1, product2));
    
            mockMvc.perform(get("/products"))
                    .andExpect(status().isOk())
                    .andExpect(content().string("[\"Product 1\", \"Product 2\"]"));
        }
    
    }

部署与运行Spring Boot应用

  1. 打包应用

    mvn clean package
  2. 运行jar包

    java -jar target/my-spring-boot-app.jar
  3. 部署到服务器
    scp target/my-spring-boot-app.jar user@server:/path/to/deploy/
    ssh user@server
    java -jar /path/to/deploy/my-spring-boot-app.jar

配置环境变量与日志管理

  1. 配置环境变量

    spring.profiles.active=dev
  2. application-dev.properties中定义环境变量值

    spring.datasource.url=jdbc:mysql://localhost:3306/db_dev
  3. 配置日志框架

    logging.level.root=INFO
    logging.file.path=/path/to/log
  4. 使用Spring Boot Actuator
    management.endpoints.web.exposure.include=*
    management.endpoint.health.show-details=always
实践案例:构建一个简单的单体应用

构建一个简单的电商应用

需求

构建一个简单的电商应用,包含用户注册、登录、商品浏览等功能。

构建项目

  1. 创建新的Spring Boot项目:选择Web依赖。
  2. 初始化项目
    • 创建新的Spring Boot项目,选择Web依赖。
    • 初始化项目后,运行项目以确保一切正常。

实现用户注册与登录功能

  1. 创建用户实体类

    package com.example.demo.entity;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class User {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        private String username;
    
        private String password;
    
        // getters and setters
    
    }
  2. 创建用户Repository接口

    package com.example.demo.repository;
    
    import com.example.demo.entity.User;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface UserRepository extends JpaRepository<User, Long> {
    }
  3. 创建用户Service类

    package com.example.demo.service;
    
    import com.example.demo.entity.User;
    import com.example.demo.repository.UserRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.Optional;
    
    @Service
    public class UserService {
    
        @Autowired
        private UserRepository userRepository;
    
        public Optional<User> findByUsername(String username) {
            return userRepository.findByUsername(username);
        }
    
        public User save(User user) {
            return userRepository.save(user);
        }
    
    }
  4. 创建用户Controller类

    package com.example.demo.controller;
    
    import com.example.demo.entity.User;
    import com.example.demo.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        @PostMapping("/users")
        public User registerUser(@RequestBody User user) {
            return userService.save(user);
        }
    
        @GetMapping("/users/{username}")
        public User getUser(@PathVariable String username) {
            return userService.findByUsername(username)
                    .orElseThrow(() -> new RuntimeException("User not found"));
        }
    
    }

实现商品浏览功能

  1. 创建商品实体类

    package com.example.demo.entity;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    @Entity
    public class Product {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        private String name;
    
        private double price;
    
        // getters and setters
    
    }
  2. 创建商品Repository接口

    package com.example.demo.repository;
    
    import com.example.demo.entity.Product;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface ProductRepository extends JpaRepository<Product, Long> {
    }
  3. 创建商品Service类

    package com.example.demo.service;
    
    import com.example.demo.entity.Product;
    import com.example.demo.repository.ProductRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    
    @Service
    public class ProductService {
    
        @Autowired
        private ProductRepository productRepository;
    
        public List<Product> getAllProducts() {
            return productRepository.findAll();
        }
    
    }
  4. 创建商品Controller类

    package com.example.demo.controller;
    
    import com.example.demo.entity.Product;
    import com.example.demo.service.ProductService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class ProductController {
    
        @Autowired
        private ProductService productService;
    
        @GetMapping("/products")
        public List<Product> getAllProducts() {
            return productService.getAllProducts();
        }
    
    }

部署到本地或云服务器

  1. 打包应用

    mvn clean package
  2. 运行jar包

    java -jar target/my-spring-boot-app.jar
  3. 部署到云服务器
    scp target/my-spring-boot-app.jar user@server:/path/to/deploy/
    ssh user@server
    java -jar /path/to/deploy/my-spring-boot-app.jar
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消