第三部分: Java 服务端技术
1. Servlet 工作原理解析
Servlet 是 Java Web 的核心技术, Servlet 容器是一个独立发展的标准化产品: Jetty, Tomcat, JBoss 等
以 Tomcat 为例, Context 容器负责管理 Servlet 容器(隶属于组件 Container), 一个 Context 对应一个 Web 工程
1 | Context ctx = new StandardContext(); |
Tomcat 的启动逻辑是基于观察者模式设计的, 所有的容器都会继承 Lifecycle 接口, 所有容器的修改和状态变更会有由它去通知已经注册的观察者(Listener)
Tomcat 的启动创建了 Context 容器, 在 Context 容器中, Web 应用得以初始化, 而这个初始化的过程中, web.xml 决定了 Servlet 对象的创建和初始化
1 | <servlet> |
Servlet 的体系结构围绕着: ServletConfig, ServletRequest, ServletResponse, ServletContext(上下文) 四个类
Servlet 最终的工作原理是靠映射完成的, 这个类就是 org.apache.tomcat.util.http.mapper
Listener 是基于观察者设计模式的, Filter 是基于责任链设计模式的
/Listener.png)
2. 深入理解 Session 与 Cookie
当前 Cookie 有两个版本(0,1), 不同的浏览器支持 Cookie 的数量和大小都不同, Cookie 被加到 header 中发生在构建响应 Response 中, 基于这些限制, Session 则创建在服务端, 以一个 id 作为标识, 客户端使用这个标识可通过 URL Path Paramter, Cookie 中的一个字段来实现
服务器管理 Session 的容器: org.apache.cataline.Manager, 它来负责接管过期回收, 服务器关闭序列化到磁盘(SESSIONS.ser)等问题
Session 的安全性优于 Cookie, 适合存储用户隐私和重要的数据, 引出分布式 Session 框架的核心解决要点
订阅服务器(如 Zookeeper) 负责 Cookie 项的统一配置推送
分布式缓存系统(如 Tair, Memcache) 负责 Session 的快速存储和读取, 而实现就是配置一个 SessionFilter 在创建 Session 之前进行拦截读存等操作
处理 Cookie 被盗取的情况: 当用户登录成功后根据用户的私密信息生成一个签名, 以表示当前这个唯一的合法登录状态, 即 Session 签名; 处理 Cookie 压缩的情况: 可配置一个 Filter 在页面输出是对 Cookie 进行全部的压缩或者部分压缩, 使用 gzip 和 defalte 算法, 节省带宽; 处理表单重复提交的问题: crsf 的 hidden token 验证
3. Tomcat 的系统架构与设计模式
Tomcat 核心架构: Server - 若干个 Service - N 个 Connector 和 1 个 Container, 整个 Tomcat 生命周期由 Server 控制
1 | // conf/server.xml |
实现上来讲 StandServer、StandService 配合 LifeCycle 接口实现全程事件监听和触发控制
Connector 组件是 Tomcat 中的两个核心组件之一, 它的主要任务是负责接收浏览器发过来的 TCP 的连接请求, 创建一个 Request 和 Response 对象分别用于和请求端交换数据, 然后会产生一个线程来处理这个请求, 而处理这个请求的线程就是 Container 组件要做的事情了
1 | <Connector port="8080" protocol="HTTP/1.1" |
Tomcat 使用的设计模式有
外观模式(门面模式): Request 和 Response 对象封装、StandardWrapper 到 ServletConfig 封装、ApplicationContext 到 ServletContext 封装, 一句话, Facade 类控制暴露的数据
观察者模式: LifeCycle 接口接管 Tomcat 生命周期
命令模式: Connector 是通过命令模式调用 Container 的
责任链模式: Container 是通过责任链模式一步步传递给 Servlet 的
4. Jetty 的工作原理解析
Jetty 应该是目前最活跃也很有前景的一个 Servlet 引擎, 任何被扩展的组件都可以作为一个 Handler 添加到 Server 中, Jetty 将帮你管理这些 Handler
整个 Jetty 核心是由 Server 和 Connector 两个组件构成, Server 组件是基于 Handler 容器工作的, 关联了 Connector, 生命周期也是观察者设计模式(LifeCycle)
Jetty 可以基于两种协议工作, 一种是 Http(作为提供独立的 Web 服务), 另一种是 AJP(集成到 JBoss 和 Apache 中), Connector 的工作方式默认都是 NIO, 但支持 BIO
apr(Apache Portable Runtime/Apache可移植运行时库),Tomcat将以JNI的形式调用Apache HTTP服务器的核心动态链接库来处理文件读取或网络传输操作, 从而大大地提高Tomcat对静态文件的处理性能。从操作系统级别来解决异步的IO问题, 大幅度的提高性能。 Tomcat apr也是在Tomcat上运行高并发应用的首选模式
与 Tomcat 的比较
Jetty 的架构比 Tomcat 简单, 何被扩展的组件都可以作为一个 Handler 添加到 Server 中, Jetty 将以责任链的方式来管理这些 Handler
性能方面 Jetty 默认 NIO, Tomcat 默认 BIO, 前者适用于大量长连接的场景(聊天软件), 后者适用于短连接的场景
最新的 Servlet 特性 Jetty 的支持比 Tomcat 早许多, 这也是架构导致的原因
5. Spring 框架的设计理念与设计模式分析
Spring 的三大核心组件: Core, Context, Bean, Bean 包装的是 Object, Context 来维护 Bean 的关系集合(IoC 容器, 从 Context 中获得各种 Bean), Core 用来发现、建立和维护每个 Bean 之间的关系所需要的一系列工具
Bean 组件在 Spring 的 org.springframework.beans 包下, 主要解决: Bean 的定义、创建、及对 Bean 的解析
Bean 的创建是典型的工厂模式, 主要由三个子类: ListenBeanFactory, HierachicalBeanFactory, AutowireCapableBeanFactory, Bean 的解析主要就是对 Spring 配置文件的解析
Context 组件在 Spring 的 org.springframework.context 包下, 作为 Spring 的 IoC 容器, 完成了标识应用环境、利用 BeanFactory 创建 Bean 对象, 保存对象关系表, 能够捕获各种事件的工作
Core 组件把所有资源都抽象成了一个接口的方式来进行访问(ResourceLoader)
IoC 容器实际上是 Context 组件结合其他两个组件共同构建了一个 Bean 的关系网, 在这个构建过程中, BeanFactoryPostProcessor 和 BeanPostProcessor 分别在构建 BeanFactory 和 构建 Bean 对象时调用, InitializingBean 和 DisposableBean 分别在 Bean 的实例创建和销毁时调用
AOP 是基于动态代理实现的, 拦截器就是其中的一个特性
6. Spring MVC 的工作机制与设计模式
要使用 SpringMVC, 只需要在 web.xml 中配置一个 DispatchcerServlet 用于路径映射, 定义一个 ViewResolver 用于视图解析器, 再定义一个业务逻辑的处理流程规则
DispatcherServlet 初始化调用了 initStrategies 方法
1 | protected void initStrategies(ApplicationContext context){ |
7. 深入分析 iBatis 框架之系统架构与映射原理
ORM 框架干的事情: 1. 根据 JDBC 规范建立与数据库的连接 2. 通过反射打通 Java 对象与数据库参数交互之间相互转化的关系
做的事情如下, iBatis 就是把这几行代码分解包装
1 | Class.forName("xxx.xxx.xxx.xxx.Driver"); |