close

  起初誤會Struts-Menu和Site-Mesh是同一個。Struts-Menu整合Struts1要設定不少東西才能work,不只是在Maven設定Jar,還要下載一堆css、js和圖檔。沒有像Struts2有提供一個quickstart的archtype那樣方便。這次倒過來,先講程式再推到設定。

    MenuRepository repository = new MenuRepository();

    this.getMenu(list, repository, username, null);
    ServletContext sc = request.getSession().getServletContext();
    MenuRepository defaultRepository =
        (MenuRepository)sc.getAttribute(MenuRepository.MENU_REPOSITORY_KEY);
    repository.setDisplayers(defaultRepository.getDisplayers());

    request.getSession().setAttribute("repository", repository);

private void getMenu(
    List<Functions> list,
    MenuRepository repository,
    String username,
    MenuComponent pmc)    throws Exception
{
    for (Functions function : list) {
        List<Functions> listSub = this.functionDao.find(sqlWhere, function.getId(), username);
        MenuComponent mc = new MenuComponent();
        if (pmc != null) mc.setParent(pmc);
        mc.setTitle(function.getFunctionname());
        mc.setName("L" + function.getId());
        mc.setLocation(function.getUrl());
        if (listSub != null && listSub.size() > 0) {
            this.getMenu(listSub, repository, username, mc);
        }           
        repository.addMenu(mc);
    }
}

  上面片段取自Struts1 Action的內容,上半段目的是要把MenuRepository設給Session,再由JSP透過Struts-Menu提供的標籤產出Menu Tree,但寫法是有點怪異(紅字部份),這後面提到配置檔時再解說;下半段則是Struts-Menu核心寫法了:

  MenuRepository透過addMenu放一堆MenuTree的節點資訊:MenuComponent,所以有四個必要屬性:

  1. setName:在MenuRepository的MenuComponent的unique key(為什麼不叫ID?)。
  2. setTitle:顯示名稱。
  3. setLocation:設定URL。
  4. setParent:設定父節點MenuComponent。

  對應到JSP寫法如下:

<%@ page pageEncoding="utf-8" language="java"%>
<%@ taglib uri="/WEB-INF/tld/jstl/c.tld" prefix="c" %>
<%@ taglib uri="/WEB-INF/tld/jstl/fmt.tld" prefix="fmt" %>
<%@ taglib uri="/WEB-INF/tld/jstl/fn.tld" prefix="fn" %>
<%@ taglib uri="/WEB-INF/tld/struts/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/tld/struts-menu/struts-menu.tld" prefix="menu"%>
<%@ taglib uri="/WEB-INF/tld/struts-menu/struts-menu-el.tld" prefix="menu-el"%>
<HTML>
<HEAD>
    <TITLE>MENU</TITLE>
    <html:base/>
    <link href="css/struts-menu/menuExpandable.css" rel="stylesheet" type="text/css" media="screen" />
    <link href="css/struts-menu/global.css" rel="stylesheet" type="text/css" media="all" />
    <script src="js/struts-menu/menuExpandable.js" type="text/javascript"></script>
    <link href="css/struts-menu/xtree.css" rel="stylesheet" type="text/css" media="all" />
    <script src="js/struts-menu/xtree.js" type="text/javascript"></script>
</HEAD>
<BODY>

<h3>Function List</h3>
<script type="text/javascript">
<menu:useMenuDisplayer name="Velocity" config="/templates/xtree.html" repository="repository" bundle="">
    if (document.getElementById) {
        <c:forEach var="menu" items="${repository.topMenus}">
            <menu-el:displayMenu name="${menu.name}"/>
        </c:forEach> 
    }
</menu:useMenuDisplayer>

</script>
</BODY>
</HTML>

  紅字為核心所在,是在Java Script使用Struts-Menu的標籤,<menu-useMenuDisplayer>的repository屬性正是被Struts設置的session內容:MenuRepository,而bundle屬性是i18n。所以從上面片段程式看,除了自訂標籤就有struts、struts-menu和公用JSTL之外,還得link一堆css、js。

  在配置上也挺複雜的,第一個是要在web.xml加Listener標籤(SiteMesh是加Filter標籤):

<listener>
    <listener-class>net.sf.navigator.menu.MenuContextListener</listener-class>
</listener>

  接著要在struts_config.xml也得加plug-in標籤如下(Struts2好像不用):

<plug-in className="net.sf.navigator.menu.MenuPlugIn">
    <set-property property="menuConfig" value="/WEB-INF/menu-config.xml"/>
</plug-in>

  從上面得知還得引入一個menu-config.xml,而若JSP有設置bundle屬性,在<plug-in>標籤之前還要設置<message-resources>標籤。在struts-config.xml,標籤是有順序的。其menu-config.xml如下:

<?xml version="1.0" encoding="UTF-8" ?>
<MenuConfig>
  <Displayers>
    <Displayer   name="DropDown"
                 type="net.sf.navigator.displayer.DropDownMenuDisplayer"/>
    <Displayer   name="Simple"
                 type="net.sf.navigator.displayer.SimpleMenuDisplayer"/>
    <Displayer   name="CoolMenu"
                 type="net.sf.navigator.displayer.CoolMenuDisplayer"/>
    <Displayer   name="CoolMenu4"
                 type="net.sf.navigator.displayer.CoolMenuDisplayer4"/>
    <Displayer   name="MenuForm"
                 type="net.sf.navigator.example.PermissionsFormMenuDisplayer"/>
    <Displayer   name="ListMenu"
                 type="net.sf.navigator.displayer.ListMenuDisplayer"/>
    <Displayer   name="TabbedMenu"
                 type="net.sf.navigator.displayer.TabbedMenuDisplayer"/>
    <Displayer   name="Velocity"
                 type="net.sf.navigator.displayer.VelocityMenuDisplayer"/>
    <Displayer   name="XtreeMenu"
                 type="net.sf.navigator.displayer.XtreeMenuDisplayer"/>
    <Displayer   name="CSSListMenu"
                 type="net.sf.navigator.displayer.CSSListMenuDisplayer"/>
  </Displayers>
  <Menus>
  </Menus>
</MenuConfig>

  回過頭看JSP的<menu-useMenuDisplayer>的name屬性,是參考到名為Velocity的Displayer,Velocity又是一個Web模板系統,想當然爾要引入它們。最後解釋Struts1 Action在設定MenuRepository為何有點奇怪的地方:宣告一個MenuRepository變數,又要從ServletContext取得一個Default的MenuRepository?目的在於取得menu-context.xml內容值(getDispalyers)設給repository。在web initial時,就被存到特定名稱的session,其session name是MENU_REPOSITORY_KEY的常數。所以JSP就能使用Velocity生成Menu Tree。

  所以在pom.xml要引入不少東西,如下:

<dependency>  <!-- struts.version= 1.3.10 -->
    <groupId>org.apache.struts</groupId>
    <artifactId>struts-core</artifactId>
    <version>${struts.version}</version>
</dependency>
    <dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts-el</artifactId>
    <version>${struts.version}</version>
</dependency>
    <dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts-taglib</artifactId>
    <version>${struts.version}</version>
</dependency>
<dependency>
    <groupId>struts-menu</groupId>
    <artifactId>struts-menu</artifactId>
    <version>2.4.3</version>
</dependency>

<!-- velocity -->
<dependency>
    <groupId>velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>velocity-tools</groupId>
    <artifactId>velocity-tools</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>velocity-tools</groupId>
    <artifactId>velocity-tools-view</artifactId>
    <version>1.4</version>
</dependency>

<dependency>    <!-- 2009/4/25 -->
    <groupId>opensymphony</groupId>
    <artifactId>sitemesh</artifactId>
    <version>2.4.2</version>
</dependency>

  我試過用velocity 1.5版會有點問題,所以還是用1.4,而其它struts-menu要用的js、css等檔案及配置,得自行下載放置,參考http://struts-menu.sourceforge.net/。嚴格來說,struts-menu做到這樣算很優秀了,若有quickstart的archetype就更好了,缺點就是配置太多了。
arrow
arrow
    全站熱搜

    Jemmy 發表在 痞客邦 留言(0) 人氣()