tomcat源码解析(五)--两种配置与异步servlet
来源:互联网 发布:南昌大学怎么样知乎 编辑:程序博客网 时间:2024/06/06 01:41
常用的web基本都是用xml配置的,而在tomcat解析web.xml的过程中知道,如果类实现了ServletContainerInitializer接口的话,就可以不用在xml里面配置了.
现在对下面两种方式进行说明:
首先是xml配置,web.xml的代码如下:
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>testservlet</servlet-name> <servlet-class>com.yluo.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>testservlet</servlet-name> <url-pattern>/testservlet</url-pattern> </servlet-mapping></web-app>
这个配置大家都很熟悉的吧.
下面看到实现了ServletContainerInitializer接口的配置,代码如下:
package com.yluo.config;import com.yluo.servlet.TestServlet;import javax.servlet.ServletContainerInitializer;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletRegistration;import java.util.Set;/** * Created by 樱天寻 on 2016/7/13. */public class WebConfig implements ServletContainerInitializer { @Override public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException { ServletRegistration.Dynamic dynamic = servletContext.addServlet("testServler", TestServlet.class); dynamic.setLoadOnStartup(1); dynamic.addMapping("/testServler"); }}
不过在这里有点不一样的就是要添加下面这么一个文件
WEB-INF/classes/META-INF/services/javax.servlet.ServletContainerInitializer文件的内容如下:
com.yluo.config.WebConfig
就是把实现ServletContainerInitializer接口的类填上.这样就不用配置xml了,是不是很方便呢.
下面分析异步servlet.示例代码如下:
@Override protected void doGet(HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { final AsyncContext asyncContext = req.startAsync(); new Thread(new Runnable() { @Override public void run() { try { resp.getWriter().write("hello world!"); } catch (IOException e) { e.printStackTrace(); } } }).start(); }
异步的话一般都是在新的线程的进行的,这样才不会把任务阻塞在tomcat内部的哪个线程池里面.开启异步之后改方法就返回了,tomcat做了哪些工作呢.在上一章中有说到,请求路径的匹配是在org.apache.coyote.http11.Http11Processor类的service里面的,那么看到该方法,部分代码如下:
@Override public SocketState service(SocketWrapperBase<?> socketWrapper) throws IOException { ...... getAdapter().service(request, response); // ...... if (!isAsync()) { // 不开启异步的正常关闭 endRequest(); } ...... if (getErrorState().isError() || endpoint.isPaused()) { return SocketState.CLOSED; } else if (isAsync()) { // 异步就返回SocketState.LONG; return SocketState.LONG; } ...... }
在servlet的doGet方法返回之后,就是回到该方法判是不是异步了,接着如果是异步的话service函数就返回 SocketState.LONG 继续往前看,看到org.apache.coyote.AbstractProtocol类的process方法,部分代码如下:
@Override public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) { ...... state = processor.process(wrapper, status); try{ if (state == SocketState.LONG) { longPoll(wrapper, processor); // 第一次连接的时候就是在这里处理了 if (processor.isAsync()) { // 返回的还是这里异步的 // 添加到定时器里面定时检测是偶过期 getProtocol().addWaitingProcessor(processor); } } ...... return state; // 返回LONG } catch(java.net.SocketException e) { ...... } ...... }
processor.process发挥的state值为SocketState.LONG,在这里会判断是否开启了异步,如果开始了执行addWaitingProcessor方法,部分代码如下:
public void addWaitingProcessor(Processor processor) { waitingProcessors.add(processor); }
而waitingProcessors是一个Set集合
private final Set<Processor> waitingProcessors = Collections.newSetFromMap(new ConcurrentHashMap<Processor, Boolean>());
加进来有什么用呢,看到AbstractProtocol类的子类AsyncTimeout的run方法的代码如下:
@Override public void run() { while (asyncTimeoutRunning) { try { Thread.sleep(1000); } catch (InterruptedException e) { } long now = System.currentTimeMillis(); for (Processor processor : waitingProcessors) { processor.timeoutAsync(now); } while (endpoint.isPaused() && asyncTimeoutRunning) { try { Thread.sleep(1000); } catch (InterruptedException e) { // Ignore } } } }
从该方法可以知道,tomcat会一个子线程里面每隔一秒检测异步请求有没有结束或者超时.
O啦,tomcat的源码就分析到这里了. 第一次写博客分析源码,有很多不足之处,希望大家见谅吧. 后面就是分析netty的源码了. 如果大家有什么问题可以给我留言哈.
- tomcat源码解析(五)--两种配置与异步servlet
- Servlet与tomcat配置
- 【Tomcat 8.0】两种方法配置servlet虚拟目录
- (五)Tomcat源码解析 - Tomcat 系统架构与设计模式(一)-工作原理
- tomcat配置与servlet使用
- Tomcat源码解析(五):安全性控制
- 008.Tomcat及Servlet配置深入解析
- (七)Tomcat源码解析 - Servlet 工作原理解析
- servlet的两种配置
- Tomcat请求处理过程(Tomcat源码解析五)
- Tomcat请求处理过程(Tomcat源码解析五)
- Django源码解析(五) URL配置
- Servlet之Tomcat配置与启动(一)
- 五种方法配置tomcat
- Tomcat 源码阅读(五)解析请求ProtocolHandler
- Servlet的两种配置方式
- 配置Servlet的两种方式
- Servlet的两种配置方法
- C语言sizeof()和strlen()函数的区别
- 【Android自助餐】Handler消息机制完全解析(三)Handler解析
- DLL注入技术之依赖可信进程注入
- [Ceph003]Ceph集群创建Cephfs文件
- 使用Iterator接口输出集合
- tomcat源码解析(五)--两种配置与异步servlet
- DLL注入技术之远线程注入
- 【Android自助餐】Handler消息机制完全解析(四)Looper解析
- Hdu 5344 MZL's xor (杂)
- 浅谈android网络编程
- java8之lambda总结
- Service解析
- DLL注入技术之消息钩子注入
- 读懂心经