项目简介
Apache Tomcat是Apache软件基金会开发的一个开源的Java Servlet容器,实现了Java EE的Servlet、JSP(JavaServer Pages)和WebSocket规范。Tomcat为Java Web应用程序提供了一个”纯Java”的HTTP Web服务器环境,使得Java代码能够在其中运行。
Tomcat最初由Sun Microsystems的James Duncan Davidson开发,后来捐赠给Apache软件基金会。它是目前最受欢迎的Java Web应用服务器之一,被广泛用于开发和部署Java Web应用程序。
主要特性
- Servlet容器:完整实现Java Servlet 4.0规范
- JSP引擎:支持JSP 2.3规范,提供动态网页生成
- WebSocket支持:实现WebSocket 1.1规范
- 管理界面:提供Web界面管理应用程序和服务器
- 集群支持:支持会话复制和负载均衡
- 安全性:内置安全域和访问控制机制
- 轻量级:相比其他Java EE服务器,占用资源较少
项目原理
核心架构
Tomcat采用分层的组件架构:
1 2 3 4 5 6 7 8 9 10 11 12
| Server (服务器) └── Service (服务) ├── Connector (连接器) │ ├── HTTP/1.1 Connector │ ├── HTTP/2 Connector │ └── AJP Connector └── Engine (引擎) └── Host (虚拟主机) └── Context (Web应用上下文) ├── Servlet ├── Filter └── Listener
|
请求处理流程
- 连接接收:Connector接收HTTP请求
- 请求解析:解析HTTP请求头和参数
- 容器调用:将请求传递给Engine
- 主机匹配:根据Host匹配虚拟主机
- 上下文路由:根据URL路径匹配Web应用
- Servlet处理:调用相应的Servlet处理请求
- 响应生成:生成HTTP响应并返回
核心组件
Catalina(Servlet容器):
- 管理Servlet生命周期
- 处理请求分发和会话管理
- 实现安全和过滤机制
Coyote(HTTP连接器):
- 处理HTTP协议
- 管理网络连接
- 支持HTTP/1.1、HTTP/2和AJP协议
Jasper(JSP引擎):
- 编译JSP页面为Servlet
- 管理JSP页面的生命周期
- 提供表达式语言(EL)支持
使用场景
1. Java Web应用部署
Tomcat是部署Java Web应用程序的标准平台,支持WAR文件的热部署和管理。
2. 微服务架构
在微服务架构中,Tomcat作为嵌入式服务器,为每个微服务提供HTTP服务能力。
3. 开发和测试环境
开发者使用Tomcat搭建本地开发环境,进行Java Web应用的开发和调试。
4. 企业级Web服务
中小型企业使用Tomcat部署内部管理系统、OA系统等企业应用。
5. 反向代理后端
Tomcat与Apache HTTP Server或Nginx配合,作为处理动态内容的后端服务器。
具体案例
案例1:Spring Boot应用部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.0</version> </parent>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> </dependencies>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
@RestController public class HelloController { @GetMapping("/hello") public String hello(@RequestParam(defaultValue = "World") String name) { return String.format("Hello, %s!", name); } }
|
案例2:传统Servlet应用部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.1"> <display-name>Web Application</display-name> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.example.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> <filter> <filter-name>EncodingFilter</filter-name> <filter-class>com.example.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>EncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
|
1 2 3 4 5 6 7 8 9 10 11 12
| @WebServlet("/hello") public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<h1>Hello from Servlet!</h1>"); } }
|
案例3:集群配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions="8"> <Manager className="org.apache.catalina.ha.session.DeltaManager" expireSessionsOnShutdown="false" notifyListenersOnReplication="true"/> <Channel className="org.apache.catalina.tribes.group.GroupChannel"> <Membership className="org.apache.catalina.tribes.membership.McastService" address="228.0.0.4" port="45564" frequency="500" dropTime="3000"/> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" autoBind="100" selectorTimeout="5000" maxThreads="6"/> <Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter"> <Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/> </Sender> </Channel> <Valve className="org.apache.catalina.ha.tcp.ReplicationValve" filter=""/> <Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/> <ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/> </Cluster>
|
案例4:数据源配置
1 2 3 4 5 6 7 8 9 10 11 12 13
| <Context> <Resource name="jdbc/MyDB" auth="Container" type="javax.sql.DataSource" maxTotal="20" maxIdle="10" maxWaitMillis="-1" username="dbuser" password="dbpass" driverClassName="com.mysql.cj.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8"/> </Context>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| @WebServlet("/users") public class UserServlet extends HttpServlet { private DataSource dataSource; @Override public void init() throws ServletException { try { Context initContext = new InitialContext(); Context envContext = (Context) initContext.lookup("java:/comp/env"); dataSource = (DataSource) envContext.lookup("jdbc/MyDB"); } catch (NamingException e) { throw new ServletException("数据源初始化失败", e); } } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users"); ResultSet rs = stmt.executeQuery()) { response.setContentType("application/json;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("["); boolean first = true; while (rs.next()) { if (!first) out.println(","); out.printf("{\"id\":%d,\"name\":\"%s\"}", rs.getInt("id"), rs.getString("name")); first = false; } out.println("]"); } catch (SQLException e) { throw new ServletException("数据库查询失败", e); } } }
|
性能优化建议
1. JVM调优
1 2
| export JAVA_OPTS="-Xms2048m -Xmx4096m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+HeapDumpOnOutOfMemoryError"
|
2. 连接器调优
1 2 3 4 5 6 7 8 9 10 11
| <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="200" minSpareThreads="10" connectionTimeout="20000" acceptorThreadCount="2" enableLookups="false" compression="on" compressionMinSize="2048" compressableMimeType="text/html,text/xml,text/plain,application/javascript,text/css"/>
|
3. 会话管理优化
1 2 3 4 5 6 7 8 9 10
| <Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true" maxActiveSessions="-1" minIdleSwap="1800" maxIdleSwap="3600" maxIdleBackup="1800"> <Store className="org.apache.catalina.session.FileStore" directory="sessions"/> </Manager>
|
4. 日志配置优化
1 2 3 4 5 6 7 8 9
| handlers = 1catalina.org.apache.juli.AsyncFileHandler, java.util.logging.ConsoleHandler
.handlers = 1catalina.org.apache.juli.AsyncFileHandler, java.util.logging.ConsoleHandler
1catalina.org.apache.juli.AsyncFileHandler.level = INFO 1catalina.org.apache.juli.AsyncFileHandler.directory = ${catalina.base}/logs 1catalina.org.apache.juli.AsyncFileHandler.prefix = catalina. 1catalina.org.apache.juli.AsyncFileHandler.maxDays = 7
|
Apache Tomcat作为Java Web应用服务器的标杆,其简单易用、高性能的特点使其成为Java开发者的首选。通过合理的配置和优化,Tomcat可以支撑高并发的Web应用,满足从小型项目到企业级应用的各种需求。
版权所有,如有侵权请联系我