Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
最早支持Servlet标准的是JavaSoft的Java Web Server,此后,一些其它的基于Java的Web服务器开始支持标准的Servlet。
Servlet容器默认是采用单实例多线程的方式处理多个请求的:
1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例);
2.容器初始化Servlet主要就是读取配置文件(例如tomcat,可以通过servlet.xml的设置线程池中线程数目,初始化线程池通过web.xml,初始化每个参数值等等。
3.当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread) 调度它管理下线程池中等待执行的线程(Worker Thread)给请求者;
4.线程执行Servlet的service方法;
5.请求结束,放回线程池,等待被调用;
本次分享采用的是Spring Boot内嵌Tomcat实现的方式
本次分享对应的Spring Boot 版本号 2.0.2.RELEASE
Spring Boot启动加载流程
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
// 开始启动
stopWatch.start();
ConfigurableApplicationContext context = null;
// 添加失败分析器
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
// 属性配置
configureHeadlessProperty();
// 添加监听,包括(Spring监听和Spring Boot监听)
SpringApplicationRunListeners listeners = getRunListeners(args);
// 启动监听
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 准备应用环境参数
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
// 创建容器
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 参数准备,监听器添加
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 刷新容器
refreshContext(context);
// 容器启动完成后的处理
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
// 开启监听
listeners.started(context);
// 开始执行
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 执行监听
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
public void refresh() throws BeansException, IllegalStateException {
// 加锁实容器启动时的线程安全
synchronized (this.startupShutdownMonitor) {
// 为容器刷新做准备
prepareRefresh();
// 告诉子类启动refreshFactory,Bean定义源文件载入从子类的refreshBeanFactory中加载
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为BeanFactory配置容器特性,如:类加载器,事件处理器
prepareBeanFactory(beanFactory);
try {
// 为容器的某些子类指定特殊的BeanPost事件处理
postProcessBeanFactory(beanFactory);
// 调用所有注册BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// 为BeanFactory注册BeanPost事件处理器
registerBeanPostProcessors(beanFactory);
// 初始化信息源,和国际化相关
initMessageSource();
// 初始化容器事件传播器
initApplicationEventMulticaster();
// 调用子类的某些特殊Bean初始化方法
onRefresh();
// 为时间传播器注册事件监听器
registerListeners();
// 初始化所有所有剩余的单例Bean
finishBeanFactoryInitialization(beanFactory);
// 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
// 销毁以前创建的单态Bean
destroyBeans();
// 取消refresh操作,重置容器的同步标识
cancelRefresh(ex);
// 异常处理
throw ex;
}
finally {
// 重置
resetCommonCaches();
}
}
}
在finishRefresh()
中启动web
服务器
protected void finishRefresh() {
super.finishRefresh();
// 启动web服务器
WebServer webServer = startWebServer();
if (webServer != null) {
publishEvent(new ServletWebServerInitializedEvent(webServer, this));
}
}
开始启动Tomcat
public void start() throws WebServerException {
// 此处实现了线程安全
synchronized (this.monitor) {
if (this.started) {
return;
}
try {
addPreviouslyRemovedConnectors();
Connector connector = this.tomcat.getConnector();
if (connector != null && this.autoStart) {
// 当连接建立,getPort() >= 0;时启动Tomcat
performDeferredLoadOnStartup();
}
加载并且初始化所有的 servlets(被 load on startup 标记的)
public boolean loadOnStartup(Container children[]) {
for (ArrayList<Wrapper> list : map.values()) {
for (Wrapper wrapper : list) {
try {
wrapper.load();
...
}
初始化应用中已经描述,但没有被初始化的servlet
public synchronized void load() throws ServletException {
instance = loadServlet();
// 如果没有被初始化,则初始化servlet
if (!instanceInitialized) {
// 此处可以初始化 DefaultServlet 和 HttpServletBean,详见下文
initServlet(instance);
}
}
public synchronized Servlet loadServlet() throws ServletException {
try {
servlet = (Servlet) instanceManager.newInstance(servletClass);
...
// 初始化servlet
initServlet(servlet);
//发送加载完成事件
fireContainerEvent("load", this);
}
private synchronized void initServlet(Servlet servlet)
throws ServletException {
// 如果已经加载成功或者是实现了SingleThreadModel,直接返回
if (instanceInitialized && !singleThreadModel) return;
// 开始初始化
servlet.init(facade);
}
初始化HttpServletBean及相关组件
public final void init() throws ServletException {
// 让子类实现
initServletBean();
}
protected final void initServletBean() throws ServletException {
try {
// 初始化WebApplicationContext,此处采用事件监听实现
this.webApplicationContext = initWebApplicationContext();
initFrameworkServlet();
}
}
protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (!this.refreshEventReceived) {
// refresh刷新容器
onRefresh(wac);
}
if (this.publishContext) {
//发布容器作为servlet的attribute
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
return wac;
}
DispatcherServlet中onRefresh方法执行
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
初始化DispatcherServlet相关组件
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
至此servlet相关初始化工作已经完成
HttpServlet 对 service 的实现
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
处理请求并发布事件(不考虑结果)
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
LocaleContext localeContext = buildLocaleContext(request);
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
initContextHolders(request, localeContext, requestAttributes);
try {
// 执行 DispatcherServlet 的 doService方法
doService(request, response);
}
publishRequestHandledEvent(request, response, startTime, failureCause);
}
执行DispatcherServlet 的 doDispatch 方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
//在Spring3.2之后,支持WebAsync异步处理
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
try {
ModelAndView mv = null;
Exception dispatchException = null;
try {
//转换请求为多个部分并获得相应的处理器
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// 找到当前请求对应的handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 找到当前请求对应的handler适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
//执行拦截器preHandle
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
// 反射调用实际执行的handler,返回ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
applyDefaultViewName(processedRequest, mv);
//执行拦截器postHandle
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
catch (Throwable err) {
//此处主要是使@ExceptionHandler处理起作用
dispatchException = new NestedServletException("Handler dispatch failed", err);
}
//执行拦截器processDispatchResult,当程序正常结束时执行
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()) {
// 相当于postHandle 和 afterCompletion
if (mappedHandler != null) {
//该实现在HandlerInterceptorAdapter中也有定义
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
//清除所有请求的处理所对应的资源占用
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}
至此servlet初始化和使用的所有的代码已经完成
// 销毁资源并关闭服务
public void destroy() {
close();
}
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
// 注册 shutdownHook
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
...
}
实际执行销毁动作
protected void doClose() {
// 发布 shutdown 事件.
publishEvent(new ContextClosedEvent(this));
// 销毁所有的单例Bean
destroyBeans();
// 关闭容器
closeBeanFactory();
// 让子类执行清除
onClose();
}
在 Web 应用程序中,一个 Servlet 在一个时刻可能被多个用户同时访问。这时 Web 容器将为每个用户创建一个线程来执行 Servlet。如果 Servlet 不涉及共享资源的问题,不必关心多线程问题。但如果 Servlet 需要共享资源,需要保证 Servlet 是线程安全的。
下面是编写线程安全的 Servlet 的一些建议:
java界的小学生
https://blog.csdn.net/shang_xs
深入学习和理解Servlet(一)
https://blog.csdn.net/shang_xs/article/details/90371068
https://github.com/dwyanewede/project-learn/tree/master/src/main/java/com/learn/demo/interfaces/loan/product