可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
When I update the bean:
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="cache" value="true"/> <property name="prefix" value=""/> <property name="suffix" value=".vm"/> <property name="toolboxConfigLocation" value="tools.xml" /> </bean>
With the tools.xml path for Velocity Tools, I get:
Caused by: java.lang.ClassNotFoundException: org.apache.velocity.tools.view.ToolboxManager
I've tried plugging in tools version 2 and 1.4, neither have this package structure. Did I miss something obvious? What version of Velocity Tools is the Spring/Velocity component supporting?
回答1:
Spring has very outdated Velocity support by default. I extend VelocityView
class from Spring and override createVelocityContext
method where I initialize Tools myself. Here is how it looks at the end.
回答2:
I use a little bit simpler of a way. I also cannot force Velocity Tools to work due to lack of configuration documentation and examples. I just get the velocity-generic-tools-2.0.jar and make a little change in my view resolver:
<bean id="velocityViewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="order" value="1"/> <property name="prefix" value="/WEB-INF/vm/"/> <property name="suffix" value=".vm"/> <property name="exposeSpringMacroHelpers" value="true"/> <property name="contentType" value="text/html;charset=UTF-8"/> <property name="attributesMap"> <map> <!--Velocity Escape Tool--> <entry key="esc"><bean class="org.apache.velocity.tools.generic.EscapeTool"/></entry> </map> </property> </bean>
Then, in the velocity template you can use it as usual $esc.html($htmlCodeVar). This solution is very simple, without tons of configs and overriding spring classes.
回答3:
With 3.0.5 I used a similar class to what serg posted, with the only modification being to use the updated classes which spring did not use (tail through VelocityToolboxView -> ServletToolboxManager (used in the createVelocityContext we have overridden) That is the class which is deprecated, so I modified the initVelocityToolContext in serg's answer to be:
private ToolContext getToolContext() throws IllegalStateException, IOException { if (toolContext == null) { XmlFactoryConfiguration factoryConfiguration = new XmlFactoryConfiguration("Default Tools"); factoryConfiguration.read(getServletContext().getResourceAsStream(getToolboxConfigLocation())); ToolboxFactory factory = factoryConfiguration.createFactory(); factory.configure(factoryConfiguration); toolContext = new ToolContext(); for (String scope : Scope.values()) { toolContext.addToolbox(factory.createToolbox(scope)); } } return toolContext; }
I also had to change the line which created the VelocityContext to call this method obviously.
My bean now looks like:
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver" p:cache="false" p:prefix="" p:suffix=".vm" p:layoutUrl="templates/main.vm" p:toolboxConfigLocation="/WEB-INF/velocity/velocity-toolbox.xml" p:viewClass="path.to.overriden.class.VelocityToolsLayoutView" />
回答4:
Inspired by answers from Scott and serg, here's another way to do it that does not require XML: http://squirrel.pl/blog/2012/07/13/spring-velocity-tools-no-xml/
public class MyVelocityToolboxView extends VelocityView { @Override protected Context createVelocityContext(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) { ViewToolContext context = new ViewToolContext(getVelocityEngine(), request, response, getServletContext()); ToolboxFactory factory = new ToolboxFactory(); factory.configure(ConfigurationUtils.getVelocityView()); for (String scope : Scope.values()) { context.addToolbox(factory.createToolbox(scope)); } if (model != null) { for (Map.Entry<String, Object> entry : (Set<Map.Entry<String, Object>>) model .entrySet()) { context.put(entry.getKey(), entry.getValue()); } } return context; } }
回答5:
Inspired by all the answers above, this is my implementation of VelocityLayoutView
for spring and velocity-tools 2.0, added some improvement!
public class VelocityToolsView extends VelocityLayoutView { private static final String TOOL_MANAGER_KEY = ViewToolManager.class.getName(); @Override protected Context createVelocityContext( Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) { ServletContext application = getServletContext(); // use a shared instance of ViewToolManager ViewToolManager toolManager = (ViewToolManager)application.getAttribute(TOOL_MANAGER_KEY); if(toolManager == null) { toolManager = createToolManager(getVelocityEngine(), getToolboxConfigLocation(), application); application.setAttribute(TOOL_MANAGER_KEY, toolManager); } ViewToolContext toolContext = toolManager.createContext(request, response); if(model != null) { toolContext.putAll(model); } return toolContext; } private ViewToolManager createToolManager(VelocityEngine velocity, String toolFile, ServletContext application) { ViewToolManager toolManager = new ViewToolManager(application, false, false); toolManager.setVelocityEngine(velocity); // generic & view tools config FactoryConfiguration config = ConfigurationUtils.getVelocityView(); // user defined tools config if(toolFile != null) { FactoryConfiguration userConfig = ConfigurationUtils.load(application.getRealPath(toolFile)); config.addConfiguration(userConfig); } toolManager.configure(config); return toolManager; } }
回答6:
I found that this variation on @serg's technique worked for me.