Spring MVC源码详解

SpringMVC源码分析 目录 1、SpringMVC架构图 2、SpringMVC初始化流程图 3、SpringMVC执行流程图 4、SpringMVC组件解析 5、SpringMVC的工作机制 6、源码分析 6.1 初始化流程 6.2 请求执行流程 7、谈谈SpringMVC的优化 1、SpringMVC架构图 2、SpringMVC初始化流程图 3、SpringMVC执行流程图 用户发送请求至前端控制器DispatcherServlet。 DispatcherServl. 阅读详情

什么是Spring MVC ?

Spring MVC就是Spring+MVC。
Spring就不介绍了,什么是MVC?

  • M:模型,javabean
  • V:视图,如jsp
  • C:控制层,如Controller、Servlet

SpringMVC请求处理流程

在这里插入图片描述

  1. 用户发送请求至前端控制器DispatcherServlet;
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器;
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)HandlerExecutionChain一并返回给DispatcherServlet;
  4. DispatcherServlet通过HandlerAdapter处理器适配器调用处理器,执行处理器(Controller,也叫后端控制器);
  5. Controller执行完成返回ModelAndView,并返回给HandlerAdapter,HandlerAdapter将结果返回给DispatcherServlet;
  6. DispatcherServlet将ModelAndView传给ViewReslover视图解析器,ViewReslover解析后返回具体View给DispatcherServlet;
  7. DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)后返回给给客户;

源码分析

代码调试准备

新建项目

新建Springboot项目,依赖如下:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

打断点

断点打在下面的位置:
org.springframework.web.servlet.DispatcherServlet#initStrategies:初始化阶段
org.springframework.web.servlet.DispatcherServlet#doDispatch:运行调用阶段。

项目调试启动时未进入上面的两个方法,当第一次调用Controller的请求时,会执行初始化阶段代码,每次调用Controller都会调用运行调用阶段代码。

初始化阶段

initStrategies方法初始化

第一次调用Controller时,会调用org.springframework.web.servlet.DispatcherServlet#initStrategies方法初始化SpringMVC的九大组件

protected void initStrategies(ApplicationContext context) {
		//多文件上传组件
		initMultipartResolver(context);
		//初始化本地语言环境
		initLocaleResolver(context);
		//初始化模版处理器
		initThemeResolver(context);
		//初始化处理器映射器
		initHandlerMappings(context);
		//初始化处理器适配器
		initHandlerAdapters(context);
		//初始化异常拦截器
		initHandlerExceptionResolvers(context);
		//初始化视图预处理器
		initRequestToViewNameTranslator(context);
		//初始化视图解析器
		initViewResolvers(context);
		//初始化FlashMap管理器
		initFlashMapManager(context);
	}

org.springframework.web.servlet.DispatcherServlet#initStrategies方法的调用链路如下:
在这里插入图片描述

HandlerMapping初始化

HandlerMapping是处理器映射器,简单讲是Controller中的方法与请求地址的映射关系,通过它可以找到Controller中的方法来处理请求。

什么是Handler?

Handler是controller中带请求路径的方法,最常用的是Controller中@RequestMapping注解标注的方法。如下面getProduct方法是Handler,loginPage方法不是Handler。

@Controller
@Slf4j
public class ClassifyController {
    @Autowired
    IClassifyService classifyService;




    @RequestMapping("/getClassify")
    @ResponseBody
    Object getProduct(){
        log.error("你妹的");
       return classifyService.selectByTenant("0000000001");
    }
//    @GetMapping("/index")
    public String loginPage(Model model){
        model.addAttribute("name","登科");
        return "welcom";
    }

}

Spring中共四种Handler

  • 加RequestMapping注解的方法(常用的)
  • 实现Controller接口的Bean对象(古老的方法)
  • 实现HttpRequestHandler接口的Bean对象(古老的方法)
  • HandlerFunction对象(新的)

什么是HandlerMapping?

HandlerMapping是处理器映射器,简单讲是Controller中的方法与请求地址的映射关系,通过它可以找到Controller中的方法来处理请求。

三种常用的HandlerMapping

  • BeanNameUrlHandlerMapping:处理实现Controller、HttpRequestHandler接口的Bean对象对应的Handler
  • RequestMappingHandlerMapping:处理加RequestMapping注解的方法对应的Handler,也是最常用的。
  • RouterFunctionMapping:处理HandlerFunction对象对应的Handler

HandlerMapping初始化源码分析

private void initHandlerMappings(ApplicationContext context) {
		this.handlerMappings = null;

		if (this.detectAllHandlerMappings) {
			// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
			//获取所有的HandlerMappings,其中包括RequestMappingHandlerMapping
			Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
			if (!matchingBeans.isEmpty()) {
				//将获取到HandlerMapping赋值给DispatcherServlet.handlerMappings 
				this.handlerMappings = new ArrayList<>(matchingBeans.values());
				// We keep HandlerMappings in sorted order.
				AnnotationAwareOrderComparator.sort(this.handlerMappings);
			}
		}
		else {
			try {
				HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
				this.handlerMappings = Collections.singletonList(hm);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, we'll add a default HandlerMapping later.
			}
		}

		// Ensure we have at least one HandlerMapping, by registering
		// a default HandlerMapping if no other mappings are found.
		if (this.handlerMappings == null) {
			this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
			if (logger.isTraceEnabled()) {
				logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
						"': using default strategies from DispatcherServlet.properties");
			}
		}
	}

下面的代码获取了所有的HandlerMapping,其中包括RequestMappingHandlerMapping

Map<String, HandlerMapping> matchingBeans =
					BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);

以RequestMappingHandlerMapping为例,HandlerMapping中是如何为何请求地址与Handler之间的映射呢?

上面的方法通过BeanFactory获取RequestMappingHandlerMapping对应的实例,因为RequestMappingHandlerMapping是单例的,容器启动的时候会创建单例对象。查看RequestMappingHandlerMapping的父类,实现了InitializingBean接口,因此创建实例的时候会执行初始化方法,而绑定请求地址与Handler的逻辑就在初始化方法中。

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSet

public void afterPropertiesSet() {
		this.config = new RequestMappingInfo.BuilderConfiguration();
		this.config.setUrlPathHelper(getUrlPathHelper());
		this.config.setPathMatcher(getPathMatcher());
		this.config.setSuffixPatternMatch(useSuffixPatternMatch());
		this.config.setTrailingSlashMatch(useTrailingSlashMatch());
		this.config.setRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch());
		this.config.setContentNegotiationManager(getContentNegotiationManager());
		//跳转到父类的初始化方法
		super.afterPropertiesSet();
	}

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#afterPropertiesSet

@Override
	public void afterPropertiesSet() {
		initHandlerMethods();
	}

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#initHandlerMethods

protected void initHandlerMethods() {
		for (String beanName : getCandidateBeanNames()) {
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
				//绑定url与Handler的逻辑
				processCandidateBean(beanName);
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#processCandidateBean

protected void processCandidateBean(String beanName) {
		Class<?> beanType = null;
		try {
			beanType = obtainApplicationContext().getType(beanName);
		}
		catch (Throwable ex) {
			// An unresolvable bean type, probably from a lazy bean - let's ignore it.
			if (logger.isTraceEnabled()) {
				logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
			}
		}
		//isHandler方法就是判断这个bean是否是Controller(有@Controller或者@RequestMapping注解)
		if (beanType != null && isHandler(beanType)) {
			detectHandlerMethods(beanName);
		}
	}

org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#detectHandlerMethods
根据给定的Controller,找出这个Controller中的所有Handler,也就是带@RequestMapping注解的方法

protected void detectHandlerMethods(Object handler) {
		Class<?> handlerType = (handler instanceof String ?
				obtainApplicationContext().getType((String) handler) : handler.getClass());

		if (handlerType != null) {
			Class<?> userType = ClassUtils.getUserClass(handlerType);
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.MetadataLookup<T>) method -> {
						try {
							return getMappingForMethod(method, userType);
						}
						catch (Throwable ex) {
							throw new IllegalStateException("Invalid mapping on handler class [" +
									userType.getName() + "]: " + method, ex);
						}
					});
			if (logger.isTraceEnabled()) {
				logger.trace(formatMappings(userType, methods));
			}
			methods.forEach((method, mapping) -> {
				Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
				registerHandlerMethod(handler, invocableMethod, mapping);
			});
		}
	}

最后通过org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#registerHandlerMethod方法将映射关系维护到org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#registry对应的Map中。key是mapping对象,其实就是@RequestMapping注解中对应的信息,value是MappingRegistration对象。

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

MappingRegistration中

  • mapping是@RequestMapping注解中对应的信息

  • handlerMethod是Handler,也就是@RequestMapping注解的方法

  • directUrl是请求地址,这里观察是/getClassify

  • mappingName是映射的名称,这里观察室CC#getProduct

private static class MappingRegistration<T> {

		private final T mapping;

		private final HandlerMethod handlerMethod;

		private final List<String> directUrls;

		@Nullable
		private final String mappingName;
		............
}

HandlerMapping初始化总结

  • org.springframework.web.servlet.DispatcherServlet#initStrategies:初始化SpringMVC的九大组件。第一次调用请求Controller时,会初始化DispatcherServlet,因此会调用该方法
  • org.springframework.web.servlet.DispatcherServlet#initHandlerMappings:初始化处理器映射器
  • 获取所有的处理器映射器实例,并放入到org.springframework.web.servlet.DispatcherServlet#handlerMappings中,其实是List。以RequestMappingHandlerMapping这个处理器映射器为例子,因为RequestMappingHandlerMapping是单例、非延时加载,因此启动项目时会实例化该对象,handlerMappings是直接从缓存中获取的对象。
  • 实例化RequestMappingHandlerMapping对象时会调用初始化方法org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSet
  • 初始化方法会调用父类初始化方法org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#afterPropertiesSet
  • 父类初始化方法中会调用org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#initHandlerMethods
  • initHandlerMethods方法中会调用org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#processCandidateBean
  • processCandidateBean方法中,会判断是否为Controller,如果是则调用org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#detectHandlerMethods,该方法会查找Controller中所有的Handler,也就是该Controller所有标注@RequestMapping注解的方法,并解析注册到org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#registry中 。
  • 最终请求相关的信息和Handler就会绑定在一起,存储在HandlerMapping中。

运行调用阶段

随便调用一个Controller中的请求,会访问到org.springframework.web.servlet.DispatcherServlet#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.
				//根据请求获取handler,获取到的是HandlerExecutionChain,HandlerExecutionChain中包括handler和interceptors
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					//走没有Handler的逻辑,404
					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.
				//调用handler,也就是Controller中对应的@RequestMapping注解的方法,并返回ModelAndView
				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

下面的代码是根据请求获取handler,获取到的是HandlerExecutionChain,HandlerExecutionChain中包括handler和interceptors。

mappedHandler = getHandler(processedRequest);

org.springframework.web.servlet.DispatcherServlet#getHandler方法,遍历所有的handlerMapping,其中包括RequestMappingHandlerMapping,根据Request通过HandlerMapping获取Handler。

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;
	}

org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler方法,根据请求获取HandlerExecutionChain。HandlerExecutionChain中包含handler和interceptors。因为初始化阶段初始化HandlerMapping时,已经将请求信息与Handler绑定到一起,所以这里可以通过绑定信息获取,不继续往下跟了。

根据请求获取HandlerAdapter

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

之前初始化阶段也初始化了HandlerAdapter,因此有下面的几个:
在这里插入图片描述
org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter方法中,循环遍历HandlerAdapter,匹配到则返回,这里匹配到了RequestMappingHandlerAdapter。

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {//初始化阶段获取的实例
			for (HandlerAdapter adapter : this.handlerAdapters) {//遍历所有的HandlerAdapter ,匹配到则返回
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		}
		throw new ServletException("No adapter for handler [" + handler +
				"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
	}

调用通过HandlerAdapter调用handler

这里执行了Controller中@RequestMapping注解的方法,走到了请求真正想处理的逻辑,并返回ModelAndView

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

org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle方法:

@Override
	@Nullable
	public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return handleInternal(request, response, (HandlerMethod) handler);
	}

调用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal方法

调用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod

上面的方法中通过下面代码,最终通过反射调用方法。

invocableMethod.invokeAndHandle(webRequest, mavContainer);

视图解析器返回View,并渲染页面

org.springframework.web.servlet.DispatcherServlet#processDispatchResult

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {

		boolean errorView = false;

		if (exception != null) {//如果有异常则渲染异常页面
			if (exception instanceof ModelAndViewDefiningException) {
				logger.debug("ModelAndViewDefiningException encountered", exception);
				mv = ((ModelAndViewDefiningException) exception).getModelAndView();
			}
			else {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(request, response, handler, exception);
				errorView = (mv != null);
			}
		}

		// Did the handler return a view to render?
		if (mv != null && !mv.wasCleared()) {
			//获取视图并进行渲染
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("No view rendering, null ModelAndView returned.");
			}
		}

		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Concurrent handling started during a forward
			return;
		}

		if (mappedHandler != null) {
			// Exception (if any) is already handled..
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

获取视图并进行页面渲染

if (mv != null && !mv.wasCleared()) {
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}

org.springframework.web.servlet.DispatcherServlet#render
方法中

//根据视图解析器获取视图,这里的视图解析器是初始化的时候通过initViewResolvers方法获取的
view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
			Locale locale, HttpServletRequest request) throws Exception {

		if (this.viewResolvers != null) {
			for (ViewResolver viewResolver : this.viewResolvers) {
				View view = viewResolver.resolveViewName(viewName, locale);
				if (view != null) {
					return view;
				}
			}
		}
		return null;
	}

org.springframework.web.servlet.DispatcherServlet#render方法中的下面代码,对视图进行渲染。

view.render(mv.getModelInternal(), request, response);

SpringMVC运行调用阶段源码总结

  • org.springframework.web.servlet.DispatcherServlet#getHandler:根据请求通过HandlerMapping获取Handler
  • org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter:根据Handler获取HandlerAdapter
  • org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#handle:调用HandlerAdap的handle方法,执行Handler(Controller中的方法)中的逻辑,返回ModelAndView。
  • org.springframework.web.servlet.DispatcherServlet#processDispatchResult:处理视图相关逻辑
  • org.springframework.web.servlet.DispatcherServlet#resolveViewName:根据视图解析器获取视图View
  • 调用View的render方法渲染jsp页面
SpringMVC源码深度解析 springmvc的源码解析,建议收藏,多看几遍!!! 阅读详情

相关推荐

Spring MVC源码分析——初始化过程

1.      概述 对于Web开发者,MVC模型是大家再熟悉不过的了,SpringMVC中,满足条件的请求进入到负责请求分发的DispatcherServlet,DispatcherServlet根据请求url到控制器的映射(HandlerMapping中保存),HandlerMapping最终返回HandlerExecutionChain,其中包含了具体的处理对象handler(也即我们编程

看看写写,记录所学,权当笔记の 3万+

SpringMvc源码全解

文章目录一、SpringMVC请求处理流程2、 一、SpringMVC请求处理流程 SpringMVC的核心组件和请求处理流程如下: 1、 DispatcherServlet是SpringMVC中的前端控制器(front controller),负责接收request并将request转发给对应的处理组件。 2、HanlerMapping是SpringMVC中完成url到Controller映射的组件。DispatcherServlet接收request,然后从HandlerMapping查找处

weixin_38650898的博客 4308

Qualcomm工具的使用

简介   由于我们公司主要是以高通平台为主,所以工具的使用是必不可少的,包括QPST、QRCT3、QXDM、QDART等。   高通工具顾名思义就是,对于高通平台的软件开发进行软件的烧录,软件的调试,软件的Log的抓取和分析过程,像我们平常用的大致就是烧版本、改NV、制作QCN、然后校准、强发强收等操作。 QPST   QPST主要是用来做一些参数的配置,包括EFS文件的编辑,QCN的导入和备份与...

Jimmy 2万+

Spring MVC源码分析

一、SpringMVC请求处理流程 在阅读源码之前先进行SpringMVC源码环境的搭建SpringMVC环境搭建 里面也对Controller控制器的几种实现方式,进行了简单说明,便于我们后续的理解。 下面也给一张流程图,方便我们进行梳理。 DispatcherServlet:DispatcherServlet是SpringMVC中的前端控制器,负责接收request并将request转发给对应的处理组件。 HandlerMapping:HanlerMapping是SpringMVC.

Jak的博客 5557

解决Word中英文混排的5个常见排版问题(含单词换行、间距调整等)

本文详细解析Word中英文混排的5大常见排版问题,包括单词换行、间距调整、标点混用等,提供专业解决方案。通过设置段落格式、调整兼容性选项和使用字体组合等技巧,帮助用户轻松解决文档排版难题,提升专业性和阅读体验。

vim8coder的博客 1332

Trae+Playwright MCP自动化测试全流程指南:从环境搭建到智能体运行

本文提供了一份详细的Trae与Playwright MCP集成指南,涵盖从Node.js、Python环境搭建到智能体创建的全流程。通过结合MCP协议,AI智能体能够理解任务并驱动Playwright执行复杂的浏览器自动化操作,实现从网页数据抓取到端到端测试的智能工作流。

banana的博客 531

超详细SpringMVC源码剖析

Nullable= null) {for (ViewResolver viewResolver : this.viewResolvers) {//viewResolvers存放了两个视图解析器(1)InternalResourceViewResolver默认视图解析器 (2)BeanNameViewResolver自定义视图解析器if (view!= null) {//如果返回的视图为空,那么会继续遍历所有的视图解析器;

m0_59084856的博客 2760

【excel+vba】一表拆多表+不同收件人附带不同附件

快捷处理:拆分多个不同表 给不同人发送不同内容且附带附件

weixin_42779327的博客 2968

【spring】Spring MVC 类图与源码请求处理流程

类图清晰:DispatcherServlet➡️HandlerMapping➡️HandlerAdapter➡️Controller➡️ViewResolver➡️View来源:DispatcherServlet.doDispatch() 为中心,全流程控制参数解析、消息转换、JSON 支持都是通过策略组件实现结合源码拆解流程,能快速知道每个环节干了啥我精心收集了一份10万字的java全面知识总结,包括了java几乎所有的面试基础解读,有兴趣可以获取看看领取方式。

2401_88055648的博客 1361

SRS(简单实时视频服务) 笔记(5)- 视频录制

在SRS使用中实现视频录制功能。

irainsa的博客 1698

基于Simulink的伺服电机位置闭环控制仿真

本文带你从零构建了伺服电机位置闭环控制系统​ 的完整Simulink仿真模型,实现了:✅ 搭建PMSM伺服电机、逆变器、机械臂负载的主电路与编码器反馈模型;✅ 用MATLAB Function实现三环控制(位置环PID、坐标变换、电流环PI);✅ 验证阶跃定位(稳态误差0.002°、响应0.08s)与正弦跟踪(误差0.008°)的高性能;✅ 对比开环控制,明确位置闭环在精度、响应、抗扰上的优势;✅ 理解“三环嵌套+反馈校正”的核心思想(精密定位的工程实现)。核心收获。

amy_mhd的博客 173

Spring MVC 源码跟踪

按照程序执行流程看下执行顺序 当我们发送一个请求的时候,最开始进入的是DispatcherServlet 我们来看下这个类: 看图查看这个类的引用后,会发现他就是一个标准的Servlet 然而Servlet的生命周期是: init()——>service()——>distory() 在DispatcherServlet父类FrameworkServlet类中没有发现init()方法,...

weixin_42862203的博客 294

YOLOv11改进缝合FasterBlock | 一种新型轻量化卷积结构C3k2的设计与实证:兼顾精度与速度的改进方法(附代码)

YOLO系列一直是目标检测领域的明星算法,凭借其实时性和准确性在众多应用中占据一席之地。随着YOLO版本的不断迭代,网络架构逐渐变得更为复杂,尤其是在卷积模块的设计上。本文将介绍如何利用FasterNet的FasterBlock创新,并通过二次创新C3k2提出一种全新的卷积结构。该结构旨在提高YOLOv11的计算效率和准确性,特别是在视觉任务中的表现。我们的创新在保证高精度的前提下,有效降低了计算量和内存需求,特别适合在资源受限的设备上运行。

一键难忘的博客 906

spring 源码解读-MVC

spring 源码解读-MVC

杨宇昌的博客 222

LeRobot 入门教程(一)软件环境、部署流程及摄像头配置

🤖 LeRobot:开源机器人学习平台 摘要:LeRobot是一个基于PyTorch的开源机器人学习平台,提供模型、数据集和工具,旨在降低机器人技术门槛。平台包含经过验证的模仿学习和强化学习方法,并提供预训练模型、人类演示数据集及模拟环境。安装需从源码获取,支持Python 3.10环境,可选扩展包括仿真环境(如gym-aloha)、电机控制(Dynamixel/Feetech SDK)和实验跟踪(Weights & Biases)。该平台托管在HuggingFace,并设有社区Discord频道

2506_90492529的博客 3416

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Spring MVC ViewResolver 源码详解与主流程解析

Spring MVC 的 ViewResolver 体系,以高度解耦和策略模式为核心,实现了视图技术的灵活切换与扩展。主流程围绕视图名解析、对象创建、渲染三步展开,源码实现简洁明了,缓存与链式组合提升了性能与可维护性。开发调试需关注配置顺序与性能瓶颈,业务场景可灵活应用于多视图、API、错误页面等。与其他技术栈的集成进一步提升了开发效率和系统扩展性。速记总口诀“视图名,找对象,拼路径,创视图,模型加,转发去;多个试,谁能返,缓存用,性能高。

IT技术学习与工作笔记分享 1956

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

spring-mvc源码

spring-mvc源码

m0_54258715的博客 1215

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Spring MVC 原理与源码

虽然整体流程不复杂,但是通过阅读 Spring MVC 的源码,我们会发现,Spring MVC 优雅的提供了各种拓展点,例如 HttpMessageConvert、ExceptionHandler 等等。但是随着前后端分离,后端大多提供 Restful API ,里面的 ViewResolver 和 View 的流程,已经不再被需要。源码中,我们将得到解答。Spring MVC 整体代码量有 5w+ 行,通过本专栏,可以快速的研读核心部分的代码,节省你的时间。

qq_38599266的博客 423

09. Spring MVC源码解析

09 Spring MVC源码解析 目录 09 Spring MVC源码解析 Pt1 Spring MVC架构 Pt1.1 Servlet Pt1.2 Servlet MVC Pt1.3 Spring MVC Pt2 Spring MVC九大组件 Pt2.1 HandlerMapping Pt2.2 HandlerAdapter Pt2.3 HandlerExceptionResolver Pt2.4 ViewResolver Pt2.5 RequestToViewNameTrans

Java是世界上最好的语言 870

spring及spring mvc源码透彻解析

这几天一直在研究spring的源码,现将研究过程和成果记录一下,以便以后查看。 一、从spring加载的入口 二、阅读《spring源码深入解析》一书,并结合博客【Spring源码分析】Bean加载流程概览 及这篇博客的后续几篇,再根踪spring的源码,理解了spring初始化beanFactory,加载并解析bean配置为BeanDefinition,后又实例化bean的过程 三、阅读...

3月3的风筝 322

【spring】spring mvc请求源码流程

一篇文章从源码层面了解spring mvc请求过来后如何是如何执行的!

qq_35436158的博客 306

面试官:讲一讲Spring MVC源码解析

Spring MVC 的核心流程通过 DispatcherServlet 调度请求,根据请求 URL 查找处理器,然后通过 HandlerAdapter 调用处理器执行业务逻辑,最终由 ViewResolver 解析视图并返回结果。这一系列的组件协作形成了强大的 Web 框架,既能支持注解驱动,也能扩展成多种视图技术。可以微信搜索【小奇JAVA面试】第一时间阅读,回复【资料】获取福利,回复【项目】获取项目源码,回复【简历模板】获取简历模板,回复【学习路线图】获取学习路线图。

真正的大师永远怀着一颗学徒的心 2713

浅谈对Spring mvc的理解和DispatherServlet源码深入分析

简介Spring mvc是Spring 为展示层提供的一个优秀的Web框架,它基于MVC的设计理念,并采用松耦合、可插拔的组件结构,让它比其他的MVC框架更具有灵活性和扩展性。体系结构学习Spring MVC的时候,最重要还是要懂得它里面内部的各个组件是如何运转工作的,我刚开始接触的时候,只想着一门心思去写代码,而忽略了其最精髓的原理理解和逻辑流程,这也导致我在进行Spring mvc配置和编写代码

1Q84emo的博客 1095

java mvc 源码分析_Spring MVC 源码解析

写在前面在分析 Spring AOP 源码之前,如果你对 Spring IOC、依赖注入(DI) 原理不是很清楚,建议您先了解一下:Spring IOC 源码解析、Spring 依赖注入(DI) 源码解析,这样或许会让你的思路更加清晰。1.什么是 MVCMVC 作为一种设计模式,并不是仅限于 Java Web 应用,还包括许多应用,比如前端、PHP、.NET 等语言。之所以那么做的根本原因在于解耦...

weixin_29095587的博客 249

Spring MVC Showcase源码分析:深入理解Spring MVC工作原理

Spring MVC Showcase是Spring官方提供的完整示例项目,通过一系列小而精的案例展示了Spring MVC框架的核心功能。这个项目是学习Spring MVC工作原理的终极指南,能够帮助开发者快速掌握Spring MVC的核心机制和最佳实践。🌟 ## 🔍 项目概览与核心价值 Spring MVC Showcase项目位于[src/main/java/org/springfr

gitblog_00384的博客 858

Spring MVC的源码理解

本文深入解析Spring MVC源码的核心机制,围绕启动初始化和请求处理两条主线展开。首先剖析DispatcherServlet的继承体系,展示其如何从基础Servlet演变为Spring MVC的核心调度器。重点阐述了初始化阶段的九大组件装配过程,特别是HandlerMapping、HandlerAdapter和ViewResolver等关键组件的初始化。然后详细解析请求处理流程,通过流程图清晰呈现从请求接收到响应返回的完整链路,包括处理器匹配、拦截器执行、业务处理、视图渲染等关键环节。

无论云泥意贯一 791
上一篇: Spring中Bean的生命周期及源码详解
下一篇: HashMap源码解析(jdk1.8)
ludkjava
博客等级 码龄11年 173粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值