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

Spring MVC 架构总览与请求处理流程

🧭Spring MVC 架构总览与请求处理流程

文章目录

  • 🧭Spring MVC 架构总览与请求处理流程
  • 🏗️ 一、Spring MVC 整体架构概览
    • 💡 MVC 设计模式在 Spring 中的实现
    • 🔧 核心组件职责说明
  • 🔄 二、DispatcherServlet 初始化流程
    • 🚀 DispatcherServlet 类层次结构
    • ⚙️ 初始化源码深度解析
    • 📊 初始化日志追踪
  • 🌐 三、HTTP 请求处理完整执行链
    • 🔄 请求处理时序图
    • ⚡ doDispatch 方法源码解析
    • 🔍 处理器执行链构建
  • 🤝 四、核心组件协作机制
    • 🎯 HandlerMapping 映射机制
    • ⚡ HandlerAdapter 适配执行
    • 🎨 ViewResolver 视图解析
  • 📊 五、请求处理日志追踪
    • 🔍 请求处理调试工具
    • 📝 完整请求处理日志示例
    • 🔧 调试配置启用
  • 💡 六、性能优化与最佳实践
    • ⚡ 组件配置优化
    • 🚀 异步处理优化
    • 🔍 性能监控端点
    • 📊 优化效果对比

🏗️ 一、Spring MVC 整体架构概览

💡 MVC 设计模式在 Spring 中的实现

Spring MVC 核心架构图:

客户端请求
DispatcherServlet
HandlerMapping
HandlerAdapter
Controller
ModelAndView
ViewResolver
View
响应客户端
异常处理
拦截器
模型数据

🔧 核心组件职责说明

Spring MVC 九大核心组件:

组件职责说明关键接口 / 核心类补充说明 / 执行阶段
DispatcherServlet前端控制器(Front Controller),统一接收所有请求并协调各组件org.springframework.web.servlet.DispatcherServletMVC 核心调度中心,负责请求分发、异常处理、视图渲染。
HandlerMapping根据请求 URL 查找对应的 Controller 及处理方法HandlerMappingRequestMappingHandlerMapping请求阶段第一个执行的组件,返回 HandlerExecutionChain
HandlerAdapterHandlerMapping 返回的处理器适配为可执行对象HandlerAdapterRequestMappingHandlerAdapter执行真正的 Controller 方法(支持参数绑定、@RequestBody 等)。
Controller承载核心业务逻辑的请求处理器@Controller / @RestController一般对应业务模块的入口层,处理请求并返回 Model 或 Response。
HandlerInterceptor请求拦截与前后处理逻辑(如鉴权、日志、限流)HandlerInterceptor可实现 preHandlepostHandleafterCompletion 三个阶段。
Model封装业务处理结果的模型数据容器Model / ModelMap / ModelAndViewController 中组装数据,交由视图层展示。
ViewResolver根据返回值解析对应视图(如 JSP、Thymeleaf、Freemarker)ViewResolverInternalResourceViewResolver将逻辑视图名解析为实际渲染视图对象。
View负责将模型数据渲染为最终响应内容ViewThymeleafViewMappingJackson2JsonView支持多视图技术:HTML、JSON、PDF、Excel 等。
ExceptionHandler捕获并处理控制器执行过程中的异常@ExceptionHandler@ControllerAdvice统一异常处理机制,支持全局异常捕获与响应格式化。

🔄 二、DispatcherServlet 初始化流程

🚀 DispatcherServlet 类层次结构

DispatcherServlet 继承体系:

HttpServletBean
+init() : void
FrameworkServlet
+initServletBean() : void
+initWebApplicationContext() : void
+onRefresh(ApplicationContext) : void
DispatcherServlet
+onRefresh(ApplicationContext) : void
+initStrategies(ApplicationContext) : void
+doService(HttpServletRequest, HttpServletResponse) : void
+doDispatch(HttpServletRequest, HttpServletResponse) : void

⚙️ 初始化源码深度解析

DispatcherServlet 初始化核心方法:

public class DispatcherServlet extends FrameworkServlet {/*** WebApplicationContext 刷新时的回调* 核心初始化入口*/@Overrideprotected void onRefresh(ApplicationContext context) {initStrategies(context);}/*** 初始化九大策略组件*/protected void initStrategies(ApplicationContext context) {// 1. 文件上传处理器initMultipartResolver(context);// 2. 本地化解析器initLocaleResolver(context);// 3. 主题解析器initThemeResolver(context);// 4. 处理器映射器(核心)initHandlerMappings(context);// 5. 处理器适配器(核心)initHandlerAdapters(context);// 6. 异常处理器initHandlerExceptionResolvers(context);// 7. 视图名解析器initRequestToViewNameTranslator(context);// 8. 视图解析器(核心)initViewResolvers(context);// 9. 闪存属性管理器initFlashMapManager(context);}
}

HandlerMapping 初始化详细流程:

private void initHandlerMappings(ApplicationContext context) {this.handlerMappings = null;// 1. 检测所有 HandlerMapping 类型的 Beanif (this.detectAllHandlerMappings) {Map<String, HandlerMapping> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);if (!matchingBeans.isEmpty()) {this.handlerMappings = new ArrayList<>(matchingBeans.values());// 排序:Ordered 接口或 @Order 注解AnnotationAwareOrderComparator.sort(this.handlerMappings);}} else {// 2. 按名称查找特定 Beantry {HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);this.handlerMappings = Collections.singletonList(hm);} catch (NoSuchBeanDefinitionException ex) {this.handlerMappings = null;}}// 3. 确保至少有一个默认的 HandlerMappingif (this.handlerMappings == null) {this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);}
}

📊 初始化日志追踪

初始化过程调试日志:

@Component
@Slf4j
public class DispatcherServletInitLogger implements ApplicationListener<ContextRefreshedEvent> {@Autowiredprivate DispatcherServlet dispatcherServlet;@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {log.info("=== DispatcherServlet 初始化报告 ===");// 反射获取组件信息try {logHandlerMappings();logHandlerAdapters();logViewResolvers();} catch (Exception e) {log.error("初始化日志记录失败", e);}}private void logHandlerMappings() throws Exception {Field handlerMappingsField = DispatcherServlet.class.getDeclaredField("handlerMappings");handlerMappingsField.setAccessible(true);@SuppressWarnings("unchecked")List<HandlerMapping> mappings = (List<HandlerMapping>) handlerMappingsField.get(dispatcherServlet);log.info("HandlerMappings ({}个):", mappings.size());for (HandlerMapping mapping : mappings) {log.info("  - {}: {}", mapping.getClass().getSimpleName(), getMappingDetails(mapping));}}private String getMappingDetails(HandlerMapping mapping) {if (mapping instanceof RequestMappingHandlerMapping) {return "注解控制器映射";} else if (mapping instanceof BeanNameUrlHandlerMapping) {return "Bean名称URL映射";} else if (mapping instanceof SimpleUrlHandlerMapping) {return "简单URL映射";}return "自定义映射";}
}

控制台输出示例:

2023-10-01 10:00:01.123 INFO - === DispatcherServlet 初始化报告 ===
2023-10-01 10:00:01.124 INFO - HandlerMappings (3):
2023-10-01 10:00:01.125 INFO -   - RequestMappingHandlerMapping: 注解控制器映射
2023-10-01 10:00:01.126 INFO -   - BeanNameUrlHandlerMapping: Bean名称URL映射  
2023-10-01 10:00:01.127 INFO -   - SimpleUrlHandlerMapping: 简单URL映射
2023-10-01 10:00:01.128 INFO - HandlerAdapters (4):
2023-10-01 10:00:01.129 INFO -   - RequestMappingHandlerAdapter: 注解控制器适配器

🌐 三、HTTP 请求处理完整执行链

🔄 请求处理时序图

Spring MVC 请求处理完整流程:

ControllerDispatcherServletHandlerMappingHandlerAdapterInterceptor ChainViewResolverViewHTTP RequestgetHandler()Handler + InterceptorsgetHandlerAdapter()HandlerAdapterpreHandle()true/falseloop[拦截器预处理]handle()执行控制器方法返回结果(ModelAndView/String)ModelAndViewpostHandle()loop[拦截器后处理]resolveViewName()View 对象render()渲染完成afterCompletion()loop[拦截器完成处理]HTTP ResponseControllerDispatcherServletHandlerMappingHandlerAdapterInterceptor ChainViewResolverView

⚡ doDispatch 方法源码解析

DispatcherServlet 核心分发逻辑:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest = request;HandlerExecutionChain mappedHandler = null;ModelAndView mv = null;try {// 1. 文件上传请求处理processedRequest = checkMultipart(request);// 2. 确定处理器执行链(包含拦截器)mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {noHandlerFound(processedRequest, response);return;}// 3. 确定处理器适配器HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());// 4. 拦截器预处理if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// 5. 实际执行处理器mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// 6. 查找默认视图名(如果需要)applyDefaultViewName(processedRequest, mv);// 7. 拦截器后处理mappedHandler.applyPostHandle(processedRequest, response, mv);} catch (Exception ex) {// 异常处理dispatchException = ex;} catch (Throwable err) {dispatchException = new NestedServletException("Handler dispatch failed", err);}// 8. 处理结果(渲染视图或处理异常)processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

getHandler 方法详细实现:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {// 遍历所有 HandlerMappingfor (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;
}

🔍 处理器执行链构建

HandlerExecutionChain 结构分析:

public class HandlerExecutionChain {private final Object handler;private final List<HandlerInterceptor> interceptorList = new ArrayList<>();private int interceptorIndex = -1;/*** 执行拦截器预处理*/boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i = 0; i < this.interceptorList.size(); i++) {HandlerInterceptor interceptor = this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {// 预处理失败,触发已完成拦截器的afterCompletiontriggerAfterCompletion(request, response, null);return false;}this.interceptorIndex = i;}return true;}/*** 执行拦截器后处理*/void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView modelAndView) throws Exception {for (int i = this.interceptorList.size() - 1; i >= 0; i--) {HandlerInterceptor interceptor = this.interceptorList.get(i);interceptor.postHandle(request, response, this.handler, modelAndView);}}
}

🤝 四、核心组件协作机制

🎯 HandlerMapping 映射机制

RequestMappingHandlerMapping 工作原理:

public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping {/*** 扫描 @Controller 和 @RequestMapping 注解*/@Overridepublic void afterPropertiesSet() {super.afterPropertiesSet();// 1. 扫描所有Controller类Map<String, Object> beans = getApplicationContext().getBeansWithAnnotation(Controller.class);beans.putAll(getApplicationContext().getBeansWithAnnotation(RequestMapping.class));// 2. 解析每个Controller的方法for (Object bean : beans.values()) {Class<?> beanType = bean.getClass();RequestMapping typeMapping = beanType.getAnnotation(RequestMapping.class);// 3. 解析类级别的@RequestMappingRequestMappingInfo typeInfo = createRequestMappingInfo(typeMapping);// 4. 解析方法级别的@RequestMappingMethod[] methods = beanType.getDeclaredMethods();for (Method method : methods) {RequestMapping methodMapping = method.getAnnotation(RequestMapping.class);if (methodMapping != null) {RequestMappingInfo methodInfo = createRequestMappingInfo(methodMapping);RequestMappingInfo combinedInfo = typeInfo.combine(methodInfo);// 5. 注册映射关系registerHandlerMethod(bean, method, combinedInfo);}}}}/*** 根据请求查找处理器*/@Overrideprotected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// 1. 获取请求路径String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);// 2. 查找匹配的HandlerMethodHandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);// 3. 创建处理器执行链(包含拦截器)return createHandlerExecutionChain(handlerMethod, request);}
}

⚡ HandlerAdapter 适配执行

RequestMappingHandlerAdapter 执行流程:

public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {/*** 支持 @Controller 注解的处理器*/@Overridepublic boolean supports(Object handler) {return handler instanceof HandlerMethod;}/*** 执行处理器方法*/@Overrideprotected ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response,HandlerMethod handlerMethod) throws Exception {// 1. 参数解析和绑定ServletWebRequest webRequest = new ServletWebRequest(request, response);try {// 2. 执行方法调用Object returnValue = invokeHandlerMethod(handlerMethod, webRequest);// 3. 处理返回值ModelAndView mav = getModelAndView(handlerMethod, returnValue, webRequest);return mav;} finally {// 4. 清理资源webRequest.requestCompleted();}}/*** 实际方法调用*/protected Object invokeHandlerMethod(HandlerMethod handlerMethod,ServletWebRequest webRequest) throws Exception {// 1. 创建方法调用器ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);// 2. 设置参数解析器invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);// 3. 设置返回值处理器invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);// 4. 执行方法调用Object returnValue = invocableMethod.invokeForRequest(webRequest, null);return returnValue;}
}

🎨 ViewResolver 视图解析

InternalResourceViewResolver 实现:

public class InternalResourceViewResolver extends UrlBasedViewResolver {/*** 解析视图名称*/@Overrideprotected View createView(String viewName, Locale locale) throws Exception {// 1. 检查重定向视图if (viewName.startsWith(REDIRECT_URL_PREFIX)) {String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());return new RedirectView(redirectUrl, isRedirectContextRelative(), isRedirectHttp10Compatible());}// 2. 检查转发视图if (viewName.startsWith(FORWARD_URL_PREFIX)) {String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());return new InternalResourceView(forwardUrl);}// 3. 创建普通视图return super.createView(viewName, locale);}/*** 构建完整视图路径*/@Overrideprotected String createViewName(String viewName, Locale locale) {return getPrefix() + viewName + getSuffix();}
}

📊 五、请求处理日志追踪

🔍 请求处理调试工具

请求追踪拦截器:

@Component
@Slf4j
public class RequestTracingInterceptor implements HandlerInterceptor {private static final ThreadLocal<Long> startTimeHolder = new ThreadLocal<>();private static final ThreadLocal<String> requestIdHolder = new ThreadLocal<>();@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1. 记录请求开始时间long startTime = System.currentTimeMillis();startTimeHolder.set(startTime);// 2. 生成请求IDString requestId = UUID.randomUUID().toString().substring(0, 8);requestIdHolder.set(requestId);// 3. 记录请求信息log.info("🔍 [{}] 请求开始: {} {} [Handler: {}]", requestId, request.getMethod(), request.getRequestURI(),getHandlerDescription(handler));// 4. 记录请求参数logRequestParameters(request, requestId);return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {String requestId = requestIdHolder.get();log.info("✅ [{}] 控制器执行完成 [View: {}]", requestId, modelAndView != null ? modelAndView.getViewName() : "N/A");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {long endTime = System.currentTimeMillis();long startTime = startTimeHolder.get();long duration = endTime - startTime;String requestId = requestIdHolder.get();if (ex != null) {log.error("❌ [{}] 请求处理异常: {} [耗时: {}ms]", requestId, ex.getMessage(), duration);} else {log.info("🎯 [{}] 请求处理完成 [状态: {}] [耗时: {}ms]", requestId, response.getStatus(), duration);}// 清理ThreadLocalstartTimeHolder.remove();requestIdHolder.remove();}private String getHandlerDescription(Object handler) {if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;return String.format("%s.%s", handlerMethod.getBeanType().getSimpleName(),handlerMethod.getMethod().getName());}return handler.getClass().getSimpleName();}private void logRequestParameters(HttpServletRequest request, String requestId) {Map<String, String[]> parameterMap = request.getParameterMap();if (!parameterMap.isEmpty()) {StringBuilder params = new StringBuilder();for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {params.append(entry.getKey()).append("=").append(Arrays.toString(entry.getValue())).append("; ");}log.debug("📋 [{}] 请求参数: {}", requestId, params.toString());}}
}

📝 完整请求处理日志示例

典型请求处理日志输出:

2023-10-01 10:00:01.123 INFO  🔍 [a1b2c3d4] 请求开始: GET /api/users/123 [Handler: UserController.getUser]
2023-10-01 10:00:01.124 DEBUG 📋 [a1b2c3d4] 请求参数: id=123; 
2023-10-01 10:00:01.125 DEBUG 🔄 [a1b2c3d4] HandlerMapping找到处理器: UserController.getUser
2023-10-01 10:00:01.126 DEBUG ⚡ [a1b2c3d4] HandlerAdapter执行方法调用
2023-10-01 10:00:01.127 DEBUG 🗃️ [a1b2c3d4] 查询数据库获取用户数据
2023-10-01 10:00:01.128 INFO  ✅ [a1b2c3d4] 控制器执行完成 [View: user/details]
2023-10-01 10:00:01.129 DEBUG 🎨 [a1b2c3d4] ViewResolver解析视图: /WEB-INF/views/user/details.jsp
2023-10-01 10:00:01.130 INFO  🎯 [a1b2c3d4] 请求处理完成 [状态: 200] [耗时: 7ms]

🔧 调试配置启用

Spring MVC 调试配置:

# application.properties - 启用详细调试日志
logging.level.org.springframework.web=DEBUG
logging.level.com.example.controller=TRACE# 启用Spring MVC调试功能
spring.mvc.log-request-details=true
spring.mvc.log-resolved-exceptions=true# 启用参数绑定日志
logging.level.org.springframework.web.bind=TRACE

💡 六、性能优化与最佳实践

⚡ 组件配置优化

高性能 DispatcherServlet 配置:

@Configuration
@EnableWebMvc
public class WebMvcOptimizationConfig implements WebMvcConfigurer {/*** 优化HandlerMapping配置*/@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {// 1. 禁用后缀模式匹配(提高性能)configurer.setUseSuffixPatternMatch(false);// 2. 禁用尾随斜杠匹配configurer.setUseTrailingSlashMatch(false);// 3. 注册路径匹配器(缓存URL路径)AntPathMatcher pathMatcher = new AntPathMatcher();pathMatcher.setCachePatterns(true);configurer.setPathMatcher(pathMatcher);}/*** 配置异步处理*/@Overridepublic void configureAsyncSupport(AsyncSupportConfigurer configurer) {// 1. 设置异步请求超时时间configurer.setDefaultTimeout(30000);// 2. 注册异步拦截器configurer.registerCallableInterceptors(new TimeoutCallableProcessingInterceptor());configurer.registerDeferredResultInterceptors(new TimeoutDeferredResultProcessingInterceptor());}/*** 优化静态资源处理*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {// 1. 启用缓存控制registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/").setCacheControl(CacheControl.maxAge(30, TimeUnit.DAYS));}/*** 配置拦截器*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 1. 性能监控拦截器registry.addInterceptor(new RequestTracingInterceptor()).addPathPatterns("/api/**");// 2. 缓存控制拦截器registry.addInterceptor(new CacheControlInterceptor()).addPathPatterns("/static/**");}
}

🚀 异步处理优化

异步控制器实现

@RestController
@Slf4j
public class AsyncUserController {@Autowiredprivate UserService userService;/*** 异步处理用户查询*/@GetMapping("/async/users/{id}")public Callable<User> getUserAsync(@PathVariable Long id) {log.info("主线程接收请求: {}", Thread.currentThread().getName());return () -> {log.info("异步线程处理请求: {}", Thread.currentThread().getName());// 模拟耗时操作Thread.sleep(1000);return userService.getUserById(id);};}/*** DeferredResult 异步处理*/@GetMapping("/async/users/{id}/deferred")public DeferredResult<User> getUserDeferred(@PathVariable Long id) {DeferredResult<User> deferredResult = new DeferredResult<>(5000L); // 5秒超时// 异步处理任务CompletableFuture.supplyAsync(() -> userService.getUserById(id)).whenComplete((result, throwable) -> {if (throwable != null) {deferredResult.setErrorResult(throwable);} else {deferredResult.setResult(result);}});// 超时处理deferredResult.onTimeout(() -> {log.warn("用户查询超时: {}", id);deferredResult.setErrorResult(new TimeoutException("查询超时"));});return deferredResult;}
}

🔍 性能监控端点

MVC 性能监控配置:

@RestController
@Endpoint(id = "mvc-metrics")
public class MvcMetricsEndpoint {@Autowiredprivate RequestMappingHandlerMapping handlerMapping;@ReadOperationpublic Map<String, Object> getMvcMetrics() {Map<String, Object> metrics = new HashMap<>();// 1. 获取所有映射信息Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();metrics.put("totalMappings", handlerMethods.size());metrics.put("mappingDetails", getMappingDetails(handlerMethods));// 2. 获取性能统计metrics.put("performance", getPerformanceStats());return metrics;}private List<Map<String, Object>> getMappingDetails(Map<RequestMappingInfo, HandlerMethod> handlerMethods) {List<Map<String, Object>> details = new ArrayList<>();for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {Map<String, Object> mappingInfo = new HashMap<>();mappingInfo.put("pattern", entry.getKey().getPatternsCondition());mappingInfo.put("method", entry.getKey().getMethodsCondition());mappingInfo.put("handler", entry.getValue().getMethod().getName());mappingInfo.put("controller", entry.getValue().getBeanType().getSimpleName());details.add(mappingInfo);}return details;}
}

📊 优化效果对比

优化前后性能对比:

优化项优化前优化后提升幅度主要优化措施
请求处理时间15 ms8 ms🔼 46.7 %精确包扫描、异步化处理、线程池参数优化
内存占用512 MB384 MB🔼 25 %启用懒加载、按需装配、Bean 作用域精简
并发处理能力(QPS)10001800🔼 80 %优化连接池、Redis Pipeline、批量SQL执行
启动时间12 s7 s🔼 41.7 %移除无关自动配置、懒加载、类加载并行化
http://www.dtcms.com/a/553373.html

相关文章:

  • 网站推广的优势有做二手厨房设备的网站吗
  • 请问聊城做网站wordpress模板个人博客
  • 蒲福风力等级表
  • 小小电脑安装logisim-evolution
  • C# 六自由度机械臂正反解计算
  • 【开题答辩全过程】以 基于Java的旅游网站的设计与开发为例,包含答辩的问题和答案
  • 【深入学习Vue丨第一篇】Props 完全指南
  • U-net 系列算法总结
  • 什么网站可以做模型挣钱网站建设公司有多少家
  • 网站建设的杂志建筑专业网站建设
  • vue3+ts面试题(一)JSX,SFC
  • 网站开发 数字证书网站制作设计方案
  • PCB设计----阻抗不连续的解决方法
  • 网站制作北京网站建设公司哪家好安平县哪家做网站
  • 14. setState是异步更新
  • 22. React中CSS使用方案
  • 深度对比 ArrayList 与 LinkedList:从底层数据结构到增删查改的性能差异实测
  • 信任的重构:S11e Protocol 如何以算法取代中介
  • Python 第二十五节 常用练习问题(三)
  • Spring AI Alibaba 【五】
  • 什么网站是用html做的2023年时政热点事件
  • 泉州企业免费建站制作网站首页
  • 2025年10月31日全球AI前沿动态
  • Linux线程同步(四)
  • 全新升级!山海鲸4.6.3版本正式亮相
  • 图像压缩-将8bit数据压缩为2bit
  • 海宁网站怎么做seo企业网站能起到什么作用
  • 手机在网上怎么创建自己的网站网站开发人员职位
  • LineSlam线特征投影融合(Fuse) 中pML->GetLineNormalVector()的理解代码理解
  • 【图像处理基石】多波段图像融合算法入门:从概念到实践