
使用velocity後,原來的很多标簽無法使用了,必須借助velocity tools來完成,目前velocity tools最新版本是2.0,下面是velocity tools的一些注意事項:
1. 與Spring MVC 3.x/4.x的內建問題
Spring 3.x/4.x隻支援1.3.x的velocity tools,要使用2.0必須自己擴充VelocityToolboxView類
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 }
View Code
注:31行tm.configure(getServletContext().getRealPath(getToolboxConfigLocation()));這裡,在某些容器,比如weblogic中,getRealPath可能取不到值,可改成
getResource試試
然後在spring mvc的servlet配置檔案中參考如下設定:
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. 如何擷取目前應用的contextPath
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}即可得到目前的contextPath
3、如何擷取url參數
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部分
4、如何與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,詳情可參考:
編寫自定義的 Velocity 指令
作者:菩提樹下的楊過
出處:http://yjmyzz.cnblogs.com
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。