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

publicinterfaceServletContext {

// Servlet Container为当前Web Application设置临时目录,并将该临时目录的值存储到当前ServletContext的属性中使用的属性名。// Jetty使用WebInfConfiguration(在preConfig

ure()方法中)来设置该值,设置temp目录的规则:// 1. 如果存在WEB-INF/work目录,则temp目录的值为:WEB-INF/work/Jetty______// 2. 如果"javax.servlet.context.tempdir"已经在外部被设置,并且该目录存在且可写,则temp目录直接设置为该目录实例。// 3. 如果系统变量中"jetty.home"目录下存在"work"目录且可写,则设置temp目录的值为:${jetty.home}/work/Jetty______

// 4. 如果存在"org.eclipse.jetty.webapp.basetempdir"的属性,且该目录存在并可写,设置temp目录为:${org.eclipse.jetty.webapp.basetempdir}/Jetty______

// 5. 如果以上条件都不成立,则设置temp目录为:${java.io.tmpdir}/Jetty______,且删除已存在临时目录。// 注:对temp目录的父目录不是work,会注册在JVM退出时删除该temp目录,并在temp目录下创建.active目录。

publicstaticfinalString 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类型,包含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(...,即Jetty中的实现)

public int getEffectiveMajorVersion();

//返回当前Web Application基于的Servlet规范的次版本,如在web.xml文件中定义的version(...,即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 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的名称和版本号,其格式为:/,如: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 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 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 createServlet(Class clazz) throws ServletException;

// 根据servletName获取ServletRegistration实例

public ServletRegistration getServletRegistration(String servletName);

// 获取所有在ServletContext中注册的servletName到ServletRegistration映射的Map。所有动态注册和使用配置注册的映射。

public Map 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 createFilter(Class clazz) throws ServletException;

// 根据filterName获取FilterRegistration实例。

public FilterRegistration getFilterRegistration(String filterName);

// 返回所有filterName到FilterRegistration映射的Map,包括所有动态注册和使用配置注册的映射。

public Map getFilterRegistrations();

// 返回SessionCookieConfig实例,用于session tracking的cookie属性,多次调用该方法返回相同的实例。

public SessionCookieConfig getSessionCookieConfig();

// 设置session tracking模式,可以是URL、COOKIE、SSL。Jetty8只支持URL和COOKIE。

public void setSessionTrackingModes(Set sessionTrackingModes);

// 返回当前ServletContext默认支持的session tracking模式。

public Set getDefaultSessionTrackingModes();

// 返回当前ServletContext目前使用的session tracking模式。

public Set getEffectiveSessionTrackingModes();

// 向ServletContext动态的注册Listener,该Listener类或实例必须实现以下的一个或多个接口://ServletContextAttributeListener、ServletRequestListener、ServletRequestAttributeListener、HttpSessionListener、HttpSessionAttributeListener}

// 如果这个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  void addListener(T t);

public void addListener(Class  extends EventListener> listenerClass);

// 创建clazz对应的EventListener实例,一般这个新创建的EventListener会之后注册到ServletContext中。

public  T createListener(Class clazz) throws ServletException;

// 返回web.xml和web-fragment.xml配置文件中定义的汇总,或返回null如果没有相关配置。看起来像Jetty并没有实现该方法。

public JspConfigDescriptor getJspConfigDescriptor();

// 返回当前Web Application对应的ClassLoader实例。

public ClassLoader getClassLoader();

// 定义角色名。角色名在ServletRegistration.Dynamic.setServletSecurity()和ServletRegistration.Dynamic.setRunAsRole()中默认定义,因而不需要重新使用这个方法定义。

public void declareRoles(String

9b8a8a44dd1c74ae49c20a7cd451974e.png roleNames);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值