我继承了一个在Tomcat下运行的Java应用程序(servlets)。由于历史原因,代码具有不同的“外观和感觉”选项,具体取决于应用程序的部署位置(基本上是品牌推广)。
有几个常量控制着这个品牌推广过程,它们具有不同的功能,不应该压缩成一个常量(即BRAND,MULTI-LANGUAGE,加上图标和css样式表的位置等)。
目前,开发团队必须手动更改常量(它们至少本地化在一个数据类中并有详细记录),然后使用ANT重新编译应用程序。
至少假设Ant 1.8和Java 6.x,自动执行此过程的最佳方法是什么?
我知道使用编译器参数没有任何好的解决方案(就像在C或C ++中可以做到的那样),并且我倾向于使用一些“最好的方法”来编辑包含常量的源文件,或者将它们放入另一个文件并使用ant构建过程交换它们。我希望得到的结果可以使用像“ant build brand-x”这样的东西,改变品牌会改变结果。
谢谢,
-Richard
答案 0 :(得分:9)
将您的值放入属性文件中,例如“myapp.properties”,然后在启动时从类路径将它们加载到常量中(请参阅下文,了解它如何适合构建过程):
public class Constants
{
private static final Properties props = new Properties();
public static final String MY_CONSTANT;
static
{
InputStream input = Constants.class.getResourceAsStream("/myapp.properties");
if(input != null)
{
try
{
properties.load(input);
}
catch(IOException e)
{
// TODO log error
}
}
// Initialize constants (dont' forget defaults)
MY_CONSTANT = properties.getProperty("constant", "default");
// .. other constants ...
}
}
现在,为每个品牌设置一个单独的属性文件。通过-D或build.properties将其名称传递给ANT,然后在将jar文件(或者用于它)之前将文件复制到构建目录中。
显然,上面的代码可行,但有很多方法可以清理它并使其成为防弹。
答案 1 :(得分:2)
使用Ant中的替换任务来更改值。
答案 2 :(得分:1)
还有一种“spring”方式,即使用属性文件,以及从属性中提取值并将它们注入需要它们的类的bean,例如:
<bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:configuration.properties" />
</bean>
然后,您可以使用“类似ant”的语法注入属性:
<bean id="connectionPool" class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
<property name="databaseName" value="mydb" />
<property name="url" value="${db.url}" />
...
这可能需要比你想要的更多的重写。如果你要在每次编译时改变常量,我会注意这个问题(如果你正在使用静态韵母,那就是)。
public class Foo {
public static final int SOME_CONSTANT=1;
..
}
public class Bar {
...
int x=5+Foo.SOME_CONSTANT;
...
}
如果然后将Foo中的SOME_CONSTANT更改为2但不重新编译Bar,则为SOME_CONSTANT保留值1,因为编译了静态韵母(因为编译器发现它不需要重复编码)他们再次出局)。
答案 3 :(得分:1)
我更喜欢使用ant的expandproperties过滤器而不是替换任务。使用替换任务,构建文件趋于增长,主要是标记化。 expandproperties允许您直接在文本中嵌入ant属性。
<copy file="from" tofile="to">
<filterchain>
<expandproperties />
</filterchain>
</copy>
答案 4 :(得分:1)
我有一个适合这种特殊情况的解决方案。我已经将Ant替换任务与常量类的“已保存”版本结合使用:
<target name="one" description="constant substitution #1">
<delete file="./tme3/MyConst.java" />
<copy file="./save/MyConst.java" tofile="./tme3/MyConst.java" />
<replace file="./tme3/MyConst.java" token="@BRANDING@" value="ONE_BRAND"/>
<replace file="./tme3/MyConst.java" token="@STYLESHEET@"
value="../stylesheet/onebrand.css"/>
<replace file="./tme3/MyConst.java" token="@FAVICON@" value="../images/onebrand.ico"/>
<replace file="./tme3/MyConst.java" token="@SHOW_LANGUAGES@" value="false"/>
</target>
我只是制作了这个块的副本并更改了我需要的案例的替换 - 在我的特定情况下,现在有3套,但更多的预期。
感谢所有人的回复。
答案 5 :(得分:0)
使用Ant property files,并使用“-Dbrand = X”进行构建。