springboot单体项目的执行流程

首先就是启动springboot项目,即执行主函数,这个主函数的类通常带有SpingBootApplication注解,类中的main方法就是程序的入口。

启动主函数后,SpringBoot会按特定顺序加载配置文件,如application.properties或application.yml,这两种格式的文件都行,还能根据不同的环境加载不同的加载文件,如生产环境,测试环境等。配置文件里一般包含数据库连接的信息,服务端接口,日志级别等。

接着main函数中的run方法会创建一个Spring容器负责管理项目中的Bean,具体过程就是在调用SpingApplication.run方法时,会先创建一个SpringApplication实例,该实例会进行如下工作:

1.推断应用类型,判断时Web应用还是非Web应用。

2.查找并加载初始化器(ApplicationContextInitializer),这些初始化器可以在 ApplicationContext(应用上下文,是一个管理Spring应用中各种组件如Bean,配置信息,时间等的高级容器)刷新之前进行自定义配置。

3.查找并加载监听器,监听器会监听应用启动过程中的各种时间,如应用启动,上下文刷新等。

4.推断主应用类,即包含main方法的类

然后SpringApplition实例会根据应用类型创建相应的ApplicationContext实例。

接下来就是加载Bean定义,ApplicationContext会加载所有的Bean定义,这些Bean定义可以来自多个地方:

1.通过@ComponentScan扫描指定路径下的带有@Component,@Service,@Repository, @Controller等注解的类

2.@Configuration注解的配置类中使用@Bean注解定义的类

接着就是在Applicationtext刷新的过程中,会根据Bean定义创建Bean实例,并进行依赖注入和生命周期管理。Spring容器会确保Bean的单例性(默认情况下,也可以指定为多例),并处理Bean的初始化和销毁方法。

在Sping容器和Bean加载完成后,还会启动服务器,执行命令运行器和应用启动运行器(对实现了CommandLineRunner或ApplicationRunner接口的Bean在应用启动后执行一些初始化操作),最后发布应用启动完成事件。

讲完了springboot的启动后下面就是交互过程了。

客户端发起请求,这个请求是HTTP请求,它包括如下方法:

1.请求方法:常见的有GET(用于获取资源),POST(用于提交数据),PUT(用于更新资源),DELETE(用于更新资源),DELETE(用于删除资源)等

2.请求URL:指明要访问的资源地址

3.请求头:携带关于请求的额外信息,包含很多信息,如客户端类型,请求体的数据格式,请求发送的日期时间,身份验证(例如把token放到请求头中)等等

4.请求体:POST,PUT等方法可能会携带请求体,用于传递数据,数据格式可以是JSON,XML等

接着请求到达了SpringBoot应用所监听的端口,在请求到达之前,服务器一直在监听该端口,端口一般是8080。

嵌入式服务器接收到请求后,会进行如下操作:

1.将原始的HTTP请求封装成HttpServletRequest对象,该对象提供了一系列方法用于获取请求的各种信息,如请求方法,请求URL,请求头,请求体等。

2.同时创建一个HttpServletResponse响应对象,用于后续后端向前端返回消息

请求在到达DispatcherServlet之前,会经过一系列过滤器,过滤器可以实现编码转换,请求日志,权限验证等功能,通过实现Filter接口来定义过滤器。

DispatcherServlet作为SpringMVC的核心调度器,继承自HttpServlet,在SpringBoot启动时自动配置和初始化,接受经过过滤器链处理后的请求。

在查找处理器(三层架构中的controller)之前,DispatcherServlet会进行一些预处理操作:

1.检查请求是否为文件上传请求,若为文件上传请求,则将请求包装成MultipartHttpServletRequest。

2.根据请求的Accept头确定合适的消息转换器,用于后续处理响应数据的格式转换

(这里的Accept头是HTTP请求头中的一个字段,他用于告知服务器客户端能够接受的响应内容类型)

HandlerMapping根据请求的URL和请求方法,从被@Controller或@RestController注解标记的类中查找对应的处理器方法。常见的HandlerMapping实现是RequestMappingHandlerMapping,它依据@RequestMapping,@GetMappingdeng等注解来匹配处理器方法。

在确定请求对应的处理器之后,调用处理器方法之前,会执行拦截器的preHandle方法。拦截器是SpringMVC提供的功能,可用于对处理器方法进行增强,如权限验证,日志记录,性能监控等。

示例:

复制代码
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 权限验证
        if (request.getSession().getAttribute("user") == null) {
            response.sendRedirect("/login");
            return false;
        }
        // 记录请求开始时间
        request.setAttribute("startTime", System.currentTimeMillis());
        return true;
    }
}

若拦截器的preHandle方法返回true,HandlerAdapter会将请求中的参数(如URL参数,请求体参数等)绑定到处理器方法的参数上,并调用处理器方法。在这个过程中,控制器可能会调用服务层的方法来处理业务逻辑。

服务层主要负责处理业务规则,数据访问和事务管理等操作。控制器调用服务层的方法,服务层再调用数据访问层(DAO)来与数据库或其他数据源进行交互。

数据访问层负责与底层数据源进行交互,执行数据的增删改查,通常用mybatis或者mybatisplus进行实现。

处理器方法执行完成后,在视图渲染之前,会执行拦截器的postHandle方法。此方法可用于对处理器方法的执行结果进行修改或补充。

处理器方法处理完业务逻辑后,返回一个结果。结果可以是视图名称(用于视图渲染),也可以是数据对象(如JSON,XML等)。如果使用@RequestController注解,默认会将返回的对象转换为JSON格式返回给客户端。

若处理器方法返回的是视图名称,DispatcherServlet会使用ViewResolver解析视图,将模型数据传递给视图模版进行渲染。

视图模板将模型数据和视图模版合并,生成最终的HTML页面。(如果有)

在整个请求处理完成后,包括视图渲染完成,会执行拦截器的afterComletion方法。此方法主要用于进行资源清理操作,如关闭数据库连接,记录请求处理的总时长等。

处理器方法返回的结果(视图或数据)被封装到HttpServletResponse对象中,DispatcherServlet设置响应的状态码,响应头和响应体。

响应在返回客户端之前,再次经过过滤器,过滤器可对响应进行后置处理,如添加响应头,压缩响应数据等。

嵌入式服务器将HttpServletResponse对象中的响应数据返回给客户端,客户端根据响应内容进行相应处理。

相关推荐
devlei3 小时前
从源码泄露看AI Agent未来:深度对比Claude Code原生实现与OpenClaw开源方案
android·前端·后端
pshdhx_albert3 小时前
AI agent实现打字机效果
java·http·ai编程
沉鱼.444 小时前
第十二届题目
java·前端·算法
努力的小郑4 小时前
Canal 不难,难的是用好:从接入到治理
后端·mysql·性能优化
赫瑞5 小时前
数据结构中的排列组合 —— Java实现
java·开发语言·数据结构
Victor3565 小时前
MongoDB(87)如何使用GridFS?
后端
Victor3565 小时前
MongoDB(88)如何进行数据迁移?
后端
小红的布丁5 小时前
单线程 Redis 的高性能之道
redis·后端
GetcharZp5 小时前
Go 语言只能写后端?这款 2D 游戏引擎刷新你的认知!
后端
周末也要写八哥6 小时前
多进程和多线程的特点和区别
java·开发语言·jvm