# MyBatis Mapper文件不想手动注册?启动时自动扫描conf目录,动态拼配置

张开发
2026/4/10 0:18:39 15 分钟阅读

分享文章

# MyBatis Mapper文件不想手动注册?启动时自动扫描conf目录,动态拼配置
MyBatis Mapper文件不想手动注册启动时自动扫描conf目录动态拼配置非科班野生程序员深耕政务信息化20年。从VC到PB再到Java自研框架browise也打磨了十几年。最近整理框架代码发现不少有趣的决策写出来和大家聊聊。最后感谢豆包、智谱、OpenCode决策是我做的代码是我搓的文字是他们总结的。问题MyBatis 的DBconfig.xml里每个 Mapper 文件都要手动注册mappersmapperresourcecom/browise/conf/UserMapper.xml/mapperresourcecom/browise/conf/OrderMapper.xml/!-- 每加一个Mapper就要改这个文件 --/mappers政务项目里 Mapper 文件几十上百个每次新加表就得改配置文件开发人员经常忘记注册启动不报错但运行时才暴露BindingException。方案启动时自动扫描com/browise/conf/目录下的所有.xml文件动态追加到DBconfig.xml的mappers节点里然后把拼好的配置作为 InputStream 传给 MyBatis 的SqlSessionFactory。代码// ScanXml.javapublicclassScanXml{// 递归扫描目录收集指定类型的文件privatestaticvoidshowList(Filef,ArrayListFileal,Stringtype){File[]fArrf.listFiles();for(Filep:fArr){if(p.isDirectory()){showList(p,al,type);}else{if((p.getName()).endsWith(type)!DBconfig.xml.equals(p.getName()))al.add(p);}}}publicstaticListFilegetFlieList(Stringpath,Stringtype){ArrayListFilealnewArrayListFile();FilefnewFile(path);showList(f,al,type);returnal;}publicstaticInputStreamget()throwsIOException,DocumentException{StringpathgetAbsolutePathByClass();Stringxmlpathcom/browise/conf/;// 第一步扫描目录收集所有.xml文件排除DBconfig.xml自身ListFilelistgetFlieList(path,.xml);// 第二步读取DBconfig.xml的基础配置FilefnewFile(path/DBconfig.xml);SAXReadersaxReadernewSAXReader();saxReader.setFeature(http://apache.org/xml/features/nonvalidating/load-external-dtd,false);DocumentdocumentsaxReader.read(f);// 第三步找到mappers节点动态追加mapperStringxpath/configuration/mappers;ListElementnodelist(ListElement)document.selectNodes(xpath);Elementmappersnodelist.get(0);for(inti0;ilist.size();i){Elementmappermappers.addElement(mapper);mapper.addAttribute(resource,xmlpathlist.get(i).getName());}// 第四步Document转成InputStream返回OutputFormatopfnewOutputFormat(\t,true,UTF-8);opf.setTrimText(true);ByteArrayOutputStreambosnewByteArrayOutputStream();XMLWriterwriternewXMLWriter(bos,opf);writer.write(document);writer.close();InputStreamstreamnewByteArrayInputStream(bos.toByteArray());bos.close();returnstream;}// 定位conf目录的物理路径privatestaticStringgetAbsolutePathByClass()throwsIOException{EnumerationURLdirsThread.currentThread().getContextClassLoader().getResources(com/browise/conf);URLurldirs.nextElement();StringfilePathURLDecoder.decode(url.getFile(),UTF-8);returnfilePath;}}关键点排除自身showList里有这个判断if((p.getName()).endsWith(type)!DBconfig.xml.equals(p.getName()))DBconfig.xml本身也在conf目录下如果不排除扫描出来的列表里会把它也注册成 MapperMyBatis 会报解析错误。用 ClassLoader 定位路径Thread.currentThread().getContextClassLoader().getResources(com/browise/conf);不用硬编码路径通过 ClassLoader 的getResources定位conf目录。这样不管部署在 Tomcat、WebLogic 还是 Resin 里路径都能正确找到。返回 InputStream 而不是写文件最终返回的是InputStream不是把修改后的 XML 写回磁盘。这意味着DBconfig.xml文件本身永远不用改每次启动时动态生成一份带完整 Mapper 列表的配置传给 MyBatis// SqlSessionFactory 初始化时InputStreamstreamScanXml.get();SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder().build(stream);禁用外部DTDsaxReader.setFeature(http://apache.org/xml/features/nonvalidating/load-external-dtd,false);DBconfig.xml里引用了 MyBatis 的 DTD但运行时不一定能联网访问。禁用外部 DTD 加载避免启动卡住。小结ScanXml 156行代码做的事情很简单启动时扫目录把所有 Mapper 文件动态注册到 MyBatis 配置里。开发人员只需要把 Mapper XML 扔到conf目录下不用改任何配置文件重启就生效。这种约定优于配置的思路在 Spring Boot 里很常见但我们的框架从2012年就这么干了。你们的MyBatis Mapper是怎么注册的手写还是自动扫描评论区聊聊。标签#Java #MyBatis #自动扫描 #零配置 #政务信息化 #自研框架

更多文章