Jetty

  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

  这是个包装类,人如其名,看下它的结构和属性:

Jetty

  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的大体流程搞清楚了,自己的学习,可能有错误,后续持续修正。

上一篇:java – 嵌入式jetty中的异步servlet似乎在高负载时写入错误的响应


下一篇:java – BeanCurrentlyInCreationException Spring Boot