图解MVC

一,SpringMVC执行流程

Web 容器启动时会通知 Spring 初始化容器(加载Bean 的定义信息和初始化所有单例 Bean),然后 SpringMVC 会遍历容器中的 Bean,获取每一个 Controller 中的所有方法访问的 url,然后将 url 和 Controller 保存到一个 Map中;这样就可以根据 Request 快速定位到 Controller,因为最终处理 Request 的是Controller 中的方法,Map 中只保留了 url 和 Controller 中的对应关系,所以要根据Request 的 url 进一步确认 Controller 中的 Method,这一步工作的原理就是拼接Controller 的 url(Controller 上@RequestMapping 的值)和方法的 url(Method 上@RequestMapping 的值),与 request 的 url 进行匹配,找到匹配的那个方法;确定处理请求的 Method 后,接下来的任务就是参数绑定,把 Request 中参数绑定到方法的形式参数上。

1.ApplicationContext 初始化时用 Map 保存所有 url 和 Controller 类的对应关系
initStrategies() 容器刷新完成回调
	initHandlerMappings()初始化处理器映射器
		initApplicationContext()   AbstractDetectingUrlHandlerMapping
			detectHandlers()
				registerHandler()
					determineUrlsForHandler()

2.根据请求 url 找到对应的 Controller,并从 Controller 中找到处理请求的方法
doService()
	doDispatch()
		getHandler()
3.Request 参数绑定到方法的形参,执行方法处理请求,并返回结果视图
getHandler()
	getHandlerInternal()
		super.getHandlerInternal()
			initLookupPath()
			lookupHandlerMethod() 获取 url 匹配的方法
applyPreHandle()
	interceptor.preHandle()
handle()
	handleInternal()
		invokeHandlerMethod() 
			invokeAndHandle() 
				invokeForRequest() 
					getMethodArgumentValues() 
						resolveArgument()参数绑定
					doInvoke()返回结果
applyPostHandle()
	interceptor.postHandle()

在这里插入图片描述

从 HandlerMapping 中找到 url 和Controller 的对应关系。也就是 Map<url,Controller>。

最终处理 Request的是 Controller 中的方法

从 Map<urls,beanName>中取得 Controller 后,经过拦截器的预处理方法,再通过反射获取该方法上的注解和参数,解析方法和参数上的注解,然后反射调用方法获取ModelAndView 结果视图。最后,调用的就是 RequestMappingHandlerAdapter 的handle()中的核心逻辑由 handleInternal(request, response, handler)实现。

二,springMVC使用建议

1、Controller 如果能保持单例,尽量使用单例

这样可以减少创建对象和回收对象的开销。也就是说,如果 Controller 的类变量和实例变量可以以方法形参声明的尽量以方法的形参声明,不要以类变量和实例变量声明,这样可以避免线程安全问题。

2、处理 Request 的方法中的形参务必加上@RequestParam 注解

这样可以避免 Spring MVC 使用 asm 框架读取 class 文件获取方法参数名的过程。即便Spring MVC 对读取出的方法参数名进行了缓存,如果不要读取 class 文件当然是更好。

3、缓存 URL

Spring MVC 并没有对处理 url 的方法进行缓存,也就是说每次都要根据请求 url 去匹配 Controller 中的方法 url,如果把 url 和 Method 的关系缓存起来,会不会带来性能上的提升呢?事实上,负责解析 url 和 Method 对应关系的 ServletHandlerMethodResolver 是一个 private 的内部类,不能直接继承该类增强代码,必须要改代码后重新编译。当然,如果缓存起来,必须要考虑缓存的线程安全问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值