如何在Maven原型中提供自定义逻辑? [英] How can I provide custom logic in a Maven archetype?

查看:160
本文介绍了如何在Maven原型中提供自定义逻辑?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对创建Maven原型很感兴趣,我认为我掌握了大多数基础知识.但是,我坚持的一件事是有时我想使用自定义逻辑来填充模板.例如,如果有人生成了我的原型,并将artifactId指定为hello-world,我想生成一个名为HelloWorld的类,该类将简单地输出"Hello World!".到控制台.如果其他人使用artifactId = howdy-there生成了它,则生成的类将是HowdyThere,并且将打印出"Howdy There!".

I'm interested in creating a Maven archetype, and I think I have most of the basics down. However, one thing I'm stuck on is that sometimes I want to use custom logic to fill in a template. For example, if somebody generates my archetype and specifies the artifactId as hello-world, I'd like to generate a class named HelloWorld that simply prints out "Hello World!" to the console. If another person generates it with artifactId = howdy-there, the genned class would be HowdyThere and it would print out "Howdy There!".

我知道在幕后,Maven的原型机制利用了Velocity模板引擎,因此我在

I know that under the covers, Maven's archetype mechanism leverages the Velocity Template Engine, so I read this article on creating custom directives. This seemed to be what I was looking for, so I created a class called HyphenatedToCamelCaseDirective that extends org.apache.velocity.runtime.directive.Directive. In that class, my getName() implementation returns "hyphenatedCamelCase". In my archetype-metadata.xml file, I have the following...

<requiredProperties>
    <requiredProperty key="userdirective">
        <defaultValue>com.jlarge.HyphenatedToCamelCaseDirective</defaultValue>
    </requiredProperty>
</requiredProperties>

我的模板类如下...

My template class looks like this...

package ${package};

public class #hyphenatedToCamelCase('$artifactId') {

    // userdirective = $userdirective
    public static void main(String[] args) {
        System.out.println("#hyphenatedToCamelCase('$artifactId')"));
    }
} 

安装原型然后执行原型:通过指定artifactId = howdy-there和groupId = f1.f2生成后,生成的类如下所示……

After I install my archetype and then do an archetype:generate by specifying artifactId = howdy-there and groupId = f1.f2, the resulting class looks like this...

package f1.f2;

public class #hyphenatedToCamelCase('howdy-there') {

    // userdirective = com.jlarge.HyphenatedToCamelCaseDirective    
    public static void main(String[] args) {
        System.out.println("#hyphenatedToCamelCase('howdy-there')"));
    }
}

结果表明,即使按照我期望的方式设置了userdirective,也没有像我希望的那样逃避#hyphenatedToCamelCase指令.在指令类中,我有render方法将一条消息记录到System.out,但该消息未显示在控制台中,因此使我相信该方法在原型:generate期间从未执行过.

The result shows that even though userdirective is being set the way I expected it to, It's not evaulating the #hyphenatedToCamelCase directives like I was hoping. In the directive class, I have the render method logging a message to System.out, but that message doesn't show up in the console, so that leads me to believe that the method never got executed during archetype:generate.

我在这里遗漏了一些简单的东西吗,还是这种方法不是可行的方法?

Am I missing something simple here, or is this approach just not the way to go?

推荐答案

archetype-metatadata xml的必需属性部分用于将其他属性传递给速度上下文,这不是通过速度发动机配置.因此,设置名为userDirective的属性只会使变量$ userDirective可用,而不会向速度引擎添加自定义指令.

The required properties section of the archetype-metatadata xml is used to pass additional properties to the velocity context, it is not meant for passing velocity engine configuration. So setting a property called userDirective will only make the variable $userDirective availble and not add a custom directive to the velocity engine.

如果您看到源代码,则maven-archetype插件使用的速度引擎对其配置不依赖任何外部属性源.

If you see the source code, the velocity engine used by maven-archetype plugin does not depend on any external property source for its configuration. The code that generates the project relies on an autowired (by the plexus container) implementation of VelocityComponent.

这是初始化速度引擎的代码:

This is the code where the velocity engine is initialized:

public void initialize()
    throws InitializationException
{
    engine = new VelocityEngine();

    // avoid "unable to find resource 'VM_global_library.vm' in any resource loader."
    engine.setProperty( "velocimacro.library", "" );

    engine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, this );

    if ( properties != null )
    {
        for ( Enumeration e = properties.propertyNames(); e.hasMoreElements(); )
        {
            String key = e.nextElement().toString();

            String value = properties.getProperty( key );

            engine.setProperty( key, value );

            getLogger().debug( "Setting property: " + key + " => '" + value + "'." );
        }
    }

    try
    {
        engine.init();
    }
    catch ( Exception e )
    {
        throw new InitializationException( "Cannot start the velocity engine: ", e );
    }
}

有一种添加自定义指令的简单方法.您从

There is a hacky way of adding your custom directive. The properties you see above are read from the components.xml file in the plexus-velocity-1.1.8.jar. So open this file and add your configuration property

<component-set>
  <components>
    <component>
      <role>org.codehaus.plexus.velocity.VelocityComponent</role>
      <role-hint>default</role-hint>
      <implementation>org.codehaus.plexus.velocity.DefaultVelocityComponent</implementation>
      <configuration>
        <properties>
          <property>
            <name>resource.loader</name>
            <value>classpath,site</value>
          </property>
          ...
          <property>
            <name>userdirective</name>
            <value>com.jlarge.HyphenatedToCamelCaseDirective</value>
          </property>
        </properties>
      </configuration>
    </component>
  </components>
</component-set>

接下来,将自定义指令类文件添加到此jar中,然后运行archetype:generate.

Next add your custom directive class file to this jar and run archetype:generate.

如您所见,这非常脆弱,您将需要找到一种方法来分发被入侵的神经丛速度罐.根据您计划使用此原型的情况,可能值得付出努力.

As you see this is very fraglie and you will need to figure a way to distribute this hacked plexus-velocity jar. Depending on what you are planning to use this archetype for it might be worth the effort.

这篇关于如何在Maven原型中提供自定义逻辑?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆