可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a project where I want to load a velocity template to complete it with parameters. The whole application is packaged as a jar file. What I initially thought of doing was this:
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 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();
And this works fine when I run it in eclipse. However, once I package the program and try to run it using the command line I get an error because the file could not be found.
I imagine the problem is in this line:
ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath());
Because in a jar the absolute file does not exist, since it's inside a zip, but I couldn't yet find a better way to do it.
Anyone has any ideas?
回答1:
If you want to use resources from classpath, you should use resource loader for classpath:
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
回答2:
Final code, developed using the ideas presented in both answers above:
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 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();
回答3:
Unless JAR is exploded, you can't read the resource in JAR as file. Use an input stream.
See following code snippets,
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)) ......
回答4:
To make Velocity look for the templates in classpath:
VelocityEngine ve = new VelocityEngine(); ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); ve.setProperty("classpath.resource.loader.class",ClasspathResourceLoader.class.getName()); ve.init();