作为一个 PHP 程序员内心是空虚的,抛开了 fastcgi 我就无所适从了.所以我要学一些和以往不一样的东西.
Java 的 web 开发框架很多, 为什么选择 latke?没有理由,因为我没得对比嘛.为什么要阅读框架而不是基于框架做一个应用?因为个人习惯.做 php 时也是一样,每用一个新框架都会读一遍它的源码(结构上),当然了 php 的框架结构都很简单.
我对 Java 一无所知,以下一定会有错误疏漏,若有路过的大神肯开示一二,不胜感激!
这个学习笔记暂时会停留在 servlet, latke 上, 暂时不会跨越 jetty.
从 Starter 开始
Latkes.setScanPath("org.b3log.latke.demo.hello"); // For Latke IoC
Latkes.initRuntimeEnv();
String classesPath = ClassLoader.getSystemResource("").getPath(); // Real path including maven sub folder
String webappDirLocation = classesPath.replace("target/classes/","src/main/webapp/"); // POM structure in dev env
final File file = new File(webappDirLocation);
if (!file.exists()) {
webappDirLocation = "." // production environment
}
System.out.println(webappDirLocation);
final Server server = new Server(Integer.valueOf(Latkes.getServerPort()));
final WebAppContext root = new WebAppContext();
root.setParentLoaderPriority(true); // Use parent class loader
root.setContextPath("/");
root.setDescriptor(webappDirLocation + "/WEB-INF/web.xml");
root.setResourceBase(webappDirLocation);
server.setHandler(root);
try {
server.start();
} catch (final Exception e) {
e.printStackTrace();
System.exit(-1);
}
前两行 Latkes 的先略过不表.
ClassLoader.getSystemResource("") get 到了什么?
行为上看: 按照 classpath
顺序查找参数中指定的资源,包括 jar 包里面.但是当参数为空串的时候,只会查找目录而不包含 jar 包.
比如: java -cp WEB-INF/lib/*:WEB-INF/classes Starter
传递空串会返回 /path/to/WEB-INF/classes
路径
非空串则会检索 jar 包,返回这种路径 /path/to/WEB-INF/lib/cdi-api-1.0.jar!beans.xsd
但内部实现没有找到,如果有人知道请指教.
classPath.replace
目的是调试, 因为打包后的和开发时生成的目录结构不一样, 应该算是一个补丁.
上面的代码在产品环境下按照注释:
java-cpWEB-INF/lib/*:WEB-INF/classesorg.b3log.latke.demo.hello.Starter
应该是跑不通的,因为找不到 web.xml,只需要 -cp .:WEB-INF/lib/*:WEB-INF/classes
这样, 原因还是看前面的 classloader.
接下来都是关于 jetty 的, 主要是加载 web.xml, 相关资料看这里: http://www.eclipse.org/jetty/documentation/current/embedding-jetty.html ,暂时不会深入.
Latkes.getServerPort()
问题: 这个 port 是怎么来的呢?
我们回到最前面两句
Latkes.setScanPath("org.b3log.latke.demo.hello"); // For Latke IoC
Latkes.initRuntimeEnv();
Latke 类有一个静态初始化块, 里面加载了
- latke.properties
- local.properties
- remote.properties
三个文件, 第一个是 latke 框架本身的配置.端口在此配置.
Latkes::initRuntimeEnv
这个函数根据 latke.properties
初始化了运行环境和数据库配置, 看代码 runtimeEnv
的值总是 Local
, 这样的话就会总是去初始化数据库了.
latke 到这里算是一个阶段小阶段.
接下来看一点 servlet 相关的
Starter 的代码中, jetty 加载了 web.xml, 到底 jetty 如何运作我们先不管,以免战线太长.总之先理解为 jetty 按照 web.xml 的说明进行一些初始化工作吧.
但是 servlet 是绕不过去的,先看 web.xml 定义了什么:
Listener: org.b3log.latke.demo.hello.HelloServletListener
(编辑器不能插入 xml 标签)
里面设定了一个 servlet 的 listerner, 什么是 listener 呢?看此文档: https://docs.oracle.com/cd/B14099_19/web.1012/b14017/filters.htm
如上文档可知, event listener 在 servlet(容器?)发生关键事件时给予应用监听此事件的能力. servlet 事件包含两个级别:
- 应用级别(如何形容?就是应用)
- 会话级别(同一个用户的一系列请求)
但是看 latke 的代码还有一个请求级别的 ServletRequestListener, 暂时还不确定和 session 级别有多大区别,之后验证.
现在我们知道 jetty 在初始化后会通过 ServletContextListener
通知我们的应用可以接收请求了.接下来 latke 到底做了哪些事情?
明天继续.
PS: jetty 工作原理,可以先大概了解下 http://www.ibm.com/developerworks/cn/java/j-lo-jetty/index.html
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于