上一次簡單介紹了如何編寫一個Maven插件,并且如何將插件的執(zhí)行與Maven生命周期綁定,這樣通過調(diào)用maven生命周期方法時,則會在配置的階段按照插件的目標(biāo)來執(zhí)行代碼。
今天通過一個具體的插件來熟悉在項目中的使用。
一般公司的項目結(jié)構(gòu)或者代碼結(jié)構(gòu)都是非常固定的,有一些框架針對這種固化的代碼結(jié)構(gòu)或約定的規(guī)范,在開發(fā)前會嚴(yán)格對項目進(jìn)行模塊劃分,對各個模塊的代碼結(jié)構(gòu)也會嚴(yán)格要求。那么我們則可以根據(jù)這種約定的規(guī)范,通過工具來自動化的生成代碼,從而減少開發(fā)人員的工作量。
比如我們的項目一般都會由多個模塊組成,比如下面的示例:
DMP ├ system │ ├ account │ ├ entity │ ├ dao │ └ service │ └ web │ ├ role │ ├ ... │ ├ permission │ ├ ... │ └ pom.xml ├ monitor │ ├ database │ ├ ... │ ├ disk │ ├ ... │ ├ memory │ ├ ... │ └ pom.xml └ pom.xml
在上面的例子中,我們項目包括了system、monitor等多個模塊,其中system模塊包含了account、role、permission三個子模塊, monitor模塊包含了database、disk、memory三個子模塊,每個子模塊又包含了特定的代碼結(jié)構(gòu). 這個屬于我們約定的模塊劃分規(guī)則,那么基于這樣的規(guī)則,我們完全可以通過開發(fā)一個插件來自動生成這種約定結(jié)構(gòu)的空項目。
假設(shè)插件名稱為 `module-create-maven-plugin`,將來我們會通過該插件實現(xiàn)
項目模塊文件夾和一些通用文件的自動生成。插件大概配置如下:
<build> <plugins> <plugin> <groupId>com.sucls.blog.plugin</groupId> <artifactId>module-create-plugin</artifactId> <version>1.0.0</version> <configuration> <basedir>E://_projects//demo//DMP</basedir> <modules> <module>system/account</module> <module>system/role</module> <module>monitor/databse</module> <module>monitor/disk</module> <module>monitor/memory</module> </modules> </configuration> </plugin> </plugins></build>
根據(jù)我們預(yù)期要求,來設(shè)想插件的開發(fā)過程。
創(chuàng)建一個maven插件項目,在pom.xml中添加如下配置:
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sucls.blog.plugin</groupId> <artifactId>module-create-plugin</artifactId> <version>1.0.0</version> <packaging>maven-plugin</packaging> <dependencies> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>3.8.1</version> </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-core</artifactId> <version>3.8.1</version> </dependency> <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>3.8.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.32</version> </dependency> </dependencies></project>
goal的名字設(shè)計成modules,由于最終項目是基于maven構(gòu)建,所以會生成pom.xml,插件中的幾個參數(shù)就是為了生成pom而設(shè)計
@Mojo(name = "run")public class ModulesCreatePlugin extends AbstractMojo { @Parameter(property = "basedir",defaultValue = "${project.basedir}") private String basedir; @Parameter private String project; @Parameter(property = "groupId",defaultValue = "${project.groupId}") private String groupId; @Parameter(property = "artifactId",defaultValue = "${project.artifactId}") private String artifactId; @Parameter(property = "version",defaultValue = "${project.version}") private String version; @Parameter private List<String> modules; private ModuleTemplateHelper moduleTemplateHelper; public ModulesCreatePlugin(){ init(); } public void init(){ moduleTemplateHelper = new ModuleTemplateHelper(); } @Override public void execute() throws MojoExecutionException, MojoFailureException { Log log = getLog(); log.info(StringUtils.repeat("=",50)); log.info(modules.toString()); createModules(); log.info(StringUtils.repeat("=",50)); } private void createModules() { if(modules != null && modules.size() >0){ List<File> moduleFiles = new ArrayList<>(); modules.forEach(module -> { // 創(chuàng)建目錄 File path = new File(basedir,module); path.mkdirs(); moduleFiles.add(path); }); Set<String> parentModules = new HashSet<>(); // 添加pom.xml for (File module : moduleFiles) { File parent = module.getParentFile(); parentModules.add(parent.getName()); // 上級pom if( !new File(parent,"pom.xml").exists() ){ moduleTemplateHelper.process("pom.ftl", new ModuleEntity(groupId,project,version, parent.getName()),parent.getAbsolutePath()+"/pom.xml"); } // 追繳module XmlUtils.appendModule(new File(parent,"pom.xml"), module.getName()); // 模塊pom moduleTemplateHelper.process("jar.ftl", new ModuleEntity(groupId,parent.getName(),version,module.getName()),module.getAbsolutePath()+"/pom.xml"); new File(module,"src/main/java").mkdirs(); new File(module,"src/main/resources").mkdirs(); } // 項目pom.xml追加module if(new File(basedir,"pom.xml").exists()){ for (String parentModule : parentModules) { XmlUtils.appendModule(new File(basedir,"pom.xml"), parentModule); } } } }}
上面我們通過ModuleTemplateHelper輔助類結(jié)合freemaker框架,最后為各個模塊生成對應(yīng)的pom.xml文件;通過自定義的XmlUtils工具類結(jié)合JDK Documentation API,實現(xiàn)父級模塊中modules節(jié)點的添加子module;
public class ModuleTemplateHelper { private Configuration configuration; public ModuleTemplateHelper() throws IOException { configuration = new Configuration(Configuration.VERSION_2_3_22); configuration.setTemplateLoader(new ClassTemplateLoader(this.getClass(), "/templates")); configuration.setDefaultEncoding("UTF-8"); } public void process(String tpl, Object module, String outputPath){ Template template = configuration.getTemplate(tpl); template.process(module, new FileWriter(outputPath)); }}
public class XmlUtils { static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); static TransformerFactory transformerFactory = TransformerFactory.newInstance(); static DocumentBuilder documentBuilder; static { try { documentBuilder = documentBuilderFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } } /** * * @param pomXmlPath * @param moduleName */ public static void appendModule(File pomXml, String moduleName) { try { Document document = documentBuilder.parse(pomXml); NodeList modules = document.getElementsByTagName("modules"); Node modulesNode = null; if( modules.getLength()>0 ){ modulesNode = modules.item(0); } if( modulesNode == null ){ modulesNode = document.createElement("modules"); document.appendChild(modulesNode); } // 追加 Element module = document.createElement("module"); module.setTextContent(moduleName); modulesNode.appendChild(module); // 保存 transformerFactory.newTransformer().transform(new DOMSource(document), new StreamResult(pomXml)); } catch (Exception e) { throw new RuntimeException(e); } }}
執(zhí)行下面的命令即可生成插件jar,并安裝到本地倉庫
mvn clean package
在項目中引入插件,并且按照需要的模塊添加配置,最后在IDEA右側(cè)則可以看到該插件,雙擊運行,最終項目結(jié)構(gòu)如下圖:
很多技術(shù)本身不復(fù)雜,合理使用與加工則可以將我們平時工作中重復(fù)相似的工作內(nèi)容進(jìn)行簡化,很多自動化工具亦是如此,只不過這些工作由別人完成了。通過今天的示例,主要了解如何將學(xué)到的知識具體化到工作中。
本文鏈接:http://www.www897cc.com/showinfo-26-60918-0.html現(xiàn)學(xué)現(xiàn)用,寫個Maven插件用下
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com