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

springMvc源码解析

入口:找到springboot的自动配置,将DispatcherServlet和DispatcherServletRegistrationBean注入spring容器(DispatcherServletRegistrationBean间接实现了ServletContextInitializer接口,最终ServletContextInitializer的onStartup()方法会被调用),将DispatcherServlet设置到ServletContext里,设置loadOnStartup属性(默认值-1,表示Servlet对象在用户访问时创建)和addUrlMappings(默认"/")
在这里插入图片描述

		@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,webMvcProperties.getServlet().getPath());registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());multipartConfig.ifAvailable(registration::setMultipartConfig);return registration;}
		@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {//设置UrlMappings 默认"/"DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,webMvcProperties.getServlet().getPath());registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);//设置默认值-1registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());multipartConfig.ifAvailable(registration::setMultipartConfig);return registration;}

DispatcherServletRegistrationBean 在dispatcherServlet存在的情况下创建

一、首先看看springboot是怎么启动tomcat的

1.从SpringApplication.run(WebApplicaiton.class,args),这个入口进入

	public ConfigurableApplicationContext run(String... args) {long startTime = System.nanoTime();DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);refreshContext(context);afterRefresh(context, applicationArguments);Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}listeners.started(context, timeTakenToStartup);callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);listeners.ready(context, timeTakenToReady);}catch (Throwable ex) {handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;}

2.找到refreshContext方法并进入

	private void refreshContext(ConfigurableApplicationContext context) {if (this.registerShutdownHook) {shutdownHook.registerApplicationContext(context);}refresh(context);}

3.找到refresh方法并进入

	protected void refresh(ConfigurableApplicationContext applicationContext) {applicationContext.refresh();}

4.进入到AbstractApplicationContext下的refresh()

	public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);beanPostProcess.end();// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();contextRefresh.end();}}}

5.我们进入ServletWebServerApplicationContext下的onRefresh方法

	protected void onRefresh() {super.onRefresh();try {createWebServer();}catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex);}}

6.进入createWebServer方法

	private void createWebServer() {WebServer webServer = this.webServer;ServletContext servletContext = getServletContext();if (webServer == null && servletContext == null) {StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");ServletWebServerFactory factory = getWebServerFactory();createWebServer.tag("factory", factory.getClass().toString());// 调用spring容器里所有ServletContextInitializer接口实现类的onStartup方法(包含DispatcherServletAutoConfiguration配置类配置的DispatcherServletRegistrationBean类)// 配置DispatcherServlet到tomcat上下文this.webServer = factory.getWebServer(getSelfInitializer());createWebServer.end();getBeanFactory().registerSingleton("webServerGracefulShutdown",new WebServerGracefulShutdownLifecycle(this.webServer));getBeanFactory().registerSingleton("webServerStartStop",new WebServerStartStopLifecycle(this, this.webServer));}else if (servletContext != null) {try {getSelfInitializer().onStartup(servletContext);}catch (ServletException ex) {throw new ApplicationContextException("Cannot initialize servlet context", ex);}}initPropertySources();}

7.再进入TomcatServletWebServerFactory的getWebServer方法(把DispatcherServletRegistrationBean中持有的DispatcherServlet注册到Tomcat中,然后Tomcat会回调DispatcherServlet的init方法把初始化SpringMVC的所有组件)

	public WebServer getWebServer(ServletContextInitializer... initializers) {if (this.disableMBeanRegistry) {Registry.disableRegistry();}Tomcat tomcat = new Tomcat();File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");tomcat.setBaseDir(baseDir.getAbsolutePath());for (LifecycleListener listener : this.serverLifecycleListeners) {tomcat.getServer().addLifecycleListener(listener);}Connector connector = new Connector(this.protocol);connector.setThrowOnFailure(true);tomcat.getService().addConnector(connector);customizeConnector(connector);tomcat.setConnector(connector);tomcat.getHost().setAutoDeploy(false);configureEngine(tomcat.getEngine());for (Connector additionalConnector : this.additionalTomcatConnectors) {tomcat.getService().addConnector(additionalConnector);}//把DispatcherServletRegistrationBean中持有的DispatcherServlet注册到Tomcat中prepareContext(tomcat.getHost(), initializers);return getTomcatWebServer(tomcat);}

8.prepareContext的configureContext()方法配置相关环境

	protected void configureContext(Context context, ServletContextInitializer[] initializers) {TomcatStarter starter = new TomcatStarter(initializers);if (context instanceof TomcatEmbeddedContext) {TomcatEmbeddedContext embeddedContext = (TomcatEmbeddedContext) context;embeddedContext.setStarter(starter);embeddedContext.setFailCtxIfServletStartFails(true);}context.addServletContainerInitializer(starter, NO_CLASSES);for (LifecycleListener lifecycleListener : this.contextLifecycleListeners) {context.addLifecycleListener(lifecycleListener);}for (Valve valve : this.contextValves) {context.getPipeline().addValve(valve);}for (ErrorPage errorPage : getErrorPages()) {org.apache.tomcat.util.descriptor.web.ErrorPage tomcatErrorPage = new org.apache.tomcat.util.descriptor.web.ErrorPage();tomcatErrorPage.setLocation(errorPage.getPath());tomcatErrorPage.setErrorCode(errorPage.getStatusCode());tomcatErrorPage.setExceptionType(errorPage.getExceptionName());context.addErrorPage(tomcatErrorPage);}for (MimeMappings.Mapping mapping : getMimeMappings()) {context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());}configureSession(context);configureCookieProcessor(context);new DisableReferenceClearingContextCustomizer().customize(context);for (String webListenerClassName : getWebListenerClassNames()) {context.addApplicationListener(webListenerClassName);}for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {customizer.customize(context);}}

9.进入getTomcatWebServer(tomcat)得到web的服务端,然后进行初始化

	protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());}
	public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {Assert.notNull(tomcat, "Tomcat Server must not be null");this.tomcat = tomcat;this.autoStart = autoStart;this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;initialize();}

10.初始化

	private void initialize() throws WebServerException {logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));synchronized (this.monitor) {try {addInstanceIdToEngineName();Context context = findContext();context.addLifecycleListener((event) -> {if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {// Remove service connectors so that protocol binding doesn't// happen when the service is started.removeServiceConnectors();}});// Start the server to trigger initialization listenersthis.tomcat.start();// We can re-throw failure exception directly in the main threadrethrowDeferredStartupExceptions();try {ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());}catch (NamingException ex) {// Naming is not enabled. Continue}// Unlike Jetty, all Tomcat threads are daemon threads. We create a// blocking non-daemon to stop immediate shutdownstartDaemonAwaitThread();}catch (Exception ex) {stopSilently();destroySilently();throw new WebServerException("Unable to start embedded Tomcat", ex);}}}

11.调用 this.tomcat.start()方法启动tomcat

方法调用流程图:
在这里插入图片描述
tomcat请求流程分析参考:
https://blog.csdn.net/qq_43188744/article/details/108083683
其中主要是StandardWrapper.allocate()方法,如果发现severlet没有实例化则会进行initServlet(instance)

二、springmvc处理请求

1.DispatcherServlet的初始化

初始化时会进入DispatcherServlet的init()方法
然后会执行onRefresh()方法进行初始化

	protected void onRefresh(ApplicationContext context) {initStrategies(context);}protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);}

2.处理请求

1.进入到HttpServlet 的service,这里会处理get、post等请求

    protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String method = req.getMethod();if (method.equals(METHOD_GET)) {long lastModified = getLastModified(req);if (lastModified == -1) {// servlet doesn't support if-modified-since, no reason// to go through further expensive logicdoGet(req, resp);} else {long ifModifiedSince;try {ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);} catch (IllegalArgumentException iae) {// Invalid date header - proceed as if none was setifModifiedSince = -1;}if (ifModifiedSince < (lastModified / 1000 * 1000)) {// If the servlet mod time is later, call doGet()// Round down to the nearest second for a proper compare// A ifModifiedSince of -1 will always be lessmaybeSetLastModified(resp, lastModified);doGet(req, resp);} else {resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);}}} else if (method.equals(METHOD_HEAD)) {long lastModified = getLastModified(req);maybeSetLastModified(resp, lastModified);doHead(req, resp);} else if (method.equals(METHOD_POST)) {doPost(req, resp);} else if (method.equals(METHOD_PUT)) {doPut(req, resp);} else if (method.equals(METHOD_DELETE)) {doDelete(req, resp);} else if (method.equals(METHOD_OPTIONS)) {doOptions(req,resp);} else if (method.equals(METHOD_TRACE)) {doTrace(req,resp);} else {//// Note that this means NO servlet supports whatever// method was requested, anywhere on this server.//String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[1];errArgs[0] = method;errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);}}

2.进入DispatcherServlet 的doService–>doDispatch()方法,doDispatch()是核心

	/*** Process the actual dispatching to the handler.* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters* to find the first that supports the handler class.* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers* themselves to decide which methods are acceptable.* @param request current HTTP request* @param response current HTTP response* @throws Exception in case of any kind of processing failure*/@SuppressWarnings("deprecation")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 = HttpMethod.GET.matches(method);if (isGet || HttpMethod.HEAD.matches(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.//执行具体HandlerAdapter对象的handle()方法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 afterCompletionif (mappedHandler != null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}

3. 进入getHandler(processedRequest)

	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}

这里的this.handlerMappings默认加在的是DispatcherServlet.properties里面定义的
三个handlerMappings:

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\org.springframework.web.servlet.function.support.RouterFunctionMapping

在初始化调用initHandlerMappings(context),进行初始化的。

4.以AbstractHandlerMapping为例子进入:getHandler方法

	public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {Object handler = getHandlerInternal(request);if (handler == null) {handler = getDefaultHandler();}if (handler == null) {return null;}// Bean name or resolved handler?if (handler instanceof String) {String handlerName = (String) handler;handler = obtainApplicationContext().getBean(handlerName);}// Ensure presence of cached lookupPath for interceptors and othersif (!ServletRequestPathUtils.hasCachedPath(request)) {initLookupPath(request);}HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);if (logger.isTraceEnabled()) {logger.trace("Mapped to " + handler);}else if (logger.isDebugEnabled() && !DispatcherType.ASYNC.equals(request.getDispatcherType())) {logger.debug("Mapped to " + executionChain.getHandler());}if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {CorsConfiguration config = getCorsConfiguration(handler, request);if (getCorsConfigurationSource() != null) {CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);config = (globalConfig != null ? globalConfig.combine(config) : config);}if (config != null) {config.validateAllowCredentials();}executionChain = getCorsHandlerExecutionChain(request, executionChain, config);}return executionChain;}

5.进入AbstractHandlerMethodMapping的getHandlerInternal(request),通过initLookupPath(request)查找HandlerMethod

	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {String lookupPath = initLookupPath(request);this.mappingRegistry.acquireReadLock();try {HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);}finally {this.mappingRegistry.releaseReadLock();}}

6.回到doDispatch,以AbstractHandlerMethodAdapter为例,执行ha.handle

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

7.RequestMappingHandlerAdapter的handleInternal

	protected ModelAndView handleInternal(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ModelAndView mav;checkRequest(request);// Execute invokeHandlerMethod in synchronized block if required.if (this.synchronizeOnSession) {HttpSession session = request.getSession(false);if (session != null) {Object mutex = WebUtils.getSessionMutex(session);synchronized (mutex) {mav = invokeHandlerMethod(request, response, handlerMethod);}}else {// No HttpSession available -> no mutex necessarymav = invokeHandlerMethod(request, response, handlerMethod);}}else {// No synchronization on session demanded at all...mav = invokeHandlerMethod(request, response, handlerMethod);}if (!response.containsHeader(HEADER_CACHE_CONTROL)) {if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);}else {prepareResponse(response);}}return mav;}

8.进入invokeHandlerMethod

	protected ModelAndView invokeHandlerMethod(HttpServletRequest request,HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ServletWebRequest webRequest = new ServletWebRequest(request, response);try {WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);if (this.argumentResolvers != null) {invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}if (this.returnValueHandlers != null) {invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);}invocableMethod.setDataBinderFactory(binderFactory);invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);ModelAndViewContainer mavContainer = new ModelAndViewContainer();mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));modelFactory.initModel(webRequest, mavContainer, invocableMethod);mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);asyncWebRequest.setTimeout(this.asyncRequestTimeout);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.setTaskExecutor(this.taskExecutor);asyncManager.setAsyncWebRequest(asyncWebRequest);asyncManager.registerCallableInterceptors(this.callableInterceptors);asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);if (asyncManager.hasConcurrentResult()) {Object result = asyncManager.getConcurrentResult();mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];asyncManager.clearConcurrentResult();LogFormatUtils.traceDebug(logger, traceOn -> {String formatted = LogFormatUtils.formatValue(result, !traceOn);return "Resume with async result [" + formatted + "]";});invocableMethod = invocableMethod.wrapConcurrentResult(result);}invocableMethod.invokeAndHandle(webRequest, mavContainer);if (asyncManager.isConcurrentHandlingStarted()) {return null;}return getModelAndView(mavContainer, modelFactory, webRequest);}finally {webRequest.requestCompleted();}}

9.进入invocableMethod.invokeAndHandle(webRequest, mavContainer)

	public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,Object... providedArgs) throws Exception {//处理请求,通过反射调用方法Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);setResponseStatus(webRequest);if (returnValue == null) {if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {disableContentCachingIfNecessary(webRequest);mavContainer.setRequestHandled(true);return;}}else if (StringUtils.hasText(getResponseStatusReason())) {mavContainer.setRequestHandled(true);return;}mavContainer.setRequestHandled(false);Assert.state(this.returnValueHandlers != null, "No return value handlers");try {//处理返回值,通过MessageConverters转换为想要的格式this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);}catch (Exception ex) {if (logger.isTraceEnabled()) {logger.trace(formatErrorForReturnValue(returnValue), ex);}throw ex;}}

相关文章:

springMvc源码解析

入口&#xff1a;找到springboot的自动配置&#xff0c;将DispatcherServlet和DispatcherServletRegistrationBean注入spring容器&#xff08;DispatcherServletRegistrationBean间接实现了ServletContextInitializer接口&#xff0c;最终ServletContextInitializer的onStartup…...

采用aar方式将react-native集成到已有安卓APP

关于react-native和android的开发环境搭建、环境变量配置等可以查看官方文档。 官方文档地址 文章中涉及的node、react等版本&#xff1a; node:v16.18.1 react:^18.1.0 react-native:^0.70.6 gradle:gradle-7.2开发工具&#xff1a;VSCode和android studio 关于react-native和…...

Tomcat目录介绍,结构目录有哪些?哪些常用?

bin 启动&#xff0c;关闭和其他脚本。这些 .sh文件&#xff08;对于Unix系统&#xff09;是这些.bat文件的功能副本&#xff08;对于Windows系统&#xff09;。由于Win32命令行缺少某些功能&#xff0c;因此此处包含一些其他文件。 比如说&#xff1a;windows下启动tomcat用的…...

Elasticsearch也能“分库分表“,rollover实现自动分索引

一、自动创建新索引的方法 MySQL的分库分表大家是非常熟悉的&#xff0c;在Elasticserach中有存在类似的场景需求。为了不让单个索引太过于庞大&#xff0c;从而引发性能变差等问题&#xff0c;我们常常有根据索引大小、时间等创建新索引的需求&#xff0c;解决方案一般有两个…...

6 大经典机器学习数据集,3w+ 用户票选得出,建议收藏

内容一览&#xff1a;本期汇总了超神经下载排名众多的 6 个数据集&#xff0c;涵盖图像识别、机器翻译、遥感影像等领域。这些数据集质量高、数据量大&#xff0c;经历人气认证值得收藏码住。 关键词&#xff1a;数据集 机器翻译 机器视觉 数据集是机器学习模型训练的基础&…...

Logview下载

Logview下载 之前一直用的NotePad 后来偶尔的看到作者有发布不当言论 就卸载了又去下载了NotePad– 但是&#xff0c;其实不管是 还是 – 打开大一些的文件都会卡死 所以就搜了这个logview 用起来还不错&#xff0c;目前我这再大的文件 这个软件都是秒打开 但是也会有一点点小…...

macos 下载 macOS 系统安装程序及安装U盘制作方法

01 下载 macOS 系统安装程序的方法 本文来自: https://discussionschinese.apple.com/docs/DOC-250004259 简介 Mac 用户时不时会需要下载 macOS 的安装程序&#xff0c;目的不同&#xff0c;或者升级或者降级&#xff0c;或者研究或者收藏。为了方便不同用户&#xff0c;除…...

c++动态内存分布以及和C语言的比较

文章目录 前言一.c/c内存分布 C语言的动态内存管理方式 C内存管理方式 operator new和operator delete函数 malloc/free和new/delete的区别 定位new 内存泄漏的危害总结前言 c是在c的基础上开发出来的&#xff0c;所以关于内存管理这一方面是兼容c的&…...

软考高级信息系统项目管理师系列之三十一:项目变更管理

软考高级信息系统项目管理师系列之三十一:项目变更管理 一、项目变更管理内容二、项目变更管理基本概念1.项目变更管理定义2.项目变更产生的原因3.项目变更的分类三、项目变更管理的原则和工作流程1.项目变更管理的原则2.变更管理的组织机构3.变更管理的工作程序四、项目变更管…...

【Vue3源码】第二章 effect功能的完善补充

【Vue3源码】第二章 effect功能的完善补充 前言 上一章节我们实现了effect函数的功能stop和onstop&#xff0c;这次来优化下stop功能。 优化stop功能 之前我们的单元测试中&#xff0c;stop已经可以成功停止了响应式更新&#xff08;清空了收集到的dep依赖&#xff09; st…...

CHAPTER 2 Web Server - apache(httpd)

Web Server - httpd2.1 http2.1.1 协议版本2.1.2 http报文2.1.3 web资源(web resource)2.1.4 一次完整的http请求处理过程2.1.5 接收请求的模型2.2 httpd配置2.2.1 MPM(多进程处理模块)1. 工作模式2. 切换MPM3. MPM参数配置2.2.2 主配置文件1. 基本配置2. 站点访问控制常见机制…...

【Vagrant】下载安装与基本操作

文章目录概述软件安装安装VirtualBox安装Vagrant配置环境用Vagrant创建一个VMVagrantfile文件配置常用命令概述 Vagrant是一个创建虚拟机的技术&#xff0c;是用来创建和管理虚拟机的工具&#xff0c;本身自己并不能创建管理虚拟机。创建和管理虚拟机必须依赖于其他的虚拟化技…...

常用类(五)System类

(1)System类常见方法和案例&#xff1a; &#xff08;1&#xff09;exit:退出当前程序 我们设计的代码如下所示&#xff1a; package com.ypl.System_;public class System_ {public static void main(String[] args) {//exit: 退出当前程序System.out.println("ok1"…...

Navicat Premium 安装 注册

Navicat Premium 一.Navicat Premium的安装 1.暂时关闭windows的病毒与威胁防护弄完再开&#xff0c;之后安装打开过程中弹窗所有警告全部允许,不然会被拦住 2.下载安装包&#xff0c;解压 链接&#xff1a;https://pan.baidu.com/s/1X24VPC4xq586YdsnasE5JA?pwdu4vi 提取码…...

回溯算法总结

首先回溯算法本身还是一个纯暴力的算法&#xff0c;只是回溯过程可能比较抽象&#xff0c;导致大家总是感觉看到的相关题目做的不是很顺畅&#xff0c;回溯算法一般来说解决的题目有以下几类&#xff1a;组合问题&#xff1a;lq77、lq17、lq39、lq40、lq216、切割问题&#xff…...

ccc-pytorch-基础操作(2)

文章目录1.类型判断isinstance2.Dimension实例3.Tensor常用操作4.索引和切片5.Tensor维度变换6.Broadcast自动扩展7.合并与分割8.基本运算9.统计属性10.高阶OP大伙都这么聪明&#xff0c;注释就只写最关键的咯1.类型判断isinstance 常见类型如下&#xff1a; a torch.randn(…...

独居老人一键式报警器

盾王居家养老一键式报警系统&#xff0c;居家养老一键式报警设备 &#xff0c;一键通紧急呼救设备&#xff0c;一键通紧急呼救系统&#xff0c;一键通紧急呼救器 &#xff0c;一键通紧急呼救终端&#xff0c;一键通紧急呼救主机终端产品简介&#xff1a; 老人呼叫系统主要应用于…...

软考案例分析题精选

试题一&#xff1a;阅读下列说明&#xff0c;回答问题1至问题4&#xff0c;将解答填入答题纸的对应栏内。某公司中标了一个软件开发项目&#xff0c;项目经理根据以往的经验估算了开发过程中各项任务需要的工期及预算成本&#xff0c;如下表所示&#xff1a;任务紧前任务工期PV…...

基于SpringBoot+vue的无偿献血后台管理系统

基于SpringBootvue的无偿献血后台管理系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背…...

详解js在事件中,如何传递复杂数据类型(数组,对象,函数)

文章目录 前言一、何谓预编译&#xff0c;变量提升&#xff1f;二、复杂数据类型的传递 1.数组2.对象3.函数总结前言 在JavaScript这门编程语言学习中&#xff0c;如何传参&#xff0c;什么是变量提升&#xff0c;js代码预编译等等。要想成为一名优秀的js高手&#xff0c;这些内…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

MySQL JOIN 表过多的优化思路

当 MySQL 查询涉及大量表 JOIN 时&#xff0c;性能会显著下降。以下是优化思路和简易实现方法&#xff1a; 一、核心优化思路 减少 JOIN 数量 数据冗余&#xff1a;添加必要的冗余字段&#xff08;如订单表直接存储用户名&#xff09;合并表&#xff1a;将频繁关联的小表合并成…...