Using Velocity Tools with Spring 3.0.3

匿名 (未验证) 提交于 2019-12-03 08:46:08

问题:

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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!