DispatcheServlet类图,我们根据其类图进行源码分析
GenericServlet 源码分析
/**
* 定义一个通用的,协议无关的Servlet.如果需要编写一个在Web中使用的Http Severlet需要继承HttpServlet
* GeneraicServlet实现了Servlet接口和ServletConfig接口。GenericServlet *可以直接通过Servlet扩展,虽然这是比较常见的一种是继承特殊协议的子类,如HttpServlet
* GenericServlet使写Servlet变的更容易。它提供简单的版本的生命周期方法 init,destory和ServletCOnfig接口中的方法
* GenericServlet同样实现了生命在ServeltContext接口中的log方法s
*/
public abstract class GenericServlet
implements Servlet, ServletConfig, java.io.Serializable
{
private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
private static ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE);
private transient ServletConfig config;
/**
*无参构造方法
*
*/
public GenericServlet() { }
/**
* 被servlet容器调用,用来指示一个servlet正在停止服务
*
*/
public void destroy() {
}
/**
* 返回一个命名的初始化参数的字符串值,如果这个初始化参数不存在则返回null
* 这个方法对从ServletConfig对象中获指定名称的参数的值提供了便利
*/
public String getInitParameter(String name) {
//获取ServletConfig对象
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
// 从servletConfig中获取指定名称初始化参数值
return sc.getInitParameter(name);
}
/**
* 将所有参数名称作为一个Enumeration<String>返回。如果没有初始化参数则返回一个空的Enumration
*/
public Enumeration<String> getInitParameterNames() {
//获取servletConfig对象
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
//获取参数名称的枚举
return sc.getInitParameterNames();
}
/**
* 获取一个ServletConfig对象
*/
public ServletConfig getServletConfig() {
return config;
}
/**
*返回一个servlet正在其中运行的ServletContext的引用
*
*
*/
public ServletContext getServletContext() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
return sc.getServletContext();
}
/**
*返回一个关于serlvet信息,比如 *作者,版本以及版权等。默认情况下,这个方法返回一个空字符串。如果需要返回有意义的值需要重写这个方法
*
*/
public String getServletInfo() {
return "";
}
/**
* 被Servlet容器调用,用来标示一个servlet正准备开始服务。在该方法中将
* * ServletConfig赋值给属性config后调用init()方法
*/
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}
/**
* 初始化处理,具体处理过程延迟到子类
**/
public void init() throws ServletException {
}
public void log(String msg) {
getServletContext().log(getServletName() + ": "+ msg);
}
public void log(String message, Throwable t) {
getServletContext().log(getServletName() + ": " + message, t);
}
/**
* 被servlet容器调用,让一个servlet响应一个请求
* 这是一个抽象方法,所以子类比如HttpServlet必须重写这个方法
*/
public abstract void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
/**
* 返回servlet实例的名称
*/
public String getServletName() {
ServletConfig sc = getServletConfig();
if (sc == null) {
throw new IllegalStateException(
lStrings.getString("err.servlet_config_not_initialized"));
}
return sc.getServletName();
}
}
HttpServlet 源码分析
/**
* 提供了一个抽象类用来被继承创建一个Http servlet来使用一个web站点。
* 一个HttpServlet的子类必须至少重写下述中的一个方法
* doGet,如果servlet支持Http get请求
* doPost,支持http post请求
* doPut, 支持http put请求
* doDelete 支持http delete请求
* init 和destroy 来管理servlet声明周期资源
* getServletInfo,servlet用来提供自身信息
* 几乎没有理由去重写service方法。service方法处理标准的Http请求时通过将其分发给相应请求类型的处理方法。
* Servlet通常运行在多线程服务器上,所以必须注意一个servlet必须处理并发请求,同时谨慎地同步访问共享资源。
* 共享资源包括内存数据例如 实例或类变量和外部对象如文件,数据库连接,网络连接
*
*/
public abstract class HttpServlet extends GenericServlet
{
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
private static final String HEADER_IFMODSINCE = "If-Modified-Since";
private static final String HEADER_LASTMOD = "Last-Modified";
private static final String LSTRING_FILE =
"javax.servlet.http.LocalStrings";
private static ResourceBundle lStrings =
ResourceBundle.getBundle(LSTRING_FILE);
/**
*无参构造方法
*
*/
public HttpServlet() { }
/**
* 服务器通过service方法调用处理一个Http的get请求
* 重写这个方法支持get请求同时也自动支持Http Head请求。Head请求是一个响应中没有返回体,只有请求头部字段
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
/**
* 返回HttpServletRequest对象的最后修改时间
*/
protected long getLastModified(HttpServletRequest req) {
return -1;
}
protected void doHead(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
NoBodyResponse response = new NoBodyResponse(resp);
//委托给doGet方法
doGet(req, response);
response.setContentLength();
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_post_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
protected void doPut(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_put_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
protected void doDelete(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_delete_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
private Method[] getAllDeclaredMethods(Class<?> c) {
if (c.equals(javax.servlet.http.HttpServlet.class)) {
return null;
}
Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
Method[] thisMethods = c.getDeclaredMethods();
if ((parentMethods != null) && (parentMethods.length > 0)) {
Method[] allMethods =
new Method[parentMethods.length + thisMethods.length];
System.arraycopy(parentMethods, 0, allMethods, 0,
parentMethods.length);
System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
thisMethods.length);
thisMethods = allMethods;
}
return thisMethods;
}
/**
* 从公开的service方法中接收标准的HTTP请求,将其分发给相应的处理方法。
*/
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// 获取请求方法
String method = req.getMethod();
// 如果是get方法
if (method.equals(METHOD_GET)) {
//获取最后修改时间
long lastModified = getLastModified(req);
// 如果最后修改时间未知
if (lastModified == -1) {
//分发给doGet方法处理
doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
// 如果servlet最后修改时间小于请求的最后修改时间则调用doGet,否则返回304
if (ifModifiedSince < lastModified) {
maybeSetLastModified(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 {
//没有支持的处理方法,返回一个错误响应
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);
}
}
/*
* Sets the Last-Modified entity header field, if it has not
* already been set and if the value is meaningful. Called before
* doGet, to ensure that headers are set before response data is
* written. A subclass might have set this header already, so we
* check.
*/
private void maybeSetLastModified(HttpServletResponse resp,
long lastModified) {
if (resp.containsHeader(HEADER_LASTMOD))
return;
if (lastModified >= 0)
resp.setDateHeader(HEADER_LASTMOD, lastModified);
}
/**
* 将请求委托给给protected void service(HttpServletRequest req, HttpServletResponse resp)
*/
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequest request;
HttpServletResponse response;
if (!(req instanceof HttpServletRequest &&
res instanceof HttpServletResponse)) {
throw new ServletException("non-HTTP request or response");
}
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
service(request, response);
}
}
}
HttpServletBean
public abstract class HttpServletBean extends HttpServlet implements EnvironmentAware {
protected final Log logger = LogFactory.getLog(getClass());
/**
* 一组必须为这个servlet提供的配置参数
*/
private final Set<String> requiredProperties = new HashSet<String>();
private Environment environment = new StandardServletEnvironment();
/**
* 强制子类调用这个方法来指定属性,并且必须提供作为作为配置参数。这个方法应该在子类的构造方法中调用y
*/
protected final void addRequiredProperty(String property) {
this.requiredProperties.add(property);
}
/**
* 映射配置参数到这个Servlet bean的书zing同时调用子类的初始化方法
*/
@Override
public final void init() throws ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Initializing servlet '" + getServletName() + "'");
}
// 使用初始化参数设置bean的属性
try {
//创建一个ServletConfigPropertyValues对象
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
//获取当前对象的BeanWrapper,使用JavaBean风格访问bean的属性
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
//创建一个ServletContextResourceLoader
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
// 设置bw的属性编辑器
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));
//初始化当前对象的BeanWrapper
initBeanWrapper(bw);
//设置bean属性
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
throw ex;
}
//调用子类初始化方法
initServletBean();
if (logger.isDebugEnabled()) {
logger.debug("Servlet '" + getServletName() + "' configured successfully");
}
}
/**
* 对初始化BeanWrapper,可以使用自定义属性编辑器
* 默认实现是一个空方法
*/
protected void initBeanWrapper(BeanWrapper bw) throws BeansException {
}
/**
* 重写方法,如果没有servletConfig 则返回null
*/
@Override
public final String getServletName() {
return (getServletConfig() != null ? getServletConfig().getServletName() : null);
}
@Override
public final ServletContext getServletContext() {
return (getServletConfig() != null ? getServletConfig().getServletContext() : null);
}
/**
*子类通过重写这个方法实现自定义的初始化,在这个方法调用之前,这个Servlet所有bean属性都已经设置好了
*/
protected void initServletBean() throws ServletException {
}
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* 从的ServletConfig初始化参数创建PropertyValues。
*/
private static class ServletConfigPropertyValues extends MutablePropertyValues {
/**
* 创建一个新的ServeltConfigPropertyValues
*/
public ServletConfigPropertyValues(ServletConfig config, Set<String> requiredProperties)
throws ServletException {
//获取所有丢失的参数
Set<String> missingProps = (requiredProperties != null && !requiredProperties.isEmpty()) ?
new HashSet<String>(requiredProperties) : null;
// 获取所有初始化参数名枚举
Enumeration en = config.getInitParameterNames();
//遍历所有初始化参数
while (en.hasMoreElements()) {
String property = (String) en.nextElement();
Object value = config.getInitParameter(property);
//添加到property数组中
addPropertyValue(new PropertyValue(property, value));
if (missingProps != null) {
missingProps.remove(property);
}
}
// 如果依然有丢失的属性则抛出异常
if (missingProps != null && missingProps.size() > 0) {
throw new ServletException(
"Initialization from ServletConfig for servlet '" + config.getServletName() +
"' failed; the following required properties were missing: " +
StringUtils.collectionToDelimitedString(missingProps, ", "));
}
}
}
}
FrameworkServlet
/**
* Spring's web框架的Servlet基类。提供在一个基于JavaBean集成Spring应用上下文的解决方案
* 这个类提供了如下功能:
* 管理每个Servlet的WebApplicationContext实例。servlet的配置servlet命名空间中的bean由决定
* 发布请求处理事件,不论请求是否被成功处理 publishEvents=true,默认为true
* 子类必须实现doService方法去处理请求。因为这个类继承HttpeServletBean类而不是直接继承HttpServlet类,
* 子类可以重写initFrameworkServlet来自定义初始化
* 在servlet初始化参数中检测contextClass并将其设置为默认的上下文类,如果没有找到则使用XmlWEbApplicationContext.一般都是使用默认值
* 注意,默认情况下自定义的上下文类需要实现ConfigurableWebApplicationContext接口。
* 接受一个可选参的servelt初始化参数contextInitializerClassers指定一个或多个ApplicationContextInitializer;托管的WebApplicationContext会
* 委托给这些指定的初始化器增加一些额外的程序化配置。
* ContextLoader也支持具有相同语义的contextInitializerClassers上线文参数,对根上下文进行程序化配置。
* 传递servlet初始化配置参数contextConfigLocation到上下文中,解析成潜在可以通过逗号空格分割的多文件路径,
* 例如“test-servlet.xml,myServlet.xml”
* 如果没有明确指明contextConfigLocation,则从servlet命名空间中加载默认的路径的配置文件
* 需要注意的是:在配置多个路径时,后面Bean中定义将覆盖前一个加载文件中的配置,至少Spring默认ApplicationContext实现是这么处理的。
* 默认的命名空间是servletName-servlet,例如test-servlet, servlet的名称就是test,
* XmlWebApplication默认的加载路径是/WEB-INF/test-servlet.xml
*
*/
@SuppressWarnings("serial")
public abstract class FrameworkServlet extends HttpServletBean {
/**
* *WebApplicationContext命名空间的后缀。如果一个servlet在这个类的上下文中给定的名字是“test”,这个servlet的命名空间则使**用test-servelt
*/
public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
/**
*FrameworkServlet默认的上下文
*/
public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
/**
* WebApplicationContext在servlet 上下文中属性名称的前缀。最后.
*/
public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";
/**
* 在一个初始化参数的多个值之间使用分割符分割
*
*/
private static final String INIT_PARAM_DELIMITERS = ",; \t\n";
/** */
private String contextAttribute;
/** WebApplicationContext实现类 */
private Class<?> contextClass = DEFAULT_CONTEXT_CLASS;
/** WebApplicationContext的Id*/
private String contextId;
/** 当前servlet的命名空间 */
private String namespace;
/** 上下文配置路径 */
private String contextConfigLocation;
/** 是否将WebApplicationContext发布为Servlet上下文的一个属性。默认是true */
private boolean publishContext = true;
/** 是否在每个请求结束发布一个ServletRequestHandledEvent */
private boolean publishEvents = true;
/** Expose LocaleContext and RequestAttributes as inheritable for child threads? */
private boolean threadContextInheritable = false;
/** 是否分发Http opetion请求 */
private boolean dispatchOptionsRequest = false;
/** 是否分发http trace请求 */
private boolean dispatchTraceRequest = false;
/**当前servlet的WebApplicationContext */
private WebApplicationContext webApplicationContext;
/** 标志onFreash方法是否已经被调用过*/
private boolean refreshEventReceived = false;
/** Comma-delimited ApplicationContextInitializer classnames set through init param */
private String contextInitializerClasses;
/** Actual ApplicationContextInitializer instances to apply to the context */
private ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
public FrameworkServlet() {
}
public FrameworkServlet(WebApplicationContext webApplicationContext) {
this.webApplicationContext = webApplicationContext;
}
// setter and getter
/**
* 重写HttpServletBean的方法,在所有属性设置完成后调用,创建当前servlet的WebApplicationContext
*/
@Override
protected final void initServletBean() throws ServletException {
//记录日志
getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
if (this.logger.isInfoEnabled()) {
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
}
long startTime = System.currentTimeMillis();
try {
//初始化webApplicationContext
this.webApplicationContext = initWebApplicationContext();
//初始化FrameworkServlet
initFrameworkServlet();
}
catch (ServletException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
catch (RuntimeException ex) {
this.logger.error("Context initialization failed", ex);
throw ex;
}
if (this.logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
elapsedTime + " ms");
}
}
/**
* 初始化WebApplicationContext
*/
protected WebApplicationContext initWebApplicationContext() {
//获取根WebApplicationContext
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
// 如果一个上下文对象已经在构造方法中创建则直接使用
if (this.webApplicationContext != null) {
wac = this.webApplicationContext;
//如果web应用上下文是ConfiguableWebApplicontionContext
if (wac instanceof ConfigurableWebApplicationContext) {
// 强制类型转换
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
//如果上下文不是活跃的,即上线问没有被刷新
if (!cwac.isActive()) {
// 如果没有父上下文对象,则将根上下文设置为父上下文
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
//配置同时刷新上下文
configureAndRefreshWebApplicationContext(cwac);
}
}
}
//如果在构造方法中没有注入上下文,则在servlet上下文中找到一个已经注册的上下文。
if (wac == null) {
wac = findWebApplicationContext();
}
if (wac == null) {
// 如果当前servlet没有定义上下文对象则创建一个本地webApplicationContext
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
onRefresh(wac);
}
if (this.publishContext) {
//将上下文发布为一个servlet上下文属性
// 获取属性名称
String attrName = getServletContextAttributeName();
//将其设置为servlet上下文的一个属性
getServletContext().setAttribute(attrName, wac);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
"' as ServletContext attribute with name [" + attrName + "]");
}
}
return wac;
}
/**
*
*/
protected WebApplicationContext findWebApplicationContext() {
//获取上下文属性名称
String attrName = getContextAttribute();
// 如果属性名称为null则返回null
if (attrName == null) {
return null;
}
// 从servlet 上下文中获取Web应用上下文
WebApplicationContext wac =
WebApplicationContextUtils.getWebApplicationContext(getServletContext(), attrName);
// 如果web应用上下文为null则抛出一个异常,否则返回这个上下文
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: initializer not registered?");
}
return wac;
}
/**
*穿件一个新的WebApplicaitonContext对象
*/
protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
Class<?> contextClass = getContextClass();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Servlet with name '" + getServletName() +
"' will try to create custom WebApplicationContext context of class '" +
contextClass.getName() + "'" + ", using parent context [" + parent + "]");
}
// 如果web应用上下文类不是ConfigurableWebApplicationContext类或其子类则抛出一个异常
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException(
"Fatal initialization error in servlet with name '" + getServletName() +
"': custom WebApplicationContext class [" + contextClass.getName() +
"] is not of type ConfigurableWebApplicationContext");
}
// 创建一个ConfiguableWebApplicaitonContext对象
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
// 设置父上下文
wac.setParent(parent);
//设置配置资源路径
wac.setConfigLocation(getContextConfigLocation());
// 刷新
configureAndRefreshWebApplicationContext(wac);
//返回上下文对象
return wac;
}
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// 如果当前contextId不为null则将web应用上下文的Id设置为contextId
if (this.contextId != null) {
wac.setId(this.contextId);
}
else {
// 获取servlet上下文对象
ServletContext sc = getServletContext();
// 如果Servlet版本小于2.5,如果web.xml中配置servlet名称则使用其作为上下文的ID
if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
// 获取servlet上下文名称
String servletContextName = sc.getServletContextName();
// 如果servetContextName不为null则使用其构建一个Id并设置为WebApplicationContext的ID
if (servletContextName != null) {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + servletContextName +
"." + getServletName());
}
else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + getServletName());
}
}
else {
// servlet2.5
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getContextPath()) + "/" + getServletName());
}
}
}
//设置servletContext
wac.setServletContext(getServletContext());
// 设置servletConfig
wac.setServletConfig(getServletConfig());
// 设置nameSpace
wac.setNamespace(getNamespace());
//设置监听器
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
//后置处理
postProcessWebApplicationContext(wac);
applyInitializers(wac);
wac.refresh();
}
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
return createWebApplicationContext((ApplicationContext) parent);
}
/**
* 在WebApplicationContext被刷新前,委派给在当前servlet初始化参数init-param中指定的contextInitializerClasses 类处理
*/
@SuppressWarnings("unchecked")
protected void applyInitializers(ConfigurableApplicationContext wac) {
if (this.contextInitializerClasses != null) {
String[] initializerClassNames =
StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS);
for (String initializerClassName : initializerClassNames) {
ApplicationContextInitializer<ConfigurableApplicationContext> initializer;
try {
Class<?> initializerClass = ClassUtils.forName(initializerClassName, wac.getClassLoader());
initializer = BeanUtils.instantiateClass(initializerClass, ApplicationContextInitializer.class);
}
catch (Exception ex) {
throw new IllegalArgumentException(
String.format("Could not instantiate class [%s] specified via " +
"'contextInitializerClasses' init-param", initializerClassName), ex);
}
this.contextInitializers.add(initializer);
}
}
Collections.sort(this.contextInitializers, new AnnotationAwareOrderComparator());
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
initializer.initialize(wac);
}
}
protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
}
public String getServletContextAttributeName() {
return SERVLET_CONTEXT_PREFIX + getServletName();
}
public final WebApplicationContext getWebApplicationContext() {
return this.webApplicationContext;
}
protected void initFrameworkServlet() throws ServletException {
}
/**
* 刷新web应用上下文对象
*/
public void refresh() {
WebApplicationContext wac = getWebApplicationContext();
if (!(wac instanceof ConfigurableApplicationContext)) {
throw new IllegalStateException("WebApplicationContext does not support refresh: " + wac);
}
((ConfigurableApplicationContext) wac).refresh();
}
/**
*应用上下文刷新事件监听器回调方法
*/
public void onApplicationEvent(ContextRefreshedEvent event) {
this.refreshEventReceived = true;
onRefresh(event.getApplicationContext());
}
/**
*模板方法模式,具体的处理逻辑延迟到子类中
*/
protected void onRefresh(ApplicationContext context) {
// For subclasses: do nothing by default.
}
/**
* Http请求的具体处理方法
**/
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//获取当前时间
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// 获取目前线程持有的LocalContext.
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
//将localContext和当前线程关联
LocaleContextHolder.setLocaleContext(buildLocaleContext(request), this.threadContextInheritable);
//获取当前线程持有的RequestAttributes
RequestAttributes previousRequestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = null;
// 如果当前线程没有持有RequestAttributes对象或者持有对象的是ServletReqeustAttributes则创建一个新的ServletREquestAttributes
if (previousRequestAttributes == null || previousRequestAttributes.getClass().equals(ServletRequestAttributes.class)) {
requestAttributes = new ServletRequestAttributes(request);
//与当前线程关联
RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
}
if (logger.isTraceEnabled()) {
logger.trace("Bound request context to thread: " + request);
}
try {
// 将请求委托给子类的doService方法处理
doService(request, response);
}
catch (ServletException ex) {
failureCause = ex;
throw ex;
}
catch (IOException ex) {
failureCause = ex;
throw ex;
}
catch (Throwable ex) {
failureCause = ex;
throw new NestedServletException("Request processing failed", ex);
}
finally {
// 清除请求同时复位线程上下文
LocaleContextHolder.setLocaleContext(previousLocaleContext, this.threadContextInheritable);
//复位RequestAttributes
if (requestAttributes != null) {
RequestContextHolder.setRequestAttributes(previousRequestAttributes, this.threadContextInheritable);
requestAttributes.requestCompleted();
}
if (logger.isTraceEnabled()) {
logger.trace("Cleared thread-bound request context: " + request);
}
if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request", failureCause);
}
else {
this.logger.debug("Successfully completed request");
}
}
// 如果需要发布一个请求处理完成的事件则发送该事件
if (this.publishEvents) {
// Whether or not we succeeded, publish an event.
long processingTime = System.currentTimeMillis() - startTime;
//发布一个ServeltReqeustHandledEvent事件,用户可以对该事件进行监听
this.webApplicationContext.publishEvent(
new ServletRequestHandledEvent(this,
request.getRequestURI(), request.getRemoteAddr(),
request.getMethod(), getServletConfig().getServletName(),
WebUtils.getSessionId(request), getUsernameForRequest(request),
processingTime, failureCause));
}
}
}
protected LocaleContext buildLocaleContext(HttpServletRequest request) {
return new SimpleLocaleContext(request.getLocale());
}
protected String getUsernameForRequest(HttpServletRequest request) {
Principal userPrincipal = request.getUserPrincipal();
return (userPrincipal != null ? userPrincipal.getName() : null);
}
/**
* 模板方法模式,将具体实现延迟到子类中
**/
protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
throws Exception;
/**
* 关闭应用上下文
*/
@Override
public void destroy() {
getServletContext().log("Destroying Spring FrameworkServlet '" + getServletName() + "'");
if (this.webApplicationContext instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) this.webApplicationContext).close();
}
}
/**
* 应用上下文监听器
*/
private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
public void onApplicationEvent(ContextRefreshedEvent event) {
//
FrameworkServlet.this.onApplicationEvent(event);
}
}
}