tomcat启动报java.lang.unsatisfiedlinkerror: no apr-1错误,表明apr本地库缺失;需安装apr-1、apr-util-1和openssl,编译匹配版本的tomcat-native,将libtcnative-1.so放入java_home/jre/lib/amd64并配置ld_library_path。

Tomcat启动失败报 java.lang.UnsatisfiedLinkError: no apr-1 in java.library.path
这是 APR 模式启用后最典型的错误,说明 Tomcat 找不到本地 APR 库(libapr-1.so 或 tcnative-1.dll)。APR 模式本身不依赖 Redis,但很多人在配 Redis Session 管理时顺手启用了 APR,结果卡在这一步。
解决方法不是删掉 APR,而是补全依赖:
- 确认已安装
apr-1、apr-util-1和 OpenSSL(Linux 下用yum install apr apr-util openssl-devel) - 编译或下载对应版本的
tomcat-native(必须与 Tomcat 版本匹配,例如 Tomcat 8.5.55 对应 tcnative 1.2.x) - 把编译出的
libtcnative-1.so放到JAVA_HOME/jre/lib/amd64/(Linux)或JAVA_HOME/jre/bin/(Windows),并确保LD_LIBRARY_PATH(Linux)或PATH(Windows)包含该路径 - 检查
java -Djava.library.path=... -version是否能正常输出,验证库路径是否生效
context.xml 中配置 RedisSessionManager 后 Session 仍不写入 Redis
常见原因是 Manager 类加载失败或配置项缺失。Tomcat 8.5+ 默认使用 StandardManager,即使你写了 RedisSessionManager,只要类找不到或初始化异常,就会静默回退到本地 Session。
关键检查点:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
tomcat/lib/下必须有三个 jar:tomcat-redis-session-manager-1.2.jar(或更新版如tomcat-cluster-redis-session-manager-4.0.jar)、jedis-2.9.0.jar(注意不要用 3.x,它默认 require Redis 6+ 的 RESP3 协议)、commons-pool2-2.6.2.jar -
context.xml中Manager必须放在<context></context>标签下,不能嵌套在<host></host>或<engine></engine>外层;且className必须拼写完全正确,大小写敏感 - Redis 连接参数中,
password为空时不能写password="",应直接删掉该属性,否则某些旧版 manager 会尝试连接带空密码的 Redis 导致超时 - 加一行
logging.properties配置:在tomcat/conf/logging.properties中添加com.orangefunction.tomcat.redissessions.level = FINE,看日志里是否有Connecting to Redis at ...或Failed to store session
多个 Tomcat 实例连同一 Redis,Session ID 一致但数据不同步
这通常不是 Redis 问题,而是 Tomcat 自身的 jvmRoute 未配置导致的 Session 覆盖。当两个 Tomcat 实例没区分身份,它们生成的 Session ID(如 ABC123.tomcat1)可能被当成同一个 key 写入 Redis,后启动的实例会覆盖前者的值。
修复方式很简单:
- 在
conf/server.xml的<engine></engine>标签上加jvmRoute="tomcat1"(第一个实例)和jvmRoute="tomcat2"(第二个) - 确保每个实例的
conf/context.xml中maxInactiveInterval值一致,否则一个实例认为 Session 过期删了,另一个还在用,造成状态错乱 - 如果用了 Nginx 做负载均衡,建议配合
ip_hash或sticky插件做会话粘滞,不是为了绕过 Redis,而是避免跨实例高频读写引发的 CAS 冲突
Redis 写入成功但应用里 request.getSession().getAttribute("xxx") 拿不到值
本质是序列化问题。Tomcat 把 Session 对象序列化后存进 Redis,反序列化时若 classpath 缺少对应类、或类定义变动(比如加了新字段但没加 serialVersionUID),就会静默失败,返回 null。
排查重点:
- 所有存入 Session 的 Java Bean 必须实现
java.io.Serializable,且推荐显式声明private static final long serialVersionUID = 1L; - 检查应用 WAR 包中是否含重复或冲突的类(比如两个不同版本的
commons-lang3),会导致反序列化时 ClassLoader 找到错误的类定义 - 禁用 Tomcat 默认的
StandardSession序列化机制:在context.xml的Manager标签下加sessionPersistPolicy="always"和saveOnRestart="false",强制走 Redis 路径,避开本地磁盘序列化干扰 - 临时在代码里加
session.setAttribute("test", "ok");和System.out.println(session.getAttribute("test"));,排除业务逻辑误判










