??xml version="1.0" encoding="utf-8" standalone="yes"?> 1.web.xml的配|?br />
2.security.xml的配|?/font> <?xml version="1.0" encoding="GBK"?> <filter> <filter-mapping> </web-app> 上面配置文g指定了装饰器面所在的路径Qƈ指定了一个名为main的装饰器Q该装饰器默认装饰web应用根\径下的所有页面?br />
五?font size="2">建立一个的被装饰页?/index.jsp(内容面) 最后访问index.jspQ将生成如下面Q?/font> 而且Q所有的面也会如同index.jsp一P被sitemesh的filter使用装饰模式修改成如上图般模P却不用再使用include标签?/font> 可糟p的是前端的面逻辑很难被复用,当你在每一个页面中用数之不的include来复用公qheader, stylesheet, scriptsQfooterӞ一个问题出C-重复的代码,每个面必须用copy来复用页面结构,而当你需要创意性的改变面l构ӞNq上了你?/font> sitemesh通过filter截取request和responseQƈl原始的面加入一定的装饰(可能为header,footer...)Q然后把l果q回l客LQƈ且被装饰的原始页面ƈ不知道sitemesh的装饎ͼq也pCp的目的?/font> 据说卛_新出台的Portlet规范会帮助我们标准的实现比这些更多更cool的想法,但可怜的我还不懂它到底是一个什末东东,有兴的人可以研I?br />
jetspeedQ或JSR (Java Specification Request) 168,但我想sitemesh如此单,我们不妨先用着?/font> Page Parsers Q负责读取stream的数据到一个Page对象中以被SiteMesh解析和操作?不太常用Q默认即? Decorator Mappers : 不同的装饰器U类Q我发现2U比较有用都列在下面。一U通用的mapper,可以指定装饰器的配置文g名,另一U可打印的装饰器Q可以允怽当用http://localhost/aaa/a.html?printable=true方式讉K时给出原始页面以供打?免得把header,footer{的花哨的图片也搭上) 范例Q?/strong> decorators.xml Q定义构成复合视囄所有页面构件的描述(主要l构面Qheader,footer...)Q如下例Q?/font> 让我们来先看一看最单的用法Q其实最常用也最单的用法是我们的hello例子Q面对如此众多的技术,我想只要辑ֈ功能点到为止卛_Q没必要ȝI太?除非您有更深的需??/font> 我们在装饰器面只用?个标{: <decorator:title default="装饰器页?.." /> Q?把请求的原始面的title内容插入?lt;title></title>中间?/font> <decorator:body /> Q?把请求的原始面的body内的全部内容插入到相应位|?/font> 然后我们在decorator.xml中加入以下描q即可: <decorator name="main" page="main.jsp"> q样Q请求的所有页面都会被重新处理Qƈ按照main.jsp的格式重新展现在你面前?/font> 插入原始面(被包装页?的head标签中的内容(不包括head标签本n)?/font> 插入原始面(被包装页?的body标签中的内容?/font> <decorator:title [ default="..." ] /> 插入原始面(被包装页?的title标签中的内容Q还可以d一个缺省倹{?/font> 例: /decorator/main.jsp?Q装饰器面Q? <title><decorator:title default="却省title-hello" /> - 附加标题</title> /aaa.jsp?(原始面)Q?lt;title>aaa面</title> 讉K/aaa.jsp的结果:<title>aaa面 - 附加标题</title> <decorator:getProperty property="..." [ default="..." ] [ writeEntireProperty="..." ]/> 在标{֤插入原始面(被包装页?的原有的标签的属?/font>中的内容Q还可以d一个缺省倹{?/font> sitemesh文档中的例子很好理解Q?/font> 注意Q?/strong> <decorator:usePage id="..." /> 例:可用<decorator:usePage id="page" /> Q?/strong><%= 应用包装器到指定的页面上Q一般用于被包装面中主动应用包装器。这个标{有点不好理解,我们来看一个例子: 包装器页?/decorators/panel.jspQ?lt;p><decorator:title /></p> ... <p><decorator:body /></p> 最后会是什末结果呢Q除?page.jsp会被默认的包装页面包装上header,footer外,page.jsp面中还内嵌了date.jsp面Qƈ且此date.jsp面q会被panel.jsp包装Z个title加body的有2D늚面Q第1D|date.jsp的titleQ第2D|date.jsp的body内容?/font> 另外Q?a name="page:applyDecorator">page:applyDecorator中包含的page:param标签所声明的属性D可以在包装页面中?/font>decorator:getProperty标签讉K到? 让我们来看一看怎样实现他: 1.首先在WEB-INFO/sitemesh.xml中设|: 2.在WEB-INFO/decorators.xml中定义相应的printable装饰?br />
<decorator name="printable" page="printable.jsp"/> 3.最后编写printable装饰?decorators/printable.jsp q样可以让一个原始页面通过?printable=true开x切换不同的装饰器面?/font> 1.配置好环境, 2.在WEB-INFO/decroators.xml中描qC徏立的包装器?/font> 3.开发在decroators.xml中描q的包装器,最好存攑֜/_decorators目录?/font> 4.ok Q可以看看辛勤的成果?:)
]]>
]]>
]]>
]]>
]]>
]]>web.xml加入如下Filter的配|?br />
<filter>
<filter-name>securityFilter</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
FilterToBeanProxy是Acegiqo器Bean的代理,功能是把httph按顺序分zqo器BeanQ?br />
说明QAcegi对WEB应用的支持主要是依靠servlet qo器(filterQ?来实现的。每一个http request都将被这?似鞑悴憷?q进行安全处理(包括认证和授权)。针对不同的安全处理QAcegi提供了不同的qo器。过滤器的配|信息理Z应位于web.xmlQ但是我们又希望把Acegi的过滤器配置信息攑֜SpringFramework的配|文仉QapplicationContext-security-acegi.xmlQ,从而实现对q些qo器的“控制反{”。解册个问题的Ҏ是采用Acegi提供的FilterToBeanProxy。FilterToBeanProxy思义是对Acegiqo器Bean的代理,它的主要功能是httph依次分派l对应的qo器Bean?br />
q个Filter需要一个参数targetClass(目标c?Q意思是说代理哪个beanQؓ它配|的值是FilterChainProxyQ就是由q个FilterChainProxyc负责将需要代理的q些Filterl成Filter代理“?#8221;(q些Filter在Security.xmlq个配置文g里以bean的Ş式进行配|了)
web.xml加入如下内容
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/j_security_check</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
q个好理解了,是q样的url都让他被securityFilterq个qo器过滤处?br />
web.xml加入如下内容
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-*.xml,/WEB-INF/security.xml</param-value>
</context-param>
q个是让上下文载入/WEB-INF/applicationContext-*.xml,/WEB-INF/security.xmlq些配置文g
首先加入filterChainProxyq个bean的定义,因ؓ前面在web.xml配置的filter需要这个bean
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON定义了url比较前先转ؓ写Q?PATTERN_TYPE_APACHE_ANT定义了用Apache ant的匹配模?br />
q个beanhttpSessionContextIntegrationFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptorq些beanl成了filter链,当发生需要web.xml配置的过滤器的对应的需要过滤的url的请求时Q这些filter会按照定义的顺?/font>被调用,q个qo器的mapping?#8220;/*”?br />
既然配置了这些需要被调用的给filterChainProxyQ那么就要对q些filterq行逐个配置Q以便filterChainProxy能找到ƈ调用他们?br />
httpSessionContextIntegrationFilter的配|及作用
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
每次request?HttpSessionContextIntegrationFilter从Session中获?u>Authentication对象q?/u>l装ContextHolder。ContextHolder主要用于存放SecureContextQ包括用L权限信息Q在request完后, 又把Authentication对象保存到Session中供下次request使用,此filter必须其他Acegi filter前用,使之能跨多个请求?/strong>
authenticationProcessingFilter的配|及作用
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureUrl" value="/login.jsp?error=true"/> dp|的url
<property name="defaultTargetUrl" value="/"/> d成功后的url
<property name="filterProcessesUrl" value="/j_security_check"/> 需要这个filter处理的url
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
该Filter负责处理登陆w䆾验证。当接受CfilterProcessesUrl所定义相同的请求时Q它会首先通过 AuthenticationManager来验证用戯n份。如果验证成功,则重定向到defaultTargetUrl所定义的成功登陆页面。如果验证失败,则再从rememberMeServices中获取用戯n份,若再获取p|Q则重定向到authenticationFailureUrl所定义登陆p|面?br />
securityContextHolderAwareRequestFilter的配|及作用
<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>
该Filter负责通过Decorate Model(装饰模式)Q装饰的HttpServletRequest对象。其Wapper是ServletRequest包装c?HttpServletRequestWrapper的子c?SavedRequestAwareWrapper?SecurityContextHolderAwareRequestWrapper)Q附上获取用h限信息,request参数Qheaders, Date headers ?cookies 的方法?br />
在appfuse中用的struts-menu.xml对用戯单权限的控制参数roleq行配置时必ȝ合该FilterQ因filter有isUserInRoleҎQ而struts menu也是通过request.isUserInRoleҎ来控制菜单是否显C的
RememberMeProcessingFilter的配|及作用
<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="rememberMeServices" ref="rememberMeServices" />
</bean>
该Filter负责在用L录后在本地机上记录用户cookies信息Q免除下ơ再ơ登陆。检查AuthenticationManager 中是否已存在Authentication对象Q如果不存在则会调用RememberMeServices的aotoLoginҎ来从cookies中获取Authentication对象
AnonymousProcessingFilter的配|及作用
<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="anonymous"/>
<property name="userAttribute" value="anonymous,ROLE_ANONYMOUS"/>
</bean>
该Filter负责为当不存在Q何授权信息时Q自动ؓAuthentication对象duserAttribute中定义的匿名用户权限
ExceptionTranslationFilter的配|及作用
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp" />
<property name="forceHttps" value="false" />
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/accessDenied.jsp" />
</bean>
</property>
</bean>
该过滤器负责处理各种异常Q然后重定向到相应的面中?br />
filterInvocationInterceptor的配|及作用
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="accessDecisionManager"/>
<property name="objectDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/signup.html*=ROLE_ANONYMOUS,admin,user
/passwordHint.html*=ROLE_ANONYMOUS,admin,user
/**/*.html*=admin,user
/clickstreams.jsp*=admin
</value>
</property>
</bean>
?br />
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/> 认证服务
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter">
<property name="rolePrefix" value=""/> //q里定义数据库中存放的角色和我们在这里声明的角色间是否需要加个前~Q这里没?nbsp;
</bean>
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
PATTERN_TYPE_APACHE_ANT
/admin.htm*=a q里是数据库中对应的tyep a
/student*=s ׃没有前缀和数据库里一?nbsp;
/teacher*=t
</value>
</property>
</bean>
按照多数的ACEGI的配|文档,权限表的权限标识多以AUTH_或ROLE_开_那么如果你的表中是这么存储的可以在rolePrefix处配|一个开头标识(其实q仅仅是个标识,没有M实际意义Qappfuse没有这么配|)
该过滤器会首先调用AuthenticationManager判断用户是否已登陆认证,如还没认证成功,则重定向到登陆界面。认证成功,则ƈ?Authentication中获取用L权限。然后从objectDefinitionSource属性获取各UURL资源所对应的权限。最后调?AccessDecisionManager来判断用h拥有的权限与当前受保华的URL资源所对应的权限是否相匚w。如果匹配失败,则返?03错误 (止讉K)l用戗匹配成功则用户可以讉K受保护的URL资源?br />
]]>
sitemesh应用Decorator模式Q用filter截取request和response,把页面组件head,content,bannerl合Z个完整的视图。通常我们都是用include标签在每个jsp面中来不断的包含各Uheader, stylesheet, scripts and footerQ现在,在sitemesh的帮助下Q我们可以开心的删掉他们了。如下图Q你惌杄辑ֈ复合视图模式Q那末看完本文吧?/font>
一、在WEB-INF/web.xml中copy以下filter的定?
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三?建立WEB-INF/decorators.xml描述各装饰器面?/font>
<decorators defaultdir="/decorators">
<decorator name="main" page="main.jsp">
<pattern>*</pattern>
</decorator>
</decorators>
四?建立装饰器页?/decorators/main.jsp
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator"%> <html>
<head>
<title><decorator:title default="装饰器页?.." /></title>
<decorator:head />
</head>
<body>
sitemesh的例?lt;hr>
<decorator:body />
<hr>chen56@msn.com
</body>
</html>
<%@ page contentType="text/html; charset=GBK"%>
<html>
<head>
<title>Agent Test</title>
</head>
<body>
<p>本页只有一句,是本句.</p>
</body>
</html>
装饰?nbsp; decorator概念
Z建立可复用的web应用E序,一个通用的方法是建立一个分层系l,如同下面一个普通的web应用Q?/font>
让我们看看怎样配置环境
除了要copy到WEB-INF/lib中的sitemesh.jar外,q有2个文件要建立到WEB-INF/Q?/font>
sitemesh.xml 可以讄2U信?
(但一般不用徏立它Q默认设|够了Qcom/opensymphony/module/sitemesh/factory/sitemesh-default.xmlQ:
<sitemesh>
<mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper">
<page-parsers>
<parser default="true" class="com.opensymphony.module.sitemesh.parser.DefaultPageParser" />
<parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
<parser content-type="text/html;charset=ISO-8859-1" class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
</page-parsers>
<decorator-mappers>
<mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
<param name="config" value="/WEB-INF/decorators.xml" />
</mapper>
<param name="decorator" value="printable" />
<param name="parameter.name" value="printable" />
<param name="parameter.value" value="true" />
</mapper>
</decorator-mappers>
</sitemesh>
<decorators defaultdir="/decorators">
<decorator name="main" page="main.jsp">
<pattern>*</pattern>
</decorator>
<decorator name="printable" page="printable.jsp" role="customer" webapp="aaa" />
</decorators>
最重要的是写出装饰器本w?也就是那些要复用面Q和l构面)?/font>
其实Q重要的工作是制作装饰器页面本w?也就是包含结构和规则的页?Q然后把他们描述到decorators.xml中?/font>
<%@ page contentType="text/html; charset=GBK"%>
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<html>
<head>
<title><decorator:title default="装饰器页?.." /></title>
<decorator:head />
</head>
<body>
sitemesh的例?lt;hr>
<decorator:body />
<hr>chen56@msn.com
</body>
</html>
<pattern>*</pattern>
</decorator>
让我们看看更多的用法?抄袭sitemesh文档)
以下列着全部标签Q?/font>
Decorator Tags
Page Tags
被用于徏立装饰器面.
被用于从原始内容面讉K装饰?
<decorator:head />
<decorator:body />
<decorator:title />
<decorator:getProperty />
<decorator:usePage />
<page:applyDecorator />
<page:param
The decorator:
The undecorated page:
The decorated page: <body bgcolor="white" onload="document.someform.somefield.focus();">
writeEntireProperty="true"会在插入内容前加入一个空根{?/font>
象jsp面中的<jsp:useBean>标签一P可以使用被包装ؓ一个Page对象的页面?(懒的?<page:applyDecorator name="..." [ page="..." title="..." ] >
<page:param name="..."> ... </page:param>
<page:param name="..."> ... </page:param>
</page:applyDecorator>
q且在decorators.xml中有<decorator name="panel" page="panel.jsp"/>
一个公共页面,卛_被panel包装Q?public/date.jsp:
... <%=new java.util.Date()%> ...<decorator:getProperty property="myEmail" />
被包装页?/page.jsp Q?
<title>page的应?lt;/title>
.....
<page:applyDecorator name="panel" page="/_public/date.jsp" >
<page:param name="myEmail"> chen_p@neusoft.com </page:param>
</page:applyDecorator>
可打印的界面装饰
前面说过?U可打印的装饰器Q可以允怽当用http://localhost/aaa/a.html?printable=true方式讉KӞ应用其他的装饰器(自己指定)Q给出原始页面以供打?免得把header,footer{的花哨的图片也搭上)?/font>
<mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper">
<param name="decorator" value="printable" />
<param name="parameter.name" value="printable" />
<param name="parameter.value" value="true" />
</mapper>
q样可以通过?printable=true来用名为printable的装饰器Q而不是用原来的装饰器?/font>
<%@ taglib uri="sitemesh-decorator" prefix="decorator" %>
<html>
<head>
<title><decorator:title /></title>
<decorator:head />
</head>
<body>
<h1><decorator:title /></h1>
<p align="right"><i>(printable version)</i></p>
<decorator:body />
</body>
</html>
中文问题
׃sitemesh内部所使用的缺省字W集为iso-8859-1Q直接用会产生qQ我们可以通过以下ҎU正之:
charset的项目,然后设成gbk或gb2312卛_
Ҏ2Q这也是我们一直用的Ҏ?br />
1.在每一个jsp里讄: <%@ page contentType="text/html; charset=gbk"%> 来告诉server你所要求的字W集?br />
2.在每个jsp늚head中定义:<META HTTP-EQUIV="content-type" CONTENT="text/html; charset=gbk"> 来告诉浏览器你所用的字符集?/font>
ȝQ用sitemesh最通常的途径Q?/font>
]]>
一、从1.X升?.X需要做以下事情Q?br />
1、改变你的taglib声明中的URI?br />
<% at taglib uri="" prefix="menu" %>
2、改?lt;plug-in>,使用新的包名"net.sf.navigator." ?br />
<plug-in className="net.sf.navigator.menu.MenuPlugIn">
3、改变你的menu-config.xml文gQ用新的包?net.sf.navigator." ?br />
<Displayer name="Simple"
type="net.sf.navigator.displayer.SimpleMenuDisplayer"/>http://struts-menu.sf.net/tag
二、快速开始:
1、下载最新的struts-menu版本Q?br />
2、解包到本地目录Q?br />
3、下载Tomcat或者其它Servlet容器Q?br />
4、把struts-menu.war包放入Tomcat安装目录的wabapps目录下,q启Tomcat服务?br />
5、打开htpp://localhost:8080/struts-menu/
三、把Struts Menu整合C的应用程序中Q?br /> Struts Menu能够被轻易的整合C的Struts应用E序中,它也可以整合C个非Struts的应用程序中Q但是我不喜Ƣ这样做Q所以在此没有提供相应的教程。这里将一步步的带你整合这个标{ֺ?br /> 你需要把struts-menu.jar攑ֈ你的WEB-INF/lib目录下。然后用URI标签声明你的JSP文g中想使用的这个标{ֺ?br /> 如果使用Struts Menu 2.1Q你q需?Jakarta's Standard Tag Library JAR包放入你的WEB-INF/lib目录下。下载地址Q?a >http://ibiblio.org/maven/taglibs/jars/standard-1.0.4.jarQ这个文件包括例EWAR包文件和二进制发布包?br /> 1、放入struts-menu.jar包到你的应用E序的WEB-INF/lib目录中?br /> 2、在你的struts-config.xml文g中加入plug-in讄?br />
3、你需要在你的应用E序?WEB-INF/menu-config.xml文g中定义你的菜单,q里提供一个简单的片断Q?br />
更多全面的例E,h看应用程序的web/WEB-INF目录中的menu-config.xml文gQ你可以截取一D作Z需要的菜单。完整的属性列表,可以查看MenuBase class's javadocsQ?a >http://struts-menu.source......avigator/menu/MenuBase.htmlQ?br />
4、在你的JSP文g的顶部加入taglib声明Q?br />
5、在你的JSP文g中要攄菜单的位|加入taglib代码Q?br />
属性name="TabbedMenu"被定义在menu-config.xml文g的顶部:
(译注Q其实到此步卛_在你的JSP文g中添加相应的菜单了,只不q是没有l合Velocity。在menu-config.xml文g的头部可以定义多个DisplayerQ每个Displayer都有name和type属性,name属性与JSP文g中menu:useMenuDisplayer标签的name属性相对应Q即表明使用何种样式Q具体的样式定义便在type属性中定义Qtype属性中是一个class。在menu-config.xml文g中的菜单定义中的name属性则与JSP文g中的menu:displayMenu标签的name属性相对应?
使用定制的Velocity模版实施你的菜单Q你需要整合VelocityC的WEB应用E序中。如果需要这样做的话Q请完成下面的步骤:
1、确定你的menu-config.xml文g?#8220;Velocity”的displayer定义Q?br />
2、加入Velocity的JARs包到你的WEB-INF/lib目录中,下蝲velocity-1.4-rc1.jarQ?a >http://www.ibiblio.org/ma......y/jars/velocity-1.4-rc1.jarQ和velocity-tools-view-1.0.jarQ?a >http://www.ibiblio.org/ma......velocity-tools-view-1.0.jarQ?
3、加入globalMacros.vmQ?a >http://cvs.sourceforge.net/viewcvs.py/*checkout*/struts-menu/navigator/web/WEB-INF/classes/globalMacros.vm?content-type=text%2Fplain&rev=1.1Q右键另存ؓQ)C的WEB-INF/lib目录中?br />
4、改变你的JSP文g中displayer的gؓ“Velocity”Q?#8220;config”属性指向一个文Ӟ如config="/templates/tabs.html"Q或者如果tabs.htm在你的WEB-INF/classes目录中的话,则可设config="tabs.html"?/p>
q里提供了一些用Velocity的displayer例子Q可在sample applicationQ?a >http://demo.raibledesigns.com/struts-menu/index.jspQ中查看。它L在你的菜单需要的时候显CCSSQJavaScript和图像文件。下面有一些在当前的Struts Menu中用到的Velocity模版的例子的链接Q?br />
CoolMenus: DemoQ?a >http://demo.raibledesigns......menu/velocity-coolmenu4.jspQ?
TemplateQ?a >http://struts-menu.sourceforge.net/templates/coolmenus.htmlQ?
NiceTabs: Demo, Template
Tabs: Demo, Template
XTree: Demo, Template
所有相关的有用的文件如果你需要的话都可以在下面的站点上下载:
Images Q?a >http://struts-menu.sourceforge.net/menu-images/Q?br />
Stylesheets Q?a >http://struts-menu.sourceforge.net/styles/Q?br />
Scripts Q?a >http://struts-menu.sourceforge.net/scripts/Q?br />
Templates Q?a >http://struts-menu.sourceforge.net/templates/Q?/p>
更多的基于roles的显C?隐藏菜单的信息,h看FAQsQ?a >http://struts-menu.sourceforge.net/faq.htmlQ?/p>
四、在Struts之外使用Struts Menu:
?.2版中QMenu Repository能够使用MenuContextListener载入Q?br />
或者如果你使用SpringQ甚xҎ。仅仅需要加入下面的部分C的applicationContext.xml文g中:
感谢Dan Luputan提供MenuLoadercȝ源代码?/p>
五、从源文件编译:
要从源文件编译这个项目,执行下面的步骤:
1、下载ƈ安装MavenQ?a >http://maven.apache.org/Q;
2、创Z个环境变量MAVENQHOME指出你的Maven的安装目录,然后d$MAVEN_HOME/binC的PATH变量中;
3、操U这个目录你可以扩展源代码,执行“maven.jar”创徏target/struts-menu.jar?/p>
要展开struts-menu例程Q需要下面的步骤Q?br />
1、下载和安装TomcatQ?br />
2、创Z个环境变量CATALINAQHOME指出你的Tomcat的安装目录;
3、执?#8220;maven deploy”把应用程序展开到Tomcat中;
4、打开http://localhost:8080/struts-menu在你喜爱的浏览器中?/p>
如果你喜Ƣ用Eclipse开发项目,请参考此份开发向|http://struts-menu.sourceforge.net/devguide.htmlQ?/p>
struts-menu2.3做动态菜?/p>
1 web.xml
struts-menu2.3版本不用建立在struts框架之上Q但需要struts的jar?br />
要做的是在web.xml文g中配|一个监?/p>
其中context-param是可选的Q?WEB-INF/menu-config.xml是struts-menu的默认配|文件的路径Q如果要改变文g的名字或路径要改写context-param
2 menu-config.xml
需要配|菜单的昄样式Q如下:
3 dynamicmenu.jsp
menu的数据结?br /> MenuRepositoryQ包含了所有的菜单数据Q它的里面保存菜单的形式是二l表的Ş式。一个菜单就是一条记?br /> MenuComponentQ?代表一个菜单,也就是二l表中的一条记录,父菜单和子菜单在q里区分Q如果它的getParentQ)Ҏq回为空Q那么它是菜单Q它下面的子菜单讄它ؓ父菜单方法:setParentQMenuComponent parentQ,该菜单的下面q可以有子菜单?br /> 最后要做的是把所有设|好的菜单项Q用repository.addMenu(mc) Ҏ加入到repository中。那么一个联菜单就做好了,CZ代码Q?/p>
下面是菜单的昄Q?/p>
上面代码的含义:
取得菜单的显C样式,讄lrepositoryQ也是上面menu-config.xml中设|的八种样式?/p>
pageContext.setAttribute("net.sf.navigator.menu.MENU_REPOSITORY",repository);
把菜单装入到.jsp文g中,赋值给属?net.sf.navigator.menu.MENU_REPOSITORY" 然后jsp的menu标签׃从该属性中取得菜单的显C样式和数据
=================
使用Struts Menu实现权限理
Struts Menu也是Matt Raible的作品,我以前一直在找能够在Java里面指定实现面上树形菜单和下拉菜单的东西,我去q找C个JS的东西,可以从XML文g中读取结构,我用XSLT来生成显C的菜单Q后来感觉不灉|Q也没有用到目上,2004q?1月开始接触AppFuseQ发现里面有个Struts MenuQ从例子看v来外观还不错Q用hQ发现更不错Q可以在配置文g中指定那些角色可以看到当前的链接Q如果roles中没有指定的角色q入pȝ后,则自动隐藏。我在去q的一个小目用了一下,发现q行Q至不用我把逻辑嵌入C堆JS里面?br />
因ؓ今年上半q要对以前的一个系l进行升U,要根据用h者角色的权限把一些菜单隐藏v来,如果使用Struts Menu的roles的话Q则角色是写d代码里面的,是"编?(hardcode)Q而且q里的角色是Application Server上配|的Q在Tomcat上配|还简单,在WebLogic{大型的服务器程序上配置Q必M用他们提供的Console软gQ否则,要自己写好几个文Ӟ比较J琐Q而且q些角色是在安装是就指定的,如果用户以后x加新的角色名字,q要修改应用服务器的配置文gQ不是手工Q还是代码处理)?br />
如果你的pȝ负责处理权限Q如生成用户、角Ԍq要艌Ӏ用h定有操作哪些模块的哪些操作,一个系l很可能有几十个或者上百个角色Q往极端情况LQ呵呵)Q那么如果能够动态的控制昄哪些菜单Ҏ我们pȝ中必解决的问题Q而Struts Menu完全胜Qq样的要求,具体实现可以参看Struts Menu的下载文件中的文档,需要重点看的是http://demo.raibledesigns.com/struts-menu/dynamicMenu.jsp(动态构单结?和http://struts-menu.sourceforge.net/security.htmlQ这文章我视而不见,以ؓ没有用处Q谢谢倦兔的提醒,^_^Q。这两篇文章的用法是独立的,q不一定都要实玎ͼ如果你的菜单Ҏ固定的,短期不会有所变动Q那么可以写d配置文g中,然后用第二篇文章中说的那P写一个类Q实现接口PermissionsAdapterQisAllowedҎ中传入菜单项的名字,然后军_是否昄该项菜单Q?br />
String[] menus = request.getParameterValues("menuNames");
注释QmenuNames是从数据库中d的记录的集合Q数l)Q你也可以用其他机构Q?br />
然后攑օ使用request.setAttribute("menuNames", String[] 变量) 攑օrequest中?br />
PermissionsAdapter permissions = new SimplePermissionsAdapter(menus);//menus是菜单名字的数组
request.getSession().setAttribute("YourAdapter", permissions);} //"YourAdapter"随便L名字Q?br />