小菜鸟

java菜鸟号正在起航

Tomcat 内置过滤器详解

Tomcat 提供了多种内置过滤器(Filter),用于处理跨域请求、安全防护、编码设置等常见场景。这些过滤器通过配置 web.xml 即可生效,无需手动编码实现。本文将详细介绍常用的 Tomcat 内置过滤器及其配置方式。

CorsFilter:跨域资源共享过滤器

org.apache.catalina.filters.CorsFilter 实现了 W3C 跨域资源共享(CORS)规范,用于解决前端跨域请求被浏览器拦截的问题。其核心功能是在 HTTP 响应中添加 Access-Control-* 系列头信息,允许指定域的请求访问资源。

配置示例

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
  <!-- 允许访问的源域名(多个用逗号分隔,* 表示允许所有) -->
  <init-param>
    <param-name>cors.allowed.origins</param-name>
    <param-value>https://example.com,http://localhost:3000</param-value>
  </init-param>
  <!-- 允许的 HTTP 方法 -->
  <init-param>
    <param-name>cors.allowed.methods</param-name>
    <param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
  </init-param>
  <!-- 允许的请求头 -->
  <init-param>
    <param-name>cors.allowed.headers</param-name>
    <param-value>Content-Type,Authorization,X-Requested-With</param-value>
  </init-param>
  <!-- 允许暴露给客户端的响应头 -->
  <init-param>
    <param-name>cors.exposed.headers</param-name>
    <param-value>Access-Control-Allow-Origin</param-value>
  </init-param>
  <!-- 是否支持带凭据的请求(如 Cookie、Authorization) -->
  <init-param>
    <param-name>cors.support.credentials</param-name>
    <param-value>true</param-value>
  </init-param>
  <!-- 预检请求(OPTIONS)结果的缓存时间(秒) -->
  <init-param>
    <param-name>cors.preflight.maxage</param-name>
    <param-value>3600</param-value> <!-- 1小时 -->
  </init-param>
</filter>
<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern> <!-- 对所有请求生效 -->
</filter-mapping>

关键参数说明

  • cors.allowed.origins:限制允许跨域的源(避免滥用 *,生产环境建议指定具体域名)。
  • cors.support.credentials:设为 true 时,cors.allowed.origins 不能为 *,需指定具体域名。
  • cors.preflight.maxage:减少预检请求次数,提升性能。

CsrfPreventionFilter:跨站请求伪造防护

CsrfPreventionFilter 用于防御跨站请求伪造(CSRF)攻击,原理是:

阅读全文 »

Google Bigtable:分布式结构化存储的开山之作,HBase 就是照着它做的

关系型数据库在数据量到 PB 级的时候撑不住了——单机存不下、分库分表太复杂、高并发读写扛不住。

Google 的 Bigtable 就是在这个背景下诞生的:一个专门为”海量结构化数据”设计的分布式存储系统。

它影响了后来几乎所有 NoSQL 数据库的设计思路。HBase 就是 Bigtable 的开源实现——数据模型一样、架构一样、连组件名字都是对应的。

Bigtable 的数据模型:一张三维的稀疏大表

Bigtable 的数据模型可以用一句话概括:

一个稀疏的、分布式的、多版本的三维映射表。

(row, column, timestamp) → value

拆开看四个概念:

1. 行(Row)

每行有一个唯一的 Row Key,按字典序排序。

排序这个设计很关键: 相近的 Row Key 会存到一起,范围查询效率极高。比如你要查 user_001user_100 的数据,它们物理上连续,一次扫描就能拿到。

2. 列(Column)

列分两级:列族(Column Family)+ 限定符(Qualifier)

格式是 family:qualifier,比如 user:nameuser:agelog:timestamp

  • 列族 必须预先定义,是存储和权限控制的基本单位
  • 限定符 不用预先定义,随时可以加

这个设计让 Bigtable 非常灵活: 你可以在同一个列族下动态添加新列,不用改表结构。

3. 时间戳(Timestamp)

每个单元格可以存多个版本,用时间戳区分:

Row Key: user_001
Column: log:login
  t1: "2023-10-01 08:00"
  t2: "2023-10-02 09:30"

可以配置保留最近 N 个版本,或者保留某个时间范围内的版本。

4. 单元格(Cell)

(Row Key, Column, Timestamp) 三者唯一确定一个值。值就是普通的字符串(二进制安全,可以存任意数据)。

Bigtable 的数据模型 vs 关系型数据库

关系型数据库 Bigtable
表结构 预定义 schema,列固定 列族预定义,限定符动态添加
数据行 有主键,但无排序保证 按 Row Key 字典序排序
多版本 不支持(需自己实现) 原生支持多版本时间戳
稀疏性 每行都有所有列 空的单元格不占存储

Bigtable 适合”半结构化”数据——每行字段不完全一样,比如用户行为日志、爬虫抓取的数据。

系统架构:Master 管调度,Tablet Server 存数据

Bigtable 是典型的”管理 + 执行”分离架构:

阅读全文 »

Tomcat server.xml 配置文件详解

server.xml 是 Tomcat 最核心的配置文件,定义了服务器的整体结构、组件关系及运行参数。本文将逐节点解析其配置细节,帮助理解 Tomcat 的工作机制及优化配置。

配置文件整体结构

Tomcat 的 server.xml 采用 XML 格式,核心节点层级关系如下:

<Server>                 <!-- 整个 Tomcat 服务器 -->
  <Listener />           <!-- 生命周期监听器 -->
  <GlobalNamingResources /> <!-- 全局命名资源 -->
  <Service>              <!-- 服务(连接器 + 引擎) -->
    <Executor />         <!-- 共享线程池 -->
    <Connector />        <!-- 连接器(接收请求) -->
    <Engine>             <!-- 引擎(处理请求) -->
      <Host>             <!-- 虚拟主机 -->
        <Context />      <!-- Web 应用上下文 -->
      </Host>
    </Engine>
  </Service>
</Server>

每个节点代表 Tomcat 的一个核心组件,负责特定功能。

核心节点解析

<Server>:整个 Tomcat 实例的根节点

<Server> 是配置文件的根元素,代表整个 Tomcat 服务器,负责启动和管理所有组件。

主要属性
  • port:服务器监听的关闭端口(默认 8005),用于接收关闭命令。

  • shutdown:关闭服务器的指令字符串(默认 SHUTDOWN)。

    示例:通过 telnet 发送关闭命令:

    telnet 127.0.0.1 8005
    > SHUTDOWN  # 输入后 Tomcat 会关闭
子节点
  • <Listener>:生命周期监听器,用于监控服务器启动、停止等事件(如 VersionLoggerListener 记录版本信息)。
  • <GlobalNamingResources>:全局 JNDI 资源配置(如数据源),供所有应用共享。
  • <Service>:一个或多个服务组件,每个服务包含连接器和引擎。

<Service>:连接器与引擎的组合

<Service> 将多个连接器(Connector)与一个引擎(Engine)绑定,形成一个独立的服务单元。

属性
  • name:服务名称(默认 Catalina),用于标识服务。
子节点
  • <Executor>:配置共享线程池,供多个连接器复用(优化性能)。
  • <Connector>:连接器,负责接收客户端请求。
  • <Engine>:引擎,负责处理连接器接收的请求。

<Executor>:共享线程池(性能优化关键)

<Executor> 定义全局线程池,多个连接器可共享该线程池,避免重复创建线程,提升性能。默认不配置,需手动添加。

配置示例
阅读全文 »

Tomcat JSP 引擎:Jasper 工作机制详解

在 Java Web 开发中,JSP(JavaServer Pages)是一种动态网页技术,它允许在 HTML 中嵌入 Java 代码。Tomcat 作为主流的 Servlet 容器,内置了专门的 JSP 引擎 ——Jasper,负责将 JSP 文件编译为 Servlet 类并执行。本文将详细解析 Jasper 的工作原理,包括运行时编译和预编译两种模式。

Jasper 引擎概述

Jasper 是 Tomcat 处理 JSP 的核心组件,其主要功能包括:

  • JSP 解析:将 JSP 文件中的 HTML 标签、JSP 指令(如 <%@ page %>)、脚本片段(如 <% ... %>)等解析为 Java 代码。
  • 编译:将解析后的 Java 代码编译为 Class 文件(Servlet 实现类)。
  • 执行:通过生成的 Servlet 类处理 HTTP 请求,生成动态响应。

Jasper 集成在 Tomcat 中,无需额外配置即可工作。其入口是 Tomcat 内置的 JspServlet,该 Servlet 在 conf/web.xml 中默认配置,用于处理所有以 .jsp.jspx 结尾的请求。

运行时编译:首次请求触发

Tomcat 并不会在 Web 应用启动时自动编译所有 JSP 文件,而是采用惰性编译策略 —— 仅在客户端第一次请求某个 JSP 页面时才触发编译。这一过程由 JspServlet 主导,具体流程如下:

1. JspServlet 配置

Tomcat 的 conf/web.xml 中默认配置了 JspServlet,负责拦截 JSP 请求:

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
        <param-name>fork</param-name>
        <param-value>false</param-value> <!-- 是否使用独立进程编译 -->
    </init-param>
    <init-param>
        <param-name>xpoweredBy</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup> <!-- 启动时加载,优先级 3 -->
</servlet>

<servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jsp</url-pattern>
    <url-pattern>*.jspx</url-pattern>
</servlet-mapping>
阅读全文 »

Google GFS:分布式文件系统的开山之作,HDFS 就是照着它做的

Google 的数据量到了 PB 级,单机文件系统撑不住了——硬盘不够大、数据没备份、节点会坏。

GFS 就是 Google 为这个场景设计的分布式文件系统。它不追求 POSIX 兼容,不追求低延迟,追求的是:海量数据、高吞吐、容错性强、能跑在普通硬件上。

后来 Hadoop 的 HDFS 就是 GFS 的开源实现——架构一样、概念一样、连组件名字都是对应的。

GFS 的三个角色:各管一摊

GFS 是典型的主从架构,三个角色分工明确:

graph TD
    A[客户端 Client<br/>应用程序接口] -->|1. 获取元数据| B[主控服务器 Master<br/>元数据管理]
    A -->|2. 直接读写数据| C[数据块服务器 ChunkServer1] & D[ChunkServer2] & E[ChunkServer3]
    B -->|3. 心跳/元数据同步| C & D & E
    C & D & E -->|存储数据| F[本地磁盘<br/>Chunk 副本]
    note[核心思想 Master 管元数据,ChunkServer 存数据,Client 直接访问数据节点]
角色 管什么 存什么
Master 管”账本”:文件名、目录、Chunk 位置 元数据(全在内存里)
ChunkServer 管”货”:实际数据块 Chunk 数据(本地磁盘)
Client 应用程序接口 缓存元数据,不存数据

关键设计:Master 不参与数据读写。 Client 只找 Master 要”数据在哪”,拿到地址后直接跟 ChunkServer 传数据。Master 不经过数据流,压力小,集群规模可以做得很大。

阅读全文 »
0%