Jetty作为Servlet服务器,和Tomcat一样也是成名已久,但是和tomcat不同的是它的体量较小,作为大型企业的服务器资格不足,但是作为分布式服务器和小型企业服务器还是很不错的选择,与作为补丁服务器的tomcat自然有些差距,介绍下jetty。
这里是Jetty和Tomcat的比较:https://blog.51cto.com/825272560/2058729
Jetty的架构:
Jetty和Tomcat都采用了观察者模式,定义的接口都是LifeCycle,但是Jetty的较简单,注意Jetty中所有的组件都是有生命周期的,包括Server,也就是说Jetty的起点是LifeCycle接口,所以下面就不再提这个接口了。
Jetty定义了两个接口,分别是Handler,HandlerContainer;这两个接口代表了Jetty的两个重要的功能,同时Jetty提供了抽象实现类AbstractHandler和AbstractHandlerContainer,注意AbstractHandlerContainer继承了AbstractHandler,他们是Jetty的默认实现。还有AbstractHandlerContainer抽象类,这个抽象类又继承了AbstractHandlerContainer,至此,Jetty的功能抽象类都已经完成。
HandlerWrapper
这是个包装类,人如其名,看下它的结构和属性:
HandlerWrapper包装了一个Handler,这个Handler需要你自己决定你需要什么样的handler,这个Handler与后面讲的Jetty的两种实现方式有关。同时Server也继承了HandlerWrapepr,Server继承它的原因是因为Server是Jetty的启动类,所以这个Handler需要被Sever引用,并通过生命周期管理这个handler,仅此而已。
下面是Jetty的Handler的两种实现方式:
1. ScopedHandler
这个Handler继承自HandlerWrapper,这是个抽象类无关紧要,但是jetty为我们提供了这个抽象类的实现子类,这些是我们需要考虑的选择。
如ServletHandler:
1 public class ServletHandler extends ScopedHandler { 2 private static final Logger LOG = Log.getLogger(ServletHandler.class); 3 public static final String __DEFAULT_SERVLET = "default"; 4 private ServletContextHandler _contextHandler; 5 private ServletContext _servletContext; 6 private FilterHolder[] _filters = new FilterHolder[0]; 7 private FilterMapping[] _filterMappings; 8 private int _matchBeforeIndex = -1; 9 private int _matchAfterIndex = -1; 10 private boolean _filterChainsCached = true; 11 private int _maxFilterChainsCacheSize = 512; 12 private boolean _startWithUnavailable = false; 13 private boolean _ensureDefaultServlet = true; 14 private IdentityService _identityService; 15 private boolean _allowDuplicateMappings = false; 16 private ServletHolder[] _servlets = new ServletHolder[0]; 17 private ServletMapping[] _servletMappings; 18 private final Map<String, FilterHolder> _filterNameMap = new HashMap(); 19 private List<FilterMapping> _filterPathMappings; 20 private MultiMap<FilterMapping> _filterNameMappings; 21 private final Map<String, ServletHolder> _servletNameMap = new HashMap(); 22 private PathMappings<ServletHolder> _servletPathMap; 23 private ListenerHolder[] _listeners = new ListenerHolder[0]; 24 private boolean _initialized = false; 25 protected final ConcurrentMap<String, FilterChain>[] _chainCache = new ConcurrentMap[31]; 26 protected final Queue<String>[] _chainLRU = new Queue[31];
这个类允许你实现自己的filter,它会在调用Servlet之前执行这些filter。
如ContextHandler:
1 public class ContextHandler extends ScopedHandler implements Attributes, Graceful { 2 public static final int SERVLET_MAJOR_VERSION = 3; 3 public static final int SERVLET_MINOR_VERSION = 1; 4 public static final Class<?>[] SERVLET_LISTENER_TYPES = new Class[]{ServletContextListener.class, ServletContextAttributeListener.class, ServletRequestListener.class, ServletRequestAttributeListener.class, HttpSessionIdListener.class, HttpSessionListener.class, HttpSessionAttributeListener.class}; 5 public static final int DEFAULT_LISTENER_TYPE_INDEX = 1; 6 public static final int EXTENDED_LISTENER_TYPE_INDEX = 0; 7 private static final String UNIMPLEMENTED_USE_SERVLET_CONTEXT_HANDLER = "Unimplemented {} - use org.eclipse.jetty.servlet.ServletContextHandler"; 8 private static final Logger LOG = Log.getLogger(ContextHandler.class); 9 private static final ThreadLocal<ContextHandler.Context> __context = new ThreadLocal(); 10 private static String __serverInfo = "jetty/" + Server.getVersion(); 11 public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes"; 12 public static final String MAX_FORM_KEYS_KEY = "org.eclipse.jetty.server.Request.maxFormKeys"; 13 public static final String MAX_FORM_CONTENT_SIZE_KEY = "org.eclipse.jetty.server.Request.maxFormContentSize"; 14 public static final int DEFAULT_MAX_FORM_KEYS = 1000; 15 public static final int DEFAULT_MAX_FORM_CONTENT_SIZE = 200000; 16 protected ContextHandler.Context _scontext; 17 private final AttributesMap _attributes; 18 private final Map<String, String> _initParams; 19 private ClassLoader _classLoader; 20 private String _contextPath; 21 private String _contextPathEncoded; 22 private String _displayName; 23 private Resource _baseResource; 24 private MimeTypes _mimeTypes; 25 private Map<String, String> _localeEncodingMap; 26 private String[] _welcomeFiles; 27 private ErrorHandler _errorHandler; 28 private String[] _vhosts; 29 private boolean[] _vhostswildcard; 30 private String[] _vconnectors; 31 private Logger _logger; 32 private boolean _allowNullPathInfo; 33 private int _maxFormKeys; 34 private int _maxFormContentSize; 35 private boolean _compactPath; 36 private boolean _usingSecurityManager; 37 private final List<EventListener> _eventListeners; 38 private final List<EventListener> _programmaticListeners; 39 private final List<ServletContextListener> _servletContextListeners; 40 private final List<ServletContextListener> _destroySerletContextListeners; 41 private final List<ServletContextAttributeListener> _servletContextAttributeListeners; 42 private final List<ServletRequestListener> _servletRequestListeners; 43 private final List<ServletRequestAttributeListener> _servletRequestAttributeListeners; 44 private final List<ContextHandler.ContextScopeListener> _contextListeners; 45 private final List<EventListener> _durableListeners; 46 private String[] _protectedTargets; 47 private final CopyOnWriteArrayList<ContextHandler.AliasCheck> _aliasChecks; 48 private volatile ContextHandler.Availability _availability;
这个类看起来才像正儿八经的容器类,它允许你接触到容器上下文,web容器的handler一般都会继承自这个类。
还有ServletContextHandler:
1 public class ServletContextHandler extends ContextHandler { 2 private static final Logger LOG = Log.getLogger(ServletContextHandler.class); 3 public static final int SESSIONS = 1; 4 public static final int SECURITY = 2; 5 public static final int GZIP = 4; 6 public static final int NO_SESSIONS = 0; 7 public static final int NO_SECURITY = 0; 8 protected final DecoratedObjectFactory _objFactory; 9 protected Class<? extends SecurityHandler> _defaultSecurityHandlerClass; 10 protected SessionHandler _sessionHandler; 11 protected SecurityHandler _securityHandler; 12 protected ServletHandler _servletHandler; 13 protected GzipHandler _gzipHandler; 14 protected int _options; 15 protected JspConfigDescriptor _jspConfig; 16 private boolean _startListeners;
这个类继承自ContextHandler,同时它又允许你加入Jetty实现的一些特定Handler,如SessionHandler等。
后面还有一些其他的继承自ScopedHandler的Handler,原理是一样的,这些Handler最后都会执行Servlet的Service方法。
2. HandlerCollection
这个类继承自AbstractHandlerContainer,这个类属于暴力类,举个例子:
1 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { 2 if (this.isStarted()) { 3 HandlerCollection.Handlers handlers = (HandlerCollection.Handlers)this._handlers.get(); 4 if (handlers == null) { 5 return; 6 } 7 8 MultiException mex = null; 9 Handler[] var7 = handlers._handlers; 10 int var8 = var7.length; 11 12 for(int var9 = 0; var9 < var8; ++var9) { 13 Handler handler = var7[var9]; 14 15 try { 16 handler.handle(target, baseRequest, request, response); 17 } catch (RuntimeException | IOException var12) { 18 throw var12; 19 } catch (Exception var13) { 20 if (mex == null) { 21 mex = new MultiException(); 22 } 23 24 mex.add(var13); 25 } 26 } 27 28 if (mex != null) { 29 if (mex.size() == 1) { 30 throw new ServletException(mex.getThrowable(0)); 31 } 32 33 throw new ServletException(mex); 34 } 35 } 36 37 }
这个类的作用很简单,将需要处理的handler加到这个集合类中,并把这个集合类注入到Server中的Handler中,这个类就会循环处理其中的Handler。
Connector和Tomcat中的Connector一样,负责接受请求,将请求交给Server,由Server交给Handler.hande处理:
1 public void handle(HttpChannel channel) throws IOException, ServletException { 2 String target = channel.getRequest().getPathInfo(); 3 Request request = channel.getRequest(); 4 Response response = channel.getResponse(); 5 if (LOG.isDebugEnabled()) { 6 LOG.debug("{} {} {} on {}", new Object[]{request.getDispatcherType(), request.getMethod(), target, channel}); 7 } 8 9 if (!HttpMethod.OPTIONS.is(request.getMethod()) && !"*".equals(target)) { 10 this.handle(target, request, request, response); 11 } else if (!HttpMethod.OPTIONS.is(request.getMethod())) { 12 request.setHandled(true); 13 response.sendError(400); 14 } else { 15 this.handleOptions(request, response); 16 if (!request.isHandled()) { 17 this.handle(target, request, request, response); 18 } 19 } 20 21 if (LOG.isDebugEnabled()) { 22 LOG.debug("handled={} async={} committed={} on {}", new Object[]{request.isHandled(), request.isAsyncStarted(), response.isCommitted(), channel}); 23 } 24 25 }
这个Connector实现了LifeCycle和Container以及Graceful接口,LifeCycle和Container接口方便设置一些属性和将自己注册到Server上等功能。
至此Jetty的大体流程搞清楚了,自己的学习,可能有错误,后续持续修正。