在jar文件中加载velocity模板
我有一个项目,我想加载速度模板来完成它的参数。 整个应用程序打包成一个jar文件。 我最初想到的是这样的:
VelocityEngine ve = new VelocityEngine(); URL url = this.getClass().getResource("/templates/"); File file = new File(url.getFile()); ve = new VelocityEngine(); ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "file"); ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath()); ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true"); ve.init(); VelocityContext context = new VelocityContext(); if (properties != null) { stringfyNulls(properties); for (Map.Entry<String, Object> property : properties.entrySet()) { context.put(property.getKey(), property.getValue()); } } final String templatePath = templateName + ".vm"; Template template = ve.getTemplate(templatePath, "UTF-8"); String outFileName = File.createTempFile("report", ".html").getAbsolutePath(); BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outFileName))); template.merge(context, writer); writer.flush(); writer.close();
这在我在eclipse中运行时工作的很好。 但是,一旦我打包程序,并尝试使用命令行运行它,我得到一个错误,因为该文件找不到。
我想象这个问题是在这一行:
ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath());
因为在一个jar文件中,绝对文件不存在,因为它在一个zip文件中,但是我还找不到一个更好的方法来完成它。
任何人有任何想法?
如果你想使用classpath中的资源,你应该使用classpath的资源加载器:
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
最终代码,使用上面两个答案中提出的思想开发的:
VelocityEngine ve = new VelocityEngine(); ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); ve.init(); final String templatePath = "templates/" + templateName + ".vm"; InputStream input = this.getClass().getClassLoader().getResourceAsStream(templatePath); if (input == null) { throw new IOException("Template file doesn't exist"); } InputStreamReader reader = new InputStreamReader(input); VelocityContext context = new VelocityContext(); if (properties != null) { stringfyNulls(properties); for (Map.Entry<String, Object> property : properties.entrySet()) { context.put(property.getKey(), property.getValue()); } } Template template = ve.getTemplate(templatePath, "UTF-8"); String outFileName = File.createTempFile("report", ".html").getAbsolutePath(); BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outFileName))); if (!ve.evaluate(context, writer, templatePath, reader)) { throw new Exception("Failed to convert the template into html."); } template.merge(context, writer); writer.flush(); writer.close();
除非JAR爆炸,否则无法读取JAR中的资源作为文件。 使用inputstream。
请参阅以下代码片段,
InputStream input = classLoader.getResourceAsStream(fileName); if (input == null) { throw new ConfigurationException("Template file " + fileName + " doesn't exist"); } InputStreamReader reader = new InputStreamReader(input); Writer writer = null; try { writer = new OutputStreamWriter(output); // Merge template if (!engine.evaluate(context, writer, fileName, reader)) ......
为了使Velocity在classpath中寻找模板:
VelocityEngine ve = new VelocityEngine(); ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); ve.setProperty("classpath.resource.loader.class",ClasspathResourceLoader.class.getName()); ve.init();