注册

AI真的可以写出可商用的代码吗?

背景


在MQTT中,代理(Broker)将发布的消息(publish messages)根据它们的主题(topic)匹配到订阅了这些主题的客户端。这个过程对于客户端来说是透明的,因为客户端只需要指定它们感兴趣的主题,而MQTT代理负责将消息分发给所有订阅了匹配主题的客户端。 如果想通过topic作为解耦key,实现一个客户端多个Listener,每个Listener都具备自己的topic及业务处理逻辑(类似RocketMQ消费者模式)。所以MQTT客户端具备把消息根据topic路由到相应的Listener中。 image.png 回归主题我希望通过AI帮实现topic路由。(实现matchTopic方法)


private  boolean matchTopic(String subscribedTopic, String publishedTopic)

AI写代码


AI选择:通义千问


第一次


指令


通过java实现mqtt的topic路由匹配的方法matchTopic(String subscribedTopic,String publishedTopic)


AI输出(只粘贴代码部分)


import java.util.regex.Matcher;  
import java.util.regex.Pattern;  

public class MqttTopicMatcher {  

    /**  
     * 模拟MQTT的topic匹配。  
     *   
     * 注意:这个实现是简化的,它不支持通配符在主题字符串中的非末尾位置,  
     * 并且没有处理多层加号(`+`)和井号(`
#`)的复杂情况。  
     * 它主要用于理解和教学目的。  
     *  
     * @param subscribedTopic 订阅的主题,可能包含`+`或`
#`通配符  
     * @param publishedTopic  发布的主题  
     * @return 如果发布的主题与订阅的主题匹配,则返回true;否则返回false  
     */
  
    public static boolean matchTopic(String subscribedTopic, String publishedTopic) {  
        // 将加号(`+`)替换为正则表达式中的任意字符(`.`)  
        String regexTopic = subscribedTopic.replace("+"".");  

        // 处理井号(`#`):如果订阅的主题以`#`结尾,则替换为任意数量的任意字符(`.*`)  
        // 注意:这里我们假设`#`只出现在字符串的末尾,且前面没有其他通配符  
        if (regexTopic.endsWith("#")) {  
            regexTopic = regexTopic.substring(0, regexTopic.length() - 1) + ".*";  
        }  

        // 编译正则表达式  
        Pattern pattern = Pattern.compile("^" + regexTopic + "$");  

        // 匹配发布的主题  
        Matcher matcher = pattern.matcher(publishedTopic);  
        return matcher.matches();  
    }  

    public static void main(String[] args) {  
        // 示例  
        String subscribedTopic1 = "sensors/+/level";  
        String publishedTopic1 = "sensors/temperature/level";  
        System.out.println(matchTopic(subscribedTopic1, publishedTopic1))// 应输出 true  

        String subscribedTopic2 = "sensors/#";  
        String publishedTopic2 = "sensors/temperature/room1/level";  
        System.out.println(matchTopic(subscribedTopic2, publishedTopic2))// 应输出 true  

        String subscribedTopic3 = "sensors/+";  
        String publishedTopic3 = "sensors/temperature/level";  
        System.out.println(matchTopic(subscribedTopic3, publishedTopic3))// 应输出 false,因为`+`只匹配单个层级  

        // 注意:这个实现是简化的,不涵盖所有MQTT topic匹配的场景  
    }  
}

验证


public static void main(String[] args) {
    boolean a = matchTopic("$SYS/brokers/+/clients/#""$SYS/brokers/emqx@172.51.0.6/clients/mqttx_b2136a2c/connected");
    System.out.println("msg: " + a); // 应该输出 true
    boolean b = matchTopic("DEVICE/+/msg""DEVICE/0000000091238112/msg");
    System.out.println("msg: " + b); // 应该输出 true
}

  public static boolean matchTopic(String subscribedTopic, String publishedTopic) {  
        // 将加号(`+`)替换为正则表达式中的任意字符(`.`)  
        String regexTopic = subscribedTopic.replace("+"".");  
        // 处理井号(`#`):如果订阅的主题以`#`结尾,则替换为任意数量的任意字符(`.*`)  
        // 注意:这里我们假设`#`只出现在字符串的末尾,且前面没有其他通配符  
        if (regexTopic.endsWith("#")) {  
            regexTopic = regexTopic.substring(0, regexTopic.length() - 1) + ".*";  
        }  
        // 编译正则表达式  
        Pattern pattern = Pattern.compile("^" + regexTopic + "$");  
        // 匹配发布的主题  
        Matcher matcher = pattern.matcher(publishedTopic);  
        return matcher.matches();  
    } 

实质输出结果:

msg: false

msg: false


结论:

不符合


第二次


指令


public static void main(String[] args) {
    boolean a = matchTopic("$SYS/brokers/+/clients/#""$SYS/brokers/emqx@172.51.0.6/clients/mqttx_b2136a2c/connected");
    System.out.println("msg: " + a); // 应该输出 true
    boolean b = matchTopic("DEVICE/+/msg""DEVICE/0000000091238112/msg");
    System.out.println("msg: " + b); // 应该输出 true
}

  public static boolean matchTopic(String subscribedTopic, String publishedTopic) {  
        // 将加号(`+`)替换为正则表达式中的任意字符(`.`)  
        String regexTopic = subscribedTopic.replace("+"".");  
        // 处理井号(`#`):如果订阅的主题以`#`结尾,则替换为任意数量的任意字符(`.*`)  
        // 注意:这里我们假设`#`只出现在字符串的末尾,且前面没有其他通配符  
        if (regexTopic.endsWith("#")) {  
            regexTopic = regexTopic.substring(0, regexTopic.length() - 1) + ".*";  
        }  
        // 编译正则表达式  
        Pattern pattern = Pattern.compile("^" + regexTopic + "$");  
        // 匹配发布的主题  
        Matcher matcher = pattern.matcher(publishedTopic);  
        return matcher.matches();  
    } 
实质输出结果:
msgfalse
msgfalse

AI输出(只粘贴代码部分)


您提供的代码中,matchTopic方法用于将MQTT主题过滤器subscribedTopic转换为正则表达式,并检查发布的主题publishedTopic是否与该正则表达式匹配。但是,这里有几个需要注意的点:

正则表达式边界:

在 MQTT 主题匹配中,通常期望整个主题字符串与过滤器完全匹配(或至少从开头开始匹配,直到过滤器的末尾)。然而,find()方法在Matcher类中用于查找与正则表达式匹配的任何子序列,而不是整个字符串。因此,如果publishedTopic包含比subscribedTopic更长的前缀,find()仍然会返回true,即使后续部分不匹配。 完整的字符串匹配:

为了确保整个publishedTopic字符串与subscribedTopic匹配(或匹配到subscribedTopic指定的模式),您应该在正则表达式的前后添加^$锚点。 处理$前缀:

在MQTT中,$SYS是一个保留前缀,用于系统主题。在正则表达式中,$是一个特殊字符,表示字符串的末尾。但是,由于MQTT主题中的$仅仅是文本的一部分,您不需要在正则表达式中对它进行特殊处理(除非您打算在正则表达式中直接使用$的特殊含义)。

下面是修改后的matchTopic方法,它使用matches(),并确保整个字符串匹配:


import java.util.regex.Matcher;  
import java.util.regex.Pattern;  

public static boolean matchTopic(String subscribedTopic, String publishedTopic) {  
    // 将 + 替换为 [^/]+,将 # 替换为 .*,并在字符串前后添加 ^ 和 $ 以确保整个字符串匹配  
    String regexTopic = "^" + subscribedTopic.replace("+""[^/]+").replace("#"".*") + "$";  
    Pattern pattern = Pattern.compile(regexTopic);  
    Matcher matcher = pattern.matcher(publishedTopic);  
    return matcher.matches(); // 使用 matches() 来确保整个字符串匹配  
}   

   public static void main(String[] args) {
    boolean a = matchTopic("$SYS/brokers/+/clients/#""$SYS/brokers/emqx@172.51.0.6/clients/mqttx_b2136a2c/connected");
    System.out.println("msg: " + a); // 应该输出 true
    boolean b = matchTopic("DEVICE/+/msg""DEVICE/0000000091238112/msg");
    System.out.println("msg: " + b); // 应该输出 true
}

验证


实质输出结果:

msg: false msg: true


结论:

不符合


第三次


指令


结果还是msg: false


AI输出(只粘贴代码部分)


在从你提供的代码来看,问题可能在于正则表达式的构建方式。+#通配符需要正确地转换为正则表达式来匹配MQTT主题。

+代表单个层级中的任意非斜杠字符。

#代表从层级的某一点开始到主题结尾的所有层级。

你的代码中已经正确地处理了+#,但可能存在一些细微的问题导致输出结果为false

让我们稍微调整一下你的代码,以确保它能够正确地处理MQTT主题的匹配:


import java.util.regex.Matcher;  
import java.util.regex.Pattern;  

public static boolean matchTopic(String subscribedTopic, String publishedTopic) {
    // 将 MQTT 通配符转换为正则表达式
    String regexTopic = "^" + subscribedTopic.replace("+""[^/]+").replace("#""([^/]+)/.*") + "$";
    // 编译正则表达式
    Pattern pattern = Pattern.compile(regexTopic);
    // 创建匹配器并检查是否匹配
    Matcher matcher = pattern.matcher(publishedTopic);
    return matcher.matches(); // 使用 matches() 来确保整个字符串匹配
}  

   public static void main(String[] args) {
    boolean a = matchTopic("$SYS/brokers/+/clients/#""$SYS/brokers/emqx@172.51.0.6/clients/mqttx_b2136a2c/connected");
    System.out.println("msg: " + a); // 应该输出 true
    boolean b = matchTopic("DEVICE/+/msg""DEVICE/0000000091238112/msg");
    System.out.println("msg: " + b); // 应该输出 true
}

在上述代码中,我将#的替换部分稍作修改。原来的".*"可能会匹配任何字符(包括斜杠),这可能会导致意外匹配。通过使用"([^/]+)/.*",我们确保了 # 之前的部分必须是一个不包含斜杠的字符串,并且之后可以跟任何东西(包括零个或多个层级)。

让我们尝试运行这段修改后的代码。如果你仍然遇到问题,请告诉我,我们可以进一步调试。


验证


实质输出结果:

msg: false msg: true


结论:

不符合


第四次


指令


运行结果还是不对,$SYS/brokers/emqx@172.51.0.6/clients/mqttx_b2136a2c/connected,输出结果还是msg: false


AI输出(只粘贴代码部分)


在既然正则表达式看起来是正确的,但仍然没有匹配成功,我们需要进一步检查正则表达式的实现细节。问题可能在于正则表达式如何处理#之后的内容。 在MQTT中,#代表从层级的某一点开始到主题结尾的所有层级。这意味着#之前的部分必须是一个完整的层级,而#之后的部分可以是零个或多个层级。 让我们再次修改正则表达式以确保这一点得到正确的处理:


import java.util.regex.Matcher;  
import java.util.regex.Pattern;  

public static boolean matchTopic(String subscribedTopic, String publishedTopic) {
    // 将 MQTT 通配符转换为正则表达式
    String regexTopic = "^" + subscribedTopic
            .replace("+""[^/]+")
            .replace("#""([^/]+)(/.*)?")
            + "$";
    System.out.println("Regex topic: " + regexTopic); // 添加这一行以查看正则表达式
    // 编译正则表达式
    Pattern pattern = Pattern.compile(regexTopic);
    // 创建匹配器并检查是否匹配
    Matcher matcher = pattern.matcher(publishedTopic);
    return matcher.matches(); // 使用 matches() 来确保整个字符串匹配
}

   public static void main(String[] args) {
    boolean a = matchTopic("$SYS/brokers/+/clients/#""$SYS/brokers/emqx@172.51.0.6/clients/mqttx_b2136a2c/connected");
    System.out.println("msg: " + a); // 应该输出 true
    boolean b = matchTopic("DEVICE/+/msg""DEVICE/0000000091238112/msg");
    System.out.println("msg: " + b); // 应该输出 true
}

这里的关键变化是在#的替换部分:

"([^/]+)(/.*)?":这部分正则表达式意味着#前面的部分必须是一个不包含斜杠的字符串,而#后面的部分可以是零个或多个层级。"(.*)" / "(/.*)" 都用来匹配剩余的路径,但(/.*)?表示这个部分是可选的,即#后面可以没有更多的层级。

现在,让我们再次运行这段代码。你应该能看到输出的正则表达式,以及最终的匹配结果。如果还是有问题,请提供输出结果以便进一步分析。


验证


实质输出结果:

msg: false msg: true


结论:

不符合


第五次


指令


运行结果还是不对,$SYS/brokers/emqx@172.51.0.6/clients/mqttx_b2136a2c/connected,怀疑$SYS影响了正则匹配,输出结果还是msg: false


AI输出(只粘贴代码部分)


你提到$SYS可能影响了正则表达式的匹配。确实,在正则表达式中,某些特殊字符会被解释为具有特殊的含义,而非直接的文本匹配。在这种情况下,$是一个特殊字符,在正则表达式中通常用于表示字符串的结尾。因此,我们需要对$SYS进行转义,以确保它被视为普通文本而不是特殊符号。

让我们修改代码以转义$SYS字符串中的$,确保它被视为普通的字符。


import java.util.regex.Matcher;  
import java.util.regex.Pattern;  

public static boolean matchTopic(String subscribedTopic, String publishedTopic) {
    // 将 MQTT 通配符转换为正则表达式
    String regexTopic = "^" + subscribedTopic
            .replace("+""[^/]+")
            .replace("#""([^/]+)/.*")
            .replace("$""\$"// 转义 $ 字符
            + "$";
    // 编译正则表达式
    Pattern pattern = Pattern.compile(regexTopic);
    // 创建匹配器并检查是否匹配
    Matcher matcher = pattern.matcher(publishedTopic);
    return matcher.matches(); // 使用 matches() 来确保整个字符串匹配
}

   public static void main(String[] args) {
    boolean a = matchTopic("$SYS/brokers/+/clients/#""$SYS/brokers/emqx@172.51.0.6/clients/mqttx_b2136a2c/connected");
    System.out.println("msg: " + a); // 应该输出 true
    boolean b = matchTopic("DEVICE/+/msg""DEVICE/0000000091238112/msg");
    System.out.println("msg: " + b); // 应该输出 true
}

在这个版本中,我们添加了一个.replace("$", "\$")来转义$SYS中的$字符。这将确保$SYS在正则表达式中被视为普通文本。

现在,让我们再次运行这段代码。你应该能看到输出的正则表达式,以及最终的匹配结果。如果还是有问题,请提供输出结果以便进一步分析。


验证


实质输出结果:

msg: true msg: true


结论:

符合


代码最终结果:


对代码今天细微调整,运营到生产环境代码。


private  boolean matchTopic(String subscribedTopic, String publishedTopic) {
        String regexTopic = "^" + subscribedTopic.replace("+""[^/]+").replace("#""([^/]+)/.*").replace("$""\$") + "$";
        // 编译正则表达式
        Pattern pattern = Pattern.compile(regexTopic);
        // 创建匹配器并检查是否匹配
        Matcher matcher = pattern.matcher(publishedTopic);
        return matcher.matches(); // 使用 matches() 来确保整个字符串匹配
    }

总结


在使用AI工具进行代码生成时,‌用户可以通过简单的自然语言描述或问题,‌AI便能快速理解并生成相应的代码片段。‌这种交互方式非常直观,‌用户只需提供关键信息和问题,‌AI便能迅速响应并生成匹配的代码。‌ AI写代码的体验还体现在其高效性和便捷性上。‌通过AI的帮助,‌开发者可以更加专注于项目的核心逻辑和功能实现,‌而无需在编写基础代码上花费过多时间。‌这不仅能够提高开发效率,‌还能在一定程度上减轻开发者的负担,‌特别是在面对复杂或重复性的编程任务时,‌AI工具能够显著提升工作效率。‌ 尽管AI工具在代码生成方面展现出了强大的能力,‌但开发者在使用时仍需保持警惕,‌确保生成的代码符合项目的实际需求和标准。‌此外,‌对于特定领域的复杂应用或特定需求的实现,‌人类开发者的专业知识和经验仍然是不可或缺的。‌因此,‌AI工具与人类开发者的结合将是未来软件开发的一个重要趋势,‌共同推动软件开发的进步和创新。




作者:后端马农
来源:juejin.cn/post/7397668641645396022

0 个评论

要回复文章请先登录注册