作为一个 PHP 程序员内心是空虚的, 抛开了 fastcgi 我就无所适从了. 所以我要学一些和以往不一样的东西. Java 的 web 开发框架很多, 为什么选择 latke? 没有理由, 因为我没得对比嘛. 为什么要阅读框架而不是基于框架做一个应用? 因为个人习惯. 做 php 时也是一样, 每用一个新框架都会读 ..

从 Latke 开始学习 Java web 开发

本贴最后更新于 1123 天前,其中的信息可能已经事过景迁

作为一个 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 框架本身的配置. 端口在此配置.

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

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    2466 引用 • 7876 回帖 • 863 关注
  • Latke

    Latke 是一款以 JSON 为主的 Java Web 框架。

    61 引用 • 466 回帖 • 510 关注
回帖
请输入回帖内容...