Jetty之WebAppContext

前面的文章已经提到过,在servlet容器中,每一个webapplication都对应一个contextHandler,但是前面讲到的contextHandler的定义主要是实现了将http的请求进行路由,将其交给sessionHandler,然后再交给servletHandle然后转交给对应的servlet的来进行处理。。。

这里的WebAppContext是对其的一种补充,完善了webapp的启动和handler的管理。。。

先来看它的继承体系吧:



其实着了也可以看到它是对ContextHandler的一种扩展。。那么先来看看Context的定义吧,先来看看他的一些属性的定义:

[java] view plaincopy
  1. protected SecurityHandler _securityHandler;  //安全handler  
  2. protected ServletHandler _servletHandler;  //servlethandler,其用于将http请求路由给相应的servlet来处理  
  3. protected SessionHandler _sessionHandler;   //sessionhandler,其会对servlethandler进行一层包装  

这里定义了3个handler,每个是什么用基本上看名字就已经看出来了。。。

servletHandler是用于将http请求交给对应的servlet来处理。。。sessionHandler则是对servletHandler进行了一层包装(装饰器模式),用于一些session的预处理什么的。。。

接下来再来看看它的一些重要的方法定义:

[java] view plaincopy
  1. //添加servlet,这里将servlet的className与path对应起来。。。  
  2. public ServletHolder addServlet(String className,String pathSpec)  
  3. {  
  4.     return _servletHandler.addServletWithMapping(className, pathSpec);  
  5. }  
  6.   
  7. //将servlet的类型与path对象起来  
  8. public ServletHolder addServlet(Class servlet,String pathSpec)  
  9. {  
  10.     return _servletHandler.addServletWithMapping(servlet.getName(), pathSpec);  
  11. }  
  12.   
  13. //将servlet的holder与path对应起来。。  
  14. public void addServlet(ServletHolder servlet,String pathSpec)  
  15. {  
  16.     _servletHandler.addServletWithMapping(servlet, pathSpec);  
  17. }  
  18.   
  19. //添加filter  
  20. public void addFilter(FilterHolder holder,String pathSpec,int dispatches)  
  21. {  
  22.     _servletHandler.addFilterWithMapping(holder,pathSpec,dispatches);  
  23. }  
  24.   
  25. public FilterHolder addFilter(Class filterClass,String pathSpec,int dispatches)  
  26. {  
  27.     return _servletHandler.addFilterWithMapping(filterClass,pathSpec,dispatches);  
  28. }  
  29.   
  30. public FilterHolder addFilter(String filterClass,String pathSpec,int dispatches)  
  31. {  
  32.     return _servletHandler.addFilterWithMapping(filterClass,pathSpec,dispatches);  
  33. }  

这些方法就是用于在当前的context环境中添加servlet以及filter的。。。。这里也可以看出其实它是交给servletHandler来处理的。。这里也就知道servletHandler的重要作用了吧。。。

[java] view plaincopy
  1. //这里主要是初始化servletHandler  
  2. protected void startContext() throws Exception  
  3. {  
  4.     super.startContext();  
  5.       
  6.     // OK to Initialize servlet handler now  
  7.     if (_servletHandler != null && _servletHandler.isStarted())  
  8.         _servletHandler.initialize();  
  9. }  

这个方法用于启动context,它会在当前WebAppContext的doStart之中被调用,这里主要干的事情就是对servletHnandler进行初始化。。。


接下来我们来看WebAppContext的定义吧,这里就先不详细的看他的定义吧,因为以后webApp的创建和启动的时候会着重分析它。。。因为它封装了很多创建和启动的代码。。。来看看它的doStart方法:

[java] view plaincopy
  1. //这里可以理解为启动这个app,app都需要创建自己的classLoader  
  2. protected void doStart() throws Exception {  
  3.     try {  
  4.         loadConfigurations();  //加载器  
  5.           
  6.             //设置他们的context  
  7.         for (int i=0;i<_configurations.length;i++) {  
  8.             _configurations[i].setWebAppContext(this);  
  9.         }  
  10.   
  11.         // Configure classloader  
  12.         _ownClassLoader=false;  
  13.         if (getClassLoader()==null) {  
  14.             WebAppClassLoader classLoader = new WebAppClassLoader(this);  //创建classLoader  
  15.             setClassLoader(classLoader);  //设置当前的classLoader  
  16.             _ownClassLoader=true;  
  17.         }  
  18.   
  19.         if (Log.isDebugEnabled())   
  20.         {  
  21.             ClassLoader loader = getClassLoader();  
  22.             Log.debug("Thread Context class loader is: " + loader);  
  23.             loader=loader.getParent();  
  24.             while(loader!=null)  
  25.             {  
  26.                 Log.debug("Parent class loader is: " + loader);   
  27.                 loader=loader.getParent();  
  28.             }  
  29.         }  
  30.         //这个里面的操作会加压war文件  
  31.         for (int i=0;i<_configurations.length;i++) {  
  32.             _configurations[i].configureClassLoader();  
  33.         }  
  34.         getTempDirectory();  
  35.           
  36.         super.doStart();  
  37.   
  38.         if (isLogUrlOnStart())   
  39.             dumpUrl();  
  40.     }  
  41.     catch (Exception e)  
  42.     {  
  43.         //start up of the webapp context failed, make sure it is not started  
  44.         Log.warn("Failed startup of context "+this, e);  
  45.         _unavailableException=e;  
  46.         _unavailable = true;  
  47.     }  
  48. }  

这里主要是设置了当前的classLoader,然后还对一些配置对象进行了设置,然后让这些初始配置对象进行初始化。。。

他们都有如下:

[java] view plaincopy
  1. //一些默认的配置类,每一个配置类都有其要干的事情,都还挺重要的  
  2. private static String[] __dftConfigurationClasses =    
  3. {   
  4.     "org.mortbay.jetty.webapp.WebInfConfiguration",   //对webinfo的处理,主要用于载入class文件以及jar包  
  5.     "org.mortbay.jetty.webapp.WebXmlConfiguration",    //这个主要是对web.xml的处理  
  6.     "org.mortbay.jetty.webapp.JettyWebXmlConfiguration",  
  7.     "org.mortbay.jetty.webapp.TagLibConfiguration"   
  8. } ;  

另外来看一个方法:

[java] view plaincopy
  1. //相当于解压war包  
  2. protected void resolveWebApp() throws IOException  
  3. {  
  4.     Resource web_app = super.getBaseResource();  
  5.     if (web_app == null)  
  6.     {  
  7.         if (_war==null || _war.length()==0) {  
  8.             _war=getResourceBase();  
  9.         }  
  10.           
  11.         // Set dir or WAR  设置war的路径,相当于准备读war包了  
  12.         web_app= Resource.newResource(_war);    
  13.   
  14.         // Accept aliases for WAR files  
  15.         if (web_app.getAlias() != null) {  
  16.             Log.debug(web_app + " anti-aliased to " + web_app.getAlias());  
  17.             web_app= Resource.newResource(web_app.getAlias());  
  18.         }  
  19.   
  20.         if (Log.isDebugEnabled())  
  21.             Log.debug("Try webapp=" + web_app + ", exists=" + web_app.exists() + ", directory=" + web_app.isDirectory());  
  22.   
  23.         //这里将原来的war包包装为jar资源  
  24.         if (web_app.exists() && !web_app.isDirectory() && !web_app.toString().startsWith("jar:"))  
  25.         {  
  26.             // No - then lets see if it can be turned into a jar URL.  
  27.             Resource jarWebApp= Resource.newResource("jar:" + web_app + "!/");   //类似于jar:file:/F:/360云盘/jettywork/jetty/webapps/manager.war!/  
  28.             if (jarWebApp.exists() && jarWebApp.isDirectory())  
  29.             {  
  30.                 web_app= jarWebApp;  
  31.                 _war= web_app.toString();  
  32.             }  
  33.         }  
  34.   
  35.         // If we should extract or the URL is still not usable  
  36.         if (web_app.exists()  && (  
  37.            (_copyDir && web_app.getFile()!= null && web_app.getFile().isDirectory())   
  38.            ||  
  39.            (_extractWAR && web_app.getFile()!= null && !web_app.getFile().isDirectory())  
  40.            ||  
  41.            (_extractWAR && web_app.getFile() == null)  
  42.            ||  
  43.            !web_app.isDirectory()  
  44.            ))  
  45.         {  
  46.             // Then extract it if necessary.  
  47.             //获取解压的路径,解压之后将会放到这个地方  
  48.             File extractedWebAppDir= new File(getTempDirectory(), "webapp");  
  49.               
  50.             //如果app是文件夹的话,那么直接复制就好了  
  51.             if (web_app.getFile()!=null && web_app.getFile().isDirectory())  
  52.             {  
  53.                 // Copy directory  
  54.                 Log.info("Copy " + web_app.getFile() + " to " + extractedWebAppDir);  
  55.                 IO.copyDir(web_app.getFile(),extractedWebAppDir);  
  56.             }  
  57.             else  
  58.             {  
  59.                 //先要判断放app的路径是否已经存在  
  60.                 if (!extractedWebAppDir.exists())  {    
  61.                     //it hasn't been extracted before so extract it  
  62.                     extractedWebAppDir.mkdir();  //创建临时文件夹  
  63.                     Log.info("Extract " + _war + " to " + extractedWebAppDir);  
  64.                     JarResource.extract(web_app, extractedWebAppDir, false);   //解压  
  65.                 }  
  66.                 else  
  67.                 {  
  68.                     //only extract if the war file is newer  
  69.                     if (web_app.lastModified() > extractedWebAppDir.lastModified())  
  70.                     {  
  71.                         extractedWebAppDir.delete();  
  72.                         extractedWebAppDir.mkdir();  
  73.                         Log.info("Extract " + _war + " to " + extractedWebAppDir);  
  74.                         JarResource.extract(web_app, extractedWebAppDir, false);  
  75.                     }  
  76.                 }  
  77.             }  
  78.             //这里相当于将web_app的值指向已经解压后的路径  
  79.             web_app= Resource.newResource(extractedWebAppDir.getCanonicalPath());  
  80.   
  81.         }  
  82.   
  83.         // Now do we have something usable?  
  84.         if (!web_app.exists() || !web_app.isDirectory())  
  85.         {  
  86.             Log.warn("Web application not found " + _war);  
  87.             throw new java.io.FileNotFoundException(_war);  
  88.         }  
  89.   
  90.         if (Log.isDebugEnabled())  
  91.             Log.debug("webapp=" + web_app);  
  92.   
  93.         // ResourcePath  
  94.         super.setBaseResource(web_app);  //设置部署的文件夹的路径  
  95.     }  
  96. }  

这个就是对当前的web程序的war包进行处理,进行解压,放到相应的文件夹下面等等。。。


好了,其实到这里,对整个webApp的启动和创建已经设计都有了基本的了解了。。。


看jetty的源码过程还算蛮顺利的。。。莫非源码看多了。。。以后读源码也越来越顺利了。。。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我知道了。关于嵌入式Jetty运行Servlet的实现,可以参考以下步骤: 1. 导入相关依赖 在Maven项目中,需要在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>9.4.6.v20170531</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-servlet</artifactId> <version>9.4.6.v20170531</version> </dependency> ``` 2. 编写Servlet类 在项目中创建一个继承自javax.servlet.http.HttpServlet的类,重写doGet/doPost方法来处理请求。 ``` @WebServlet("/hello") public class HelloServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); response.getWriter().write("Hello,Jetty!"); } } ``` 3. 创建Server对象并配置 创建Server对象,并设置端口号、上下文路径等信息。 ``` Server server = new Server(8080); ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); contextHandler.setContextPath("/"); contextHandler.addServlet(new ServletHolder(new HelloServlet()), "/hello"); server.setHandler(contextHandler); ``` 4. 启动Server 调用start方法启动Server。 ``` server.start(); server.join(); ``` 完整代码示例: ``` import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.annotation.WebServlet; import java.io.IOException; @WebServlet("/hello") public class HelloServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); response.getWriter().write("Hello,Jetty!"); } } public class EmbeddedJettyDemo { public static void main(String[] args) throws Exception { Server server = new Server(8080); ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); contextHandler.setContextPath("/"); contextHandler.addServlet(new ServletHolder(new HelloServlet()), "/hello"); server.setHandler(contextHandler); server.start(); server.join(); } } ``` 这样,就可以使用嵌入式Jetty运行Servlet了。访问http://localhost:8080/hello即可看到“Hello,Jetty!”的输出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值