如何在Java及SpringBoot中使用TDLib?解决IntelliJ运行报错问题
TDLib在IntelliJ/SpringBoot中运行报错及整合方案
问题背景
已在Ubuntu 20终端成功编译TDLib Java示例,编译步骤如下:
sudo apt-get update sudo apt-get upgrade sudo apt-get install make git zlib1g-dev libssl-dev gperf php-cli cmake default-jdk g++ git clone https://github.com/tdlib/td.git cd td rm -rf build mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../example/java/td -DTD_ENABLE_JNI=ON .. cmake --build . --target install cd .. cd example/java rm -rf build mkdir build cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../../../tdlib -DTd_DIR:PATH=$(readlink -e ../td/lib/cmake/Td) .. cmake --build . --target install cd ../../.. cd .. ls -l td/tdlib
但在IntelliJ运行Example.java时出现如下错误:
/home/yashdeepsingh/.jdks/jbrsdk-17.0.9/bin/java -javaagent:/snap/intellij-idea-community/473/lib/idea_rt.jar=39397:/snap/intellij-idea-community/473/bin -Dfile.encoding=UTF-8 -classpath /home/yashdeepsingh/PROJECT/td/out/production/td org.drinkless.tdlib.example.Example java.lang.UnsatisfiedLinkError: no tdjni in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2434) at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:818) at java.base/java.lang.System.loadLibrary(System.java:1989) at org.drinkless.tdlib.Client.<clinit>(Client.java:18) at org.drinkless.tdlib.example.Example.main(Example.java:302) Exception in thread "main" java.lang.UnsatisfiedLinkError: 'void org.drinkless.tdlib.Client.nativeClientSetLogMessageHandler(int, org.drinkless.tdlib.Client$LogMessageHandler)' at org.drinkless.tdlib.Client.nativeClientSetLogMessageHandler(Native Method) at org.drinkless.tdlib.Client.setLogMessageHandler(Client.java:161) at org.drinkless.tdlib.example.Example.main(Example.java:302) Process finished with exit code 1
需要解决该报错,并将TDLib整合到SpringBoot项目中开发自定义Telegram客户端。
解决IntelliJ运行报错
报错核心是JVM找不到tdjni原生库,按以下步骤修复:
- 定位编译好的原生库
编译完成后,libtdjni.so文件位于td/tdlib/lib目录下(对应编译时的CMAKE_INSTALL_PREFIX路径)。 - 配置IntelliJ的VM参数
- 打开Run/Debug Configurations,选择运行Example的配置
- 在VM options中添加:
-Djava.library.path=/path/to/td/tdlib/lib(替换为实际的libtdjni.so所在目录绝对路径) - 保存配置后重新运行,即可解决库路径问题。
整合TDLib到SpringBoot项目
1. 准备依赖文件
- 复制
td/example/java/src/main/java/org/drinkless/tdlib下所有Java类到SpringBoot项目的对应包中(保持包结构一致)。 - 将
libtdjni.so和libtdjson.so(若存在)复制到SpringBoot项目的src/main/resources/lib目录。
2. 配置原生库加载
在SpringBoot启动类中添加静态代码块,确保JVM能加载原生库:
@SpringBootApplication public class TelegramClientApplication { static { try { // 获取资源目录下的lib文件夹绝对路径 String libDirPath = new File(TelegramClientApplication.class.getResource("/lib").getPath()).getAbsolutePath(); // 设置库路径 System.setProperty("java.library.path", libDirPath); // 强制刷新类加载器的库路径缓存 Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths"); sysPathsField.setAccessible(true); sysPathsField.set(null, null); // 加载tdjni库 System.loadLibrary("tdjni"); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { SpringApplication.run(TelegramClientApplication.class, args); } }
也可以在启动SpringBoot时通过VM参数指定库路径:-Djava.library.path=src/main/resources/lib。
3. 封装TDLib客户端为Spring Bean
将TDLib客户端配置为单例Bean,方便在项目中注入使用:
@Configuration public class TdLibConfiguration { @Bean public Client tdLibClient() { Client.Parameters parameters = new Client.Parameters(); // 替换为你的Telegram API ID和Hash(从my.telegram.org获取) parameters.apiId = 123456; parameters.apiHash = "your_api_hash_here"; parameters.databaseDirectory = "./tdlib-database"; parameters.filesDirectory = "./tdlib-files"; parameters.useMessageDatabase = true; parameters.useFileDatabase = true; parameters.useChatInfoDatabase = true; parameters.systemLanguageCode = "zh-CN"; parameters.deviceModel = "SpringBoot Telegram Client"; parameters.systemVersion = "Ubuntu 20.04"; parameters.applicationVersion = "1.0.0"; return Client.create(parameters, null, null); } }
4. 实现业务功能
在Service中注入Client,实现登录、消息收发等功能,示例:
@Service public class TelegramService { private final Client tdLibClient; @Autowired public TelegramService(Client tdLibClient) { this.tdLibClient = tdLibClient; } // 发送登录验证码请求 public void requestLoginCode(String phoneNumber) { tdLibClient.send(new Function.SetAuthenticationPhoneNumber(phoneNumber, null), null); } // 验证登录验证码 public void verifyLoginCode(String code) { tdLibClient.send(new Function.CheckAuthenticationCode(code), null); } }
内容的提问来源于stack exchange,提问作者Yashdeep Singh
相关产品推荐
相关产品推荐

