JDA框架getUsersByName()方法调用问题求助:Discord机器人实现用户@提及的用户ID获取方案
解决JDA机器人中调用
getUsersByName的问题 嗨,我来帮你理清这个问题!其实你遇到的核心点是JDA实例的获取和传递——你不需要去实例化抽象的JDA类,也不用纠结静态方法的问题,因为JDA实例在你启动机器人的时候就已经创建好了,你只需要把它传到需要用的地方就行。
核心思路
JDA实例是通过JDABuilder创建的(它会帮你处理抽象类的实例化逻辑),你可以通过两种方式拿到它:
- 在消息事件监听中直接通过
event.getJDA()获取(推荐,因为命令处理本身就应该放在消息事件里) - 在Main类中保存JDA实例,通过静态方法提供访问入口
下面给你具体的代码示例:
方案1:用事件监听器处理命令(推荐)
这种方式最符合JDA的设计逻辑,命令处理本身就是响应消息事件的一部分,不需要额外开线程(当然你要开线程也可以,后面会说)。
第一步:Main类启动机器人并注册监听器
public class Main { public static void main(String[] args) { try { // 通过JDABuilder创建JDA实例,这里会自动处理抽象类的实例化 JDABuilder.createDefault("你的机器人令牌") .addEventListeners(new CommandHandler()) // 注册命令处理监听器 .build() .awaitReady(); // 等待机器人完成初始化 } catch (LoginException | InterruptedException e) { e.printStackTrace(); } } }
第二步:编写命令处理监听器
public class CommandHandler extends ListenerAdapter { @Override public void onMessageReceived(MessageReceivedEvent event) { String messageContent = event.getContentRaw(); // 拆分命令前缀、指令和目标用户 String[] commandParts = messageContent.split(" ", 2); // 检查是否是!harass命令 if (commandParts.length >= 2 && commandParts[0].equals("!harass")) { String targetUserName = commandParts[1]; // 从事件中直接获取JDA实例,完美解决非静态方法的问题 JDA jda = event.getJDA(); // 查找匹配的用户,ignoreCase设为true支持大小写模糊匹配 List<User> matchedUsers = jda.getUsersByName(targetUserName, true); if (!matchedUsers.isEmpty()) { User targetUser = matchedUsers.get(0); // 取第一个匹配的用户 // 在频道中提及目标用户 event.getChannel().sendMessage(targetUser.getAsMention() + " 收到了你的召唤!").queue(); } else { event.getChannel().sendMessage("找不到用户 " + targetUserName + " 哦~").queue(); } } } }
方案2:如果你坚持要用Harass线程类
如果你的业务逻辑确实需要单独开线程处理,那只需要把JDA实例和必要的参数通过构造函数传递给Harass类即可:
修改Harass线程类
public class Harass extends Thread { private final JDA jda; private final String targetUserName; private final MessageChannel channel; // 通过构造函数传入需要的实例和参数 public Harass(JDA jda, String targetUserName, MessageChannel channel) { this.jda = jda; this.targetUserName = targetUserName; this.channel = channel; } @Override public void run() { List<User> matchedUsers = jda.getUsersByName(targetUserName, true); if (!matchedUsers.isEmpty()) { User targetUser = matchedUsers.get(0); channel.sendMessage(targetUser.getAsMention() + " 被线程点名啦!").queue(); } else { channel.sendMessage("线程中找不到用户 " + targetUserName + "!").queue(); } } }
在监听器中调用线程
回到CommandHandler的onMessageReceived方法里,把原来的发送逻辑替换成:
if (commandParts.length >= 2 && commandParts[0].equals("!harass")) { String targetUserName = commandParts[1]; JDA jda = event.getJDA(); MessageChannel channel = event.getChannel(); // 启动Harass线程,传入必要的实例 new Harass(jda, targetUserName, channel).start(); }
额外提示
getUsersByName返回的是用户列表,因为服务器里可能有重名用户,建议你可以在找不到用户的时候提示用户使用用户ID(更精确),或者显示所有匹配的用户让用户选择。- 尽量避免用静态变量存储JDA实例(虽然可行,但容易引发线程安全问题),优先用事件中的
event.getJDA()获取。
内容的提问来源于stack exchange,提问作者RoverKnight
相关产品推荐
相关产品推荐

