全网最容易理解的spring dispatcher请求流程解析,看不懂你打我

Silverlight企业应用复盘:RIA技术演进与跨平台工程启示 富互联网应用(RIA)是Web前端发展史上的关键范式,其核心目标是在浏览器中实现接近桌面级的交互性能与开发效率。Silverlight作为.NET生态主导的RIA技术,依托CLR轻量运行时、XAML声明式UI和MVVM架构,解决了企业级系统对UI一致性、业务逻辑复用与安全可控的刚性需求。它虽因插件依赖与生态断层退出历史舞台,却为现代跨平台实践埋下伏笔——从WebAssembly的字节码统一,到Flutter的渲染层抽象,再到GraphQL的数据层标准化,本质都是对RIA原始命题的分层重构与工程化兑现。本文基 阅读详情

servlet

在了解dispatcherServlet的流程前,首先要了解servlet这个技术。

狭义的来说,servlet只是一个接口,广义的来说,他是一个规范。

在传统的Javaweb项目里,通过继承HttpServlet(实现了service接口)重写doGet,doPost方法,再在web.xml里标识。通过tomcat作为servlet容器来管理这些servlet。

tomcat在不考虑io模型通信情况下, 只有两个主要的功能。

  • 封装request,response对象
  • 调用servlet的service方法

这个是理解dispatcher流程的关键,首先要知道tomcat到底是干什么的

我们可以看下HttpServlet的service方法的源码

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }
复制代码

也就是说传统的servlet的项目中,tomcat把请求封装后根据url调用对应路径的servlet,执行service方法,再判断请求类型去调用doGet(),doPost()等。

dispatcherServlet和servlet的关系

dispatcherServlet依赖关系很复杂,简单来说就是他间接的实现了servlet接口。先看下servlet接口的方法

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}
复制代码

我们一会重点说下init和service方法。

对于springmvc来说,需要在web.xml里配置dispatcherServlet,让tomcat去管理。对于spring的项目,tomcat只需要管理spring自带的servlet就可以了,我们不需要去写servlet,我们是通过bean让spring容器去管理。这里的spring容器和tomcat容器不是一个概念。

springboot基于自动配置不需要去手动配置。

根据上面所说,任何路径下的请求,tomcat都会调用spring的dispatcherServlet的service方法去处理,由于依赖关系复杂,service方法是在dispatcher的父类。总结来说, 最后会调用dispatch的doDispatch方法 ,中间会有些过程,这里就忽略不计了。

流程

丑陋的面经只会甩给你一张图

硬背这种八股文,完全不知道他的理念和实现细节,对我们的思想是没有一点好处的。所以要剖析下他的源码。

初始化

首先要对spring容器初始化刷新容器,才能进行交互。对于springmvc来说,tomcat会先执行dispatcher的init方法(其实是HttpServletBean的init方法)来刷新容器,底层就是调用的refresh方法。对于springboot来说,会执行main方法的run方法,里面执行一个refresh方法来刷新容器。虽然仍然会执行init方法,但里面的refresh方法应该是不会再执行的。(虽然不知道springboot为什么可以不让执行,但根据打断点来说,他确实没有执行)。总之殊途同归。

请求流程

我再把之前的捋一遍,请求过来后,先被tomcat封装request,response对象,在调用service方法,即dispatchServlet的doDispatch方法,直接看源码

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}
复制代码

这么看复杂的一比,实际上对比丑陋面经的图片,只有几个方法比较重要。

//从Handler映射器获取handlerchain
mappedHandler = getHandler(processedRequest);
//获取适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//执行handler,获取ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//判断mv中的视图是否为空
applyDefaultViewName(processedRequest, mv);
//视图解析
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
复制代码

感觉这应该是spring中最容易理解的源码了,我们逐条分析。

映射器

首先是getHandler()方法

protected HandlerExecutionChain getHandler(HttpServletRequest request) {
        //this.handlerMappings就是一个HandlerMapping数组,Spring容器启动后,会将所有定义好的映射器对象存放在这个数组里
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}
复制代码

这个理解起来很简单,由于有多种的Handler,就有多种的mapping,需要找到正确的mapping

  • RequestMappingUrlHandlerMapping 最常见的使用注解标识的handler映射
  • BeanNameUrlHandlerMapping
  • SimpleUrlHandlerMapping
  • ControllerClassNameHandlerMapping

其中第一个最为常见,使用@requestMapping注解标识的handlermapping,其他的有继承controller,httpservlet的,就不多说了。

通过循环,直到找到正确的处理器映射器,获取到handle,实际上是一个HandlerExecutionChain,他的构成其实就是拦截器数组+handler。

适配器

上一步获取到了处理器链后,获取适配器,通过getHandlerAdapter方法,参数为handler(目前拦截器数组还没有用)

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
复制代码

这里就用上了大名鼎鼎的 适配器模式 了

如果不使用适配器,以后再增加handle种类时,由于不同handle之间的逻辑完全不一样,需要通过在dispatch中使用if else的方式去判断handle的种类,再执行操作。

protected HandlerAdapter getHandlerAdapter(Object handler) {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		};
	}
复制代码

这里的this.handlerAdapters是获取适配器数组,跟上面有点像。获取到合适的适配器返回。

适配器执行handle方法

适配器使用handle方法执行

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
复制代码

最后得到了一个modelandview。在古老的jsp时代,是通过modelandview传递数据并解析jsp视图的。但由于现在前后端分离,使用@ResponseBody注释只传送json串,所以这里的modelandview为空。

所以接下来的视图解析部分我们就不关注了

拦截器

所以handerchain里的拦截器作用是什么呢。

其实在适配器执行handle方法 前后 会进行一个拦截器的处理,只是我没有写而已。

最后

tomcat的处理,我就不说了

小结

springmvc这块的流程如果不深挖其实很简单,基本上有过开发经验的都能够大概了解这块的流程。但其实我上面省略了一部分,就是适配器的 handle 方法和映射器的 getHandler 方法。这块比较难理解,所以我这里只介绍前后端分离和常用注解的情况,我尽量从顶向下的方式去说明源码。

映射器的源码分析

面经简略版

  1. 在ioc初始化时,映射器也会初始化,就把映射对应关系放在一个map里
  2. 映射器的 getHandler 方法,通过url的后缀,从map中获取到对应的handler

详细版

先说下HandlerMapping的继承关系

实际上最常用的就是 RequestMappingHandlerMapping ,他对应的就是@Controller @RequestMapping这种写法的handle映射器。我这里就只介绍这一个映射器了。

我们直接从请求流程来看

首先先是在dispatcher里循环映射器列表,调用getHandler方法(上面有写),实际就是调用AbstractHandlerMapping的getHandler方法

AbstractHandlerMapping

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		//省略版
		Object handler = getHandlerInternal(request);
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
		return executionChain;
	}
复制代码

这个getHandlerInternal()返回的就是我们需要的handle,点进去会调用 AbstractHandlerMethodMapping 的方法

getHandlerInternal()

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    //获取url,例如/user/login
    String lookupPath = initLookupPath(request);
    //获取HandlerMethod,核心方法
    HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
    return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
复制代码

先看返回值,返回了一个 HandlerMethod ,这个就是我们的处理器。之前说过,springmvc有多种handler,每个handle的处理逻辑都不一样,通过不同映射器获得的handler都不同,之后需要通过适配器来统一规范执行。这个后面再说,总之 HandlerMethod 这个对象很重要。

HandlerMethod类

看下HandlerMethod类的构造

//省略了很多
public class HandlerMethod {

   private final Object bean;

   private final Method method;
 }
复制代码

就介绍下这两个成员变量吧。bean就是controller的bean,Method是映射到controller的方法,Method不懂的话可以去看下反射的原理。总之在后面适配器那里会执行method的invoke方法,也就是执行controller上映射的方法。

我们在返回刚才的方法,看下核心方法 lookupHandlerMethod

lookupHandlerMethod()

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<>();
		//重点
		List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
		addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
		Match bestMatch = matches.get(0);
		handleMatch(bestMatch.mapping, lookupPath, request);
		return bestMatch.handlerMethod;
	}
复制代码

这个代码我进行了疯狂的省略,把一些多映射或者空的情况删掉了,我们先去理解正常代码的一个流程。

我们来分析下第二行重点代码,this. mappingRegistry .getMappingsByDirectPath(lookupPath),我们首先要看这个 mappingRegistry 是什么。

mappingRegistry类

class MappingRegistry {

   private final Map<T, MappingRegistration<T>> registry = new HashMap<>();

   private final MultiValueMap<String, T> pathLookup = new LinkedMultiValueMap<>();

   private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();

   private final Map<HandlerMethod, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();

   private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
}
复制代码

mappingRegistry是一个内部类,里面都是一堆map。这个getMappingsByDirectPath方法只是从 pathLookup 这个map里,以lookupPath(url,例如/user/login)为key获取值而已,这个值就是我们的handler。

这时候问题就来了,这些map是什么时候获取的内容呢

在springioc容器初始化时,映射器也会初始化,就把映射对应关系放在pathLookup这个map里。具体流程就跟容器初始化有关了,我就不详细叙述了。

小结

可以发现,对于这种请求来说,根本就没用到RequestMappingHandlerMapping的方法,都是他的父类AbstractHandlerMapping的方法。之后的流程就很简单了,只是把handlerMethod封装成handerchain,返回了。

适配器的源码分析

面经简略版

  • 调用 RequestMappingHandlerAdapter 的handle方法,实际是通过反射调用controller的方法,并返回值
  • 根据返回值选择特定的返回值解析器(例如使用@Response注解返回的是对象,则使用RequestResponseBodyMethodProcessor,将对象序列化为json)
  • 最后返回的mv为null,跳过了视图解析器。

详细版

HandlerAdapter

上面流程的模块介绍了适配器有很多种,他们都实现了HandleAdapter接口,看下接口的源码

public interface HandlerAdapter {
  boolean supports(Object handler);

  ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
}

复制代码

同样省略,重要的只有这两个方法。

第一个方法在上文循环判断 是否合适 时调用过,第二个方法就是dispatcher里的执行方法,返回一个modelAndView。这么一看很简单吗,所以我们来看下他的实现类。

由于handle种类很多,就会对应了很多的适配器

我们平常@Controller出来的 HandlerMethod 使用的是 RequestMappingHandlerAdapter ,是这里最复杂的。为什么复杂呢,因为他涉及了很多的url映射,参数和返回值的处理。这里我先举一个简单的例子,SimpleServletHandlerAdapter,servlet类型的handler适配器。

SimpleServletHandlerAdapter

public class SimpleServletHandlerAdapter implements HandlerAdapter {
   public boolean supports(Object handler) {
      return (handler instanceof Servlet);
   }

   public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
      ((Servlet) handler).service(request, response);
      return null;
   }
}
复制代码

这里先说明一点,spring也是可以使用servlet规范的写法的,例如继承httpservlet,只是还会走mvc的流程,因为这种servlet不归tomcat管理,而是作为一个bean被spring容器管理。

可以看到这个实现类和他的名字一样简单。supports只是判断了handler是否是servlet类型,handle只是调用了service。

AbstractHandlerMethodAdapter

//简化版
public abstract class AbstractHandlerMethodAdapter implements HandlerAdapter {
    public final boolean supports(Object handler) {
        return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
    }

    protected abstract boolean supportsInternal(HandlerMethod handlerMethod);

    public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler){
		return handleInternal(request, response, (HandlerMethod) handler);
	}

    protected abstract ModelAndView handleInternal(HttpServletRequest request,
			HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
}
复制代码

先看RequestMappingHandlerAdapter的抽象类。

  • supports判断类型是否是 HandlerMethod ,除此之外还有个新方法supportsInternal,但是对于RequestMappingHandlerAdapter来说,这个方法一直返回true。所以我们可以认为, 当一个Handler是HandlerMethod 类型的时候, 就会被这个适配器处理。这里的重点就是 HandlerMethod ,他代表这我们平常使用的handler类型
  • handle调用新方法handleInternal,作为参数的handler被强转为 HandlerMethod 类型

handle方法流程

刚才简单介绍下父类适配器的接口,接下来看流程

上面说到,dispatcher会先循环获取对应的handleAdapeter,通过的就是supports方法,我就忽略掉了。

然后会调用handle方法,其实就是RequestMappingHandlerAdapter的 handleInternal 方法

RequestMappingHandlerAdapter

handleInternal()

protected ModelAndView handleInternal(){
    ModelAndView mav;
    mav = invokeHandlerMethod(request, response, handlerMethod);
    return mav;
}
复制代码

在抽象的省略后,只剩下invokeHandlerMethod方法

invokeHandlerMethod()

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
      HttpServletResponse response, HandlerMethod handlerMethod) {
    
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        //ServletInvocableHandlerMethod是HandlerMethod的子类
        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        //核心
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        return getModelAndView(mavContainer, modelFactory, webRequest);
}
复制代码

这里有大量异步和mavcontainer的部分我都删掉了,没意义的同时也是因为我看不懂,我就不分析了。

这块代码核心就是invocableMethod.invokeAndHandle(webRequest, mavContainer),分析下参数。

  • webRequest request的封装
  • mavcontainer在前后端分离情况都是为空的。

HandlerMethod子类

public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
			Object... providedArgs) throws Exception {
        //获得返回值,providedArgs为参数
		Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
        //返回值解析
		this.returnValueHandlers.handleReturnValue(
					returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
	}
复制代码
public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer,
      Object... providedArgs) throws Exception {
	//参数解析器,例如@RequestBody,对象,变量之类的,对参数解析之后放入args数组,
   Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
   return doInvoke(args);
}
复制代码
protected Object doInvoke(Object... args) throws Exception {
        //获取method,这个method就是controller对应url的方法
		Method method = getBridgedMethod();
        //反射调用controller的方法
		return method.invoke(getBean(), args);
	}
复制代码

这是请求到controller之前的最后一步,这是InvocableHandlerMethod的 doInvoke 方法。这里只进行了一个简单的反射而已。获取到Method对象后调用invoke方法。也就是执行controller下映射url的方法,我这里举一个例子

@GetMapping
public ApiMsg get(@RequestParam(value = "current", required = false, defaultValue = "1") int current,
                  @RequestParam(value = "size", required = false, defaultValue = "10") int size){
    return adminReportService.selectAllReport(current,size);
}
复制代码

一个极其标准的controller,返回的是一个Object对象

对于返回值和参数值的解析我就不研究了。

小结

对于前后端分离传递json这种写法,modelandview都为空,都是直接对返回值处理的,我就没有关注这个modelandview的处理。

总结

作为最常使用的mvc,应该是对于我们这种web开发来说最容易理解的spring源码了。里面还有很多的学问,包括对不同handler的处理或者不同类之间的区别,jsp的解析等,我才疏学浅就不深究了。如果上面有什么写的不对,请评论告诉我。

HttpClient vs OkHttpClient:哪个更适合你的Java项目?(附性能对比实测) 本文深度对比了Apache HttpClient与OkHttpClient在Java项目中的性能表现与适用场景。通过实际性能测试,OkHttp在连接复用、高并发吞吐量及内存占用方面表现更优,尤其适合现代微服务与Spring生态。HttpClient则凭借其高度可配置性,在需要精细控制HTTP协议细节的场景中更具优势。文章提供了清晰的选型指南,帮助开发者根据项目需求做出佳决策。 阅读详情

相关推荐

【信息科学与工程学】计算机科学与自动化 第二百三十三篇 凤凰架构01

编号类型领域系统软件/硬件或系统集成方案及系统架构模块子模块函数名称/算法名称算法的数学分析及计算机体系架构及数据结构与算法详细设计及参数列表及数值范围设计关联知识1共识算法分布式基石状态机复制架构:Proposer/Acceptor/Learner 多节点角色模型,基于操作转移(Operation Transfer)分布式共识PaxosPaxos 协议(Prepare/Promise/Accept/Accepted 两阶段)数学基础:多数派(Quorum)投票,基于鸽巢原理保证 W+R>N 时读写集合必有

weixin_49199313的博客 177

SpringMvc配置dispatcher的方式

SpringMvcp配置dispacther 的方式 web.xml。

m0_51262858的博客 920

2024年上半年试题二:论性能测试方法及其应用

2025年1月,我以系统分析师的身份参与了公司OA系统的开发与建设。该系统包含的功能有打卡签到、公文流转、工资查询等。我们吸取了之前由于系统使用人数激增暴露出的短时间卡顿等问题,所以在本次开发中,我们非常重视系统的性能测试。通过自动化的测试工具模拟多种正常、峰值及异常负载条件对系统的各项性能指标进行测试。性能测试在软件的质量保证中起着重要的作用,它包括的测试内容丰富多样,常见的负载测试和压力测试都属于性能测试。

银帅 511

SpringDispatcherServlet详解及源码解析

一:SpringDispatcherServlet详解及源码解析

li-zhang-yu的博客 1585

学习 - 我大Spring框架之Dispatch 1

本文章不借鉴任何其他文章里的资料,仅为源码的直接解读和理解   翻译完后发现注释的内容十分拗口,4个方法难以理解     Dispatch 是Spring里的一个接口 该接口的直接描述是:“为一个服务的端点操作提供动态调用的支持。javax.xml.ws.Service类充当一个工厂,用于创建Dispatch的实例” 以下是其原文   那么我们开始看看Dispatch内部的方...

lcl088005的博客 304

Spring DispatcherServlet 详解

DispatcherServlet 是一个 Servlet,它接收所有的 HTTP 请求,并根据请求的信息将其分发给相应的处理器(Handler)进行处理。它是 Spring MVC 架构模式中的关键部分,将请求处理逻辑与实际的业务逻辑解耦,使得代码结构更加清晰和易于维护。

dawn191228的博客 1673

第三章、SpringMVC学习-DispatcherServlet详解

javaspringmvcweb 目录(?)[+] 3.1、DispatcherServlet作用 DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。 具体请参考第二章的图2-1。   DispatcherS

u011967230的专栏 547

虚拟电厂技术架构与实现:从概念到工程实践

虚拟电厂(VPP)是一种通过信息通信技术和智能算法,聚合与优化分布式能源资源的智慧能源管理系统。其核心原理在于将分散的光伏、储能、可控负荷等资源进行数字化建模与协调控制,形成一个可统一调度的“云上电厂”。从技术价值看,它能够有效提升电网稳定性、降低用户用能成本,并挖掘分布式资源的市场潜力。在应用场景上,虚拟电厂广泛服务于园区、工厂等用户侧,实现削峰填谷、需求响应和参与电力辅助服务。本文以安科瑞解决方案为例,深入讲解了其协调控制策略与能源管理系统的实现流程,并提供了基于Python和PuLP库的经济调度算法代

weixin_30256901的博客 475

从 Copilot 到 Agent:我的开发工作流正在被颠覆

本文记录了作者从 Copilot 走向 Agent 的真实开发经历。核心观点包括:Agent 的核心优势在于自主规划与跨文件执行,能显著提升重构和测试驱动开发的效率;面对上下文失控与结果不确定性,可通过任务拆解、测试验收和结果校验来应对;开发者的角色正从「实现者」转向「架构师与决策者」,负责定义目标、把控方向与审查质量。

qq_71356343的博客 214

springDispatcherServlet详解

文章目录1. 概述1.1 DispatcherServlet类相关的结构图2. DispatcherServlet的初始化程序2.1 HttpServletBean 的 init() 方法2.1.1 FrameworkServlet 的 initServletBean() 方法2.1.1.1 DispatcherServlet 的 onRefresh() 方法2.2 initStrategies()2.2.1 initHandlerMappings 方法2.2.2 initHandlerAdapters

m0_45406092的博客 1万+

SpringMVC中DispatcherServlet详解

DispatcherServlet是Spring MVC框架的核心组件之一,它负责请求的接收、处理和响应。DispatcherServlet在整个请求处理过程中扮演着调度者的角色,将请求分发到相应的处理器进行处理,并将处理结果返回给客户端

技术人集结地 5261

Spring mvc 核心 DispatcherServlet 详解

与许多其他的 web 框架一样,Spring MVC 也是围绕前端控制器模式设计的,核心的 Servlet DispatcherServlet 为请求处理提供了共享算法,但是实际工作由可配置的委托组件执行的。这种设计非常灵活,可以支持不同的工作流。// 核心Servlet,其他组件可配置DispatcherServlet 和其他 Servlet 一样,也需要通过一些配置去发现它的委托组件(请求映射、视图解析、异常处理等组件),这些配置可以是 Java 代码,也可以是 web.xml 文件。

swadian2008的博客 1668

springMVC源码分析--DispatcherServlet请求获取及处理

在之前的博客 springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过DispatcherServlet其实就是一个HttpServlet,其实他是HttpServlet的子类,所以它和普通的HttpServlet有同样的配置: springmvc

井底之蛙 5558

Spring执行流程

1.spring 容器的启动加载流程 首先解析 spring.xml 配置文件,把其中 &lt;bean&gt; 解析为 BeanDefinition, 存入beanFactory &lt;bean id="" class="" init-method="" destroy-method="" scope="" lazy-init=""&gt; 把 B

bryant_yang的博客 1万+

【Python开发及测试】lava中setup.py解析

#### setup.py内容 setup( name='lava-server', version=version_tag(), author=&quot;Zygmunt Krynicki&quot;, author_email=&quot;lava-team@linaro.org&quot;, namespace_packages=['lava', ], packages=find_p

nitibu的专栏 724

Spring 学习(十)--- Dispatch 分发逻辑

问题 : Spring 分发逻辑是如何的 概述 本文讲解Spring 请求到返回视图的分发过程。 分发逻辑 分发逻辑可以使用下图来表示。 总共七个步骤 : 接收请求,经过 DispatcherServlet 处理器映射,根据url 来判断执行哪里Controller 到了控制器(Controller)处理逻辑 返回模型及逻辑视图名 ...

weixin_34144848的博客 330

Error: Projects must list all files or use an ‘include‘ pattern.

在 is not listed within the file 指明的文件中的 include 中添加或修改路径正则。

qq_57756904的博客 1155

Spring进阶 - SpringMVC实现原理之DispatcherServlet处理请求的过程

前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第二篇:DispatcherServlet处理请求的过程的源码解析

珍惜当下 1258

Spring 原理之 DispatchServlet 原理

Spring MVC 的DispatchServlet解析 Spring MVC 时序图 DispatchServlet 的父类是 FrameworkServlet ,FrameworkServlet的父类是HttpServletBean 核心流程: 寻找DispatchServlet的init()方法,定位到其父类的父类HttpServletBean的init()方法 定位配置文件位置,加载配置信息 initServletBean调用 DispatchServlet的父类FrameworkS

weixin_42272869的博客 2242

Spring DispatcherServlet详解

作为Spring MVC的核心,负责初始化Spring MVC的各个组件,并协调请求处理流程。它通过和等组件,将请求映射到对应的处理器,调用处理器方法,并渲染视图。理解的工作原理对于深入掌握Spring MVC至关重要。版权声明:本博客内容为原创,转载请保留原文链接及作者信息。参考文章【springDispatcherServlet详解_spring dispatcherservlet-CSDN博客。

ning的博客 1564

VOS3000 V2.1.7.03.exe

VOS3000 V2.1.7.03.exe

上一篇: Java进阶笔记 线程池(类比银行业务来理解)
下一篇: 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现
Fightevery
博客等级 码龄5年 20粉丝 223原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值