【本文图部分取自别处】
一、Jsp与Servlet
1.JSP九大内置对象
2.生命周期
3.Servlet生命周期
init( ),service( ),destroy( )是Servlet生命周期的方法。代表了Servlet从“出生”到“工作”再到“死亡 ”的过程。Servlet容器(例如TomCat)会根据下面的规则来调用这三个方法:
1).init( ),当Servlet第一次被请求时,Servlet容器就会开始调用这个方法来初始化一个Servlet对象出来,但是这个方法在后续请求中不会在被Servlet容器调用,就像人只能“出生”一次一样。我们可以利用init( )方法来执行相应的初始化工作。调用这个方法时,Servlet容器会传入一个ServletConfig对象进来从而对Servlet对象进行初始化。
2).service( )方法,每当请求Servlet时,Servlet容器就会调用这个方法。就像人一样,需要不停的接受老板的指令并且“工作”。第一次请求时,Servlet容器会先调用init( )方法初始化一个Servlet对象出来,然后会调用它的service( )方法进行工作,但在后续的请求中,Servlet容器只会调用service方法了。
3).destory,当要销毁Servlet时,Servlet容器就会调用这个方法,就如人一样,到时期了就得死亡。在卸载应用程序或者关闭Servlet容器时,就会发生这种情况,一般在这个方法中会写一些清除代码。
4..Servlet处理流程
二、SpringMVC
1.SpringMVC处理时序图
3.SpringMVC处理流程图
DispatcherServlet
4.详解dispatcherServlet
类图
执行流程图
代码解读
HttpServletBean
初始化 :主要是通过当前的servlet类型实例转换为BeanWrapper类型实例,以便使用Spring提供的注入功能进行对应属性的注入。
1.封装初始化参数
2.将servlet实例转为BeanWrapper实例
3.注册相对于Resource的属性编辑器
如果有Resource类型的属性,就会使用ResouceEditor去解析。
4.属性注入
BeanWrapper自动注入属性。
5.servletBean的初始化
该过程由子类完成。在FrameworkServlet中覆盖了HttpServletBean中的initServletBean方法
init()
//从web.xml获取contextConfigLocation属性配置
PropertyValues pvs = new HttpServletBean.ServletConfigPropertyValues(this.getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
//将当前的Servlet类转为Spring可操作的Wrapper类
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
//服务器信息
ResourceLoader resourceLoader = new ServletContextResourceLoader(this.getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.getEnvironment()));
//该处理为空实现,留给子类,使用模板方法
this.initBeanWrapper(bw);
//属性的注入
bw.setPropertyValues(pvs, true);
}
//模板方法,子类初始化的入口方法,留给子类扩展
this.initServletBean();
FrameworkServlet:
servletBean的初始化:关键是initWebApplicationContext()方法。
1.获取spring根容器rootContext
2.设置webApplicationContext,并根据情况调用onRefresh()
a) webApplicationContext的寻找及创建包含以下几个步骤:
(1)通过构造函数的注入进行初始化。
当进入initWebApplicationContext方法后通过判断this.webApplicationContext != null 后,
便可以确定this.webApplicationContext是否是通过构造函数来初始化的。由于DispatcherServlet只可被声明一次,而this.webApplicationContext除了initWebApplicationContext()方法可以创建外,还可以通过构造函数来初始化。
(2)通过contextAttribute进行初始化
(3) 重新创建WebApplicationContext 实例
通过以上方法都没有拿到实例,则只能重新创建新的实例。
b) onRefresh():
无论是通过构造方法注入还是通过单独创建,都免不了会调用configureAndRefreshWebApplicationContext方法来对已经创建的WebApplicationContext实例进行刷新。
onRefresh是FrameworkServlet类中提供一个模版方法,在其子类DispatcherServlet中对它进行了重写,用于刷新Spring在Web功能实现中所必须使用的全局变量。
3.将webApplicationContext设置到ServletContext中
initServletBean()
//初始化webApplicationContext
this.webApplicationContext = this.initWebApplicationContext();
//获取spring的根容器rootContext
WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
//上下文实例在构造函数中被注入
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)wac;
if (!cwac.isActive()) {
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
//刷新上下文环境
this.configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
//已经存在servletContext时,获取contextAttribute
wac = this.findWebApplicationContext();
}
if (wac == null) {
//创建一个webApplicationContext
wac = this.createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
this.onRefresh(wac);
}
if (this.publishContext) {
String attrName = this.getServletContextAttributeName();
this.getServletContext().setAttribute(attrName, wac);
}
//模板方法
this.initFrameworkServlet();
DispatcherServlet.class
1.初始化
(1)MultipartResolver:用于处理文件上传
(2)LocaleResolver:在Spring中配置国际化配置
(3)初始化ThemeResolver:在Web中通过主题Theme来控制网页风格
onRefresh(ApplicationContext context)
this.initStrategies(context)
this.initMultipartResolver(context);
this.initLocaleResolver(context);
this.initThemeResolver(context);
this.initHandlerMappings(context);
this.initHandlerAdapters(context);
this.initHandlerExceptionResolvers(context);
this.initRequestToViewNameTranslator(context);
this.initViewResolvers(context);
this.initFlashMapManager(context);
doService(request, response)
doDispatch(request, response)
//通过HandlerMapping获取HandlerExecutionChain: 包括handler和List<HandlerInterceptor>
HandlerExecutionChain mappedHandler = this.getHandler(processedRequest);
HandlerMapping hm = this.handlerMappings.iterator().next();
//BeanNameUrlHandlerMapping
//SimpleUrlHandlerMapping
//RequestMappingHandlerMapping
HandlerExecutionChain handler = hm.getHandler(request);
//通过handler获取适配器HandlerAdapter
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
//执行HandlerInterceptor.preHandle
mappedHandler.applyPreHandle(processedRequest, response);//处理HandlerInterceptor
interceptor.preHandle(request, response, this.handler);
//通过HandlerAdapter调用具体handler的handle
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
//1.SimpleControllerHandlerAdapter.handle()
((Controller)handler).handleRequest(request, response);
//2.HttpRequestHandlerAdapter
((HttpRequestHandler)handler).handleRequest(request, response);
//3.SimpleServletHandlerAdapter
((Servlet)handler).service(request, response);
//4.RequestMappingHandlerAdapter
//执行HandlerInterceptor.postHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
interceptor.postHandle(request, response, this.handler, mv);
//通过ViewResolver获取view
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
//如果有异常
this.processHandlerException(request, response, handler, exception);
HandlerExceptionResolver handlerExceptionResolver = this.handlerExceptionResolvers.iterator().next();
ModelAndView exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
//无异常
this.render(mv, request, response);
ViewResolver viewResolver = this.viewResolvers.iterator().next();
View view = viewResolver.resolveViewName(viewName, locale);
重要组件
2.SpringMVC体系结构
handlerMapping url与控制器handler的映射
handlerAdapter 控制器适配器
viewResolver 视图仓库
view 视图
handlerExceptionResolver 异常捕捉
HandlerInterceptor 拦截器
5.SpringMVC体系结构 uml
三、手写Springmvc
(1)MvcBeanFactory
(2)模拟请求