MyBatis动态SQL与逆向工程实战指南
1. MyBatis动态SQL与逆向工程实战解析作为Java开发者我们经常需要与数据库打交道。MyBatis作为一款优秀的持久层框架其动态SQL和逆向工程功能能极大提升开发效率。今天我就结合自己多年使用经验详细讲解这两个核心功能的原理和实战技巧。1.1 为什么需要动态SQL在传统JDBC开发中我们经常需要根据不同的条件拼接SQL语句这不仅容易出错而且代码可读性差。MyBatis的动态SQL功能完美解决了这个问题它允许我们在XML映射文件中使用条件标签来构建灵活的SQL语句。举个例子当我们需要根据用户输入的不同查询条件来检索数据时动态SQL可以让我们避免编写大量重复的if-else逻辑。这不仅减少了代码量还提高了可维护性。1.2 逆向工程的价值逆向工程(Reverse Engineering)是MyBatis提供的一个强大工具它可以根据数据库表结构自动生成对应的实体类、Mapper接口和XML映射文件。这个功能特别适合在项目初期快速搭建持久层框架或者在对已有数据库进行二次开发时使用。我曾经参与过一个老系统重构项目数据库中有上百张表如果手动编写所有实体类和Mapper至少要花费两周时间。而使用MyBatis逆向工程配合一些定制化配置我们仅用半天就完成了基础代码的生成效率提升了数十倍。2. 动态SQL深度解析2.1 核心标签详解MyBatis提供了多种动态SQL标签每个都有其特定的使用场景if标签最基本的条件判断select idfindActiveBlogWithTitleLike resultTypeBlog SELECT * FROM BLOG WHERE state ACTIVE if testtitle ! null AND title like #{title} /if /selectchoose/when/otherwise实现多条件选择select idfindActiveBlogLike resultTypeBlog SELECT * FROM BLOG WHERE state ACTIVE choose when testtitle ! null AND title like #{title} /when when testauthor ! null and author.name ! null AND author_name like #{author.name} /when otherwise AND featured 1 /otherwise /choose /selecttrim/where/set解决SQL语法问题update idupdateAuthorIfNecessary update Author set if testusername ! nullusername#{username},/if if testpassword ! nullpassword#{password},/if if testemail ! nullemail#{email},/if /set where id#{id} /updateforeach处理集合迭代select idselectPostIn resultTypedomain.blog.Post SELECT * FROM POST P WHERE ID in foreach itemitem indexindex collectionlist open( separator, close) #{item} /foreach /select2.2 动态SQL性能优化虽然动态SQL很强大但使用不当也会带来性能问题。以下是我总结的几个优化建议避免过度使用动态SQL不是所有场景都需要动态SQL简单的CRUD操作使用静态SQL效率更高。合理使用缓存对于频繁执行且结果变化不大的动态SQL查询考虑配置二级缓存。注意SQL注入风险虽然MyBatis使用预编译语句但动态拼接SQL时仍需注意特殊字符处理。批量操作优化对于大批量数据操作使用foreach标签时注意设置合理的batchSize。提示在开发环境中可以使用MyBatis Log Free插件查看最终执行的SQL这对调试动态SQL非常有帮助。3. MyBatis逆向工程实战3.1 逆向工程配置详解MyBatis Generator(MBG)是官方提供的逆向工程工具。要使用它首先需要在项目中添加依赖dependency groupIdorg.mybatis.generator/groupId artifactIdmybatis-generator-core/artifactId version1.4.0/version /dependency然后创建generatorConfig.xml配置文件?xml version1.0 encodingUTF-8? !DOCTYPE generatorConfiguration PUBLIC -//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd generatorConfiguration context idmysqlTables targetRuntimeMyBatis3 jdbcConnection driverClasscom.mysql.jdbc.Driver connectionURLjdbc:mysql://localhost:3306/test userIdroot password123456 /jdbcConnection javaModelGenerator targetPackagecom.example.model targetProjectsrc/main/java property nameenableSubPackages valuetrue/ property nametrimStrings valuetrue/ /javaModelGenerator sqlMapGenerator targetPackagemapper targetProjectsrc/main/resources property nameenableSubPackages valuetrue/ /sqlMapGenerator javaClientGenerator typeXMLMAPPER targetPackagecom.example.mapper targetProjectsrc/main/java property nameenableSubPackages valuetrue/ /javaClientGenerator table tableName% generatedKey columnid sqlStatementMysql identitytrue/ /table /context /generatorConfiguration3.2 自定义逆向工程策略MBG提供了丰富的配置选项可以自定义生成策略忽略字段不生成特定的表字段table tableNameuser ignoreColumn columndeleted/ /table自定义类型转换处理特殊数据类型columnOverride columncreate_time javaTypejava.time.LocalDateTime/生成Example类用于构建复杂查询条件table tableNameuser property nameuseActualColumnNames valuetrue/ property nameenableCountByExample valuefalse/ property nameenableUpdateByExample valuefalse/ property nameenableDeleteByExample valuefalse/ property nameenableSelectByExample valuetrue/ property nameselectByExampleQueryId valuefalse/ /table自定义注释添加有意义的代码注释commentGenerator property namesuppressAllComments valuefalse/ property namesuppressDate valuetrue/ property nameaddRemarkComments valuetrue/ /commentGenerator3.3 执行逆向工程配置完成后可以通过以下方式执行逆向工程使用Maven插件plugin groupIdorg.mybatis.generator/groupId artifactIdmybatis-generator-maven-plugin/artifactId version1.4.0/version configuration configurationFilesrc/main/resources/generatorConfig.xml/configurationFile overwritetrue/overwrite /configuration dependencies dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.23/version /dependency /dependencies /plugin执行命令mvn mybatis-generator:generateJava代码方式public class MyBatisGenerator { public static void main(String[] args) throws Exception { ListString warnings new ArrayList(); boolean overwrite true; File configFile new File(generatorConfig.xml); ConfigurationParser cp new ConfigurationParser(warnings); Configuration config cp.parseConfiguration(configFile); DefaultShellCallback callback new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } }4. 高级技巧与常见问题4.1 动态SQL与PageHelper整合在实际项目中我们经常需要将动态SQL与分页插件结合使用。以PageHelper为例// 在Service层 public PageInfoUser searchUsers(UserQuery query, int pageNum, int pageSize) { PageHelper.startPage(pageNum, pageSize); ListUser users userMapper.selectByQuery(query); return new PageInfo(users); } // 在Mapper.xml中 select idselectByQuery resultMapBaseResultMap select * from user where if testusername ! null and username ! and username like concat(%, #{username}, %) /if if teststatus ! null and status #{status} /if /where order by create_time desc /select4.2 枚举类型处理MyBatis提供了对枚举类型的良好支持。我们可以通过TypeHandler来处理枚举public enum UserStatus { ACTIVE(1, 活跃), INACTIVE(0, 禁用); private final int code; private final String desc; // 构造方法、getter省略 } public class UserStatusTypeHandler extends BaseTypeHandlerUserStatus { Override public void setNonNullParameter(PreparedStatement ps, int i, UserStatus parameter, JdbcType jdbcType) throws SQLException { ps.setInt(i, parameter.getCode()); } // 其他方法实现省略 }在配置文件中注册TypeHandlertypeHandlers typeHandler handlercom.example.handler.UserStatusTypeHandler javaTypecom.example.enums.UserStatus/ /typeHandlers4.3 常见问题解决方案SQL注入问题问题动态SQL中直接拼接用户输入可能导致SQL注入解决方案始终使用#{}占位符避免使用${}特殊字符转义问题XML中特殊字符(, , )需要转义解决方案if testage ! null AND age ![CDATA[ ]] #{age} /if批量插入性能差问题使用foreach批量插入时效率低解决方案设置rewriteBatchedStatementstruejdbc.urljdbc:mysql://localhost:3306/test?rewriteBatchedStatementstrue主键回写问题问题插入后无法获取自增主键解决方案配置useGeneratedKeysinsert idinsert useGeneratedKeystrue keyPropertyid insert into user (name) values (#{name}) /insert列名与属性名不一致问题数据库使用下划线命名Java使用驼峰命名解决方案配置mapUnderscoreToCamelCasemybatis.configuration.map-underscore-to-camel-casetrue4.4 性能监控与优化为了确保动态SQL的性能我们需要进行监控和优化启用慢SQL日志# 设置慢SQL阈值(毫秒) mybatis.configuration.log-implorg.apache.ibatis.logging.stdout.StdOutImpl mybatis.configuration.default-statement-timeout3000使用MyBatis-Plus性能分析插件Bean public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor interceptor new PerformanceInterceptor(); interceptor.setMaxTime(1000); // SQL执行最大时长超过自动停止运行 interceptor.setFormat(true); // 是否格式化代码 return interceptor; }SQL优化建议避免在循环中执行SQL合理使用索引减少不必要的列查询考虑使用延迟加载5. 实际项目中的应用5.1 复杂查询场景在实际项目中我们经常遇到复杂的多条件查询需求。下面是一个电商系统中商品查询的示例public class ProductQuery { private String name; private BigDecimal minPrice; private BigDecimal maxPrice; private Integer categoryId; private ListInteger statusList; private Date startDate; private Date endDate; // getter/setter省略 } // Mapper.xml中的动态SQL select idsearchProducts resultMapProductResultMap SELECT * FROM product where if testname ! null and name ! AND name LIKE CONCAT(%, #{name}, %) /if if testminPrice ! null AND price #{minPrice} /if if testmaxPrice ! null AND price #{maxPrice} /if if testcategoryId ! null AND category_id #{categoryId} /if if teststatusList ! null and statusList.size() 0 AND status IN foreach collectionstatusList itemstatus open( separator, close) #{status} /foreach /if if teststartDate ! null and endDate ! null AND create_time BETWEEN #{startDate} AND #{endDate} /if /where ORDER BY choose when testsortField priceprice/when when testsortField salessales/when otherwisecreate_time/otherwise /choose choose when testsortOrder descDESC/when otherwiseASC/otherwise /choose /select5.2 动态表名处理在某些分表场景下我们需要动态决定表名。虽然MyBatis官方不建议这样做但在某些特殊场景下是必要的// 使用Param注解指定表名 ListUser selectFromTable(Param(tableName) String tableName, Param(user) User user); // Mapper.xml select idselectFromTable resultTypeUser SELECT * FROM ${tableName} where if testuser.name ! null AND name #{user.name} /if if testuser.age ! null AND age #{user.age} /if /where /select注意使用动态表名时务必做好输入验证防止SQL注入。最好使用白名单机制限制可选的表名。5.3 与Spring Boot集成在Spring Boot项目中集成MyBatis非常简便添加依赖dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.2.0/version /dependency配置application.ymlmybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.model configuration: map-underscore-to-camel-case: true default-fetch-size: 100 default-statement-timeout: 30添加Mapper扫描MapperScan(com.example.mapper) SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }5.4 自定义插件开发MyBatis允许开发自定义插件来扩展功能。下面是一个简单的SQL执行时间统计插件Intercepts({ Signature(type StatementHandler.class, method query, args {Statement.class, ResultHandler.class}), Signature(type StatementHandler.class, method update, args {Statement.class}), Signature(type StatementHandler.class, method batch, args {Statement.class}) }) public class SqlCostTimeInterceptor implements Interceptor { private static final Logger logger LoggerFactory.getLogger(SqlCostTimeInterceptor.class); Override public Object intercept(Invocation invocation) throws Throwable { long startTime System.currentTimeMillis(); try { return invocation.proceed(); } finally { long endTime System.currentTimeMillis(); long costTime endTime - startTime; StatementHandler statementHandler (StatementHandler) invocation.getTarget(); String sql statementHandler.getBoundSql().getSql(); logger.info(SQL执行耗时: {}ms - {}, costTime, sql); } } Override public Object plugin(Object target) { return Plugin.wrap(target, this); } Override public void setProperties(Properties properties) { // 可以读取配置参数 } }注册插件Bean public SqlCostTimeInterceptor sqlCostTimeInterceptor() { return new SqlCostTimeInterceptor(); }6. 最佳实践与经验分享6.1 项目结构建议一个良好的MyBatis项目结构能提高代码的可维护性src/main/java ├── com.example │ ├── config # MyBatis配置类 │ ├── model # 实体类 │ ├── mapper # Mapper接口 │ ├── service # 业务服务 │ └── handler # TypeHandler src/main/resources ├── mapper # XML映射文件 ├── generator # 逆向工程配置 └── application.yml # 配置文件6.2 代码生成策略增量生成对于已有代码的表配置property nameoverwrite valuefalse/避免覆盖手动修改的代码。自定义模板可以通过修改Velocity模板来定制生成的代码风格。注释生成配置commentGenerator添加有意义的注释方便后续维护。6.3 性能调优经验连接池配置使用高性能连接池如HikariCPspring: datasource: hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000二级缓存对于读多写少的数据考虑启用二级缓存cache evictionLRU flushInterval60000 size1024 readOnlytrue/批量操作使用SqlSession的批量模式提高性能try (SqlSession session sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper session.getMapper(UserMapper.class); for (int i 0; i 1000; i) { mapper.insert(new User(user i)); if (i % 200 0) { session.flushStatements(); } } session.commit(); }6.4 常见陷阱与规避N1查询问题问题在循环中查询关联数据导致性能问题解决方案使用collection或association实现一次性加载事务未提交问题忘记调用sqlSession.commit()导致数据未持久化解决方案使用Transactional注解或确保手动提交缓存一致性问题问题缓存数据与数据库不一致解决方案合理设置缓存过期策略或在数据修改时清除缓存大结果集内存溢出问题查询返回大量数据导致内存不足解决方案使用分页查询或游标方式处理大数据集6.5 监控与诊断启用MyBatis日志logging: level: org.mybatis: DEBUG使用Druid监控Bean public ServletRegistrationBeanStatViewServlet druidStatViewServlet() { ServletRegistrationBeanStatViewServlet registrationBean new ServletRegistrationBean(new StatViewServlet(), /druid/*); registrationBean.addInitParameter(loginUsername, admin); registrationBean.addInitParameter(loginPassword, admin); return registrationBean; }慢SQL监控Bean public FilterRegistrationBeanWebStatFilter druidWebStatFilter() { FilterRegistrationBeanWebStatFilter registrationBean new FilterRegistrationBean(new WebStatFilter()); registrationBean.addUrlPatterns(/*); registrationBean.addInitParameter(exclusions, *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*); return registrationBean; }7. 未来发展与替代方案7.1 MyBatis-Plus扩展MyBatis-Plus是MyBatis的增强工具提供了更多便捷功能通用Mapper减少基础CRUD代码public interface UserMapper extends BaseMapperUser { // 无需编写基础CRUD方法 }Lambda查询类型安全的查询条件ListUser users userMapper.selectList( Wrappers.UserlambdaQuery() .eq(User::getName, 张三) .gt(User::getAge, 18) .orderByAsc(User::getCreateTime) );自动填充自动处理创建时间、更新时间等字段TableField(fill FieldFill.INSERT) private LocalDateTime createTime; TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime;7.2 其他ORM框架比较虽然MyBatis很强大但了解其他ORM框架也很重要JPA/Hibernate优点标准规范、自动DDL、丰富的关联关系支持缺点复杂查询性能较差、学习曲线陡峭JOOQ优点类型安全的SQL、丰富的SQL功能支持缺点需要生成代码、社区相对较小Spring Data JDBC优点简单轻量、与Spring生态集成好缺点功能相对有限7.3 云原生趋势下的MyBatis随着云原生的发展MyBatis也在不断进化响应式支持MyBatis正在试验响应式编程支持Kubernetes集成动态数据源配置适应云环境Serverless适配优化冷启动性能在实际项目中我通常会根据团队技术栈和项目需求选择合适的持久层方案。对于需要精细控制SQL、处理复杂查询的场景MyBatis仍然是首选而对于简单的CRUD操作或快速原型开发JPA或MyBatis-Plus可能更合适。

相关新闻

Claude Code / Codex / OpenCode 异同对比

Claude Code / Codex / OpenCode 异同对比

三者都是终端 AI 编程 Agent,可以读写本地文件、执行 shell 命令、拆解多步骤开发任务,但授权、模型绑定、开源属性、生态差异巨大。对比项Claude CodeOpenAI CodexOpenCode(opencode‑ai)出品方Anthropic 闭源官方工具OpenAI 闭源官方 AgentOpenAI社区开…

2026/8/9 8:10:46 阅读更多 →
C++实现停止等待协议:从零构建可靠数据传输模拟器

C++实现停止等待协议:从零构建可靠数据传输模拟器

1. 项目概述与核心价值 最近在整理网络编程相关的学习笔记,发现很多朋友对TCP/IP协议栈底层的可靠传输机制很感兴趣,但往往停留在理论层面。今天,我就以一个经典的“停止等待协议”为蓝本,带大家用C从零开始,亲手实现一…

2026/8/9 8:10:45 阅读更多 →
OpenClaw vs Hermes Agent 异同

OpenClaw vs Hermes Agent 异同

二者都是开源、自托管、724 小时常驻运行的通用 AI Agent 框架,支持多消息渠道、工具调用、持久记忆、定时任务;但架构哲学完全不同:OpenClaw:网关控制优先,厚网关、薄 Agent,追求可控稳定(Type…

2026/8/9 8:10:45 阅读更多 →

最新新闻

元初混沌体系架构 第二卷 第二十五篇 高速航天器动态时空偏移实时校准模型

元初混沌体系架构 第二卷 第二十五篇 高速航天器动态时空偏移实时校准模型

第二十五篇 高速航天器动态时空偏移实时校准模型承启前置 高动态频移收官与全域时空校准升维前篇第二十四篇完整闭环星际超量级多普勒频移高阶补偿算法,彻底解决了星际高速运动引发的频率失锁、相位断裂、动态频偏漂移单维度核心难题,完成了星际通信频域…

2026/8/9 9:08:09 阅读更多 →
Zotero Citation:让学术写作中的引用管理变得轻松高效

Zotero Citation:让学术写作中的引用管理变得轻松高效

Zotero Citation:让学术写作中的引用管理变得轻松高效 【免费下载链接】zotero-citation Make Zoteros citation in Word easier and clearer. 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-citation 还在为论文写作中的引用管理而烦恼吗&#xff1f…

2026/8/9 9:08:09 阅读更多 →
浏览器调试器高效使用技巧

浏览器调试器高效使用技巧

Chrome DevTools(浏览器调试器)是前端开发、网页问题排查、性能优化的核心工具。多数开发者日常仅使用元素审查、控制台打印等基础功能,而大量高效的隐藏技巧能将调试效率提升数倍。本文从常用面板进阶、快捷键提速、高级调试、冷门功能四个维…

2026/8/9 9:08:09 阅读更多 →
从零到一:OpenHand开源机械手构建全指南

从零到一:OpenHand开源机械手构建全指南

从零到一:OpenHand开源机械手构建全指南 【免费下载链接】openhand-hardware CAD files for the OpenHand hand designs 项目地址: https://gitcode.com/gh_mirrors/op/openhand-hardware 你是一个文章写手,你负责为开源项目写专业易懂的文章。Op…

2026/8/9 9:08:09 阅读更多 →
Phaser 3实现群体AI:Boids算法详解与性能优化实战

Phaser 3实现群体AI:Boids算法详解与性能优化实战

1. 项目概述:从“3行代码”到群体AI的深度实践 看到“3行代码实现千人群集”这个标题,很多刚接触游戏开发或AI模拟的朋友可能会眼前一亮,觉得这简直是魔法。作为一个在游戏交互和模拟领域摸爬滚打了十多年的老手,我必须说&#xf…

2026/8/9 9:08:09 阅读更多 →
Java集合框架核心原理与面试高频考点解析

Java集合框架核心原理与面试高频考点解析

1. Java集合框架全景解析 作为Java开发者技术面试的必考领域,集合框架的掌握程度直接决定了候选人基础功底的扎实程度。我在技术面试中常遇到候选人能说出ArrayList和LinkedList的区别,却解释不清为什么HashMap加载因子默认是0.75;能背诵Conc…

2026/8/9 9:07:08 阅读更多 →

日新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/9 0:01:47 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/9 0:01:47 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/9 0:03:48 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/9 0:01:47 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/9 0:01:47 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/9 0:03:48 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/8 17:02:44 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/9 0:45:04 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/8 17:02:44 阅读更多 →