深入Jetty源码之Servlet框架及实现(ServletContext)

public       interface    ServletContext {  
       // Servlet Container为当前Web Application设置临时目录,并将该临时目录的值存储到当前ServletContext的属性中使用的属性名。  
     
// Jetty使用WebInfConfiguration(在preConfig ure()方法中)来设置该值,设置temp目录的规则: 
       // 1. 如果存在WEB-INF/work目录,则temp目录的值为:WEB-INF/work/Jetty_<host>_<port>__<resourceBase>_<context>_<virtualhost+base36_hashcode_of_whole_string> 
       // 2. 如果"javax.servlet.context.tempdir"已经在外部被设置,并且该目录存在且可写,则temp目录直接设置为该目录实例。 
       // 3. 如果系统变量中"jetty.home"目录下存在"work"目录且可写,则设置temp目录的值为:${jetty.home}/work/ Jetty_<host>_<port>__<resourceBase>_<context>_<virtualhost+base36_hashcode_of_whole_string>  
       // 4. 如果存在"org.eclipse.jetty.webapp.basetempdir"的属性,且该目录存在并可写,设置temp目录为:${ org.eclipse.jetty.webapp.basetempdir   }/ Jetty_<host>_<port>__<resourceBase>_<context>_<virtualhost+base36_hashcode_of_whole_string>  
       // 5. 如果以上条件都不成立,则设置temp目录为:   ${   java.io.tmpdir   }/ Jetty_<host>_<port>__<resourceBase>_<context>_<virtualhost+base36_hashcode_of_whole_string>,且删除已存在临时目录。 
       // 注:对temp目录的父目录不是work,会注册在JVM退出时删除该temp目录,并在temp目录下创建.active目录。 

       public       static       final    String TEMPDIR = "javax.servlet.context.tempdir";  
       /   / Servlet 3.0中新引入的特性,即可以在WEB-INF/lib下的jar包中定义/META-INF/web-fragment配置响应的Servlet等。 
       /   / 如果在web.xml文件中定义了absolute-ordering,或者在jar包中存在/META-INF/web-fragment.xml文件,且定义了ordering, 
       /   / 则该属性的值即为根据规范中定义的规则计算出来的读取jar包中web-fragment.xml文件的jar包名顺序,它时一个List<String>类型,包含jar包名字。 
       /   / 在Jetty中使用Ordering来表示这种顺序,它有两个实现类:AbsoluteOrdering和RelativeOrdering用来分别表示在web.xml和web-fragment.xml中定义的absolute-ordering和ordering定义, 
       /     并且将最终的解析结果汇总到Metadata类中,并根据规范中定义的规则以及metadata-complete的定义来计算实际的解析顺序  
       /     而对这两种配置文件的解析由WebDescriptor和FragmentDescriptor来实现,它们都包含了metadata-complete解析,而真正的解析入口在WebXmlConfiguration和FragmentConfiguration中。 
      /   / 该规范的定义参考:   https://blogs.oracle.com/swchan/entry/servlet_3_0_web_fragment  
      public     static     final   String ORDERED_LIBS = "javax.servlet.context.orderedLibs"; 
      // 返回当前Web Application的Context Path,即当前Web Application的根路径,Servlet Container根据该路径以及一个Request URL的匹配情况来选择一个Request应该交给那个Web Application处理该请求。 
      // Context Path以"/"开始,但是不能以"/"结尾,对默认的根Context,它返回"",而不是"/"。该值在配置Jetty的ContextHandler中设置。 
      // 有些Servlet Container支持多个Context Path指向同一个Context,此时可以使用HttpServletRequest中的getContextPath()来获取该Request实际对应的Context Path,此时这两个Context Path的值可能会不同,但是ServletContext中返回的Context Path值是主要的值。另外Jetty也不支持这种特性。  
      public   String getContextPath(); 
      // 通过给定一个Context Path以在当前   Servlet Container中找到其对应的ServletContext实例。 
      // 可以通过该方法获取Servlet Container中定义的另一个Web Application的ServletContext实例,并获得其RequestDispatcher,并将当前请求Dispatch到那个Web Application中做进一步的处理。这里的uripath必须以"/"开头,且其路径相对于当前Server的根路径。出于安全考虑,该方法可能会返回null。 
      // 在Jetty的实现中,这里uripath可以是一个具体的路径,并且支持查找最准确的匹配。如:对uripath为/foo/goo/abc.html,在Server中由以下Context Path定义:"/", "/foo", "/foo/goo",则最终查找到的ServletContext为"/foo/goo"作为Context Path对应的ServletContext实例。  
     public   ServletContext getContext(String uripath); 
     
      /   /返回Servlet规范的主版本,如3  
      public     int   getMajorVersion(); 
      /   / 返回Servlet规范的次版本,如0  
      public     int   getMinorVersion(); 
      /   / 返回当前Web Application基于的Servlet规范的主版本,如在web.xml文件中定义的version(<web-app version="..." ...>...</web-app>,即Jetty中的实现)  
      public     int   getEffectiveMajorVersion(); 
      /     返回当前Web Application基于的Servlet规范的次版本,如在web.xml文件中定义的version(<web-app version="..." ...>...</web-app>,即Jetty中的实现)  
     public     int   getEffectiveMinorVersion(); 
      // 返回给定file的MIME type,返回null如果无法计算出其MIME type。这个映射关系由Servlet Container定义或在web.xml文件中定义(mime-mapping, extension, mine-type)。 
      // 常见的MIME type有:text/html, image/gif等。Jetty使用MimeTypes类来封装所有和MIME type相关的操作,MimeTypes类中定义了所有默认支持的MIME type以及编码类型, 
      // 并且默认从org/eclipse/jetty/http/mime.properties文件中加载默认的映射,如css=text/css, doc=application/msword等,使用addMimeMapping()方法向该类注册web.xml中定义的文件名扩展名到MIME type的映射。 
      //    而从org/eclipse/jetty/http/encoding.properties文件中加载MIME type的默认编码类型,如text/xml=UTF-8等。 
      // 在使用文件名查找MIME type时,根据文件名的扩展名查找已注册或默认注册的MIME type。用户自定义的映射优先。用户定义的MIME type映射支持extension为"*",表示任意扩展名。  
      public   String getMimeType(String file); 
     
      /   / 对于给定目录,返回该目录下所有的资源以及目录。path必须以"/"开头,如果它不是指向一个目录,则返回空的Set。所有返回的路径都相对当前Web Application的根目录, 
      /     或对于/WEB-INF/lib中jar包中的/META-INF/resources/目录,如一个Web Application包含以下资源:/catalog/offers/music.html, /WEB-INF/web.xml, 
      /   / 以及   /WEB-INF/lib/catalog.jar!/META-INF/resources/catalog/moreOffers/books.html,则getResourcePaths("/catalog")返回{"/catalog/offers/", /catalog/moreOffers/"} 
      /   / Jetty的实现中,在MetaInfConfiguration中,它会扫描WEB-INF/lib目录下所有的jar包,如果发现在某个jar包中存在META-INF/resources/目录, 
      /     就会将该目录资源作为baseResource在WebInfConfiguration中注册到ContextHandler(WebAppContext)中。从而实现jar包中的META-INF/resources/目录作为根目录的查找。     
      public   Set<String> getResourcePaths(String path); 
     
      /   / 返回给定path的URL,path必须以"/"开头,它相对当前Web Application的根目录或相对/WEB-INF/lib中jar包中的/META-INF/resources/目录。 
      /     其中查找顺序前者优先于后者,但是在/WEB-INF/lib/目录下的jar包的查找顺序未定义。该方法不同于Class.getResource()在于它不使用ClassLoader,如果没有找到给定资源,返回null。 
      /   / 在WebAppContext实现中,它还支持Alias查找,并且如果其extractWAR的变量为false,给定的资源在WAR包中,则该URL返回WAR包中的URL。       
      public   URL getResource(String path)   throws   MalformedURLException; 
     
      /   / 参考getResource(path)的查找实现,如果其返回的URL为null,则该方法返回null,否则返回URL对应的InputStream。  
      public   InputStream getResourceAsStream(String path); 
      // 创建一个RequestDispatcher用于将一个Request、Response分发到path对应的URL中,这里path必须以"/"开头,且它相对于当前Context Path。如果无法创建RequestDispatcher,返回null。 
      //    path可以包含query数据用于传递参数:uriInContext?param1=abc&param2=123....该方法可以和getContext(uripath)一起使用,以将当前请求分发到另一个Web Application中。 
      // 该方法的另一种用法是先有一个Servlet或Filter处理基本的逻辑,然后使用这个RequestDispatcher将当前请求forward到另一个URL中或include一个JSP文件   生成响应页面,如果在处理过程中出错,则将其当前请求分发到错误处理的流程中。  
      // RequestDispatcher支持两种类型的分发:forward和include,唯一的区别是include只可以改变Response的内容,不可以改变其Header信息,forward则没有这种限制。  
      public   RequestDispatcher getRequestDispatcher(String path); 
      /   / 创建一个RequestDispatcher用于将一个Request、Response分发到name对应的Servlet(JSP)中。如果没能找到响应的Servlet,返回null。  
      public   RequestDispatcher getNamedDispatcher(String name);     
      /   / 将msg打印到Servlet对应的log文件中,在Jetty中,使用INFO级别打印,logger名称为web.xml定义的display-name,或者context path。 
      /     Jetty默认使用SLF4J作为日志打印框架,可以使用"org.eclipse.jetty.util.log.class"系统属性改变其日志打印框架。  
      public     void   log(String msg);    
      /   / 打印message和throwable到Servlet对应的log文件中,在Jetty中使用WARN级别打印该信息。  
      public     void   log(String message, Throwable throwable); 
      /   / 返回给定path在当前机器上操作系统对应的位置。对/META-INF/resources下的资源,除非他们已经解压到本地目录,否则对那些资源该方法返回null。 
      /   / 在Jetty实现中,使用getResource()方法相同的实现获取Resource实例,如果其getFile()返回不为null,则返回该File的canonical路径。  
     public   String getRealPath(String path); 
      // 返回Servlet Container的名称和版本号,其格式为:<servername>/<versionnumber>,如:Jetty/8.1.9.v20130131。  
      public   String getServerInfo(); 
      /   / ServletContext级别的初始参数操作,可以在web.xml中使用context-param定义,也可以手动设置。在get中如果找不到对应的项,返回null,在set时,如果已存在name,则返回false,并且不更新相应的值。  
      public   String getInitParameter(String name); 
      public   Enumeration<String> getInitParameterNames(); 
      public     boolean   setInitParameter(String name, String value); 
      // ServletContext级别的属性操作,其中属性名遵循包命名规则。在set中,如果object为null表示移除该属性,如果name以存在,则会替换原有的值,如果注册了ServletContextAttributeListener,则会出发相应的attributeRemoved、attributeReplaced、attributeAdded事件。在remove中,如果name存在且被移除了,则会触发attributeRemoved事件。 
      // 在Jetty中使用ContextHandler中的Context内部类实现ServletContext,在ContextHandler中定义了两个相关字段:_attributes以及_contextAttributes,其中_attributes表示在Jetty内部通过ContextHandler设置的属性,而_contextAttributes表示用户设置的属性,但是在获取属性值时,两个字段的属性都会考虑进去,在移除属性时,如果是移除_attributes字段中的值,则不会触发attributeRemoved事件。  
     public   Object getAttribute(String name); 
      public   Enumeration<String> getAttributeNames(); 
      public     void   setAttribute(String name, Object object); 
      public     void   removeAttribute(String name); 
      // 返回当前Web Application在web.xml中的display-name定义的ServletContext名字,在Jetty实现中,如果该值为null,则返回context path。  
      public   String getServletContextName(); 
      // 该部分具体的使用可以参考:   http://www.blogjava.net/yongboy/archive/2010/12/30/346209.html     

     // 动态的向ServletContext中注册Servlet,注册的Servlet还可以通过返回的ServletRegistration继续配置,如addMapping、setInitParameter等。 
      //    在使用className实例话Servlet时,使用当前ServletContext相关联的ClassLoader。在创建Servlet实例时,会根据该类中定义的以下Annotation做相应的配置: 
      //    javax.servlet.annotation.ServletSecurity、   javax.servlet.annotation.MultipartConfig、   javax.annotation.security.RunAs、 javax.annotation.security.DeclareRoles  
      public   ServletRegistration.Dynamic addServlet(String servletName, String className); 
      public   ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet); 
      public   ServletRegistration.Dynamic addServlet(String servletName, Class <?   extends   Servlet> servletClass); 
      // 创建给定Servlet类的Servlet实例,并且   会根据该类中定义的以下Annotation做相应的配置: 
      //    javax.servlet.annotation.ServletSecurity、   javax.servlet.annotation.MultipartConfig、   javax.annotation.security.RunAs、 javax.annotation.security.DeclareRoles  
      // 在创建Servlet实例后,一般还要调用addServlet()方法将其注册到ServletContext中。  
      public   <T   extends   Servlet> T createServlet(Class<T> clazz)   throws   ServletException; 
      // 根据servletName获取ServletRegistration实例  
      public   ServletRegistration getServletRegistration(String servletName); 
      // 获取所有在ServletContext中注册的servletName到ServletRegistration映射的Map。所有动态注册和使用配置注册的映射。  
      public   Map<String, ?   extends   ServletRegistration> getServletRegistrations(); 
      // 动态的向ServletContext中注册Filter,注册的Filter可以通过返回的FilterRegistration进一步配置,如addMappingForUrlPatterns、setInitParameter等  
      public   FilterRegistration.Dynamic addFilter(String filterName, String className); 
      public   FilterRegistration.Dynamic addFilter(String filterName, Filter filter); 
      public   FilterRegistration.Dynamic addFilter(String filterName, Class <?   extends   Filter> filterClass); 
      /   / 创建给定Filter类实例的Filter实例,一般都会后继调用addFilter将该实例注册到ServletContext中。  
      public   <T   extends   Filter> T createFilter(Class<T> clazz)   throws   ServletException; 
      // 根据filterName获取FilterRegistration实例。  
      public   FilterRegistration getFilterRegistration(String filterName); 
      /   / 返回所有filterName到FilterRegistration映射的Map,包括所有动态注册和使用配置注册的映射。  
      public   Map<String, ?   extends   FilterRegistration> getFilterRegistrations(); 
      // 返回SessionCookieConfig实例,用于session tracking的cookie属性,多次调用该方法返回相同的实例。  
      public   SessionCookieConfig getSessionCookieConfig(); 
      // 设置session tracking模式,可以是URL、COOKIE、SSL。Jetty8只支持URL和COOKIE。  
      public     void   setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes); 
      // 返回当前ServletContext默认支持的session tracking模式。  
      public   Set<SessionTrackingMode> getDefaultSessionTrackingModes(); 
      // 返回当前ServletContext目前使用的session tracking模式。  
      public   Set<SessionTrackingMode> getEffectiveSessionTrackingModes(); 
      // 向ServletContext动态的注册Listener,该Listener类或实例必须实现以下的一个或多个接口:  
    //  
ServletContextAttributeListener、   ServletRequestListener、   ServletRequestAttributeListener、   HttpSessionListener、 HttpSessionAttributeListener}</tt> 
    // 如果这个ServletContext传入ServletContainerInitializer的onStartup方法,那么这个Listener类或实例也可以实现ServletContextListener接口。 
    // 注:动态注册的ServletContextListener中的contextInitialized方法中不可以调用Servlet 3.0中定义的这些动态注册Servlet、Filter、Listener等方法,不然会抛出UnsupportedOperationException,看起来像是出于一致性、安全性或是兼容性的考虑,但是具体是什么原因一直想不出来。而且在Jetty实现中,它在注册EventListener实例是确取消了这种限制,而对注册EventListener类实例和类名确有这种限制,不知道这是Jetty的bug还是其他什么原因。。。。。 

    // 对于调用顺序按定义顺序来的EventListener(如ServletRequestListener、ServletContextListener、HttpSessionListener),那这个新的EventListener会添加到相应列表末尾。 

      public     void   addListener(String className); 
      public   <T   extends   EventListener>   void   addListener(T t); 
      public     void   addListener(Class <?   extends   EventListener> listenerClass); 
      // 创建clazz对应的EventListener实例,一般这个新创建的EventListener会之后注册到ServletContext中。  
      public   <T   extends   EventListener> T createListener(Class<T> clazz)   throws   ServletException;  
      // 返回web.xml和web-fragment.xml配置文件中定义<jsp-config>的汇总,或返回null如果没有相关配置。看起来像Jetty并没有实现该方法。  
      public   JspConfigDescriptor getJspConfigDescriptor(); 
      // 返回当前Web Application对应的ClassLoader实例。  
      public   ClassLoader getClassLoader(); 
      // 定义角色名。角色名在ServletRegistration.Dynamic.setServletSecurity()和ServletRegistration.Dynamic.setRunAsRole()中默认定义,因而不需要重新使用这个方法定义。  
      public     void   declareRoles(String  roleNames); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值