Spring Boot工程结构
.
├── pom.xml # Maven构建脚本或build.gradle(Gradle项目)
├── README.md # 项目说明文档
├── src
│ ├── main
│ │ ├── java # 主要Java源代码
│ │ │ └── com.example.springbootapp
│ │ │ ├── Application.java # Spring Boot应用主类,包含@SpringBootApplication注解
│ │ │ ├── config # 配置相关的类和包
│ │ │ ├── controller # 控制器层,处理HTTP请求和响应
│ │ │ ├── service # 服务层,封装业务逻辑
│ │ │ ├── repository # 数据访问层,处理持久化操作
│ │ │ └── model # 实体模型类
│ │ └── resources
│ │ ├── application.properties # 应用配置文件
│ │ ├── application.yml # YAML格式的配置文件(可选)
│ │ ├── static # 静态资源文件夹,如CSS, JS, 图片等
│ │ │ ├── css
│ │ │ ├── js
│ │ │ └── images
│ │ ├── templates # Thymeleaf、FreeMarker等模板引擎的HTML视图文件
│ │ └── META-INF # 可能包含额外的配置如JPA实体映射文件
│ ├── test
│ │ ├── java # 测试源代码
│ │ │ └── com.example.springbootapp
│ │ │ ├── integrationtest # 集成测试类
│ │ │ ├── unitest # 单元测试类
│ │ │ └── ApplicationTest.java # 基础测试类,用于启动Spring Boot测试环境
│ │ └── resources # 测试资源文件夹
│ └── ...
└── target # 编译后输出目录(Maven项目)
└── classes # 包含编译后的.class文件以及资源文件
此工程结构只是通用的展示方式,实际上的工程目录结构可以根据实际项目调整,并不是一蹴而就。
项目结构概述
构建配置文件
pom.xml
或build.gradle
:这是项目的构建定义文件,对于Maven项目使用pom.xml
,而Gradle项目则使用build.gradle
。这些文件中定义了项目的依赖关系、构建过程、插件配置以及其他元数据信息。
源代码目录
src/main/java
:此目录存放项目的Java源代码。根据分层架构原则组织,通常包括以下几个层次:- 控制器层(Controller):处理HTTP请求。
- 服务层(Service):实现业务逻辑。
- 数据访问层(Repository):负责与数据库交互。
- 领域模型层(Model):定义实体类和其他核心对象。
此外,Application.java
是Spring Boot应用程序的入口点,它包含@SpringBootApplication
注解,用于标记主配置类,并启用自动配置特性。
资源文件目录
src/main/resources
:该目录包含了非Java代码资源,如配置文件、静态资源和模板文件等。application.properties
或application.yml
:定义应用程序的基础配置参数,例如服务器端口、数据库连接设置、日志级别等。static
目录:放置静态资源文件(如CSS、JavaScript、图片等),这些资源在应用部署后可以通过URL直接访问。templates
目录:如果项目使用模板引擎(如Thymeleaf或FreeMarker),则在此目录下放置HTML模板文件,用于渲染动态网页内容。META-INF
目录:可以包含JPA实体映射文件或其他框架所需的特定配置文件。
测试代码目录
src/test/java
:用于编写单元测试和集成测试代码,以确保项目的各个模块功能正常,保证代码质量和稳定性。
编译输出目录(仅限Maven)
target
(Maven项目特有):这是编译后的输出目录,包含了打包后的.jar
或.war
文件,以及编译生成的.class
文件等。
@SpringBootApplication的作用
package com.cokerlk.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 类声明与注解:这里定义了一个公共类
DemoApplication
,并用@SpringBootApplication
注解标记。这个注解实际上包含以下三个注解的功能:@Configuration
:将类标记为配置类,允许使用Java代码替代传统的XML配置文件来定义Bean。@EnableAutoConfiguration
:启用Spring Boot的自动配置机制,根据类路径中的依赖关系自动配置Spring应用程序。@ComponentScan
:自动扫描并注册带有@Component等注解的类为Spring Bean,通常会从当前包及其子包开始扫描。
当您运行这个应用程序时,Spring Boot会自动处理大量的配置工作,使得开发者可以专注于业务逻辑的实现。对于初学者来说,这是一个很好的起点,因为它展示了如何快速搭建一个功能齐全的Spring Boot应用,而不需要编写大量的配置代码。
前后端分离
前后端分离架构是现代Web应用开发中的一个关键设计模式,它通过明确划分前端与后端在开发流程和运行时的角色,减少了两者之间的直接依赖,从而提升了开发效率、系统可维护性和灵活性。以下是该架构的核心特点和工作原理:
角色与责任分离:
-
- 前端(客户端):专注于用户界面的创建与交互逻辑的实现。使用HTML、CSS、JavaScript以及如React、Vue.js或Angular等现代化框架构建动态且响应式的用户界面。前端负责向后端发起数据请求,并根据返回的数据更新视图。
- 后端(服务器端):集中处理业务逻辑、数据管理和安全控制。它可能基于Java、Python、Node.js等多种编程语言和技术栈,提供RESTful API或GraphQL等标准化接口来交换结构化数据(如JSON或XML),支持前端的各种需求。
- 标准化接口:后端定义了一组清晰、稳定的API供前端调用,确保了数据传输格式的一致性和操作方法的规范性(例如HTTP方法GET用于获取资源)。这种做法不仅简化了前端与后端之间的通信,也为后续维护和扩展打下了良好基础。
- 开发过程解耦:前后端团队可以在了解彼此提供的API基础上独立进行开发和测试,各自专注于自己的领域。前端可以利用模拟数据来进行UI/UX的设计和优化,而后端则可以深入打磨业务规则和服务性能。这大大加快了项目的整体进度。
- 灵活部署选项:得益于职责分离,前端和后端可以分别部署到最适合它们运行的环境中。比如,前端静态资源可以托管在全球分布式的CDN网络中以加速访问;而复杂的后端服务可以根据实际需要轻松实现水平或垂直扩展。
- 多平台兼容性:由于前后端之间采用开放的标准协议进行通信,因此同一个后端API能够被不同类型的前端消费,包括但不限于传统的Web浏览器、移动应用程序、物联网设备等,增强了系统的适应性和复用性。
- 支持先进的架构模式:前后端分离架构天然地适合于微服务架构、分布式计算环境以及云原生部署场景。它为实现更细粒度的服务拆分、自动化运维管理、弹性伸缩提供了便利条件,有助于打造高性能、高可用的企业级解决方案。
Restful API简介
RESTful API(Representational State Transfer API)是一种遵循REST架构风格设计的Web服务接口。REST本身不是一种技术或标准,而是一套关于如何设计网络应用和服务的理念和指导原则,它提倡使用HTTP协议的标准方法来实现对资源的操作,并通过URL(统一资源定位符)来标识这些资源。
以下是RESTful API的一些核心特性:
- 无状态性:每个请求都必须包含理解该请求所需的所有信息,服务器不会保存客户端的状态。这意味着每个请求都是独立的,服务器端不需要依赖于之前的交互历史来处理当前请求。
- 资源导向:在REST中,所有东西都被视为“资源”,并且每个资源都有一个唯一的URI(Uniform Resource Identifier)。资源可以是文档、图片、视频、用户信息等任何事物。API操作围绕着资源展开,例如创建新资源、获取现有资源的信息、更新资源或删除资源。
- 统一接口:RESTful API通常采用HTTP动词(如GET、POST、PUT、DELETE等)来表示不同的操作:
GET
用于读取资源。POST
一般用来创建新的资源。PUT
可以用来更新整个资源或者创建指定ID的资源。DELETE
用来删除资源。PATCH
用来部分更新资源。
- 自描述消息:每个请求都应该携带足够的信息,使得接收方能够理解并正确处理它。这包括内容类型(比如JSON或XML)、认证信息以及其他必要的元数据。
- 分层系统:REST允许构建分层的服务器结构,意味着客户机可能不知道它是在与源服务器还是中间代理通信。这种设计提高了系统的可扩展性和安全性。
- 按需代码(可选):服务器可以通过响应向客户端发送可执行代码,比如JavaScript脚本,但这不是REST的核心特性,在实际应用中较少使用。
- 缓存机制:REST鼓励利用HTTP的缓存功能,以减少网络流量和提高响应速度。某些类型的GET请求结果是可以被缓存的,从而减少了重复查询相同数据的需求。
- 安全性和身份验证:尽管REST本身不规定具体的安全措施,但RESTful API通常会结合OAuth、JWT(JSON Web Token)等方式来进行用户认证和授权管理。
- 版本控制:为了确保向前兼容性和稳定性,RESTful API常常会引入版本号,以便在不影响旧版客户端的情况下发布新功能。
关于Restful怎么使用,就不在这里赘述了,网上有很多资料可以参考,如果对这块特别有兴趣,可以留言我们单独写一章接来聊聊Restful API
下面把常用的Restful做了一个简单的示例,业务中的code我通常用8位数表示00 000 000,前面两位表示系统,中间3位表示子服务,后面3位表示对应服务的接口
package com.cokerlk.demo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cokerlk.demo.model.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/v1")
public class SampleController {
@GetMapping(path = "/users")
public ResponseEntity<Map<String,Object>> findUser(Integer rows){
Map<String,Object> result = new HashMap<>();
result.put("code", 10100000);
result.put("message", "success");
List<User> users = new ArrayList<>();
for(int i = 0 ; i < rows ; i++){
users.add(new User("u" + i, "p" + i));
}
result.put("data", users);
return new ResponseEntity<>(result, HttpStatus.OK);
}
@PostMapping(path = "/users")
public Map<String,Object> createUser(User user){
Map<String,Object> result = new HashMap<>();
result.put("code", 10100000);
result.put("message", "success");
result.put("data", user);
return result;
}
@PutMapping(path = "/users/{uid}")
public Map updateUser(@PathVariable("uid") String uid ,User user){
Map<String,Object> result = new HashMap<>();
result.put("code", 10100000);
result.put("message", "success");
result.put("data", user);
return result;
}
@DeleteMapping(path = "/users/{uid}")
public Map deleteUser(@PathVariable("uid") String uid){
Map<String,Object> result = new HashMap<>();
result.put("code", 10100000);
result.put("message", "success");
return result;
}
@GetMapping("/header")
public Map getHeader(@RequestHeader("token") String accessToken){
Map<String,Object> result = new HashMap<>();
result.put("code", 10100000);
result.put("message", "success");
result.put("data", accessToken);
return result;
}
@PostMapping("/body")
public Map getBody(@RequestBody User user){
Map<String,Object> result = new HashMap<>();
result.put("code", 10100000);
result.put("message", "success");
result.put("data", user);
return result;
}
}