因為要搞一個簡單的權限系統,所以最近我進行了一些設計和實現。經過研究,根據業務需求,決定使用一個二級菜單和自定義標簽來實現權限的控制。
首先來解決這款二級菜單,當然實現自己也肯定能實現,但是別人做好了自己就用吧。
其他技術你可以訪問我的博客:http://cuisuqiang.iteye.com/
這個控件叫 chromemenu,官方網站是http://www.dynamicdrive.com/ ,當然我的附件里面已經帶了一個,你可以直接下載看一下。
使用很簡單,就是幾個層和超鏈接,正好我可以控制層和超鏈接的顯示來實現權限控制。
我們來定義一個標簽web-html.tld:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>html</short-name> <tag> <name>resourceUrl</name> <tag-class>com.nms.taglib.ResourceUrl</tag-class> <body-content>JSP</body-content> <attribute> <name>key</name> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>href</name> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>rel</name> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>note</name> <rtexprvalue>true</rtexprvalue> </attribute> <attribute> <name>isModule</name> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
在web.xml中配置一下:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 自定義標簽 開始 --> <jsp-config> <taglib> <taglib-uri>/tld/web-html</taglib-uri> <taglib-location> /WEB-INF/tlds/web-html.tld </taglib-location> </taglib> </jsp-config> <!-- 自定義標簽 結束 --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
看一下實現類:
package com.nms.taglib; import java.io.IOException; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.tagext.BodyTagSupport; /** * @說明 菜單生成 * @author 崔素強 */ @SuppressWarnings("serial") public class ResourceUrl extends BodyTagSupport { @Override public int doStartTag() throws JspException { try { // 從開放的接口取得是否允許Key資源的輸出 boolean isCheck = true; if(isCheck){ StringBuffer results = new StringBuffer(""); if("true".equals(isModule)){ results.append("<li>"); } results.append("<a "); if (href != null) { results.append(" href=\""); results.append(href); results.append("\""); } if (rel != null) { results.append(" rel=\""); results.append(rel); results.append("\""); } results.append(">"); results.append(note); results.append("</a>"); if("true".equals(isModule)){ results.append("</li>"); } pageContext.getOut().write(results.toString()); } } catch (IOException ex) { throw new JspTagException("錯誤"); } return EVAL_BODY_INCLUDE; } @Override public int doEndTag() throws JspException { return EVAL_PAGE; } //權限驗證標記 protected String key; // 實際連接地址 protected String href; // 對應的下拉板塊 protected String rel; // 是否是總標記 protected String isModule; // 文字 protected String note; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getHref() { return href; } public void setHref(String href) { this.href = href; } public String getRel() { return rel; } public void setRel(String rel) { this.rel = rel; } public String getIsModule() { return isModule; } public void setIsModule(String isModule) { this.isModule = isModule; } public String getNote() { return note; } public void setNote(String note) { this.note = note; } /** * doStartTag()方法是遇到標簽開始時會呼叫的方法,其合法的返回值是EVAL_BODY_INCLUDE與SKIP_BODY,前者表示將顯示標簽間的文字,后者表示不顯示標簽間的文字 * doEndTag()方法是在遇到標簽結束時呼叫的方法,其合法的返回值是EVAL_PAGE與SKIP_PAGE,前者表示處理完標簽后繼續執行以下的JSP網頁,后者是表示不處理接下來的JSP網頁 * doAfterBody(),這個方法是在顯示完標簽間文字之后呼叫的,其返回值有EVAL_BODY_AGAIN與SKIP_BODY,前者會再顯示一次標簽間的文字,后者則繼續執行標簽處理的下一步 * EVAL_BODY_INCLUDE:把Body讀入存在的輸出流中,doStartTag()函數可用 * EVAL_PAGE:繼續處理頁面,doEndTag()函數可用 * SKIP_BODY:忽略對Body的處理,doStartTag()和doAfterBody()函數可用 * SKIP_PAGE:忽略對余下頁面的處理,doEndTag()函數可用 * EVAL_BODY_BUFFERED:申請緩沖區,由setBodyContent()函數得到的BodyContent對象來處理tag的body,如果類實現了BodyTag,那么doStartTag()可用,否則非法 * EVAL_BODY_AGAIN:請求繼續處理body,返回自doAfterBody(),這個返回值在你制作循環tag的時候是很有用的 * 預定的處理順序是:doStartTag()返回SKIP_BODY,doAfterBodyTag()返回SKIP_BODY,doEndTag()返回EVAL_PAGE * 如果繼承了TagSupport之后,如果沒有改寫任何的方法,標簽處理的執行順序是:doStartTag() ->不顯示文字 * ->doEndTag()->執行接下來的網頁 如果您改寫了doStartTag(),則必須指定返回值, * 如果指定了EVAL_BODY_INCLUDE,則執行順序是:doStartTag()->顯示文字->doAfterBodyTag()->doEndTag()->執行下面的網頁 */ }
你要關注這行代碼:
boolean isCheck = true;
在使用時,你要根據 KEY 去判斷是否顯示某個菜單,具體實現就看你的了。
然后我們在JSP頁面中進行使用:
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="/tld/web-html" prefix="html"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>菜單示例</title> <link rel="stylesheet" type="text/css" href="chromestyle.css" /> <script type="text/javascript" src="chrome.js"></script> </head> <body> <div class="chromestyle" id="chromemenu"> <ul> <html:resourceUrl href="#" key="" note="Model001" isModule="true"></html:resourceUrl> <html:resourceUrl href="#" key="" note="Model002" isModule="true"></html:resourceUrl> <html:resourceUrl href="#" key="" note="Model003" isModule="true" rel="dropmenu1"></html:resourceUrl> <html:resourceUrl href="#" key="" note="Model004" isModule="true" rel="dropmenu2"></html:resourceUrl> <html:resourceUrl href="#" key="" note="Model005" isModule="true" rel="dropmenu3"></html:resourceUrl> <html:resourceUrl href="#" key="" note="Model006" isModule="true" rel="dropmenu4"></html:resourceUrl> </ul> </div> <!--1st drop down menu --> <div id="dropmenu1" class="dropmenudiv"> <html:resourceUrl href="#" key="" note="a1"></html:resourceUrl> <html:resourceUrl href="#" key="" note="a2"></html:resourceUrl> <html:resourceUrl href="#" key="" note="a3"></html:resourceUrl> </div> <!--2nd drop down menu --> <div id="dropmenu2" class="dropmenudiv" style="width: 150px;"> <html:resourceUrl href="#" key="" note="b1"></html:resourceUrl> <html:resourceUrl href="#" key="" note="b2"></html:resourceUrl> </div> <!--3rd drop down menu --> <div id="dropmenu3" class="dropmenudiv" style="width: 150px;"> <html:resourceUrl href="#" key="" note="c1"></html:resourceUrl> <html:resourceUrl href="#" key="" note="c2"></html:resourceUrl> <html:resourceUrl href="#" key="" note="c3"></html:resourceUrl> <html:resourceUrl href="#" key="" note="c4"></html:resourceUrl> </div> <!--4rd drop down menu --> <div id="dropmenu4" class="dropmenudiv" style="width: 150px;"> <html:resourceUrl href="#" key="" note="d1"></html:resourceUrl> <html:resourceUrl href="#" key="" note="d2"></html:resourceUrl> <html:resourceUrl href="#" key="" note="d3"></html:resourceUrl> <html:resourceUrl href="#" key="" note="d4"></html:resourceUrl> <html:resourceUrl href="#" key="" note="d5"></html:resourceUrl> <html:resourceUrl href="#" key="" note="d6"></html:resourceUrl> <html:resourceUrl href="#" key="" note="d7"></html:resourceUrl> </div> <script type="text/javascript"> cssdropdown.startchrome("chromemenu"); </script> </body> </html>
如果是一級菜單,那么要設置:
isModule="true"
運行你看到了所有的菜單,你可以自己控制顯示那個菜單。
這個權限就是很簡單,就是根據某個Key去判斷能否訪問那個資源。當然在實際中應該是你請求的連接,這樣再定義一個Filter去過濾所有請求,就能實現不能通過地址欄直接訪問該資源。
-
本文附件下載:
- chromemenu原文件.zip (9.9 KB)
- chromemenu.rar (12.2 KB)