当前位置: 首页 > news >正文

Day5学习--SpringBoot详解

Day5学习–SpringBoot详解

SpringBoot的核心作用

Spring Boot 是基于 Spring 框架的“快速开发脚手架”,它的核心设计理念是**“约定优于配置”**。它并不是用来替代 Spring 的,而是为了解决传统 Spring 开发中存在的痛点:

  • 告别繁琐配置:摒弃了传统 Spring 大量的 XML 配置,通过自动化配置和默认约定,实现零配置或极简配置即可启动项目。
  • 开箱即用:内置了 Tomcat、Jetty 等 Web 服务器,项目可以直接打包成 Jar 包运行,无需再单独部署到外部服务器。
  • 简化依赖管理:提供了一系列“起步依赖(Starter)”,将常用技术栈的依赖整合在一起,自动解决版本冲突问题。

自动配置原理

Spring Boot 能够实现“开箱即用”的核心在于自动配置(Auto-Configuration)。其核心入口是项目启动类上的@SpringBootApplication注解。

@SpringBootApplication是一个组合注解,主要包含以下三个核心部分:

  • @SpringBootConfiguration:标识当前类是一个配置类。
  • @ComponentScan:自动扫描并注册当前启动类所在包及其子包下的 Bean。
  • @EnableAutoConfiguration:开启自动配置的灵魂。

底层加载逻辑:
@EnableAutoConfiguration底层通过@Import导入了AutoConfigurationImportSelector类。

  • 在 Spring Boot 2.x 中,它会读取META-INF/spring.factories文件。
  • 在 Spring Boot 3.x 中,改为读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件。

加载到全量自动配置类后,Spring Boot 会通过@Conditional系列条件注解(如@ConditionalOnClass@ConditionalOnMissingBean)进行过滤。只有当类路径下存在特定的类(例如引入了 Web 依赖)且容器中不存在该 Bean 时,对应的默认配置才会生效,最终将组件实例注册到 Spring 容器中。

快速创建项目与依赖引入

目前创建 Spring Boot 项目最主流的方式是使用Spring Initializr(可以通过 IDEA 内置或官网 https://start.spring.io/ 访问)。它能自动生成符合规范的项目结构和pom.xml文件。

Spring Boot 通过Starter(起步依赖)把常用依赖封装为一个坐标,避免了手动管理版本冲突。例如,引入spring-boot-starter-web就能自动集成 Tomcat、Spring MVC 和 JSON 转换器。

pom.xml文件示例

<!-- 继承 Spring Boot 父工程,利用其版本仲裁机制 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.5</version></parent><dependencies><!-- 引入 Web 起步依赖,开箱即用 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

YML配置文件与端口配置

企业级开发中,更推荐使用.yml格式代替传统的.properties文件。YML 采用树形层级结构,可读性更强,且支持复杂的数据结构。

修改默认端口:
Spring Boot 内置的 Tomcat 默认端口是 8080。如果发生端口占用,可以直接在配置文件中修改。

application.yml示例

server:port:8081# 修改默认启动端口为 8081servlet:context-path:/api# 配置项目的访问路径前缀

日志配置(Logging)

Spring Boot 默认使用SLF4J作为日志门面,Logback作为底层实现。默认的日志级别是INFO,这意味着只会打印INFOWARNERROR级别的日志。

日志级别从低到高依次为:
TRACE<DEBUG<INFO<WARN<ERROR

在开发阶段,为了排查问题,我们通常需要开启DEBUG级别的日志。

logging:level:root:INFO# 全局日志级别com.arguan:DEBUG# 将我们自己的项目包路径设置为 DEBUG 级别

自定义参数配置与读取

除了框架自带的配置,我们经常需要在配置文件中定义一些业务参数(如第三方接口的密钥、系统名称等)。

# 自定义业务参数my-app:name:"SpringBoot-Testing"version:"1.0.0"max-retry:3

在 Java 代码中读取自定义参数:
可以使用@Value注解将配置文件中的值注入到属性中。

@RestController@RequestMapping("/test")publicclassConfigController{// 读取自定义配置@Value("${my-app.name}")privateStringappName;@Value("${my-app.max-retry:5}")// 如果配置文件中没有,默认值为 5privateIntegermaxRetry;@GetMapping("/info")publicStringgetConfig(){return"应用名称:"+appName+",最大重试次数:"+maxRetry;}}

项目分层架构(MVC思想)

在企业级开发中,为了保证代码的高内聚、低耦合以及良好的可维护性,通常采用经典的四层架构。每一层都有其明确的职责,严禁跨层调用。

  • Entity(实体层)
    也称为 POJO 或 Domain 层。它的作用是映射数据库中的表结构,一个实体类对应一张数据表。通常只包含属性、Getter/Setter 方法,不包含任何业务逻辑。
  • Mapper(持久层)
    也称为 DAO(Data Access Object)层。它的作用是直接与数据库交互,负责数据的增删改查(CRUD)。在 Spring Boot 中,通常使用 MyBatis 或 JPA 来实现。
  • Service(业务层)
    系统的“大脑”,负责处理核心业务逻辑(如参数校验、事务控制、复杂计算等)。Controller 层接收请求后,会调用 Service 层来处理具体业务,Service 层再调用 Mapper 层操作数据库。
  • Controller(控制层)
    系统的“门面”,负责接收前端发来的 HTTP 请求,解析参数,调用 Service 层获取结果,并最终将响应数据返回给前端。

请求接收与参数绑定

Spring Boot 提供了非常便捷的注解来接收前端传递的不同类型的参数。以下是开发中最常用的三种参数绑定方式:

  • @PathVariable(路径参数)

    用于接收 URL 路径中的参数,常用于 RESTful 风格的接口,比如根据 ID 查询或删除某个资源。

    • 示例GET /users/101,接收 ID101
  • @RequestParam(查询参数)
    用于接收 URL 问号?后面的键值对参数(如?name=张三&age=18)。常用于分页查询、条件搜索等简单参数的传递。

  • @RequestBody(JSON 对象参数)
    用于接收前端请求体(Request Body)中的 JSON 格式数据。常用于新增(POST)或修改(PUT)操作,可以将复杂的 JSON 对象直接映射为后端的 Java 实体对象。

本人在自学网课过程中,开发了一个智能学习辅助系统,所以我将使用系统中实现过的代码来演示三种请求接收参数

删除部门–使用@RequestParam注解

  • 在系统中,比如要对一个部门进行部门管理,其中有一个功能是删除部门,那么访问数据库时的语句就需要根据部门的ID进行删除,这时候我们就需要接收ID这个参数。
/** * 删除部门 使用@RequestParam注解 * 注意事项:一旦声明了@RequestParam注解,该参数在请求时必须传递,如果不传递将会报错 * @param id * @return */@DeleteMapping("/depts")publicResultdelete(@RequestParam("id")Integerid){System.out.println("根据ID删除部门:"+id);returnResult.success();}

获取部门信息–使用@PathVariable注解

  • 如果想在一个部门列表中针对某一个部门去获取他的信息时,我们也需要去获取他的ID从而到数据库中进行查询返回所需的部门信息,我们可以使用路径参数来获取。
/** * 获取部门信息 * @param id * @return */@GetMapping("/{id}")publicResultget(@PathVariableIntegerid){System.out.println("查询部门ID:"+id);Deptdept=deptService.findById(id);returnResult.success(dept);}

添加部门–使用@RequestBody注解

  • 需要添加部门时,系统需要接收一个部门的所有信息,这时候我们可以接受一个部门类的请求体,使用JSON格式封装数据,它会自动映射成后端在实体类中所定义的部门类的对象,实现参数接收。
/** * 添加部门 * @param dept * @return */@PostMappingpublicResultadd(@RequestBodyDeptdept){System.out.println("添加部门:"+dept.getName());deptService.addDept(dept);returnResult.success();}

响应返回与统一结果封装

  • 在前后端分离的开发模式下,为了降低前端的解析成本,后端所有接口必须返回统一的数据格式。通常我们会封装一个泛型类Result<T>,包含状态码(code)、提示信息(msg)和业务数据(data)。
publicclassResult<T>{privateIntegercode;// 状态码(200表示成功,500表示失败)privateStringmsg;// 提示信息privateTdata;// 业务数据(泛型,可适应任意类型)// 省略构造方法、Getter 和 Setter// 成功响应publicstatic<T>Result<T>success(Tdata){returnnewResult<>(200,"操作成功",data);}// 失败响应publicstatic<T>Result<T>error(Stringmsg){returnnewResult<>(500,msg,null);}}

简单接口开发实战(新增与查询)

  • 结合上述的分层架构,参数绑定和统一相应格式,我实现了一个简单的接口开发代码

Entity层(用户实体类)

publicclassUser{privateLongid;privateStringusername;privateIntegerage;// 省略 Getter 和 Setter}

Mapper 层(模拟数据库操作)

@MapperpublicinterfaceUserMapper{// 模拟插入用户intinsert(Useruser);// 模拟根据ID查询用户UserselectById(Longid);}

Service 层(处理业务逻辑)

@ServicepublicclassUserService{@AutowiredprivateUserMapperuserMapper;publicUsersaveUser(Useruser){// todo... 业务逻辑,比如校验用户名是否重复userMapper.insert(user);returnuser;}publicUsergetUserById(Longid){returnuserMapper.selectById(id);}}

Controller 层(对外暴露接口)

@RestController@RequestMapping("/api/users")publicclassUserController{@AutowiredprivateUserServiceuserService;// 接口1:新增用户(使用 @RequestBody 接收 JSON 参数)@PostMapping("/add")publicResult<User>addUser(@RequestBodyUseruser){UsersavedUser=userService.saveUser(user);returnResult.success(savedUser);}// 接口2:查询用户(使用 @PathVariable 接收路径参数)@GetMapping("/{id}")publicResult<User>getUser(@PathVariableLongid){Useruser=userService.getUserById(id);if(user!=null){returnResult.success(user);}returnResult.error("用户不存在");}// 接口3:返回统一结果测试(无参接口)@GetMapping("/hello")publicResult<String>sayHello(){returnResult.success("你好,高冠林!");}}

学习中的问题

  • 依赖冲突:在引入第三方依赖时,如果遇到版本冲突,可以利用 Maven 的依赖树(mvn dependency:tree)查看冲突情况,并使用<exclusion>标签排除不需要的依赖版本。Spring Boot 的父工程(Parent)已经帮我们管理了绝大多数常用依赖的版本,尽量优先使用 Starter。
  • 端口占用:启动项目时如果报错Port 8080 was already in use,说明 8080 端口被其他程序(或上一次未正常关闭的项目)占用。最快的解决方法是在application.yml中修改server.port: 8081,或者在命令行中查出占用端口的进程 PID 并将其强制结束。
http://www.cnnetsun.cn/news/2532392.html

相关文章:

  • 基因组规模代谢网络模型方法在工业生物技术中的应用【附程序】
  • 融合低压电力线信道时变性的量测设备静动态组网检测识别方法【附数据】
  • 谷歌收录排名怎么做比较好?每天花10分钟,收录率轻松提升80%
  • Java Lambda表达式超详细入门教程(作用、定义、函数式接口、内置接口、方法引用实战)
  • Amphenol ICC线束DRPC215003940应用解析与替代思路
  • 为什么你的AI搜索总不准?2026年5款高精度免费工具底层架构拆解:向量引擎、重排序模块与Query理解差异全曝光
  • 00 Linux环境下ARM裸机开发工程的建立示例(Cortex-A8)
  • 车载多模态Agent训练难题:1TB真实行车语料清洗指南,含ISO 21448 SOTIF合规标注模板
  • 【2024全球AI Agent商用成熟度报告】:覆盖17国、42个垂直行业、312个真实案例——你的行业处于L2还是L4?
  • 工程机械全场景一体化管理产品(打卡、积分、工时、保养、安全、薪资、年假与请假一体化)
  • Taotoken 的模型广场功能如何帮助开发者快速进行模型选型与切换
  • 跟着 MDN 学CSS day_9:(深入掌握CSS选择器核心技能测试)
  • Kafka集群重启后报错找不到meta.properties?别慌,这可能是你的/tmp目录在搞鬼
  • 【Elasticsearch从入门到精通】第15篇:Elasticsearch删除与更新API——精确操作与脚本更新
  • Taotoken多模型路由在单一服务故障时的体验保障
  • 5分钟快速上手:在电脑上免费畅玩Switch游戏的终极指南
  • 别再只调PID了!用声学定位给你的智能小车/机器人装上‘耳朵’(开源代码分享)
  • 三分钟上手:iCloud+匿名邮箱批量生成终极指南
  • SVGnest终极指南:如何免费优化材料切割布局,减少90%浪费
  • Fast-GitHub:终极免费解决方案,让GitHub访问速度提升100倍
  • 从微服务架构师视角:用Docker+Seata+Nacos搞掂分布式事务,你的配置真的安全吗?
  • 从STM32迁移到智芯车规MCU:我的开发环境踩坑与快速配置指南
  • 飞书文档导出工具:3步实现知识库批量迁移与备份
  • 解锁高效答辩新方式,okbiye AI 赋能一键打造优质毕业汇报文稿
  • AutoUnipus:终极U校园自动化答题解决方案,五分钟实现100%正确率
  • AI工程化落地的三大瓶颈与实战破局路径
  • XB1ControllerBatteryIndicator终极指南:5分钟解决Xbox手柄电量焦虑
  • 2026论文隐藏级降AIGC网站大曝光:一键压到安全线谁最稳
  • 谷歌外链怎么发:新手必看的3种免费高权重发帖渠道
  • 别再死记硬背了!用Multisim仿真软件,5分钟搞懂三极管放大电路的静态工作点设置与失真分析