Spring MVC 核心架构与请求生命周期深度解析

Spring框架父子容器机制解析与应用实践 在Java企业级开发中,控制反转(IoC)是Spring框架的核心设计原则,通过容器管理Bean的生命周期和依赖关系。Spring容器体系采用父子容器架构实现模块化设计,其中父容器(ApplicationContext)管理基础业务组件,子容器(WebApplicationContext)处理Web层特有组件。这种分层设计遵循职责分离原则,既保证了配置的灵活性,又实现了资源的有效隔离。从技术实现看,通过HierarchicalBeanFactory接口建立容器层级,采用类似但不同于类加载器双亲委派模型的查找 阅读详情

以下是一份极致详尽、系统化、可作为企业培训教材的《Spring MVC 核心架构与请求生命周期深度解析》文档,涵盖您要求的全部内容:核心组件职责、完整请求流程、可视化流程图、学习建议、规范与注意事项,并基于 Spring Framework 6.x 最新标准撰写。


📜 Spring MVC 核心架构与请求生命周期深度解析

目标:彻底掌握 Spring MVC 的架构设计哲学与请求处理全链路机制,实现从“会用”到“懂原理、能调优、可排错”的质变


✅ 一、Spring MVC 核心架构:五大核心组件职责详解

Spring MVC 的核心是前端控制器(Front Controller)模式,其架构由五个核心组件构成,各司其职,协同工作。

组件类名职责关键特性协作关系
DispatcherServletorg.springframework.web.servlet.DispatcherServlet前端控制器(总入口)
接收所有 HTTP 请求,协调其他组件工作
- 唯一入口点
- 由 Servlet 容器(Tomcat)初始化
- 配置在 web.xml 或 ServletRegistrationBean 中
接收请求 → 查询 HandlerMapping → 获取 Handler → 调用 HandlerAdapter → 执行 Controller → 获取 ModelAndView → 解析 View → 渲染响应
HandlerMappingRequestMappingHandlerMapping(默认)请求映射器
根据请求 URL、Method、Header、Params 等信息,找到匹配的 Controller 方法(Handler)
- 基于注解 @RequestMapping 等
- 支持路径变量、通配符、正则
- 支持多级匹配(最精确优先)
被 DispatcherServlet 调用 → 返回 HandlerExecutionChain(含 Handler + 拦截器列表)
HandlerAdapterRequestMappingHandlerAdapter(默认)处理器适配器
调用 Handler(Controller 方法)
负责参数绑定、类型转换、数据校验、返回值处理
- 支持 @RequestMapping, @GetMapping 等
- 支持 @RequestBody, @ModelAttribute
- 支持异步返回 DeferredResult
- 支持 @ResponseBody 转 JSON
被 DispatcherServlet 调用 → 调用 Controller 方法 → 返回 ModelAndView 或 ResponseEntity
Controller任意 @Controller / @RestController 类业务控制器
处理具体业务逻辑,返回模型数据和视图名(或直接返回响应体)
- 方法可返回 String(视图名)、ModelAndView、ResponseEntity<T>、void、Mono<T>(WebFlux)等
- 方法参数支持 @RequestParam, @PathVariable, @RequestBody 等
被 HandlerAdapter 调用 → 执行业务 → 返回数据结构
ViewResolverThymeleafViewResolver, ContentNegotiatingViewResolver视图解析器
将 Controller 返回的逻辑视图名(如 "user/list")解析为物理视图对象(如 Thymeleaf 模板文件)
- 支持多种模板引擎(Thymeleaf, FreeMarker, JSP)
- 支持内容协商(Content Negotiation)
- 可配置优先级
被 DispatcherServlet 调用 → 根据视图名 + 请求 Accept 头 → 返回 View 对象
ViewThymeleafTemplate, MappingJackson2JsonView视图渲染器
将模型数据(Model)渲染成最终的响应内容(HTML、JSON、XML)
- 模板引擎渲染 HTML
- JSON 序列化器(Jackson)生成 JSON
- 可自定义 View 实现
被 DispatcherServlet 调用 → render() 方法执行 → 输出响应流

✅ 架构图(文字版):

HTTP Request
      ↓
┌──────────────────────┐
│ DispatcherServlet    │ ← 1. 接收请求
└──────────┬───────────┘
           ↓
┌──────────────────────┐
│ HandlerMapping       │ ← 2. 找到匹配的 Controller 方法
└──────────┬───────────┘
           ↓
┌──────────────────────┐
│ HandlerExecutionChain│ ← 3. 返回 Handler + 拦截器列表
└──────────┬───────────┘
           ↓
┌──────────────────────┐
│ HandlerAdapter       │ ← 4. 调用 Controller 方法
└──────────┬───────────┘
           ↓
┌──────────────────────┐
│     Controller       │ ← 5. 执行业务逻辑,返回 ModelAndView
└──────────┬───────────┘
           ↓
┌──────────────────────┐
│ ViewResolver         │ ← 6. 解析逻辑视图名 → 物理视图对象
└──────────┬───────────┘
           ↓
┌──────────────────────┐
│        View          │ ← 7. 渲染模型数据 → HTML/JSON
└──────────┬───────────┘
           ↓
┌──────────────────────┐
│ HTTP Response        │ ← 8. 返回客户端
└──────────────────────┘

✅ 关键设计哲学:

  • 单一职责:每个组件只做一件事
  • 松耦合:组件间通过接口通信,可替换(如换 Jackson 为 Gson)
  • 可扩展:可自定义 HandlerMapping、ViewResolver、HandlerAdapter
  • 统一入口:所有请求都经过 DispatcherServlet,便于统一处理(如日志、安全)

✅ 二、请求处理完整生命周期:从 HTTP 请求到响应返回(8步详解)

我们以一个标准的 REST API 请求为例:
GET /api/users/1001 → 返回 JSON

🔹 步骤 1:请求到达 DispatcherServlet

  • 触发者:Servlet 容器(Tomcat)接收到 HTTP 请求
  • 执行者:DispatcherServlet
  • 动作:
    • 初始化(若为首次请求)
    • 获取请求 URI:/api/users/1001
    • 获取 HTTP Method:GET
    • 获取请求头(Headers)、参数(Query)、Body
  • 关键代码入口:
    // DispatcherServlet.doDispatch()
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // ...
    }
    

🔹 步骤 2:HandlerMapping 匹配 Controller 方法

  • 触发者:DispatcherServlet 调用 HandlerMapping.getHandler()
  • 执行者:RequestMappingHandlerMapping
  • 动作:
    • 遍历所有注册的 @Controller 类及其方法
    • 匹配规则(按优先级):
      1. 精确路径匹配:/api/users/1001
      2. 路径变量匹配:/api/users/{id}
      3. 通配符匹配:/api/users/**
      4. HTTP 方法匹配:GET vs POST
      5. 请求头匹配:Accept: application/json
      6. 参数匹配:params="type=active"
    • 找到匹配方法:UserController.getUser(@PathVariable("id") Long id)
  • 输出:HandlerExecutionChain
    • 包含:目标方法(HandlerMethod 对象)
    • 包含:拦截器列表(HandlerInterceptor[],按注册顺序)

✅ 路径匹配规则优先级(官方文档):

1. 精确路径(无变量) > 2. 路径变量 > 3. 通配符 > 4. 默认路径

🔹 步骤 3:执行 HandlerExecutionChain 中的拦截器 preHandle()

  • 触发者:DispatcherServlet
  • 执行者:所有注册的 HandlerInterceptor
  • 动作:
    • 按注册顺序,依次调用每个拦截器的 preHandle(request, response, handler)
    • 若任一拦截器返回 false → 请求被中断,跳过 Controller,直接调用 afterCompletion
    • 若全部返回 true → 继续执行
  • 典型用途:
    • 登录校验(if (token == null) return false;)
    • 请求日志记录(记录 startTime)
    • 性能监控(记录 startTime)
    • 跨域处理(设置 CORS 头)

✅ 拦截器执行顺序:
Interceptor1.preHandle → Interceptor2.preHandle → ... → Controller → ... → Interceptor2.postHandle → Interceptor1.postHandle → ... → Interceptor1.afterCompletion → Interceptor2.afterCompletion

🔹 步骤 4:HandlerAdapter 调用 Controller 方法

  • 触发者:DispatcherServlet
  • 执行者:RequestMappingHandlerAdapter
  • 动作:
    1. 解析方法签名:获取参数列表(@PathVariable, @RequestParam, @RequestBody 等)
    2. 参数解析器(ArgumentResolvers):
      • PathVariableMethodArgumentResolver → 提取 {id} → 转为 Long
      • RequestResponseBodyMethodProcessor → 读取 JSON Body → 反序列化为 User
      • RequestParamMethodArgumentResolver → 读取 query string
      • ModelMethodProcessor → 注入 Model
      • ServletWebRequestMethodArgumentResolver → 注入 HttpServletRequest
    3. 数据校验:
      • 若参数有 @Valid → 调用 Validator(Hibernate Validator)
      • 校验失败 → 抛出 MethodArgumentNotValidException
    4. 类型转换:
      • String "2025-01-01" → LocalDate
      • String "admin" → Role.ADMIN
    5. 调用目标方法:
      // 伪代码
      Object result = method.invoke(controllerInstance, args);
      
    6. 返回值处理器(ReturnValueHandlers):
      • 若返回 String → 包装为 ModelAndView
      • 若返回 ResponseEntity<T> → 直接使用
      • 若返回 @ResponseBody 对象 → 用 HttpMessageConverter 转为 JSON
      • 若返回 void → 无响应体

✅ 核心机制:
参数绑定 + 类型转换 + 数据校验 + 返回值序列化 全部由 HandlerAdapter 通过策略模式动态选择处理器完成。

🔹 步骤 5:Controller 执行业务逻辑

  • 执行者:开发者编写的 @Controller 类中的方法
  • 动作:
    • 调用 Service 层(userService.findById(id))
    • 处理业务逻辑(权限校验、状态变更)
    • 构造返回数据:
      @GetMapping("/users/{id}")
      public ResponseEntity<User> getUser(@PathVariable Long id) {
          User user = userService.findById(id);
          if (user == null) {
              return ResponseEntity.notFound().build();
          }
          return ResponseEntity.ok(user); // ✅ 返回 ResponseEntity
      }
      
  • 返回值类型:
    返回类型含义是否需要 @ResponseBody
    String逻辑视图名(如 "user/list")❌
    ModelAndView包含 Model + ViewName❌
    ResponseEntity<T>完整 HTTP 响应(状态码、头、体)✅(隐式)
    T + @ResponseBody直接序列化为 JSON/XML✅
    void无响应体✅(通常用于异步)
    Mono<T> / Flux<T>响应式编程✅(需 WebFlux)

✅ 最佳实践:REST API 优先使用 ResponseEntity<T>,控制力最强。

🔹 步骤 6:ViewResolver 解析视图名

  • 触发者:DispatcherServlet
  • 执行者:ViewResolver(默认 ContentNegotiatingViewResolver)
  • 动作:
    1. 获取 Controller 返回的 逻辑视图名(如 "user/list")
    2. 获取客户端请求头:Accept: application/json / text/html
    3. 内容协商(Content Negotiation):
      • 若 Accept: application/json → 选择 MappingJackson2JsonView
      • 若 Accept: text/html → 选择 ThymeleafViewResolver
    4. 根据视图名 + 内容类型,查找物理视图:
      • Thymeleaf:/WEB-INF/views/user/list.html
      • JSON:无物理文件,直接使用 HttpMessageConverter
    5. 返回 View 实例(如 JsonView 或 ThymeleafTemplate)

✅ 内容协商优先级(默认):

  1. URL 扩展(如 /user/1001.json)
  2. 请求头 Accept
  3. 请求参数 ?format=json

🔹 步骤 7:View 渲染响应内容

  • 触发者:DispatcherServlet
  • 执行者:View 对象(如 MappingJackson2JsonView)
  • 动作:
    • 获取 Controller 返回的 Model 数据(如 User user = new User(...))
    • 调用 render(model, request, response)
    • 序列化:
      • JSON:使用 ObjectMapper(Jackson) → user → {"id":1001,"name":"张三"}
      • HTML:使用 Thymeleaf 引擎 → 渲染模板 → 生成完整 HTML 字符串
    • 写入 HttpServletResponse 的输出流(OutputStream)
  • 关键点:
    • Model 数据 是一个 Map<String, Object>,键是变量名,值是对象
    • 渲染过程不涉及业务逻辑,仅是数据展示

🔹 步骤 8:执行拦截器 postHandle() 和 afterCompletion()

✅ 8.1 postHandle() —— 渲染前调用
  • 触发时机:Controller 执行完,View 渲染前
  • 执行者:所有拦截器,逆序执行(与 preHandle 顺序相反)
  • 用途:
    • 修改 Model 数据(如添加通用变量)
    • 添加响应头(如 X-Powered-By)
    • 记录处理时间(需在 preHandle 记录 startTime)
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    if (modelAndView != null) {
        modelAndView.addObject("appVersion", "v2.1.0"); // ✅ 添加全局变量
    }
}
✅ 8.2 afterCompletion() —— 响应完成后调用
  • 触发时机:无论成功或异常,响应完全写入客户端后
  • 执行者:所有拦截器,逆序执行
  • 用途:
    • 记录完整耗时(System.currentTimeMillis() - startTime)
    • 记录访问日志(URL、IP、状态码、耗时)
    • 清理线程本地变量(如 RequestContextHolder)
    • 发送监控指标(Prometheus)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    Long startTime = (Long) request.getAttribute("startTime");
    if (startTime != null) {
        long duration = System.currentTimeMillis() - startTime;
        log.info("✅ [{}] {} {} | {}ms | Status: {}", 
            request.getMethod(), 
            request.getRequestURI(), 
            response.getStatus(), 
            duration, 
            request.getAttribute("requestId"));
    }
}

✅ 为什么必须逆序?
拦截器是栈结构:preHandle 入栈,afterCompletion 出栈。
保证“先入后出”,如:日志记录先开始,后结束。


✅ 三、完整请求生命周期可视化流程图(Mermaid)

ClientDispatcherServletHandlerMappingHandlerAdapterControllerViewResolverViewInterceptor1Interceptor21. HTTP GET /api/users/10012. 查询匹配的 Handler3. 返回 HandlerExecutionChain (Handler + [Interceptor1, Interceptor2])4.1 preHandle()4.2 返回 true4.3 preHandle()4.4 返回 true5. 调用 HandlerAdapter6. 调用 UserController.getUser(id=1001)7. 返回 ResponseEntity<User>8. 返回 ModelAndView 或 ResponseEntity9. 解析视图名(此处为 JSON,无需视图)10. 返回 JsonView11. 调用 render()12. 返回 JSON 字符串13.1 postHandle()(逆序)13.2 完成13.3 postHandle()(逆序)13.4 完成14.1 afterCompletion()(逆序)14.2 记录耗时、日志14.3 afterCompletion()(逆序)14.4 记录耗时、日志15. 返回 HTTP 200 + JSONClientDispatcherServletHandlerMappingHandlerAdapterControllerViewResolverViewInterceptor1Interceptor2

✅ 图中关键点:

  • 所有组件均由 DispatcherServlet 调用
  • 拦截器在 preHandle 和 afterCompletion 中执行
  • postHandle 在 View 渲染前执行
  • 无 View 的请求(REST API)直接由 HttpMessageConverter 输出

✅ 四、学习建议:如何真正掌握 Spring MVC?

阶段建议行动目标
1. 理解架构画出上述 5 组件图,手写每个组件的职责能口述“请求如何流转”
2. 源码追踪在 IDEA 中启动 Spring Boot,Debug DispatcherServlet.doDispatch()看清每一步调用栈
3. 模拟实现自己写一个简易版 MyDispatcherServlet,只支持 @RequestMapping + @ResponseBody理解核心逻辑
4. 调试拦截器写一个拦截器,打印 request.getRequestURI()、response.getStatus()理解拦截器生命周期
5. 分析异常故意传非法参数(如 age=abc),看 MethodArgumentNotValidException 如何被处理理解异常传播链
6. 配置自定义替换 Jackson 为 Gson,自定义 ViewResolver理解可扩展性
7. 面试准备准备“请描述一个请求从浏览器到后端的完整流程”标准答案能讲 5 分钟不卡顿

✅ 推荐工具:

  • IDEA:开启 Debug 模式,断点在 DispatcherServlet.doDispatch()
  • Postman / Apifox:测试不同 Accept 头、路径变量、JSON Body
  • Spring Boot Actuator:/actuator/mappings 查看所有 URL 映射

✅ 五、使用 Spring MVC 的推荐规范与注意事项

✅ 推荐规范(企业级最佳实践)

类别规范说明
Controller 设计使用 @RestControllerREST API 统一用 @RestController,避免 @Controller + @ResponseBody 混用
请求映射优先使用 @GetMapping, @PostMapping比 @RequestMapping(method = GET) 更语义化
路径设计使用复数名词,如 /users,而非 /userRESTful 风格,符合惯例
参数绑定优先使用 @PathVariable、@RequestParam、@RequestBody禁止直接使用 request.getParameter()
数据校验使用 @Valid + JSR-380 注解所有 DTO 必须校验,禁止在 Controller 中手动校验
异常处理使用 @RestControllerAdvice 统一处理禁止每个 Controller 写 try-catch
响应格式统一返回 ResponseEntity<T> 或 CommonResult<T>前后端契约清晰,避免 null 混淆
文件上传使用 MultipartFile,校验大小、类型生产环境使用 MinIO/OSS,禁止直接存本地磁盘
拦截器用于登录、日志、性能监控禁止在拦截器中执行数据库查询(影响性能)
线程安全Controller 是单例,不要存储成员变量所有数据通过方法参数传递
性能优化开启 @EnableAsync + 异步写日志避免 I/O 阻塞主线程
内容协商明确指定 produces = "application/json"避免客户端误解析为 HTML

⚠️ 常见错误与避坑指南

错误原因正确做法
❌ @Autowired 注入 HttpServletRequest虽然能用,但违反设计改用 @RequestParam, @RequestHeader
❌ 在 Controller 中调用 response.sendRedirect()跳过 View,破坏流程使用 return "redirect:/users"
❌ @PathVariable 未校验传入 abc 导致 NumberFormatException加 @Min(1) 或 @Pattern
❌ @RequestBody 接收 null客户端没传 Body加 @NotNull 或 @Valid
❌ 拦截器中 request.setAttribute() 传数据给 Controller不推荐,耦合高改用 @ModelAttribute 或 @RequestAttribute
❌ 使用 @RequestMapping 没写 method可能被 POST 请求触发必须指定 method = GET
❌ 没有配置 ContentNegotiatingViewResolverJSON 返回乱码在 WebMvcConfigurer 中配置
❌ 使用 @Controller 返回 JSON 但没加 @ResponseBody返回视图名,不是 JSON改用 @RestController 或加注解
❌ 拦截器中调用 response.getWriter().write()会跳过后续组件只在 preHandle 中 return false 中断

✅ 高级建议(进阶)

建议说明
✅ 使用 @ControllerAdvice + @ExceptionHandler 统一处理异常避免重复代码,提升可维护性
✅ 自定义 HttpMessageConverter如支持 Protobuf、YAML 格式
✅ 启用 @EnableWebMvc 时谨慎会覆盖 Spring Boot 自动配置,仅在需要完全控制时使用
✅ 使用 @RequestScope 管理请求级状态如 UserContext 存储当前登录用户
✅ 集成 Springdoc OpenAPI自动生成 Swagger UI 文档
✅ 使用 @CrossOrigin 或全局 CORS 配置解决前后端分离的跨域问题

✅ 六、总结:Spring MVC 的设计哲学

哲学体现
约定优于配置@RestController 默认返回 JSON,无需额外配置
松耦合组件间通过接口通信,可替换(如换 Jackson 为 Gson)
可扩展自定义 HandlerMapping、ViewResolver、HandlerAdapter
统一入口所有请求走 DispatcherServlet,便于统一处理(安全、日志、监控)
声明式编程用注解声明“我要什么”,而不是“我怎么做”
关注点分离Controller 只管业务,校验归校验,视图归视图,异常归异常

✅ 终极目标:
让开发者只写业务逻辑,其余交给框架。


✅ 七、学习路线图(进阶方向)

阶段学习内容
基础理解上述 5 组件 + 请求流程
进阶自定义 HandlerInterceptor、ViewResolver、ArgumentResolver
深入阅读 DispatcherServlet.java、RequestMappingHandlerAdapter.java 源码
实战搭建一个带权限校验、日志、上传下载、统一响应的完整项目
扩展学习 Spring WebFlux(响应式)、Spring GraphQL、Spring Cloud Gateway

基于C#与Java的高效网站开发框架实战(ASP.NET MVC + Spring MVC) 现代Web应用的快速迭代与复杂业务需求催生了众多成熟的开发框架。在企业级开发领域,C# 与 Java 凭借强大的生态系统、稳定的运行时环境和丰富的第三方支持,长期占据主导地位。C# 依托 .NET 平台,尤其在 Windows 集成、IIS 托管和 ASP.NET MVC 框架下表现出色,具备高效的开发体验与紧密的工具链集成;而 Java 借助 JVM 的跨平台能力,在分布式、高并发场景中广泛应用于大型系统,Spring 框架更是成为事实上的企业级开发标准。 阅读详情

相关推荐

Java Spring MVC最小化JAR包集合项目实战

看完这一整套流程,你现在应该明白:Spring MVC 不是魔法,它的每一个功能背后都有清晰的组件协作;依赖不能乱删,每一个 JAR 包都有明确的职责边界;请求处理是有迹可循的,从到最终方法调用,每一步都可以干预;Bean 的生命周期是可以掌控的,你可以精确控制对象的创建、初始化和销毁;Spring 提供了大量扩展点,只要你愿意深入,几乎没有做不到的事。

weixin_35935514的博客 609

Spring MVC 深度解析

实现接口(或继承注册拦截器到Spring容器,指定拦截路径;// 1. 自定义拦截器@Component// 请求到达处理器前执行@Overrideresponse.getWriter().write("未登录");// 中断请求// 放行// 处理器执行后、视图渲染前执行@OverrideSystem.out.println("处理器执行完成:" + request.getRequestURI());// 视图渲染完成后执行@Override。

xiaolyuh的专栏 1801

Spring Framework 1.0早期版本架构解析与实战

大多数 Bean 直接由容器通过反射创建,但有些对象(如代理、连接池、第三方库封装)需要更复杂的初始化逻辑。为此,Spring 提供了接口:支持通过实现 DSL 风格配置:只需注册处理器并在中声明即可。

weixin_35706067的博客 679

Spring MVC 全流程深度解析:从请求到响应的暗中流程

摘要:本文深入解析SpringMVC处理HTTP请求的核心机制。通过"米其林餐厅"类比,阐述DispatcherServlet、HandlerMapping等组件分工。详细拆解请求7个关键步骤:从拦截请求到响应返回,重点说明Controller业务处理和视图解析过程。同时指出前后端分离架构下ViewResolver被HttpMessageConverter替代的变化,并提示Controller单例模式的线程安全问题。文章揭示了SpringMVC通过组件化解耦实现高效请求处理的原理,为理解

Dejong22的博客 754

官方原版Spring Framework 5.1.2完整开发包实战解析

回顾全文,你会发现 Spring 的魅力远不止于它的 API 或注解。它教会我们的是一种解耦的艺术:把对象创建交给容器、把横切逻辑抽成切面、把数据操作抽象成模板……每一个设计都在告诉你:专注你该做的事,别的交给框架。而5.1.2这个版本,恰好站在了传统与未来的交界处 —— 它既有历经考验的稳定内核,又有面向响应式的前瞻布局。理解它,不仅是掌握一门技术,更是领悟一种软件工程的哲学。

weixin_35756130的博客 729

Spring MVC与MyBatis整合完整JAR包配置实战

是MyBatis-Spring集成包提供的工厂类,用于在Spring容器中创建实例。</bean>代码逻辑逐行解读分析:dataSource:注入之前配置的数据源Bean,建立数据库连接基础。:指向MyBatis主配置文件,包含别名、插件、类型处理器等全局设置。:指定Mapper XML文件的位置,支持Ant风格通配符批量加载。注意:可选。若MyBatis配置简单,建议直接在Spring中配置相关属性(见3.3.3节),以减少配置分散。

weixin_35189483的博客 853

【Spring系列-09】Spring MVC 请求处理与源码分析

这篇文章深入解析了Spring MVC的核心处理流程,重点剖析了DispatcherServlet和HandlerMapping的工作原理。文章以用户登录请求为例,详细展示了请求从接收到响应的完整过程,包括:请求分发、处理器查找、适配器调用、视图渲染等关键步骤。通过分析doDispatch()方法源码,揭示了Spring MVC内部精巧的组件协作机制,并辅以流程图直观呈现请求流转路径。文章还介绍了HandlerMapping的作用及常见URL映射场景,为理解Spring MVC的请求处理机制提供了清晰的视角

专注后端技术架构,AI技术分享 1299

skill使用教程,从小白到大神进阶

(2)突然无法使用(NodeJS安装参考):如果正常使用中,突然发现claude命令无法启动claude-code了,可能是claude-code正在后台自动更新,等待几分钟后再尝试使用,如果还是不行,请先运行下列代码移除claude-code,注意,如果你的node安装目录不同,要替换成自己的安装目录:rm -rf /opt/homebrew/lib/node_modules/@anthropic-ai/claude-code。安装完成后,让我们启动 Claude Code,看看它长什么样。

weixin_45036829的博客 2006

嵌入式 Tomcat 与 Spring MVC 集成

本文将深入解析Spring Boot内嵌Tomcat的启动原理与实现机制。文章从Tomcat核心架构切入,对比传统部署与嵌入式场景的差异,重点分析Tomcat实例创建、Connector配置、Context构建等关键步骤。通过代码示例揭示NIO2协议选择、Spring容器独立初始化、Servlet 3.0动态注册等核心技术点,最终阐明Tomcat启动流程与主线程保活机制。全文从代码实现到底层原理,系统性地拆解嵌入式Web应用的运行本质,帮助开发者深入理解Spring Boot内嵌服务器的技术实现。

weixin_44289947的博客 966

LLMOps的崛起:如何利用Langfuse和Opik构建高效的模型监控与评估体系

本文探讨了LLMOps的崛起,详细介绍了如何利用Langfuse和Opik构建高效的模型监控与评估体系。通过开源工具Langfuse的全景监控方案和Opik的三层评估体系,帮助AI工程团队实现大语言模型的全生命周期管理,提升模型性能和迭代效率。文章还提供了实战技巧和工具链集成方案,助力企业优化AI应用。

ll5678的博客 678

适配adv7280m相机到rk3588的安卓平台

Kernel-5.10/arch/arm64/configs/firefly_defconfig里面增加配置CONFIG_VIDEO_ADV7180=y。出现一次开不了机器的情况,接调试口发现,在set_fmt里面用s_ctrl对mipi的频率进行设置会出现异常。设备树修改kernel-5.10/arch/arm64/boot/dts/rockchip/13.dts。把MEDIA_ENT_F_ATV_DECODER改回MEDIA_ENT_F_CAM_SENSOR。第二次编译,仅仅刷新boot.img。

chenyq14的专栏 2447

Spring | Spring、Spring MVC 和 Spring Boot 的分工与协作

Spring、Spring MVC与Spring Boot技术栈解析 本文系统梳理了Java企业级开发中三大核心框架的关系与功能定位: Spring框架 作为生态基石,提供IoC容器(依赖注入)和AOP两大核心能力,通过模块化设计支持数据访问、事务管理等企业级功能。 Spring MVC 作为Spring的Web模块,采用MVC架构处理HTTP请求,核心组件包括DispatcherServlet和注解驱动的控制器,支持RESTful开发和前后端分离架构。 Spring Boot 通过自动配置、起步依赖和约定

鳄鱼杆的博客 402

RT-DETR改进策略【RT-DETR和Mamba】| CVPR 2025:EfficientViM 压缩隐藏状态空间进行通道混合、单头设计减少内存操作,提升目标检测效率与精度

本文记录的是利用模块优化的目标检测网络模型。EfficientViM Block(基于隐藏状态混合器的状态空间对偶性模块) 的设计旨在,提升特征提取效率,同时兼顾全局依赖捕捉与局部细节保留。本文将深入研究的原理,并将其应用到中,通过重构特征提取流程、减少内存绑定操作、融合多阶段特征,增强模型在资源受限环境下的检测性能与速度。Depth Information Assisted Collaborative Mutual Promotion Network for Single Image DehazingLE

Limiiiing的博客 915

Spring MVC 源代码分析与实践 —— 俯视 Spring MVC

本文深入解析了SpringMVC框架的核心架构与实现机制。主要内容包括:1)SpringMVC的整体架构设计,重点分析了DispatcherServlet作为前端控制器的请求处理流程;2)核心组件实现原理,详细剖析了HandlerMapping的请求映射机制、HandlerAdapter的处理器适配策略以及ViewResolver的视图解析过程;3)扩展机制与优化实践,探讨了拦截器链、数据绑定、异常处理等关键功能,并提供了性能优化建议。文章通过源码分析展示了SpringMVC如何运用MVC模式、职责链模式等

油墨香^-^的博客 533

Python 爬虫实战:龙虎榜机构买卖数据爬取与代码详解(附数据分析)

龙虎榜是证券市场中重要的市场信息之一,记录了当日大宗交易及机构买卖情况,包括机构名称、买卖方向、成交金额、成交股数、买入卖出价格等信息。通过分析龙虎榜数据,投资者可以更好地了解市场动向和机构投资者的行为,从而做出更准确的决策。本文将详细介绍如何使用 Python 编写爬虫程序,高效地抓取龙虎榜机构买卖数据,并进行数据分析。我们将从环境搭建、数据抓取、数据存储到数据分析等关键步骤逐一展开,帮助读者掌握完整的爬虫实战流程。

u014481728的博客 702

Apollo Planning决策规划算法代码详细解析 (2):Scenario执行

上一章节讲Scenario的决策逻辑,当确认当前Scenario后,本章节继续深入讲解在代码中,Scenario的执行过程。Scenario的Process()函数根据配置文件顺序执行stage,并判断目前处于哪个stage。当确认好stage后调用该stage对应的Process()函数,来进行具体的规划任务。 码字不易,喜欢的朋友们麻烦点个关注与赞。 在本文你将学到下面这些内容: Scenario的Process()函数的作用于调用方式; Scenario对象的初始化方法; 如何给每个Scen

自动驾驶Player的博客 5608

Spring核心架构深度拆解:从IoC容器到自动装配

在Java企业级开发中,理解框架的底层设计远比背诵API重要。IoC容器作为Spring的心脏,通过依赖注入将对象间的耦合从代码中剥离,而AOP则利用动态代理实现切面逻辑的无侵入织入。当Bean之间出现循环依赖时,Spring的三级缓存机制通过提前暴露对象引用巧妙化解,但构造器注入和原型Bean仍需警惕。Bean生命周期中密集的扩展点,如BeanPostProcessor,是AOP代理与Spring Boot自动装配得以生效的基石。Spring MVC借助DispatcherServlet和HandlerM

weixin_31188927的博客 247

Siemens SIMATIC软件二次开发:使用C#进行SIMATIC软件二次开发

通过使用OPC-UA通信协议和S7通信库,可以有效地在C#应用程序中与Siemens SIMATIC软件进行数据交换。OPC-UA提供了一个标准化的平台,而S7通信库则提供了直接访问PLC数据的能力。掌握这两种通信方式,将极大地增强在工业自动化领域的二次开发能力。在Siemens SIMATIC软件中,自定义功能块开发是实现二次开发的关键步骤之一。通过C#,可以创建高度定制化的功能块,以满足特定的控制需求。下面,我们将通过一个示例来展示如何使用C#开发一个自定义功能块。OPC-UA通信。

kkchenjj的博客 1414

Spring Security核心架构与实战:从认证授权到JWT集成深度解析

在Java Web应用开发中,安全框架是保障系统可靠性的基石。Spring Security作为Spring生态的标准安全解决方案,其核心基于过滤器链(Filter Chain)机制,通过一系列可插拔的安全过滤器对HTTP请求进行拦截和处理。这一设计实现了认证(Authentication)与授权(Authorization)的分离,认证解决“你是谁”的问题,通常涉及UserDetailsService加载用户信息和PasswordEncoder进行密码校验;授权则解决“你能做什么”,通过AccessDec

cigang4063的博客 429

【Scratch考级100图】图01-等级考试scratch绘 画正方形

一、案例介绍 小朋友们应该在数学课或者平时生活中有了解过正方形,正方形在我们生活中到处可见,那我们如果通过Scratch软件来绘制一个正方形呢,我们一起来学习一下吧,在舞台正中央绘制一个边长为200的正方形,要求: 1、围绕舞台中心绘制正多边形,均匀分布在四个象限中 2、正方形边长为200个单位,线条粗细、颜色自定 3、利用画笔绘制正方形,不能有多余的线条 二、案例演示 【Scratch案例演示】Scratch图1-画正方形 三、案例分析 当我们点击小绿旗启动程序后,舞台上会出现一个画

青少年编程学习指导 2667

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

深入解析Spring ApplicationContext:核心原理、生命周期与高级应用

控制反转(IoC)是Spring框架的核心设计思想,它通过将对象的创建和依赖关系的管理交给容器来实现解耦。其核心原理在于依赖注入(DI),容器负责实例化Bean并注入所需依赖,从而简化了企业级应用的开发。这一技术价值在于提升了代码的可测试性、可维护性和模块化程度,广泛应用于Web服务、微服务架构和后台管理系统等场景。Spring ApplicationContext作为IoC容器的高级实现,不仅提供了基础的Bean管理,还集成了国际化、事件发布、资源加载等企业级服务。理解其生命周期,尤其是refresh()

weixin_34204722的博客 398

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Spring Boot请求处理全流程解析与优化实践

HTTP请求处理是Web开发的核心基础,Spring Boot通过DispatcherServlet实现了标准化的请求生命周期管理。从底层原理看,MVC框架通过HandlerMapping完成路由匹配,借助HandlerAdapter执行处理器方法,最终由ViewResolver生成响应。这种分层架构设计既保证了扩展性,又能通过自动配置快速集成常用组件。在Java企业级开发中,Spring Boot的请求处理机制显著提升了开发效率,特别适合RESTful API和微服务场景。文章深入解析了从容器启动到响应返

weixin_31236101的博客 271

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Spring 与 Spring Framework 全栈深度解析

Spring是Java生态中最核心的基础框架,自2003年发布以来已从轻量级IoC容器发展为支持云原生、响应式、AI集成的综合性平台。核心特性包括控制反转(IoC)、面向切面编程(AOP)、声明式事务和Web双模式(MVC/WebFlux)。SpringBoot提供自动配置和嵌入式服务器等增强功能。最新版本6.x要求JDK17+,支持AOT编译和GraalVM原生镜像,显著提升启动性能。虽然学习曲线陡峭,但凭借完善的生态、企业级支持和持续现代化特性,Spring仍是构建企业应用、微服务和云原生系统的首选框架

几十年资深高级架构师,技术专家的技术笔记。专注C、Java、Python、微服务、云原生、AI工程化及高并发系统分布式架构实战,分享源码剖析、性能调优与架构治理经验。 516

Spring Boot请求处理全流程解析与性能优化

HTTP请求处理是Web开发的核心基础,涉及网络通信、协议解析和业务逻辑执行等多个技术环节。在Java生态中,Spring Boot通过整合Servlet容器和Spring MVC框架,构建了一套高效的请求处理管道。其核心原理是通过分层架构(网络层、Servlet容器层、MVC层、业务层)实现关注点分离,每个层级提供可扩展的拦截点。从工程实践角度看,理解请求全流程对于性能调优至关重要,比如通过调整Tomcat线程池参数应对高并发场景,或优化消息转换器提升序列化效率。典型的应用场景包括电商系统的订单处理、金融

weixin_28327051的博客 301

Java实习模拟面试之软件架构:深入解析MVC、微服务与分布式系统核心原理

MVC(Model-View-Controller)是一种经典的关注点分离(Separation of Concerns)设计模式,广泛应用于Web应用开发中。组件职责Java实现示例Model(模型)处理业务逻辑与数据持久化User实体类、View(视图)负责数据展示与用户交互JSP、Thymeleaf、Freemarker模板Controller(控制器)协调Model与View,处理用户请求或类✅小贴士:MVC的核心价值在于解耦。

吾为热爱计科,致力于知识分享的践行者,此博客是我在这条道路上留下的足迹。 863

MVC问题记录

解决方案@Data // Lombok注解,自动生成getter/setter@JsonIgnore // 序列化时忽略password字段@JsonProperty("user_name") // 序列化后字段名为user_name(而非username)@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") // 日期格式化跳过视图解析,直接操作响应体;自动序列化(对象→JSON/XML);支撑 RESTful API 构建;

m0_74494380的博客 823
上一篇: Spring MVC 深度系统性解析:架构、原理、注解、校验、异常、文件与拦截器
下一篇: Spring MVC 注解驱动控制器深度解析
龙茶清欢
博客等级 码龄7年 3720粉丝 375原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值