使用velocity後,原來的不少標籤沒法使用了,必須藉助velocity tools來完成,目前velocity tools最新版本是2.0,下面是velocity tools的一些注意事項:javascript
1. 與Spring MVC 3.x/4.x的集成問題html
Spring 3.x/4.x只支持1.3.x的velocity tools,要使用2.0必須本身擴展VelocityToolboxView類java
1 package org.springframework.web.servlet.view.velocity; 2 3 import java.util.Map; 4 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 8 import org.apache.velocity.context.Context; 9 import org.apache.velocity.tools.Scope; 10 import org.apache.velocity.tools.ToolManager; 11 import org.apache.velocity.tools.view.ViewToolContext; 12 import org.springframework.web.servlet.view.velocity.VelocityToolboxView; 13 14 public class VelocityToolbox2View extends VelocityToolboxView { 15 @Override 16 protected Context createVelocityContext(Map<String, Object> model, 17 HttpServletRequest request, HttpServletResponse response) 18 throws Exception {// Create a 19 // ChainedContext 20 // instance. 21 ViewToolContext ctx; 22 23 ctx = new ViewToolContext(getVelocityEngine(), request, response, 24 getServletContext()); 25 26 ctx.putAll(model); 27 28 if (this.getToolboxConfigLocation() != null) { 29 ToolManager tm = new ToolManager(); 30 tm.setVelocityEngine(getVelocityEngine()); 31 tm.configure(getServletContext().getRealPath( 32 getToolboxConfigLocation())); 33 if (tm.getToolboxFactory().hasTools(Scope.REQUEST)) { 34 ctx.addToolbox(tm.getToolboxFactory().createToolbox( 35 Scope.REQUEST)); 36 } 37 if (tm.getToolboxFactory().hasTools(Scope.APPLICATION)) { 38 ctx.addToolbox(tm.getToolboxFactory().createToolbox( 39 Scope.APPLICATION)); 40 } 41 if (tm.getToolboxFactory().hasTools(Scope.SESSION)) { 42 ctx.addToolbox(tm.getToolboxFactory().createToolbox( 43 Scope.SESSION)); 44 } 45 } 46 return ctx; 47 } 48 }
注:31行tm.configure(getServletContext().getRealPath(getToolboxConfigLocation()));這裏,在某些容器,好比weblogic中,getRealPath可能取不到值,可改爲web
getResource試試spring
而後在spring mvc的servlet配置文件中參考以下設置:apache
1 <bean 2 class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> 3 <property name="order" value="0" /> 4 <property name="cache" value="true" /> 5 <property name="prefix" value="" /> 6 <property name="suffix" value=".vm" /> 7 <property name="toolboxConfigLocation" value="/WEB-INF/toolbox.xml" /> 8 <property name="contentType" value="text/html;charset=UTF-8" /> 9 <property name="viewClass" value="org.springframework.web.servlet.view.velocity.VelocityToolbox2View"></property> 10 </bean>
2. 如何獲取當前應用的contextPathmvc
1 <tool> 2 <key>link</key> 3 <scope>request</scope> 4 <class>org.apache.velocity.tools.view.LinkTool</class> 5 </tool>
藉助velocity-tools的LinkTool類,在velocity中直接用${link.contextPath}便可獲得當前的contextPathide
三、如何獲取url參數this
1 <tool> 2 <key>params</key> 3 <scope>request</scope> 4 <class>org.apache.velocity.tools.view.ParameterTool</class> 5 </tool>
而後就能夠用相似$params.returnUrl,來獲取相似 http://xxx.com/login?returnUrl=abc 中的 abc部分url
四、如何與Spring-Security集成
1 <sec:authorize access="isAnonymous()"> 2 ... 3 </sec:authorize>
之類的標籤沒法在velocity中使用,而velocity-tools中也未提供相應的支持,在老外的一篇博客上,看到了解決方案:
1 package com.cnblogs.yjmyzz.utils; 2 3 import java.util.Collection; 4 import java.util.HashSet; 5 import java.util.Set; 6 import org.springframework.security.core.GrantedAuthority; 7 import org.springframework.security.core.context.SecurityContextHolder; 8 import org.springframework.security.core.userdetails.UserDetails; 9 10 public class VelocitySecurityUtil { 11 12 public static String getPrincipal() { 13 14 Object obj = SecurityContextHolder.getContext().getAuthentication() 15 .getPrincipal(); 16 17 if (obj instanceof UserDetails) { 18 return ((UserDetails) obj).getUsername(); 19 } else { 20 return "anonymous"; 21 } 22 } 23 24 public static boolean isAuthenticated() { 25 return !getPrincipal().equals("anonymous"); 26 } 27 28 public static boolean allGranted(String[] checkForAuths) { 29 Set<String> userAuths = getUserAuthorities(); 30 for (String auth : checkForAuths) { 31 if (userAuths.contains(auth)) 32 continue; 33 return false; 34 } 35 return true; 36 } 37 38 public static boolean anyGranted(String[] checkForAuths) { 39 Set<String> userAuths = getUserAuthorities(); 40 for (String auth : checkForAuths) { 41 if (userAuths.contains(auth)) 42 return true; 43 } 44 return false; 45 } 46 47 public static boolean noneGranted(String[] checkForAuths) { 48 Set<String> userAuths = getUserAuthorities(); 49 for (String auth : checkForAuths) { 50 if (userAuths.contains(auth)) 51 return false; 52 } 53 return true; 54 } 55 56 private static Set<String> getUserAuthorities() { 57 Object obj = SecurityContextHolder.getContext().getAuthentication() 58 .getPrincipal(); 59 Set<String> roles = new HashSet<String>(); 60 if (obj instanceof UserDetails) { 61 @SuppressWarnings("unchecked") 62 Collection<GrantedAuthority> gas = (Collection<GrantedAuthority>) ((UserDetails) obj) 63 .getAuthorities(); 64 for (GrantedAuthority ga : gas) { 65 roles.add(ga.getAuthority()); 66 } 67 } 68 return roles; 69 } 70 71 }
而後修改配置:
1 <bean id="velocitySecurityUtil" class="com.cnblogs.yjmyzz.utils.VelocitySecurityUtil" /> 2 3 <bean 4 class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 5 <property name="order" value="1" /> 6 ... 7 <property name="viewResolvers"> 8 <list> 9 <bean 10 class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> 11 <property name="order" value="0" /> 12 ... 13 <property name="attributesMap"> 14 <map> 15 <entry key="sec"> 16 <ref bean="velocitySecurityUtil" /> 17 </entry> 18 </map> 19 </property> 20 21 </bean> 22 ...
頁面就能用了:
1 #if(${sec.authenticated}) 2 ... 3 #end
注:這個思路也能夠用於實現本身的Velocity-Tools類,好比咱們建立了一個本身的RequestUtil類
1 package com.cnblogs.yjmyzz.utils; 2 import javax.servlet.http.HttpServletRequest; 3 public class RequestUtil{ 4 5 /** 6 * 獲取當前請求的基地址(例如:http://localhost:8080/ctas/xxx.do 返回 http://localhost:8080/ctas/) 7 * 8 * @param request 9 * @return 10 */ 11 public static String getBaseUrl(HttpServletRequest request) { 12 return request.getRequestURL().substring(0, 13 request.getRequestURL().indexOf(request.getContextPath()) + request.getContextPath().length()) + "/"; 14 } 15 16 }
而後在配置裏,加上
1 <bean id="requestUtil" class="com.cnblogs.yjmyzz.utils.RequestUtil"/> 2 3 <bean 4 class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 5 <property name="order" value="1"/> 6 ... 7 <property name="viewResolvers"> 8 <list> 9 ... 10 <bean 11 class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> 12 <property name="order" value="0"/> 13 ... 14 <property name="viewClass" 15 value="com.cnblogs.yjmyzz.utils.VelocityToolbox2View"></property> 16 <property name="attributesMap"> 17 <map> 18 ... 19 <entry key="req"> 20 <ref bean="requestUtil"/> 21 </entry> 22 </map> 23 </property> 24 </bean> 25 ... 26 </bean>
vm頁面這樣用
1 #*取得頁面連接基地址*# 2 #macro(baseHref)${req.getBaseUrl($request)}#end 3 ... 4 <base href="#{baseHref}"> 5 ... 6 <script type="text/javascript"> 7 var baseHref = "#{baseHref}"; 8 </script> 9 ...
順便提一句:網上有一堆文章和教程,讓你在toolbox.xml中添加相似
1 <tool> 2 <key>req</key> 3 <scope>request</scope> 4 <class>com.cnblogs.yjmyzz.utils.RequestUtil</class> 5 </tool>
在Spring MVC4 + Velocity Tools2的組合下,然而,這並無什麼用,在Spring MVC4 + Velocity-Tools2下,已經很差使了。
最後,Velocity還容許自定義標籤(也有人稱爲自定義指令),支持開發人員定義本身的標籤,好比#YourDirective,詳情可參考: