Servlet生命周期了解
Servlet的生命(周期)是由容器(eg:Tomcat)管理的,换句话说,Servlet程序员不能用代码控制其生命。
加载和实例化:时机取决于web.xml的定义,如果有x则在容器启动时(eg:SSM),反之则在第一次针对这个Servlet的请求发生时(eg:Spring Boot)。
初始化(init):实例化后会立马进行初始化,也就是执行init方法,init方式只会执行一次。
请求处理:初始化后,Servlet就可以接受请求了,基本方式是执行Servlet接口中的service方法。
终止服务:容器会在合适的时候销毁某个Servlet对象,这个策略取决于容器的开发者/商,销毁时destroy方***被调用。
核心处理请求流程图
入口
前端控制器DispatcherServlet也是一个Servlet,他父类的父类HttpServletBean覆写了Servlet接口的init方法,在容器第一次加载或者第一次请求时会触发(延迟加载),这个方法是Sring Mvc初始化的入口。
启动初始化
容器启动
- Spring容器启动过程,会执行Bean的加载、创建和初始化,此处以Controller层为例分析,暂不关注其他类型资源。
- RequestMappingHandlerMapping类也是其中一个Bean,负责解析所有标识有@Controller或者@RequestMapping注解的Bean。
- RequestMappingHandlerMapping的父类实现了InitializingBean接口,覆写了afterPropertiesSet()方法,该接口是Spring的扩展点之一,在Bean初始化过程中,所i有属性注入完毕之后,会执行一系列回调(回调入口:AbstractAutowireCapableBeanFactory#initializeBean),其中一个回调会验证当前类是否实现了InitializingBean接口,如果实现了会调用afterPropertiesSet()方法,此方法是解析Controller层路径和方法对应关系的入口。
- 解析完毕之后会存储在AbstractHandlerMethodMapping#MappingRegistry中,控制器方法HandlerMethod存储了当前路径对应方法的主要信息,它只负责准备数据,封装数据,而而不提供具体使用的方式方法。
- 在接收请求时会先根据路径从urlLookup 中获取匹配条件,然后根据匹配条件获取控制器方法HandlerMethod。
class MappingRegistry {
// T:RequestMappingInfo => <请求匹配条件,控制器方法>
private final Map<T, HandlerMethod> mappingLookup = new LinkedHashMap<>();
// T:RequestMappingInfo => <路径,请求匹配条件>
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
}
public class HandlerMethod {
/** Logger that is available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
// Web控制器方法所在的Web控制器bean。可以是字符串,代表bean的名称;也可以是bean实例对象本身。
private final Object bean;
// Bean工程,如果bean属性是Sring的beanName就可以用beanName获取到对应的bean作用Handler
@Nullable
private final BeanFactory beanFactory;
// Web控制器方法所在的Web控制器bean的类型,如果该bean被代理,这里记录的是被代理的用户类信息
private final Class<?> beanType;
// Web控制器方法
private final Method method;
private final Method bridgedMethod;
// Web控制器方法的参数信息:所在类所在方法,参数,索引,参数类型
private final MethodParameter[] parameters;
// 注解@ResponseStatus的code属性
@Nullable
private HttpStatus responseStatus;
// 注解@ResponseStatus的reason属性
@Nullable
private String responseStatusReason;
@Nullable
private HandlerMethod resolvedFromHandlerMethod;
....
}
策略初始化
protected void initStrategies(ApplicationContext context) {
// 初始化文件解析器,用于支持服务器的文件上传
initMultipartResolver(context);
// 初始化国际化解析器,用来提供国际化功能;
initLocaleResolver(context);
// 初始化主题解析器,用来提供皮肤主题功能;
initThemeResolver(context);
// 初始化处理器映射器
initHandlerMappings(context);
// 初始化处理器适配器,为不同的处理器提供上下文运行环境;
initHandlerAdapters(context);
// 处理器异常解析器,用来解析处理器产生的异常;
initHandlerExceptionResolvers(context);
// 初始化视图逻辑名称转换器,根据逻辑视图的名称找到具体的视图。
// 当处理器没有返回逻辑视图名时,将请求的URL自动映射为逻辑视图名;
initRequestToViewNameTranslator(context);
// 初始化视图解析器,当控制器返回后,通过试图解析器会把逻辑视图名进行解析,从而定位实际视图;
initViewResolvers(context);
// 初始化FlashMap管理器接口,负责重定向时,保存参数到临时存储中
initFlashMapManager(context);
}
映射器初始化
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
// 默认获取应用上下文所有的处理器映射
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
// 获取所有的处理器映射
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
// 赋值,用于请求时查找
this.handlerMappings = new ArrayList<>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
else {
try {
// 根据名称获取指定的bean:handlerMapping
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) {
// 获取默认的处理器映射
// 从【DispatcherServlet.properties】文件中读取默认配置
// BeanNameUrlHandlerMapping 和 RequestMappingHandlerMapping
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
}
}
}
适配器初始化(和映射器逻辑一致)
private void initHandlerAdapters(ApplicationContext context) {
this.handlerAdapters = null;
if (this.detectAllHandlerAdapters) {
// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
Map<String, HandlerAdapter> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerAdapters = new ArrayList<>(matchingBeans.values());
// We keep HandlerAdapters in sorted order.
AnnotationAwareOrderComparator.sort(this.handlerAdapters);
}
}
else {
try {
HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
this.handlerAdapters = Collections.singletonList(ha);
}
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerAdapter later.
}
}
// Ensure we have at least some HandlerAdapters, by registering
// default HandlerAdapters if no other adapters are found.
if (this.handlerAdapters == null) {
this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
if (logger.isDebugEnabled()) {
logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
}
}
}
请求处理
流程图
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 {
try {
ModelAndView mv = null;
Object dispatchException = null;
try {
processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
// 2.获取处理器映射器
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
// 获取不到handler 抛异常或者返回404
this.noHandlerFound(processedRequest, response);
return;
}
// 4.获取处理器适配器器
HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
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;
}
}
// 6.循环调用拦截器的preHandle方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 8.实际执行代码,handler通过反射执行控制器方法
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
// 默认视图
this.applyDefaultViewName(processedRequest, mv);
// 10.循环调用拦截的postHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
} catch (Exception var20) {
dispatchException = var20;
} catch (Throwable var21) {
dispatchException = new NestedServletException("Handler dispatch failed", var21);
}
// 11.处理结果,进行视图解析 & 模板引擎渲染 & request域填充
// 12.内部会调用拦截器的afterCompletion方法
this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
} catch (Exception var22) {
// 目标方法完成之后执行
this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
} catch (Throwable var23) {
// 目标方法完成之后执行
this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
}
} finally {
if (asyncManager.isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
} else if (multipartRequestParsed) {
this.cleanupMultipart(processedRequest);
}
}
}
获取处理器映射器
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
Iterator var2 = this.handlerMappings.iterator();
while(var2.hasNext()) {
HandlerMapping mapping = (HandlerMapping)var2.next();
// 核心方法获取执行链
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 获取handler
Object handler = this.getHandlerInternal(request);
if (handler == null) {
handler = this.getDefaultHandler();
}
if (handler == null) {
// 不满足,返回
return null;
} else {
if (handler instanceof String) {
String handlerName = (String)handler;
handler = this.obtainApplicationContext().getBean(handlerName);
}
// 以handler为参数获取执行链:创建一个执行链对象,handler赋值到内部变量,添加所有拦截器
HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);
...
...
return executionChain;
}
}
获取处理器适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
Iterator var2 = this.handlerAdapters.iterator();
while(var2.hasNext()) {
HandlerAdapter adapter = (HandlerAdapter)var2.next();
// 核心判断方法,找到支持该handler的适配器
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");
}
执行拦截器前置处理preHandle方法
HandlerExecutionChain#applyPreHandle
- 拦截器的preHandle方法任意一个返回false则访问不到目标方法
- 拦截器的afterCompletion方法一定会执行
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
HandlerInterceptor interceptor = interceptors[i];
// 循环调用
if (!interceptor.preHandle(request, response, this.handler)) {
// 执行完毕拦截器的所有AfterCompletio方法后return
this.triggerAfterCompletion(request, response, (Exception)null);
// 一个返回false即停止循环
return false;
}
}
}
return true;
}
执行控制器的目标方法
InvocableHandlerMethod#doInvoke
@Nullable
protected Object doInvoke(Object... args) throws Exception {
ReflectionUtils.makeAccessible(this.getBridgedMethod());
try {
// method.invoke(obj,args);
// 反射调用目标类的目标方法
// 目标方法:this.getBridgedMethod()
// this.getBean()获取handler中的bean,即为容器中的目标类实例/可能是一个CGLIB增强后的代理对象
return this.getBridgedMethod().invoke(this.getBean(), args);
} catch (IllegalArgumentException var4) {
this.assertTargetBean(this.getBridgedMethod(), this.getBean(), args);
String text = var4.getMessage() != null ? var4.getMessage() : "Illegal argument";
throw new IllegalStateException(this.formatInvokeError(text, args), var4);
} catch (InvocationTargetException var5) {
Throwable targetException = var5.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException)targetException;
} else if (targetException instanceof Error) {
throw (Error)targetException;
} else if (targetException instanceof Exception) {
throw (Exception)targetException;
} else {
throw new IllegalStateException(this.formatInvokeError("Invocation failure", args), targetException);
}
}
}
处理返回结果 & 执行拦截器afterCompletion方法
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) {
this.logger.debug("ModelAndViewDefiningException encountered", exception);
mv = ((ModelAndViewDefiningException)exception).getModelAndView();
} else {
Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
mv = this.processHandlerException(request, response, handler, exception);
errorView = mv != null;
}
}
if (mv != null && !mv.wasCleared()) {
// a.视图解析 & 模板引擎渲染
this.render(mv, request, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
} else if (this.logger.isTraceEnabled()) {
this.logger.trace("No view rendering, null ModelAndView returned.");
}
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
if (mappedHandler != null) {
// b.调用拦截器afterCompletion方法
mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
}
}
}
a.视图解析 & 模板引擎渲染
DispatcherServlet#render
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
Locale locale = this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale();
response.setLocale(locale);
String viewName = mv.getViewName();
View view;
if (viewName != null) {
// 视图解析
view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + this.getServletName() + "'");
}
} else {
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name '" + this.getServletName() + "'");
}
}
if (this.logger.isTraceEnabled()) {
this.logger.trace("Rendering view [" + view + "] ");
}
try {
if (mv.getStatus() != null) {
response.setStatus(mv.getStatus().value());
}
// 模板引擎渲染
view.render(mv.getModelInternal(), request, response);
} catch (Exception var8) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Error rendering view [" + view + "]", var8);
}
throw var8;
}
}
b.调用拦截器afterCompletion方法,一定会执行
HandlerExecutionChain#afterCompletion
public void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) throws Exception {
HandlerInterceptor[] interceptors = this.getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var8) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
}
}
}
}
同一路径时启动报错源码位置
AbstractHandlerMethodMapping#assertUniqueMethodMapping
private void assertUniqueMethodMapping(HandlerMethod newHandlerMethod, T mapping) {
// 根据路径信息获取方法信息
// 一个路径对应2个方法时第二个方法解析时会获取到上个方法的信息
HandlerMethod handlerMethod = this.mappingLookup.get(mapping);
// 根据路径获取到方法信息 并且 2个不是同一个方法时报错提示已经存在
if (handlerMethod != null && !handlerMethod.equals(newHandlerMethod)) {
throw new IllegalStateException(
"Ambiguous mapping. Cannot map '" + newHandlerMethod.getBean() + "' method \n" +
newHandlerMethod + "\nto " + mapping + ": There is already '" +
handlerMethod.getBean() + "' bean method\n" + handlerMethod + " mapped.");
}
}
如果本文对你有帮助,麻烦转发关注支持一下
需要Java面试资料的朋友可以关注公众号“w的编程日记”免费获取