`

maven 自定义插件小示例

阅读更多
maven作为一个核心是插件的架构,所有的工作都通过插件来执行,主要分为两类build和report
  • Build plugins:在build阶段执行,在pom中必须配置在<build/>标签里面
  • Reporting plugins:在生成site阶段执行,在pom中配置在<reporting/>标签里面。

maven官方已经给我们提供了各种各样的插件maven plugins,但有时我们还是需要自己定义我们特殊的插件,比如我们项目中根据特定的文件,自动生成对应的java类,这时就需要我们实现自己的特定插件了,本示例包含两个工程,
  • 插件工程:maven-plugin-test
  • 使用插件的工程:maven-plugin-client-test

为了使示例保持简单,插件工程只演示了从特定目录下读取特定文件类型,并没有生成java类。

1.插件工程
1.1 工程结构



1.2 Mojo类
/**
 * 
 */
package falcon.chengf.maven.plugin.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.model.fileset.FileSet;
import org.apache.maven.shared.model.fileset.util.FileSetManager;
import org.yaml.snakeyaml.Yaml;

/**
 * read content from yaml files (.yml)
 *
 * @goal readyml
 * @phase generate-sources
 * @threadSafe
 */
public class ReadYmlMojo extends AbstractMojo {

	/**
	 * The source directory of yml files. This directory is added to the
	 * classpath at schema compiling time. All files can therefore be referenced
	 * as classpath resources following the directory structure under the source
	 * directory.
	 *
	 * @parameter property="sourceDirectory"
	 *            default-value="${basedir}/src/main/resources"
	 */
	private File sourceDirectory;

	/**
	 * @parameter property="outputDirectory"
	 *            default-value="${project.build.directory}/generated-sources/yml"
	 */
	private File outputDirectory;

	/**
	 * @parameter property="sourceDirectory"
	 *            default-value="${basedir}/src/test/resources"
	 */
	private File testSourceDirectory;

	/**
	 * @parameter property="outputDirectory"
	 *            default-value="${project.build.directory}/generated-test-sources/yml"
	 */
	private File testOutputDirectory;

	/**
	 * A set of Ant-like inclusion patterns used to select files from the source
	 * directory for processing. By default, the pattern
	 * <code>**&#47;*.yml</code> is used to select grammar files.
	 * 
	 * @parameter property="includes"
	 **/

	private String[] includes = new String[] { "**/*.yml" };

	/**
	 * A set of Ant-like inclusion patterns used to select files from the source
	 * directory for processing. By default, the pattern
	 * <code>**&#47;*.yml</code> is used to select grammar files.
	 *
	 * @parameter
	 */
	private String[] testIncludes = new String[] { "**/*.yml" };

	/**
	 * A set of Ant-like exclusion patterns used to prevent certain files from
	 * being processed. By default, this set is empty such that no files are
	 * excluded.
	 *
	 * @parameter
	 */
	protected String[] excludes = new String[0];

	/**
	 * A set of Ant-like exclusion patterns used to prevent certain files from
	 * being processed. By default, this set is empty such that no files are
	 * excluded.
	 *
	 * @parameter
	 */
	protected String[] testExcludes = new String[0];

	/**
	 * The current Maven project.
	 *
	 * @parameter default-value="${project}"
	 * @readonly
	 * @required
	 */
	protected MavenProject project;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.maven.plugin.Mojo#execute()
	 */
	public void execute() throws MojoExecutionException, MojoFailureException {
		getLog().info("start to read content from yml file");
		getLog().info("sourceDirectory:" + sourceDirectory.getAbsolutePath());
		getLog().info("outputDirectory:" + outputDirectory.getAbsolutePath());
		getLog().info("includes:" + Arrays.asList(includes));
		boolean hasSourceDir = null != sourceDirectory && sourceDirectory.isDirectory();
		boolean hasTestDir = null != testSourceDirectory && testSourceDirectory.isDirectory();
		if (!hasSourceDir && !hasTestDir) {
			throw new MojoExecutionException("neither sourceDirectory: " + sourceDirectory + " or testSourceDirectory: "
					+ testSourceDirectory + " are directories");
		}
		if (hasSourceDir) {
			String[] includedFiles = getIncludedFiles(sourceDirectory.getAbsolutePath(), excludes, getIncludes());
			readFiles(includedFiles, sourceDirectory, outputDirectory);
		}

		if (hasTestDir) {
			String[] includedFiles = getIncludedFiles(testSourceDirectory.getAbsolutePath(), testExcludes,
					getTestIncludes());
			readFiles(includedFiles, testSourceDirectory, testOutputDirectory);
			project.addTestCompileSourceRoot(testOutputDirectory.getAbsolutePath());
		}
		
		
		getLog().info("read from yml file end");
	}

	/**
	 * 根据条件过滤需要处理的文件
	 * @param absPath
	 * @param excludes
	 * @param includes
	 * @return
	 */
	private String[] getIncludedFiles(String absPath, String[] excludes, String[] includes) {
		FileSetManager fileSetManager = new FileSetManager();
		FileSet fs = new FileSet();
		fs.setDirectory(absPath);
		fs.setFollowSymlinks(false);

		for (String include : includes) {
			fs.addInclude(include);
		}
		for (String exclude : excludes) {
			fs.addExclude(exclude);
		}
		return fileSetManager.getIncludedFiles(fs);
	}

	private void readFiles(String[] files, File sourceDir, File outDir) throws MojoExecutionException {
		for (String filename : files) {
			getLog().info("read content from file " + filename);
			try {
				doRead(filename, sourceDir, outDir);
			} catch (IOException e) {
				throw new MojoExecutionException("Error compiling protocol file " + filename + " to " + outDir, e);
			}
		}
	}

	private static final Yaml yaml = new Yaml();

	protected void doRead(String filename, File sourceDirectory, File outputDirectory) throws IOException {
		File src = new File(sourceDirectory, filename);

		// 通过snakeyml读取yml文件内容
		Map<String,Object> content= (Map)yaml.load(new FileInputStream(src));
		getLog().info(filename+"'s content is"+content.toString());
	}


	protected String[] getIncludes() {
		return includes;
	}

	protected String[] getTestIncludes() {
		return testIncludes;
	}
}



注意点
  • 1.ReadYmlMojo类上面的注释中有三个注解,这三个注解有特定含义,不能省略,其中@goal 对应的值(readyml)必须和pom.xml中的goal一致
  • 2.属性上面注释中的@parameter注解也有特殊含义,不能省略,如sourceDirectory上的@parameter property="sourceDirectory"要和使用插件工程的pom中指定的参数一致

1.3 插件工程的pom文件
<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>falcon.chengf</groupId>
	<artifactId>maven-plugin-test</artifactId>
	<version>1.0</version>

	<packaging>maven-plugin</packaging>

	<name>maven-plugin-test</name>
	<url>http://maven.apache.org</url>
	
	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.version>2.0.10</maven.version>
        <file-management.version>1.2.1</file-management.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-project</artifactId>
            <version>${maven.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.shared</groupId>
            <artifactId>file-management</artifactId>
            <version>${file-management.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-utils</artifactId>
            <version>3.0.8</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <goalPrefix>readyml</goalPrefix>
                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
                </configuration>
                <executions>
                    <execution>
                        <id>mojo-descriptor</id>
                        <goals>
                            <goal>descriptor</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>help-goal</id>
                        <goals>
                            <goal>helpmojo</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <profiles>
        <profile>
            <id>jdk-1.8</id>
            <activation>
                <activeByDefault>true</activeByDefault>
                <jdk>1.8</jdk>
            </activation>
            <properties>
                <maven.compiler.source>1.8</maven.compiler.source>
                <maven.compiler.target>1.8</maven.compiler.target>
                <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
            </properties>
        </profile>
    </profiles>
</project>


可以看到 goalPrefix 对应的属性值和mojojava类中的值时一样的

2 使用插件的工程
2.1 工程结构


2.2 pom文件
<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>falcon.chengf</groupId>
	<artifactId>maven-plugin-client-test</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<name>maven-plugin-client-test</name>
	<url>http://maven.apache.org</url>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<build>
		<sourceDirectory>${project.basedir}/target/generated-sources</sourceDirectory>
		<plugins>
			<plugin>
				<groupId>falcon.chengf</groupId>
				<artifactId>maven-plugin-test</artifactId>
				<version>1.0</version>
				<configuration>
					<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
				</configuration>
				<executions>
					<execution>
						<id>readyml</id>
						<phase>generate-sources</phase>
						<goals>
							<goal>readyml</goal>
						</goals>
						<configuration>
							<sourceDirectory>${project.basedir}/src/main/resources/yml</sourceDirectory>
							<outputDirectory>${project.basedir}/target/generated-sources</outputDirectory>
							<includes>
								<include>**/*.yml</include>
							</includes>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
		<pluginManagement>
			<plugins>
				<!--This plugin's configuration is used to store Eclipse m2e settings 
					only. It has no influence on the Maven build itself. -->
				<plugin>
					<groupId>org.eclipse.m2e</groupId>
					<artifactId>lifecycle-mapping</artifactId>
					<version>1.0.0</version>
					<configuration>
						<lifecycleMappingMetadata>
							<pluginExecutions>
								<pluginExecution>
									<pluginExecutionFilter>
										<groupId>falcon.chengf</groupId>
										<artifactId>
											maven-plugin-test
										</artifactId>
										<versionRange>
											[0.0.1-SNAPSHOT,)
										</versionRange>
										<goals>
											<goal>readyml</goal>
										</goals>
									</pluginExecutionFilter>
									<action>
										<ignore></ignore>
									</action>
								</pluginExecution>
							</pluginExecutions>
						</lifecycleMappingMetadata>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>



注意点:
  • execution中的id属性要和插件工程对应的goal一致
  • configuration中的属性如outputDirectory要和插件工程中@parameter的property值一致
  • 在eclipse中引用插件工程后回报如下错误



  • 直接选择第二项忽略即可


在使用插件的工程中创建/src/main/resources/yml文件,存入test.yml内容如下:
name: chengf
level: 11


执行maven package命令,可以在控制台看到maven插件正确执行,解析的test.yml文件的内容


完整工程代码请参考附件
  • 大小: 124 KB
  • 大小: 52.7 KB
  • 大小: 29.8 KB
  • 大小: 41.1 KB
分享到:
评论

相关推荐

    maven打包过程执行自定义插件包

    本篇文章将详细讲解如何在Maven打包过程中执行自定义插件包,以此来满足特定的项目需求。 首先,我们需要了解Maven的生命周期。Maven的生命周期分为三个阶段:clean(清理)、default(构建)和site(站点)。在...

    AndroidStudio自定义Gradle插件

    以压缩包中的`GradlePluginDemo`为例,这是一个简单的Gradle插件示例,可能包含以下内容: - `MyPlugin`类:实现了`Plugin`接口,定义了插件的核心逻辑。 - `MyExtension`类:作为插件的配置对象,允许用户在`build....

    springboot集成generator自定义插件.rar

    在这个"springboot集成generator自定义插件.rar"项目中,我们看到的重点是如何在Spring Boot项目中集成MyBatis Generator,并且自定义注释。这通常涉及到以下几个关键知识点: 1. **Spring Boot与MyBatis集成**:...

    Maven常用插件整理.docx

    在Java开发领域,Maven是广泛使用的构建工具,它...综上所述,Maven的插件系统极大地增强了其灵活性和实用性,使得开发者能够根据项目需求自定义构建过程。正确配置和使用这些插件,能够确保项目构建高效且符合预期。

    Wowza插件开发和Maven的集成示例项目

    通过这个示例项目,你可以学习到如何将Maven的强大功能应用于Wowza插件开发,从而提高开发效率和代码质量。记得查看提供的博客文章(http://blog.csdn.net/defonds/article/details/22813295)以获取更详细的步骤和...

    maven assembly 插件 代码实现

    总结来说,Maven Assembly插件是Maven的一个强大工具,能够帮助开发者创建自定义的项目归档,包含所有必要的文件和依赖,简化了软件的分发和部署流程。通过熟练掌握其配置和使用,开发者可以更高效地管理项目构建...

    Maven的使用示例

    ** Maven的使用示例 ** Maven是一款强大的Java项目管理工具,它可以帮助开发者构建、管理和部署项目。在Java开发环境中,Maven通过依赖管理和项目生命周期管理,极大地简化了项目的构建过程。下面我们将深入探讨...

    maven相关项目的示例

    - 自定义插件配置:在POM.xml中,可以通过&lt;build&gt;&lt;plugins&gt;...&lt;/plugins&gt;&lt;/build&gt;部分配置插件参数。 5. Maven的多模块项目: - 对于大型项目,可以将项目划分为多个子模块,每个子模块都有自己的POM.xml,顶层...

    maven插件及其使用方法

    在“maven插件及其使用方法(1)”这个文件中,可能包含了更具体的插件使用示例和实战教程,涵盖了如何配置插件、如何自定义插件目标等细节。通过学习这些内容,开发者可以更加熟练地驾驭Maven,提升开发效率,确保...

    maven-examples:Maven示例

    原型生成示例Maven插件 Maven原型插件 允许从称为原型的现有模板创建Maven项目。 并从现有项目创建原型。 网站: :electric_plug: MojoHaus插件 项目 描述 网站 版本-maven-插件 在项目的POM中管理工件的版本 :...

    maven逆向工程和分页插件

    这个“反向工程”项目提供了一个完整的代码示例,包括了Maven逆向工程和分页插件的配置及使用。你可以直接将这个项目导入到IDE中,按照项目结构和配置进行学习,通过运行和修改代码,加深对Maven逆向工程和分页插件...

    (快嘉代码生成Maven插件) 基于maven插件实现

    同时,通过学习插件的实现,也可以为其他类似的任务开发自定义的Maven插件,提升工作效率。 总之,快嘉代码生成Maven插件是提升开发和测试效率的有效工具,它结合了Maven的强大构建能力与TestNG的优秀测试框架,...

    maven-compiler-plugin-3.8.0-source-release插件

    `maven-compiler-plugin-3.8.0-source-release` 版本是 Maven 编译插件的一个特定版本,该版本包含了对 Maven 3.x 系列的支持。这个插件的主要任务包括: 1. **源代码编译**:默认使用 JDK 的 `javac` 编译器进行 ...

    使用Maven assembly打多个自定义包及War包简介

    本篇文章将深入探讨如何使用Maven Assembly插件来创建多个自定义包以及War包,这对于Java开发者来说尤其重要,因为它使得项目打包和分发变得更加方便。 Maven是一个强大的Java项目管理工具,它通过配置文件POM...

    Kettle插件开发官方示例

    官方提供的Kettle插件开发示例,如"pdi-sdk-plugins-8.1.0.0-R"这个压缩包,涵盖了五种类型的插件示例,这为我们深入了解Kettle插件开发提供了宝贵的学习资源。下面将详细介绍这些类型以及它们在Kettle中的作用: 1...

    Maven的生命周期和插件

    如果默认的生命周期和插件不能满足需求,开发者可以自定义插件绑定,将插件目标绑定到特定的生命周期阶段。例如,使用`&lt;build&gt;&lt;plugins&gt;&lt;plugin&gt;`元素添加新的插件配置,通过`&lt;executions&gt;`子元素定义执行时机。 ##...

    通过自定义Gradle插件修改编译后的class文件

    要创建一个自定义插件,你需要编写一个实现了`org.gradle.api.Plugin`接口的类,并声明一个`apply`方法,用于向项目应用插件逻辑。 在我们的场景中,目标是修改编译后的class文件,这可能涉及到字节码操作,例如...

    mybatis自定义生成代码策略示例

    在 `MBGeneratorExample` 这个示例中,很可能是提供了一个完整的配置文件和自定义插件,用于演示如何自定义 MyBatis 的代码生成策略。这个例子可能包括了如何生成 Entity 类、DAO 接口及其实现,以及 Mapper XML ...

Global site tag (gtag.js) - Google Analytics