建站平台 iis2345浏览器电脑版首页
2026/1/14 13:56:28 网站建设 项目流程
建站平台 iis,2345浏览器电脑版首页,查询企业营业执照怎么查,做房间预定网站需要什么软件从入门到精通#xff1a;Tomcat底层原理与实战全解析引言#xff1a;为什么Tomcat是Java开发者的必备技能#xff1f;在Java后端开发领域#xff0c;Tomcat绝对是绕不开的核心组件。无论是小型创业公司的单体应用#xff0c;还是大型企业的分布式架构#xff0c;Tomcat都…从入门到精通Tomcat底层原理与实战全解析引言为什么Tomcat是Java开发者的必备技能在Java后端开发领域Tomcat绝对是绕不开的核心组件。无论是小型创业公司的单体应用还是大型企业的分布式架构Tomcat都以其轻量、稳定、可扩展的特性成为Java Web应用的首选容器。作为Java资深技术专家我将从底层原理、核心组件、实战配置、性能优化到故障排查用最通俗的语言讲透Tomcat结合可直接运行的实战案例让你既能夯实基础又能解决实际开发中的各类问题。一、Tomcat核心认知什么是Tomcat它能做什么1.1 Tomcat的本质与定位Tomcat是Apache软件基金会旗下的开源Java Servlet容器同时支持JSP、EL表达式等Java Web技术规范本质上是一个基于Java的HTTP服务器 Servlet容器的组合体。它的核心作用有两个一是作为HTTP服务器接收客户端的HTTP请求并返回响应二是作为Servlet容器管理Servlet的生命周期加载、初始化、运行、销毁并提供Servlet运行所需的环境如Request、Response对象的创建与传递。这里需要明确Tomcat并非全功能的Web服务器如Nginx、Apache HTTP Server它的HTTP服务器功能主要用于开发和中小型部署场景在大型生产环境中通常会将Tomcat与Nginx配合使用——Nginx负责处理静态资源、负载均衡、SSL终结Tomcat专注于处理动态请求Java Web应用。1.2 Tomcat与Java EE规范的关系Tomcat严格遵循Java EE现Jakarta EE规范中的Servlet、JSP、WebSocket等核心规范但其支持的规范子集有限不包含EJB、JMS等重型规范因此被称为“轻量级Java EE容器”。最新稳定版本Tomcat 10.1已完全支持Jakarta EE 10规范将包名从javax.servlet迁移为jakarta.servlet这是后续版本的重要变更点开发中需特别注意。1.3 Tomcat的核心优势开源免费基于Apache许可证无商业授权成本轻量灵活安装包仅几十MB配置简单可根据需求裁剪组件稳定可靠经过多年工业级验证支持高并发场景下的稳定运行生态完善与Spring、Spring Boot、MyBatis等主流Java框架无缝集成可扩展性强支持自定义Valve、Connector、Engine等组件满足个性化需求。二、Tomcat架构深度解析从顶层结构到底层组件2.1 Tomcat整体架构图2.2 核心组件层级关系从外到内Tomcat的架构采用分层设计各组件职责清晰层级关系为Server → Service → Engine → Host → Context → Servlet容器每个层级都包含特定的核心组件共同完成请求的接收与处理。2.2.1 ServerTomcat的顶层容器Server是Tomcat的最顶层组件代表一个完整的Tomcat实例一个Tomcat进程对应一个Server。其核心职责是管理Service组件一个Server可包含多个Service实现多端口监听并提供Tomcat的启动、停止等生命周期管理能力。Server的配置位于conf/server.xml的Server标签中默认配置如下Server port8005 shutdownSHUTDOWN !-- 监听8005端口接收SHUTDOWN命令关闭Tomcat -- Listener classNameorg.apache.catalina.startup.VersionLoggerListener/ Listener classNameorg.apache.catalina.core.AprLifecycleListener SSLEngineon/ Service nameCatalina !-- 后续组件配置 -- /Service /Server2.2.2 Service连接Connector与Engine的桥梁Service组件的核心作用是“串联”Connector和Engine将Connector接收的请求传递给Engine处理同时管理这两个组件的生命周期启动/停止同步。一个Service包含一个Engine和多个Connector不同Connector监听不同端口支持不同协议。默认配置中Service名称为“Catalina”Tomcat的默认引擎名称后续所有组件都隶属于该Service。2.2.3 Connector请求接收与协议解析组件Connector连接器是Tomcat与客户端通信的入口负责监听指定端口、接收客户端请求、解析请求协议HTTP/1.1、AJP、HTTP/2等并将解析后的请求封装为Tomcat内部的Request对象传递给Engine处理同时将Engine返回的Response对象转换为客户端可识别的协议格式返回给客户端。Tomcat的核心Connector实现有3种HTTP Connector处理HTTP/HTTPS请求默认监听8080端口HTTP、8443端口HTTPSAJP Connector处理AJP协议请求默认监听8009端口用于与Nginx、Apache HTTP Server等反向代理服务器通信高效传递请求减少协议转换开销HTTP/2 Connector支持HTTP/2协议提供更高的并发性能和更低的延迟。HTTP Connector核心配置示例conf/server.xmlConnector port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 maxThreads1000 minSpareThreads100 acceptCount1000 enableLookupsfalse URIEncodingUTF-8/配置参数说明port监听端口默认8080protocol协议类型推荐使用org.apache.coyote.http11.Http11Nio2ProtocolNIO2模型非阻塞IO支持高并发connectionTimeout连接超时时间毫秒默认20000redirectPortHTTP请求重定向到HTTPS的端口默认8443maxThreads最大线程数处理请求的核心线程池大小默认200minSpareThreads最小空闲线程数确保有足够线程处理突发请求acceptCount请求队列大小当所有线程都繁忙时最多可排队的请求数enableLookups是否反向解析客户端IP对应的主机名关闭可提升性能URIEncodingURI编码格式必须设置为UTF-8避免中文参数乱码。2.2.4 Engine请求处理的核心引擎Engine是Service的核心组件也称为“引擎”负责接收所有Connector传递的请求并根据请求的主机名Host将请求分发到对应的Host组件处理。一个Engine可以包含多个Host虚拟主机实现多域名部署如www.jam.com、blog.jam.com共用一个Tomcat实例。Engine的默认配置Engine nameCatalina defaultHostlocalhost !-- 虚拟主机配置 -- Host namelocalhost appBasewebapps unpackWARstrue autoDeploytrue !-- Context配置 -- /Host /Engine参数说明name引擎名称默认“Catalina”defaultHost默认虚拟主机名称当请求的主机名无法匹配任何Host时由该Host处理默认localhost。2.2.5 Host虚拟主机组件Host代表一个虚拟主机对应一个域名如localhost、www.jam.com负责管理多个ContextWeb应用。其核心职责是根据请求的URI路径将请求分发到对应的Context组件即具体的Web应用。Host的核心配置Host namelocalhost appBasewebapps unpackWARstrue autoDeploytrue !-- 别名配置一个Host可对应多个域名 -- Aliaswww.jam.com/Alias !-- 访问日志配置 -- Valve classNameorg.apache.catalina.valves.AccessLogValve directorylogs prefixlocalhost_access_log suffix.txt pattern%h %l %u %t quot;%rquot; %s %b quot;%{Referer}iquot; quot;%{User-Agent}iquot;/ /Host参数说明name虚拟主机名称必须与域名一致appBaseWeb应用的部署目录默认webapps可改为自定义路径unpackWARs是否自动解压WAR包true则解压为文件夹false直接运行WAR包autoDeploy是否自动部署监测appBase目录新增/修改Web应用时自动加载开发环境推荐开启生产环境建议关闭Alias虚拟主机别名支持多个域名映射到同一个Host。2.2.6 ContextWeb应用上下文Context代表一个具体的Web应用如Spring Boot应用、传统JSP应用是Tomcat中最小的部署单元。每个Context对应一个Web应用的目录结构包含Servlet、JSP、静态资源、配置文件等。Context的核心职责是管理Web应用的生命周期以及Servlet、Filter、Listener等组件的初始化与运行。Context的配置方式有3种自动部署将Web应用的WAR包或文件夹放入Host的appBase目录如webappsTomcat自动创建Context配置文件方式在conf/Catalina/localhost目录下创建xxx.xml文件xxx为Context路径配置Context信息直接在server.xml的Host标签内配置Context不推荐修改需重启Tomcat。推荐配置方式示例conf/Catalina/localhost/demo.xmlContext path/demo docBaseD:/webapps/demo reloadablefalse !-- 资源链接配置如数据库连接池 -- Resource namejdbc/demoDB authContainer typejavax.sql.DataSource driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/demo?useSSLfalseserverTimezoneUTCallowPublicKeyRetrievaltrue usernameroot passwordroot maxTotal100 maxIdle20 minIdle5 maxWaitMillis10000/ /Context参数说明pathWeb应用的访问路径如/demo则访问地址为http://localhost:8080/demodocBaseWeb应用的实际物理路径可绝对路径或相对路径reloadable是否自动重载监测classes和lib目录文件变化时自动重启应用开发环境true生产环境falseResource配置JNDI资源如数据库连接池供Web应用通过JNDI lookup获取。2.2.7 Servlet容器Web组件的运行环境Servlet容器是Context的核心子组件也称为“Servlet引擎”负责管理Servlet、Filter、Listener的生命周期提供Web应用运行所需的核心服务如Request/Response对象创建、会话管理、安全控制等。Servlet容器的核心工作流程加载Web应用的web.xml配置文件或注解配置初始化Filter、Listener接收Context传递的请求根据请求URI匹配对应的Servlet通过映射规则若Servlet未初始化则调用其init()方法初始化调用Servlet的service()方法处理请求根据HTTP方法分发到doGet()/doPost()等方法处理完成后将Response对象返回给Context最终传递给客户端当Web应用停止时调用Servlet的destroy()方法销毁实例。三、Tomcat请求处理全流程从客户端请求到响应返回3.1 完整请求处理流程图3.2 分步拆解核心流程以“用户访问http://localhost:8080/demo/hello”为例拆解Tomcat的请求处理全流程客户端发起请求用户通过浏览器发送HTTP GET请求目标地址为http://localhost:8080/demo/hello其中localhost是主机名8080是Tomcat的HTTP Connector监听端口/demo/hello是请求URI。Connector接收并解析请求监听8080端口的HTTP Connector接收到请求解析HTTP请求行方法GET、URI/demo/hello、协议HTTP/1.1、请求头Host: localhost、User-Agent等将解析后的请求信息封装为Tomcat内部的org.apache.catalina.connector.Request对象实现jakarta.servlet.http.HttpServletRequest接口同时创建对应的Response对象。Engine分发请求到HostConnector将Request和Response传递给EngineCatalinaEngine解析请求头中的Host字段localhost匹配到名称为localhost的Host虚拟主机。Host分发请求到ContextHost解析请求URI中的/demoContext路径匹配到路径为/demo的ContextWeb应用。Servlet容器匹配并执行ServletContext解析URI剩余部分/hello通过Web应用的映射规则如web.xml中的servlet-mapping或RequestMapping注解匹配到对应的HelloServlet若HelloServlet未初始化首次访问Servlet容器调用其init()方法完成初始化仅执行一次调用HelloServlet的service()方法传入Request和Response对象HelloServlet在doGet()方法中处理请求如查询数据、生成响应内容并将结果写入Response对象。返回响应给客户端Servlet处理完成后Response对象包含响应行状态码200 OK、响应头Content-Type: text/html、响应体Hello World!Connector将Response对象转换为标准的HTTP响应格式通过8080端口返回给浏览器浏览器接收响应后渲染响应体内容展示给用户。四、Tomcat实战环境搭建与Web应用部署4.1 Tomcat最新稳定版安装与配置Windows/Linux通用4.1.1 环境准备JDK版本推荐JDK 17Tomcat 10.1要求JDK 8JDK 17性能更优下载地址Tomcat 10.1.20最新稳定版官网地址https://tomcat.apache.org/download-10.cgi系统要求Windows 10、Linux CentOS 7/Ubuntu 20.04内存≥2GB。4.1.2 安装步骤下载Tomcat安装包二进制压缩包如apache-tomcat-10.1.20-windows-x64.zip解压到自定义目录如WindowsD:/apache-tomcat-10.1.20Linux/usr/local/apache-tomcat-10.1.20配置环境变量可选用于全局访问Tomcat命令Windows新增系统变量CATALINA_HOME值为Tomcat解压目录在Path中添加%CATALINA_HOME%\binLinux编辑/etc/profile添加export CATALINA_HOME/usr/local/apache-tomcat-10.1.20执行source /etc/profile生效。4.1.3 核心配置优化生产环境必改修改Connector配置conf/server.xml优化线程池和IO模型提升并发能力Connector port8080 protocolorg.apache.coyote.http11.Http11Nio2Protocol connectionTimeout30000 redirectPort8443 maxThreads2000 minSpareThreads200 acceptCount1500 enableLookupsfalse URIEncodingUTF-8 maxConnections10000 compressionon compressionMinSize2048 compressableMimeTypetext/html,text/xml,text/plain,application/json/关闭自动部署conf/server.xml的Host标签生产环境关闭autoDeploy避免误部署风险Host namelocalhost appBasewebapps unpackWARstrue autoDeployfalse配置访问日志格式优化日志可读性和性能Valve classNameorg.apache.catalina.valves.AccessLogValve directorylogs prefixlocalhost_access_log suffix.txt pattern%h %l %u %t quot;%rquot; %s %b %D quot;%{Referer}iquot; quot;%{User-Agent}iquot;/其中%D表示请求处理时间毫秒便于后续性能分析。设置JVM参数bin/catalina.sh或bin/catalina.bat优化JVM内存配置避免OOM和GC频繁Linuxcatalina.sh在文件开头添加JAVA_OPTS-Xms2g -Xmx2g -XX:MetaspaceSize256m -XX:MaxMetaspaceSize512m -XX:UseG1GC -XX:MaxGCPauseMillis200 -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/usr/local/apache-tomcat-10.1.20/logs/heapdump.hprofWindowscatalina.bat在文件开头添加set JAVA_OPTS-Xms2g -Xmx2g -XX:MetaspaceSize256m -XX:MaxMetaspaceSize512m -XX:UseG1GC -XX:MaxGCPauseMillis200 -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPathD:/apache-tomcat-10.1.20/logs/heapdump.hprof参数说明-Xms2g初始堆内存2GB-Xmx2g最大堆内存2GB与初始堆一致避免频繁扩容-XX:MetaspaceSize元空间初始大小-XX:UseG1GC使用G1垃圾收集器适合大内存场景-XX:HeapDumpOnOutOfMemoryErrorOOM时自动生成堆转储文件用于故障排查。4.1.4 启动与验证启动TomcatWindows双击bin/startup.batLinux执行bin/startup.sh需添加执行权限chmod x bin/*.sh。验证启动成功访问http://localhost:8080若出现Tomcat默认主页则启动成功查看日志logs/catalina.outLinux或logs/catalina.2025-xx-xx.logWindows无ERROR日志即为正常。停止TomcatWindows双击bin/shutdown.batLinux执行bin/shutdown.sh。4.2 Web应用部署的3种核心方式4.2.1 自动部署开发环境首选将Web应用的WAR包如demo.war或解压后的文件夹复制到Tomcat的webapps目录若Host的autoDeploytrueTomcat会自动检测并部署应用访问应用http://localhost:8080/应用名WAR包名称即为应用名如demo.war对应/demo路径。4.2.2 配置文件部署生产环境首选在conf/Catalina/localhost目录下创建demo.xml文件文件名即为应用访问路径配置Context信息如4.2.6节示例指定docBase为应用的物理路径重启Tomcat生产环境无autoDeploy时应用自动部署优势应用路径与物理路径解耦便于管理多个应用。4.2.3 控制台部署可视化操作启用Tomcat管理控制台默认情况下管理控制台未开放需配置用户权限配置用户conf/tomcat-users.xmltomcat-users xmlnshttp://tomcat.apache.org/xml xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://tomcat.apache.org/xml tomcat-users.xsd version1.0 user usernameadmin passwordadmin123 rolesmanager-gui,admin-gui/ /tomcat-users允许远程访问控制台默认仅允许本地访问修改webapps/manager/META-INF/context.xmlContext antiResourceLockingfalse privilegedtrue !-- 注释掉以下内容允许远程访问 -- !-- Valve classNameorg.apache.catalina.valves.RemoteAddrValve allow127\.\d\.\d\.\d|::1|0:0:0:0:0:0:0:1 / -- /Context重启Tomcat访问控制台http://localhost:8080/manager/html点击“Deploy”选择WAR包上传并部署。五、实战案例基于Tomcat的Spring Boot Web应用开发5.1 项目架构设计本案例采用“Spring Boot 3.2 MyBatis-Plus 3.5 MySQL 8.0 Tomcat 10.1”技术栈开发一个用户管理系统包含用户查询、新增、修改、删除功能最终打包为WAR包部署到Tomcat。5.2 项目初始化Maven配置5.2.1 pom.xml核心依赖?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.5/version relativePath/ /parent groupIdcom.jam.demo/groupId artifactIdtomcat-demo/artifactId version1.0.0/version nametomcat-demo/name descriptionTomcat实战demo/description !-- 打包类型为WAR -- packagingwar/packaging properties java.version17/java.version mybatis-plus.version3.5.5/mybatis-plus.version fastjson2.version2.0.45/fastjson2.version lombok.version1.18.30/lombok.version springdoc.version2.3.0/springdoc.version /properties dependencies !-- Spring Boot Web Starter排除内置Tomcat -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId exclusions exclusion groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-tomcat/artifactId /exclusion /exclusions /dependency !-- Tomcat依赖provided避免打包时包含 -- dependency groupIdjakarta.servlet/groupId artifactIdjakarta.servlet-api/artifactId scopeprovided/scope /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId version${lombok.version}/version scopeprovided/scope /dependency !-- MyBatis-Plus -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version${mybatis-plus.version}/version /dependency !-- MySQL驱动 -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency !-- FastJSON2 -- dependency groupIdcom.alibaba.fastjson2/groupId artifactIdfastjson2/artifactId version${fastjson2.version}/version /dependency !-- SpringDocSwagger3 -- dependency groupIdorg.springdoc/groupId artifactIdspringdoc-openapi-starter-webmvc-ui/artifactId version${springdoc.version}/version /dependency !-- Spring 工具类 -- dependency groupIdorg.springframework/groupId artifactIdspring-context-support/artifactId /dependency !-- Google Guava集合工具类 -- dependency groupIdcom.google.guava/groupId artifactIdguava/artifactId version33.2.1-jre/version /dependency /dependencies build plugins !-- Spring Boot Maven插件 -- plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration excludes exclude groupIdorg.projectlombok/groupId artifactIdlombok/artifactId /exclude /excludes /configuration /plugin !-- 编译插件指定JDK17 -- plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.8.1/version configuration source17/source target17/target encodingUTF-8/encoding /configuration /plugin /plugins /build /project关键说明打包类型为war并排除Spring Boot内置Tomcat避免与外部Tomcat冲突添加jakarta.servlet-api依赖provided范围由外部Tomcat提供集成Swagger3SpringDoc用于接口文档生成引入Spring工具类、Google Guava、FastJSON2符合工具类使用规范。5.2.2 应用配置文件application.ymlspring: # 数据库配置 datasource: url: jdbc:mysql://localhost:3306/tomcat_demo?useSSLfalseserverTimezoneUTCallowPublicKeyRetrievaltruecharacterEncodingUTF-8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # 事务管理器编程式事务 transaction: default-timeout: 30 # MyBatis-Plus配置 mybatis-plus: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.jam.demo.entity configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: AUTO table-prefix: t_ # 服务器配置部署到Tomcat后以Tomcat的Connector配置为准 server: servlet: context-path: /tomcat-demo port: 8080 # SpringDocSwagger3配置 springdoc: api-docs: path: /api-docs swagger-ui: path: /swagger-ui.html operationsSorter: method packages-to-scan: com.jam.demo.controller # 日志配置 logging: level: root: INFO com.jam.demo: DEBUG file: name: logs/tomcat-demo.log pattern: console: %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n file: %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n5.3 核心代码实现5.3.1 启动类War包部署必须继承SpringBootServletInitializerpackage com.jam.demo; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; /** * 应用启动类WAR包部署需继承SpringBootServletInitializer * * author ken */ SpringBootApplication MapperScan(com.jam.demo.mapper) ComponentScan(basePackages com.jam.demo) public class TomcatDemoApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(TomcatDemoApplication.class, args); } }关键说明WAR包部署到Tomcat时必须继承SpringBootServletInitializer确保Tomcat能正确加载Spring Boot应用MapperScan指定MyBatis-Plus的Mapper接口扫描路径。5.3.2 实体类Userpackage com.jam.demo.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.experimental.Accessors; import java.io.Serializable; import java.time.LocalDateTime; /** * 用户实体类 * * author ken */ Data Accessors(chain true) TableName(t_user) public class User implements Serializable { private static final long serialVersionUID 1L; /** * 主键ID */ TableId(type IdType.AUTO) private Long id; /** * 用户名 */ private String username; /** * 密码加密存储 */ private String password; /** * 手机号 */ private String phone; /** * 状态0-禁用1-正常 */ private Integer status; /** * 创建时间 */ private LocalDateTime createTime; /** * 更新时间 */ private LocalDateTime updateTime; }5.3.3 Mapper接口UserMapperpackage com.jam.demo.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.jam.demo.entity.User; import org.springframework.stereotype.Repository; /** * 用户Mapper接口 * * author ken */ Repository public interface UserMapper extends BaseMapperUser { }5.3.4 服务层UserService与实现类package com.jam.demo.service; import com.baomidou.mybatisplus.extension.service.IService; import com.jam.demo.entity.User; import com.jam.demo.vo.req.UserAddReq; import com.jam.demo.vo.req.UserUpdateReq; import com.jam.demo.vo.resp.UserResp; import java.util.List; /** * 用户服务接口 * * author ken */ public interface UserService extends IServiceUser { /** * 查询所有用户 * * return 用户列表 */ ListUserResp listAllUsers(); /** * 根据ID查询用户 * * param id 用户ID * return 用户详情 */ UserResp getUserById(Long id); /** * 新增用户 * * param req 新增请求参数 * return 新增后的用户ID */ Long addUser(UserAddReq req); /** * 修改用户 * * param req 修改请求参数 */ void updateUser(UserUpdateReq req); /** * 根据ID删除用户 * * param id 用户ID */ void deleteUserById(Long id); }实现类package com.jam.demo.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.Lists; import com.jam.demo.entity.User; import com.jam.demo.mapper.UserMapper; import com.jam.demo.service.UserService; import com.jam.demo.vo.req.UserAddReq; import com.jam.demo.vo.req.UserUpdateReq; import com.jam.demo.vo.resp.UserResp; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.util.ObjectUtils; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; /** * 用户服务实现类编程式事务 * * author ken */ Service Slf4j public class UserServiceImpl extends ServiceImplUserMapper, User implements UserService { Resource private UserMapper userMapper; Resource private PlatformTransactionManager transactionManager; Override public ListUserResp listAllUsers() { log.info(查询所有用户); ListUser userList userMapper.selectList(null); if (ObjectUtils.isEmpty(userList)) { return Lists.newArrayList(); } // 实体转换为响应VO return userList.stream().map(user - { UserResp resp new UserResp(); BeanUtils.copyProperties(user, resp); return resp; }).collect(Collectors.toList()); } Override public UserResp getUserById(Long id) { log.info(根据ID查询用户id:{}, id); // 判空校验 if (ObjectUtils.isEmpty(id)) { throw new IllegalArgumentException(用户ID不能为空); } User user userMapper.selectById(id); if (ObjectUtils.isEmpty(user)) { throw new RuntimeException(用户不存在id: id); } UserResp resp new UserResp(); BeanUtils.copyProperties(user, resp); return resp; } Override public Long addUser(UserAddReq req) { log.info(新增用户req:{}, req); // 开启事务 DefaultTransactionDefinition transactionDefinition new DefaultTransactionDefinition(); TransactionStatus status transactionManager.getTransaction(transactionDefinition); try { // 实体转换 User user new User(); BeanUtils.copyProperties(req, user); user.setStatus(1) .setCreateTime(LocalDateTime.now()) .setUpdateTime(LocalDateTime.now()); // 插入数据库 userMapper.insert(user); // 提交事务 transactionManager.commit(status); log.info(新增用户成功userId:{}, user.getId()); return user.getId(); } catch (Exception e) { // 回滚事务 transactionManager.rollback(status); log.error(新增用户失败, e); throw new RuntimeException(新增用户失败, e); } } Override public void updateUser(UserUpdateReq req) { log.info(修改用户req:{}, req); // 判空校验 if (ObjectUtils.isEmpty(req.getId())) { throw new IllegalArgumentException(用户ID不能为空); } // 开启事务 DefaultTransactionDefinition transactionDefinition new DefaultTransactionDefinition(); TransactionStatus status transactionManager.getTransaction(transactionDefinition); try { // 查询用户是否存在 User user userMapper.selectById(req.getId()); if (ObjectUtils.isEmpty(user)) { throw new RuntimeException(用户不存在id: req.getId()); } // 复制修改字段 BeanUtils.copyProperties(req, user); user.setUpdateTime(LocalDateTime.now()); // 更新数据库 userMapper.updateById(user); // 提交事务 transactionManager.commit(status); log.info(修改用户成功userId:{}, req.getId()); } catch (Exception e) { // 回滚事务 transactionManager.rollback(status); log.error(修改用户失败, e); throw new RuntimeException(修改用户失败, e); } } Override public void deleteUserById(Long id) { log.info(删除用户id:{}, id); // 判空校验 if (ObjectUtils.isEmpty(id)) { throw new IllegalArgumentException(用户ID不能为空); } // 开启事务 DefaultTransactionDefinition transactionDefinition new DefaultTransactionDefinition(); TransactionStatus status transactionManager.getTransaction(transactionDefinition); try { // 查询用户是否存在 User user userMapper.selectById(id); if (ObjectUtils.isEmpty(user)) { throw new RuntimeException(用户不存在id: id); } // 删除用户 userMapper.deleteById(id); // 提交事务 transactionManager.commit(status); log.info(删除用户成功userId:{}, id); } catch (Exception e) { // 回滚事务 transactionManager.rollback(status); log.error(删除用户失败, e); throw new RuntimeException(删除用户失败, e); } } }关键说明采用编程式事务PlatformTransactionManager手动控制事务的开启、提交、回滚符合需求要求使用ObjectUtils进行对象判空符合工具类使用规范日志打印使用Slf4j注解符合日志规范所有方法都进行了参数校验和异常处理确保代码健壮性。5.3.5 控制器UserControllerpackage com.jam.demo.controller; import com.jam.demo.service.UserService; import com.jam.demo.vo.req.UserAddReq; import com.jam.demo.vo.req.UserUpdateReq; import com.jam.demo.vo.resp.ApiResponse; import com.jam.demo.vo.resp.UserResp; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; /** * 用户管理控制器 * * author ken */ RestController RequestMapping(/user) Tag(name 用户管理, description 用户查询、新增、修改、删除接口) Slf4j public class UserController { Resource private UserService userService; /** * 查询所有用户 * * return 接口响应用户列表 */ GetMapping(/listAll) Operation(summary 查询所有用户, description 获取系统中所有正常状态的用户列表) ApiResponses({ io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 200, description 查询成功, content Content(schema Schema(implementation ApiResponse.class))), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 500, description 服务器内部错误) }) public ApiResponseListUserResp listAllUsers() { ListUserResp userList userService.listAllUsers(); return ApiResponse.success(userList, 查询成功); } /** * 根据ID查询用户 * * param id 用户ID * return 接口响应用户详情 */ GetMapping(/{id}) Operation(summary 根据ID查询用户, description 根据用户ID获取用户详细信息) ApiResponses({ io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 200, description 查询成功), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 400, description 参数错误), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 500, description 服务器内部错误) }) public ApiResponseUserResp getUserById( Parameter(description 用户ID, required true, example 1) PathVariable Long id) { UserResp userResp userService.getUserById(id); return ApiResponse.success(userResp, 查询成功); } /** * 新增用户 * * param req 新增请求参数 * return 接口响应新增用户ID */ PostMapping Operation(summary 新增用户, description 新增系统用户默认状态为正常) ApiResponses({ io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 201, description 新增成功), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 400, description 参数错误), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 500, description 服务器内部错误) }) ResponseStatus(HttpStatus.CREATED) public ApiResponseLong addUser( Parameter(description 新增用户参数, required true) RequestBody UserAddReq req) { Long userId userService.addUser(req); return ApiResponse.success(userId, 新增成功, HttpStatus.CREATED.value()); } /** * 修改用户 * * param req 修改请求参数 * return 接口响应 */ PutMapping Operation(summary 修改用户, description 根据用户ID修改用户信息) ApiResponses({ io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 200, description 修改成功), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 400, description 参数错误), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 500, description 服务器内部错误) }) public ApiResponseVoid updateUser( Parameter(description 修改用户参数, required true) RequestBody UserUpdateReq req) { userService.updateUser(req); return ApiResponse.success(null, 修改成功); } /** * 根据ID删除用户 * * param id 用户ID * return 接口响应 */ DeleteMapping(/{id}) Operation(summary 删除用户, description 根据用户ID删除用户) ApiResponses({ io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 200, description 删除成功), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 400, description 参数错误), io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode 500, description 服务器内部错误) }) public ApiResponseVoid deleteUserById( Parameter(description 用户ID, required true, example 1) PathVariable Long id) { userService.deleteUserById(id); return ApiResponse.success(null, 删除成功); } }5.3.6 通用VO请求与响应用户响应UserResppackage com.jam.demo.vo.resp; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; /** * 用户响应VO * * author ken */ Data Schema(description 用户响应参数) public class UserResp implements Serializable { private static final long serialVersionUID 1L; Schema(description 主键ID, example 1) private Long id; Schema(description 用户名, example zhangsan) private String username; Schema(description 手机号, example 13800138000) private String phone; Schema(description 状态0-禁用1-正常, example 1) private Integer status; Schema(description 创建时间, example 2025-05-20 10:00:00) private LocalDateTime createTime; Schema(description 更新时间, example 2025-05-20 11:00:00) private LocalDateTime updateTime; }5.4 数据库脚本MySQL 8.0-- 创建数据库 CREATE DATABASE IF NOT EXISTS tomcat_demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 使用数据库 USE tomcat_demo; -- 创建用户表 DROP TABLE IF EXISTS t_user; CREATE TABLE t_user ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT 主键ID, username VARCHAR(50) NOT NULL COMMENT 用户名, password VARCHAR(100) NOT NULL COMMENT 密码加密存储, phone VARCHAR(20) NOT NULL COMMENT 手机号, status TINYINT NOT NULL DEFAULT 1 COMMENT 状态0-禁用1-正常, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_username (username), UNIQUE KEY uk_phone (phone) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT用户表; -- 初始化数据 INSERT INTO t_user (username, password, phone, status) VALUES (zhangsan, e10adc3949ba59abbe56e057f20f883e, 13800138000, 1), (lisi, e10adc3949ba59abbe56e057f20f883e, 13800138001, 1);说明密码为MD5加密后的123456生产环境建议使用BCrypt等更安全的加密方式。5.5 项目打包与部署5.5.1 打包WAR包执行Maven打包命令mvn clean package -DskipTests打包完成后在target目录下生成tomcat-demo-1.0.0.war文件重命名为tomcat-demo.war简化访问路径。5.5.2 部署到Tomcat将tomcat-demo.war复制到Tomcat的webapps目录启动Tomcat若已启动需重启因生产环境关闭了autoDeployTomcat自动解压WAR包生成tomcat-demo文件夹验证部署成功访问Swagger接口文档http://localhost:8080/tomcat-demo/swagger-ui.html调用查询接口http://localhost:8080/tomcat-demo/user/listAll返回用户列表即为成功。六、Tomcat性能优化从配置到调优全攻略6.1 性能优化核心方向Tomcat性能优化需从“硬件、JVM、Tomcat配置、应用层”四个维度入手核心目标是提升并发能力、降低响应时间、避免资源耗尽。6.2 JVM优化核心JVM是Tomcat运行的基础不合理的JVM配置会导致GC频繁、OOM、响应延迟等问题优化配置如下适配8核16G服务器JAVA_OPTS-Xms8g -Xmx8g \ -XX:MetaspaceSize512m -XX:MaxMetaspaceSize1024m \ -XX:UseG1GC \ -XX:MaxGCPauseMillis100 \ -XX:G1HeapRegionSize16m \ -XX:G1ReservePercent20 \ -XX:ParallelRefProcEnabled \ -XX:HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath/usr/local/apache-tomcat-10.1.20/logs/heapdump.hprof \ -XX:PrintGCDetails \ -XX:PrintGCTimeStamps \ -XX:PrintGCDateStamps \ -Xloggc:/usr/local/apache-tomcat-10.1.20/logs/gc.log \ -XX:UseGCLogFileRotation \ -XX:NumberOfGCLogFiles5 \ -XX:GCLogFileSize100M参数说明-Xms8g -Xmx8g堆内存初始值和最大值设为8G服务器内存的50%避免堆扩容-XX:UseG1GCG1收集器适合大内存场景兼顾吞吐量和延迟-XX:MaxGCPauseMillis100目标最大GC停顿时间100msG1会自适应调整-XX:G1HeapRegionSize16mG1堆区域大小根据堆内存调整8G堆建议16m开启GC日志和堆转储便于故障排查。6.3 Tomcat Connector优化Connector是Tomcat处理请求的入口优化参数直接影响并发能力核心配置如下Connector port8080 protocolorg.apache.coyote.http11.Http11Nio2Protocol connectionTimeout30000 redirectPort8443 maxThreads4000 minSpareThreads500 acceptCount2000 maxConnections20000 enableLookupsfalse URIEncodingUTF-8 compressionon compressionMinSize2048 compressableMimeTypetext/html,text/xml,text/plain,application/json,application/javascript,text/css keepAliveTimeout60000 maxKeepAliveRequests10000 acceptorThreadCount4 pollerThreadCount8/参数说明maxThreads最大工作线程数建议设为“CPU核心数*2 有效磁盘数”8核设为4000maxConnections最大连接数NIO模型下该值远大于maxThreads因连接是非阻塞的keepAliveTimeout长连接超时时间设为60s减少TCP握手开销maxKeepAliveRequests单个长连接最大请求数设为10000避免长连接占用资源acceptorThreadCount接收连接的线程数建议设为CPU核心数8核设为4pollerThreadCount轮询连接的线程数建议设为CPU核心数*28核设为8。6.4 禁用不必要的组件Tomcat默认加载很多非必需组件禁用可减少资源占用禁用默认Web应用docs、examples、host-manager、manager、ROOT删除webapps目录下的这些文件夹禁用AJP连接器若未使用NginxAJP注释server.xml中的Connector port8009 protocolAJP/1.3 redirectPort8443/关闭Session持久化在context.xml中添加Manager pathname/避免Session写入磁盘。6.5 应用层优化禁用Servlet自动重载Context的reloadablefalse避免监测文件变化消耗CPU使用连接池数据库连接池如HikariCP、Redis连接池等避免频繁创建/销毁连接静态资源交由Nginx处理将CSS、JS、图片等静态资源放在Nginx目录Tomcat仅处理动态请求接口异步化使用Spring的Async或Servlet 3.0异步处理提升并发能力。七、Tomcat故障排查常见问题与解决方案7.1 常见问题及排查思路问题现象可能原因排查方案Tomcat启动失败日志报“Port 8080 already in use”8080端口被占用1. 执行netstat -tlnp请求响应慢CPU使用率高1. JVM GC频繁2. 应用代码死循环3. Connector线程数不足1. 查看GC日志gc.log分析GC频率和停顿时间2. 使用jstack pid生成线程快照排查死循环/锁等待3. 调整Connector的maxThreads参数报“OutOfMemoryError: Java heap space”堆内存不足或内存泄漏1. 分析堆转储文件heapdump.hprof使用MAT工具定位内存泄漏点2. 调大-Xmx参数3. 优化应用代码如关闭未释放的流、缓存合理设置中文参数乱码1. Connector未设置URIEncoding2. 请求体编码不一致1. 确保Connector的URIEncodingUTF-82. 应用层统一设置请求编码request.setCharacterEncoding(UTF-8)Session丢失1. Tomcat集群未配置Session共享2. Session超时时间过短1. 配置Redis/数据库实现Session共享2. 调整web.xml中session-configsession-timeout30/session-timeout/session-config7.2 核心排查工具jps查看Java进程IDjps -ljstack生成线程快照排查死锁、线程阻塞jstack 1234 thread.logjstat监控JVM GC状态jstat -gc 1234 1000每秒输出一次GC信息jmap生成堆转储文件jmap -dump:formatb,fileheapdump.hprof 1234MATMemory Analyzer Tool分析堆转储文件定位内存泄漏VisualVM可视化监控JVM状态、线程、内存。八、Tomcat集群与高可用生产环境部署方案8.1 集群架构设计8.2 核心配置步骤8.2.1 Nginx负载均衡配置nginx.confhttp { upstream tomcat_cluster { # 加权轮询weight越大权重越高 server 192.168.1.101:8080 weight10; server 192.168.1.102:8080 weight10; server 192.168.1.103:8080 weight5; # 健康检查 keepalive 32; } server { listen 80; server_name www.jam.com; # 静态资源缓存 location ~* \.(css|js|png|jpg|jpeg|gif|ico)$ { root /usr/local/nginx/html; expires 7d; add_header Cache-Control public, max-age604800; } # 动态请求转发到Tomcat集群 location / { proxy_pass http://tomcat_cluster; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; } } }8.2.2 Tomcat Session共享Redis实现下载Tomcat Redis Session共享插件tomcat-redis-session-manager-2.0.0.jar、jedis-4.4.6.jar、commons-pool2-2.12.0.jar放入Tomcat的lib目录修改conf/context.xml添加Redis配置Valve classNamecom.orangefunction.tomcat.redissessions.RedisSessionHandlerValve/ Manager classNamecom.orangefunction.tomcat.redissessions.RedisSessionManager host192.168.1.100 port6379 passwordredis123 database0 maxInactiveInterval1800/所有Tomcat节点配置相同的Redis信息实现Session共享。九、总结与进阶方向9.1 核心总结Tomcat作为Java Web的核心容器其本质是“HTTP服务器Servlet容器”的组合体核心架构分层清晰Server→Service→Engine→Host→Context请求处理流程围绕Connector接收、Engine分发、Servlet容器执行展开。开发中需重点关注版本适配Tomcat 10使用jakarta.servlet包需注意与Spring Boot版本兼容配置优化JVM、Connector、应用层的优化是提升性能的关键故障排查熟练使用JVM工具定位内存、线程问题生产部署结合Nginx实现负载均衡Redis实现Session共享保证高可用。9.2 进阶方向自定义Tomcat组件开发自定义Valve拦截请求、Connector自定义协议、Realm自定义认证Tomcat源码深度解析阅读Connector、Servlet容器的核心源码理解底层IO模型BIO/NIO/NIO2云原生部署将Tomcat应用打包为Docker镜像结合K8s实现自动扩缩容、滚动更新性能监控集成PrometheusGrafana监控Tomcat的并发数、响应时间、GC状态等指标。通过本文的学习相信你已掌握Tomcat的底层原理、实战配置、性能优化和故障排查的核心技能。在实际开发中需结合业务场景灵活调整配置持续优化性能才能让Tomcat在生产环境中稳定、高效地运行。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询