一、从1.x升级到2.x需要做以下事情:
1、改变你的taglib声明中的uri。
<% at taglib uri="" prefix="menu" %>
2、改变
3、改变你的menu-config.xml文件,使用新的包名"net.sf.navigator." 。
二、快速开始:
1、下载最新的struts-menu版本;
2、解包到本地目录;
3、下载tomcat或者其它servlet容器;
4、把struts-menu.war包放入tomcat安装目录的wabapps目录下,并重启tomcat服务。
5、打开htpp://localhost:8080/struts-menu/
三、把struts menu整合到你的应用程序中:
struts menu能够被轻易的整合到你的struts应用程序中,它也可以整合到一个非struts的应用程序中,但是我不喜欢这样做,所以在此没有提供相应的教程。这里将一步步的带你整合这个标签库。
你需要把struts-menu.jar放到你的web-inf/lib目录下。然后使用uri标签声明你的jsp文件中想使用的这个标签库。
如果使用struts menu 2.1,你还需要 jakarta's standard tag library jar包放入你的web-inf/lib目录下。下载地址:,这个文件包括例程war包文件和二进制发布包。
1、放入struts-menu.jar包到你的应用程序的web-inf/lib目录中。
2、在你的struts-config.xml文件中加入plug-in设置。
3、你将需要在你的应用程序的/web-inf/menu-config.xml文件中定义你的菜单,这里提供一个简单的片断:
(译注:其实到此步即可在你的jsp文件中添加相应的菜单了,只不过是没有结合velocity。在menu-config.xml文件的头部可以定义多个displayer,每个displayer都有name和type属性,name属性与jsp文件中menu:usemenudisplayer标签的name属性相对应,即表明使用何种样式,具体的样式定义便在type属性中定义,type属性中是一个class。在menu-config.xml文件中的菜单定义中的name属性则与jsp文件中的menu:displaymenu标签的name属性相对应。)
使用定制的velocity模版实施你的菜单,你需要整合velocity到你的web应用程序中。如果需要这样做的话,请完成下面的步骤:
1、确定你的menu-config.xml文件有“velocity”的displayer定义:
2、加入velocity的jars包到你的web-inf/lib目录中,下载velocity-1.4-rc1.jar()和velocity-tools-view-1.0.jar()。
3、加入globalmacros.vm(*checkout*/struts-menu/navigator/web/web-inf/classes/globalmacros.vm?content-type=text/plain&rev=1.1(右键另存为))到你的web-inf/lib目录中。
4、改变你的jsp文件中displayer的值为“velocity”,“config”属性指向一个文件(如config="/templates/tabs.html")或者如果tabs.htm在你的web-inf/classes目录中的话,则可设config="tabs.html"。
这里提供了一些使用velocity的displayer例子,可在sample application()中查看。它总是在你的菜单需要的时候显示css,javascript和图像文件。下面有一些在当前的struts menu中用到的velocity模版的例子的链接:
coolmenus: demo(),
template()
nicetabs: demo, template
tabs: demo, template
xtree: demo, template
所有相关的有用的文件如果你需要的话都可以在下面的站点上下载:
images ()
stylesheets ()
scripts ()
templates ()
更多的基于roles的显示/隐藏菜单的信息,请查看faqs()。
四、在struts之外使用struts menu:
在2.2版中,menu repository能够使用menucontextlistener载入:
或者如果你使用spring,甚至更容易。仅仅需要加入下面的部分到你的applicationcontext.xml文件中:
感谢dan luputan提供menuloader类的源代码。
五、从源文件编译:
要从源文件编译这个项目,执行下面的步骤:
1、下载并安装maven();
2、创建一个环境变量maven_home指出你的maven的安装目录,然后添加$maven_home/bin到你的path变量中;
3、操纵这个目录你可以扩展源代码,执行“maven.jar”创建target/struts-menu.jar。
要展开struts-menu例程,需要下面的步骤:
1、下载和安装tomcat;
2、创建一个环境变量catalina_home指出你的tomcat的安装目录;
3、执行“maven deploy”把应用程序展开到tomcat中;
4、打开在你喜爱的浏览器中。
如果你喜欢使用eclipse开发项目,请参考此份开发向导()。
struts 2为大家提供了不少常用的很酷的表单标志,简化了我们程序员的工作。不过,由于这些都是新标志,大家可能在使用上还存在不少疑问。本文将就朋友们的回复、留言或email上的问题,分别对这些酷标志进行讲述。
struts 2的表单标志在输出(render)html时,使用了模板的概念,增加了复杂性(因为它不像struts 1.x的表单标志,它通常都是一个标志对应html的一个元素),因此大家在使用时,需要一些技巧:
下面我将分别对这些标志进行讲述:
大家对
答案其实很简单,只需要将其“value”属性设为你的要选中的值,如以代码所示:
分布运行应用程序,在浏览器中键入:,出现如下图所示页面:
清单2 checkboxlist.jsp页面
大家看struts 2的showcase的例子,
很多朋友问:“上面的‘list’属性只有两个值,如果我有三个或更多的值,‘doublelist’属性应该如何设定呢?”
我建议的做法是先定义一个map类型的对象,键为“list”的集合,值则为“doublelist”的集合,然后“doublelist”的ognl写成“#mymap[top]”,如以下代码所示:
分布运行应用程序,在浏览器中键入:,出现如下图所示页面:
清单5 doubleselect.jsp页面
这个标志可能大家不常用,不过本人认为它还是挺有用的。在使用struts 1.x时,因为跳转通常是用forward(而不是redirect)实现的,所以当用户完成请求后,按“f5”刷新页面时,就会重新提交上次的请求,这样经常会出错。要解决这个问题,
在页面加载时,
同时,将guid放到会话(session)中;在执行action之前,“token”拦截器将会话token与请求token比较,如果两者相同,则将会话中的token删除并往下执行,否则向actionerrors加入错误信息。如此一来,如果用户通过某种手段提交了两次相同的请求,两个token就会不同。
首先看一下action的代码:
以上代码一目了然,再看看jsp的写法:
jsp也很简单,就是加入
以上xml片段值注意的是加入了“token”拦截器和“invalid.token”结果,因为“token”拦截器在会话token与请求token不一致时,将会直接返回“invalid.token”结果。
发布运行应用程序,在浏览器中键入:,出现如下图所示页面:
清单10 正常显示的token.jsp页面
随便填点东西并提交页面,一切正常返回以上页面,然后按“f5”刷新页面,在弹出的对话框中点击“retry”,出现如下图所示页面:
清单11 重复提交出错显示
这几个标志的使用相对简单,所以我想小举一例即可,以下是jsp的代码:
发布运行应用程序,在浏览器中键入:,出现如下图所示页面:
清单13 其它表单标志页面
struts 2在标志上的确比struts 1.x丰富了许多,同时模板机制也给程序员带来不少方便(如果你不太喜欢个性化的风格)。另外,struts 2还有一些ajax(如等)的标志和非表单的ui标志(如等),我会在以后的文章中讲述其使用。
struts2提供了对不同种类返回结果的支持,常见的有jsp,freemarker,velocity等。
struts2支持的不同类型的返回结果为:
名字 |
说明 |
chain result |
用来处理action链 |
dispatcher result |
用来转向页面,通常处理jsp |
freemarker result |
处理freemarker模板 |
httpheader result |
用来控制特殊的http行为 |
redirect result |
重定向到一个url |
redirect action result |
重定向到一个action |
stream result |
向浏览器发送inputsream对象,通常用来处理文件下载 |
velocity result |
处理velocity模板 |
xls result |
处理xml/xlst模板 |
plaintext result |
显示原始文件内容,例如文件源代码 |
s2plugins:tiles result |
结合tile使用 |
另外第三方的result类型还包括jasperreports plugin,专门用来处理jasperreport类型的报表输出。
在struts-default.xml文件中已经有了对于所有类型result的定义:
class="com.opensymphony.xwork2.actionchainresult"/>
class="org.apache.struts2.dispatcher.servletdispatcherresult"
default="true"/>
class="org.apache.struts2.views.freemarker.freemarkerresult"/>
class="org.apache.struts2.dispatcher.httpheaderresult"/>
class="org.apache.struts2.dispatcher.servletredirectresult"/>
class="org.apache.struts2.dispatcher.servletactionredirectresult"/>
class="org.apache.struts2.dispatcher.streamresult"/>
class="org.apache.struts2.dispatcher.velocityresult"/>
class="org.apache.struts2.views.xslt.xsltresult"/>
class="org.apache.struts2.dispatcher.plaintextresult" />
class="org.apache.struts2.dispatcher.servletactionredirectresult"/>
class="org.apache.struts2.dispatcher.plaintextresult" />
从上述代码中可以看出在不指定result类型的时候使用dispatcher类型。
定义一个result值,
/thankyou.jsp
由于type默认值是dispatcher,所以这里不需要定义,另外name的默认值为success所以这里也不需要定义。
上述代码可以简写为:
/thankyou.jsp
另外location参数也可以直接卸载result标签内部,所以上述代码的最简单的写法为:
我们也可以定义多个不同的result
上述代码的含义为,名字为hello的action有三个返回结果,并且都是dispatcher类型(默认类型),这三个返回值的名字分别为success(默认值),error,input,对应的页面的路径分别为/hello/result.jsp,/hello/error.jsp,/hello/input.jsp。
有些时候我们需要一个定义在全局的result,这个时候我们可以在package内部定义全局的result,例如:
动态返回结果
有些时候,只有当action执行完璧的时候我们才知道要返回哪个结果,这个时候我们可以在action内部定义一个属性,这个属性用来存储action执行完璧之后的result值,例如:
private string nextaction;
public string getnextaction() {
return nextaction;
}
在strutx.xml配置文件中,我们可以使用${nextaction}来引用到action中的属性,通过${nextaction}表示的内容来动态的返回结果,例如:
上述action的execute方法返回next的时候,还需要根据nextaction的属性来判断具体定位到哪个action。
在strutx.xml配置文件中,我们可以使用method=""来设置调用类的哪个方法,这样就可以在一个java类中使用不同的方法来实现不同的功能,就无需每个功能写一类了,例如:
表达式语言主要有以下几大好处:
避免(mytype) request.getattribute()和mybean.getmyproperty()之类的语句,使页面更简洁;
支持运算符(如 -*/),比普通的标志具有更高的自由度和更强的功能;
简单明了地表达代码逻辑,使用代码更可读与便于维护。
struts 2中的表达式语言
struts 2支持以下几种表达式语言:
ognl(object-graph navigation language),可以方便地操作对象属性的开源表达式语言;
jstl(jsp standard tag library),jsp 2.0集成的标准的表达式语言;
groovy,基于java平台的动态语言,它具有时下比较流行的动态语言(如python、ruby和smarttalk等)的一些起特性;
velocity,严格来说不是表达式语言,它是一种基于java的模板匹配引擎,具说其性能要比jsp好。
struts 2默认的表达式语言是ognl,原因是它相对其它表达式语言具有下面几大优势:
支持对象方法调用,如xxx.dosomespecial();
支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.string@format('foo %s', 'bar')或@tutorial.myconstant@app_name;
支持赋值操作和表达式串联,如price=100, discount=0.8, calculateprice(),这个表达式会返回80;
访问ognl上下文(ognl context)和actioncontext;
操作集合对象。
ognl的用法
ognl是通常要结合struts 2的标志一起使用,如
首先新建名为struts2_ognl的web工程,配置开发环境。之前很多朋友在使用struts 2的过程中都遇到乱码问题。当然乱码问题由来已久,而且涉及多方面的知识,所以并非三言两语可以说明白,而且互联网上也已经有很多这方便的文章,大家可以google一下。不过,如果你在开发的过程,多注意一下,避免乱码问题也不难。乱码多数是由于编码与解码所使用的方式不同造成的,所以我建议大家将编码方式都设为“utf-8”,如<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8" %>。另外,在配置web.xml时使用actioncontextcleanup过滤器(filter),如下面代码所示:
xmlns:xsi=""
xsi:schemalocation=" ">
org.apache.struts2.dispatcher.actioncontextcleanup
org.apache.struts2.dispatcher.filterdispatcher
清单1 webcontent/web-inf/web.xml
“#”主要有三种用途:
访问ognl上下文和action上下文,#相当于actioncontext.getcontext();下表有几个actioncontext中有用的属性: 名称 作用 例子
parameters 包含当前http请求参数的map #parameters.id[0]作用相当于request.getparameter("id")
request 包含当前httpservletrequest的属性(attribute)的map #request.username相当于request.getattribute("username")
session 包含当前httpsession的属性(attribute)的map #session.username相当于session.getattribute("username")
application 包含当前应用的servletcontext的属性(attribute)的map #application.username相当于application.getattribute("username")
attr 用于按request > session > application顺序访问其属性(attribute) #attr.username相当于按顺序在以上三个范围(scope)内读取username属性,直到找到为止
用于过滤和投影(projecting)集合,如books.{?#this.price<100};
构造map,如#{'foo1':'bar1', 'foo2':'bar2'}。
下面让我们它们的具体写法,首先是action类代码:
package tutorial.action;
import java.util.linkedlist;
import java.util.list;
import java.util.map;
import javax.servlet.servletcontext;
import javax.servlet.http.httpservletrequest;
import org.apache.struts2.interceptor.servletrequestaware;
import org.apache.struts2.interceptor.sessionaware;
import org.apache.struts2.util.servletcontextaware;
import tutorial.model.book;
import com.opensymphony.xwork2.actionsupport;
public class ognlaction extends actionsupport implements servletrequestaware, sessionaware, servletcontextaware {
private static final long serialversionuid = 1l;
private httpservletrequest request;
private map
private servletcontext application;
private list
public void setservletrequest(httpservletrequest request) {
this.request = request;
}
@suppresswarnings("unchecked")
public void setsession(map session) {
this.session = session;
}
public void setservletcontext(servletcontext application) {
this.application = application;
}
public list
return books;
}
@override
public string execute() {
request.setattribute("username", "max from request");
session.put("username", "max from session");
application.setattribute("username", "max from application");
books = new linkedlist
books.add(new book("978-0735619678", "code complete, second edition", 32.99));
books.add(new book("978-0596007867", "the art of project management", 35.96));
books.add(new book("978-0201633610", "design patterns: elements of reusable object-oriented software", 43.19));
books.add(new book("978-0596527341", "information architecture for the world wide web: designing large-scale web sites", 25.19));
books.add(new book("978-0735605350", "software estimation: demystifying the black art", 25.19));
return success;
}
}清单2 src/tutorial/action/ognlaction.java
以上代码分别在request、session和application的范围内添加“username”属性,然后再在jsp页面使用ognl将其取回。我还创建了book对象的列表用于演示“用于过滤和投影(projecting)集合”的功能,至于book的代码大家可以在我前一文章《在struts 2中实现crud》看到。
下面是ognl.jsp的代码,内容如下:
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
http://www.w3.org/1999/xhtml">
parameters:
request.username:
session.username:
application.username:
attr.username:
books more than $35
the price of "code complete, second edition" is:
the value of key "foo1" is
最后是struts 2的配置文件struts.xml,内容如下:
"-//apache software foundation//dtd struts configuration 2.0//en"
"">
发布运行应用程序,结果如下所示:
清单5 示例运行结果1
“%”符号的用途是在标志的属性为字符串类型时,计算ognl表达式的值。例如在ognl.jsp中加入以下代码:
清单7 示例运行结果2
“$”有两个主要的用途
用于在国际化资源文件中,引用ognl表达式,例子请参考《在struts 2.0中国际化(i18n)您的应用程序》
在struts 2配置文件中,引用ognl表达式,如
总结
ognl是一种功能很大的表达式语言,熟悉它可以使我们的开发变得更快捷。
true
或者在页面中<%@page language="java" deferredsyntaxallowedasliteral="true" %>
>
办法3 :不用 jsp2.1 el
>
>*.jsp
>true
>
>
我现在的疑问
在一个页面中采用两个 el 引擎,是否会对性能造成一定影响?
较小。
struts2与struts1struts2与struts1对比
action 类:
struts1要求action类继承一个抽象基类。struts1的一个普遍问题是使用抽象类编程而不是接口。
struts 2 action类可以实现一个action接口,也可实现其他接口,使可选和定制的服务成为可能。struts2提供一
个actionsupport基类去实现 常用的接口。action接口不是必须的,任何有execute标识的pojo对象都可以用作
struts2的action对象。
线程模式:
struts1 action是单例模式并且必须是线程安全的,因为仅有action的一个实例来处理所有的请求。单例策略限制
了struts1 action能作的事,并且要在开发时特别小心。action资源必须是线程安全的或同步的。
struts2 action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生
许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
servlet 依赖:
struts1 action 依赖于servlet api ,因为当一个action被调用时httpservletrequest 和 httpservletresponse
被传递给execute方法。
struts 2 action不依赖于容器,允许action脱离容器单独被测试。如果需要,struts2 action仍然可以访问初始的
request和response。但是,其他的元素减少或者消除了直接访问httpservetrequest 和 httpservletresponse的必要
性。
可测性:
测试struts1 action的一个主要问题是execute方法暴露了servlet api(这使得测试要依赖于容器)。一个第三方
扩展--struts testcase--提供了一套struts1的模拟对象(来进行测试)。
struts 2 action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。
捕获输入:
struts1 使用actionform对象捕获输入。所有的actionform必须继承一个基类。因为其他javabean不能用作
actionform,开发者经常创建多余的类捕获输入。动态bean(dynabeans)可以作为创建传统actionform的选择,但是
,开发者可能是在重新描述(创建)已经存在的javabean(仍然会导致有冗余的javabean)。
struts 2直接使用action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的
rich对象类型。action属性能够通过 web页面上的taglibs访问。struts2也支持actionform模式。rich对象类型,包
括业务对象,能够用作输入/输出对象。这种 modeldriven 特性简化了taglib对pojo输入对象的引用。
表达式语言:
struts1 整合了jstl,因此使用jstl el。这种el有基本对象图遍历,但是对集合和索引属性的支持很弱。
struts2可以使用jstl,但是也支持一个更强大和灵活的表达式语言--"object graph notation language"
(ognl).
绑定值到页面(view):
struts 1使用标准jsp机制把对象绑定到页面中来访问。
struts 2 使用 "valuestack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。
valuestack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。
类型转换:
struts 1 actionform 属性通常都是string类型。struts1使用commons-beanutils进行类型转换。每个类一个转换
器,对每一个实例来说是不可配置的。
struts2 使用ognl进行类型转换。提供基本和常用对象的转换器。
校验:
struts 1支持在actionform的validate方法中手动校验,或者通过commons validator的扩展来校验。同一个类可以
有不同的校验内容,但不能校验子对象。
struts2支持通过validate方法和xwork校验框架来进行校验。xwork校验框架使用为属性类类型定义的校验和内容校
验,来支持chain校验子属性
action执行的控制:
struts1支持每一个模块有单独的request processors(生命周期),但是模块中的所有action必须共享相同的生命
周期。
struts2支持通过拦截器堆栈(interceptor stacks)为每一个action创建不同的生命周期。堆栈能够根据需要和不
同的action一起使用。
--------------------------------------------------------------------------------
注释struts.action.extension
the url extension to use to determine if the request is meant for a struts action
用url扩展名来确定是否这个请求是被用作struts action,其实也就是设置 action的后缀,例如
login.do的'do'字。
struts.configuration
the org.apache.struts2.config.configuration implementation class
org.apache.struts2.config.configuration接口名
struts.configuration.files
a list of configuration files automatically loaded by struts
struts自动加载的一个配置文件列表
struts.configuration.xml.reload
whether to reload the xml configuration or not
是否加载xml配置(true,false)
struts.continuations.package
the package containing actions that use rife continuations
含有actions的完整连续的package名称
struts.custom.i18n.resources
location of additional localization properties files to load
加载附加的国际化属性文件(不包含.properties后缀)
struts.custom.properties
location of additional configuration properties files to load
加载附加的配置文件的位置
struts.devmode
whether struts is in development mode or not
是否为struts开发模式
struts.dispatcher.parametersworkaround
whether to use a servlet request parameter workaround necessary for some versions of weblogic
(某些版本的weblogic专用)是否使用一个servlet请求参数工作区(parametersworkaround)
struts.enable.dynamicmethodinvocation
allows one to disable dynamic method invocation from the url
允许动态方法调用
struts.freemarker.manager.classname
the org.apache.struts2.views.freemarker.freemarkermanager implementation class
org.apache.struts2.views.freemarker.freemarkermanager接口名
struts.i18n.encoding
the encoding to use for localization messages
国际化信息内码
struts.i18n.reload
whether the localization messages should automatically be reloaded
是否国际化信息自动加载
struts.locale
the default locale for the struts application
默认的国际化地区信息
struts.mapper.class
the org.apache.struts2.dispatcher.mapper.actionmapper implementation class
org.apache.struts2.dispatcher.mapper.actionmapper接口
struts.multipart.maxsize
the maximize size of a multipart request (file upload)
multipart请求信息的最大尺寸(文件上传用)
struts.multipart.parser
the org.apache.struts2.dispatcher.multipart.multipartrequest parser implementation for a
multipart request (file upload)
专为multipart请求信息使用的org.apache.struts2.dispatcher.multipart.multipartrequest解析器接口
(文件上传用)
struts.multipart.savedir
the directory to use for storing uploaded files
设置存储上传文件的目录夹
struts.objectfactory
the com.opensymphony.xwork2.objectfactory implementation class
com.opensymphony.xwork2.objectfactory接口(spring)
struts.objectfactory.spring.autowire
whether spring should autowire or not
是否自动绑定spring
struts.objectfactory.spring.useclasscache
whether spring should use its class cache or not
是否spring应该使用自身的cache
struts.objecttypedeterminer
the com.opensymphony.xwork2.util.objecttypedeterminer implementation class
com.opensymphony.xwork2.util.objecttypedeterminer接口
struts.serve.static.browsercache
if static content served by the struts filter should set browser caching header properties or
not
是否struts过滤器中提供的静态内容应该被浏览器缓存在头部属性中
struts.serve.static
whether the struts filter should serve static content or not
是否struts过滤器应该提供静态内容
struts.tag.altsyntax
whether to use the alterative syntax for the tags or not
是否可以用替代的语法替代tags
struts.ui.templatedir
the directory containing ui templates
ui templates的目录夹
struts.ui.theme
the default ui template theme
默认的ui template主题
struts.url.http.port
the http port used by struts urls
设置http端口
struts.url.https.port
the https port used by struts urls
设置https端口
struts.url.includeparams
the default includeparams method to generate struts urls
在url中产生 默认的includeparams
struts.velocity.configfile
the velocity configuration file path
velocity配置文件路径
struts.velocity.contexts
list of velocity context names
velocity的context列表
struts.velocity.manager.classname
org.apache.struts2.views.velocity.velocitymanager implementation class
org.apache.struts2.views.velocity.velocitymanager接口名
struts.velocity.toolboxlocation
the location of the velocity toolbox
velocity工具盒的位置
struts.xslt.nocache
whether or not xslt templates should not be cached
是否xslt模版应该被缓存
在struts2中,action中的getxxx()只在服务器启动时执行一次,一刷新页面显示的数据内容全都没了,这种问题的解
决办法是:
在web.xml中配置struts2.0时,
把/*改成*.ation就ok了
一、struts2配置文件
struts2相关的配置文件有web.xml,struts.xml,struts.properties,
struts-default.xml,velocity.properties,struts-default.vm。其中web.xml,struts.xml是必须的,其它的配置
文件可选择。它们在web应用中的功能如下:
web.xml:包含所有必须的框架组件的web部署描述符。
struts.xml:配置包含result/view类型、action映射、拦截器等的struts2的主要配置文件。
struts.properties:配置struts2的框架属性。
struts-default.xml:在文件在struts-action-x.x.jar中,该文件是应该被包含在struts.xml中的缺省配置。
welocity.properties:重写了velocity的配置文件。
struts-default.vm:相对于velocity的缺省配置。
二、struts2配置元素
struts2核心的配置文件是缺省的struts.xml。
必要的时候,缺省的配置文件可以包含其它的配置文件;struts文件可以放入jar中,并自动插入应用程序,这样每个
模块可以包含自己的配置文件并自动配置。在freemarker和velocity模块中,模板也能从classpath中加载,所以整个
模块可以作为一个简单的jar文件被包含。
struts.xml配置文件可以包含interceptor、action类和results。
struts.xml配置元素说明:
1、packages
packages:packages把actions、results、results types、interceptors
和interceptor-stacks组装到一个逻辑单元中,从概念上讲,packages就像一个对象,可以被其它子包从写,而且可
以拥有自己独立的部分。
name属性是packages的必填元素,它作为一个关键字被后边的包引用;extends元素是可选的,它允许包扩展一个和多
个前边定义的包。注意,
struts.xml文件是至上而下处理的,所有被扩展的包,需要在扩展包前定义。
abstract元素是可选的,它可以申明一个不包含actions的配置文件。
2、namespace
namespace元素把actions细分到逻辑模块,每一个namespace都有自己的
前缀(prefix),namespace避免了action之间的名字冲突,当前缀出现在uri中时,这些标签都是名字空间感知的(
“namespace aware”),所以这些namespace prefix不必嵌入到表单或连接中。
default的namespace是一个空字符串“”,如果在指定的配置文件中,没有找到action,缺省的namespace也会被查找
。local/global策略允许应用程序在action “extends”元素层次结构之外,有全局的action配置。缺省的namespace
也可以不在package中申明。
namespace prefix可以注册为java的申明式安全,以确保授权的用户才能访问namespace的资源。
root namespace(“/”)也被支持,root就是当直接请求context path的时候的namespace。
[个人理解:namespace的用法就像struts1.x中的path一样,只不过它在package中什么路径,而在action中申明
action名子罢了]
3、include
include元素使得框架能应用“divide and conquer”来配置文件。被include
的每个配置文件必须和struts.xml有一样的格式,一个大的项目可以采用这样方式来组织程序模块。
include元素也可以和package交替出现,框架将按照顺序加载配置文件。
4、interceptor configuration
interceptor允许应用程序在action方法执行前后定义执行代码,
interceptor在应用程序开发中十分重要,对于interceptor有许多用例,如validation, property population,
security, logging, 和profiling。
interceptor被定义为一个java类,interceptor也可以组装成interceptor-stack,他们将按照定义的顺序执行。
在struts-default.xml中定义了一些缺省的interceptor-stack,以便框架能很好地运行。
5、action
action是框架的“工作单元”。action可以指定一个interceptor-stack、
一序列的return type和一序列的异常处理,但只有name属性是必须的。
--------------------------------------------------------------------------------
struts2.0简单的例子今天在apache网站上无意中看到了struts项目2.0.8正式发布了,怀着欣喜的心情我下载了
stuts2.0.8完整包。 struts2.0.8是struts项目和webwork2.2项目的合并版本,集成了两大流行mvc框架的优点,对
struts框架来说是一个大的提升,同时也更大程度地简化了开发人员的开发过程。我简单地研究了一下这个新版本,
现在给大家介绍一个入门级的小例子,希望能对学习这个新版本的朋友有点帮助。
这个例子完成了一次url调用返回结果页面的过程。
首先,要从apache网站上下载struts2.0.8的完整包(可以从这里下载:
),解压后需要找到下列几个文
件:
commons-logging-1.0.4.jar
freemarker-2.3.8.jar
ognl-2.6.11.jar
struts2-core-2.0.8.jar
xwork-2.0.3.jar
然后,我们就开始做第一个例子,我们就使用经典的“helloworld”的名字吧!
1. 制作目录结构
如下图所示:
stuts2是web应用的根目录。
2. 拷贝引用文件
将上面列举的jar文件拷贝到步骤1中制作的目录struts2\web-inf\lib中。
3. 制作jsp文件helloworld.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
package example;
/** *//**
* set welcome message.
*/
import com.opensymphony.xwork2.actionsupport;
public class helloworld extends actionsupport ...{
public static final string message = "struts is up and running ...";
public string execute() throws exception ...{
setmessage(message);
return success;
}
private string message;
public void setmessage(string message)...{
this.message = message;
}
public string getmessage() ...{
return message;
}
}
使用下面的命令编译这个java文件:
set classpath=yourdirectory\xwork-2.0-beta-1.jar
javac helloworld.java
将编译后的helloworld.class文件拷贝到步骤1中制作的目录struts2\web-inf\classes\example中。
5.制作web应用的描述文件web.xml
xmlns:xsi=""
xsi:schemalocation=" -
app_2_4.xsd"
version="2.4">
将该文件拷贝到步骤1中制作的目录struts2\web-inf中。
6.制作manifest.mf文件(从其它地方随便找一个即可)
将该文件拷贝到步骤1中制作的目录struts2\meta-inf中。
7.制作struts配置文件struts.xml和struts.properties
struts.xml文件:
"-//apache software foundation//dtd struts configuration 2.0//en"
"">
struts.properties文件:
struts.devmode = true
struts.enable.dynamicmethodinvocation = false
将这两个文件拷贝到步骤1中制作的目录struts2\ web-inf\classes中。
好了整个例子的文件我们都搞定了。
最后,你可以将制作好的web应用struts2拷贝到tomcat下运行。
访问如果能够看到页面上的“struts is up and
running ...”提示信息说明你的例子是正确的。
--------------------------------------------------------------------------------
struts2.0 中文乱码1.为了能正确显示 jsp页面直接写的中文 在jsp页面正确显示添加下面字符设置。
<%@ page contenttype="text/html;charset=gbk"%>
2.为了解决form提交到action中的中文参数乱码问题,在src\struts.properties文件添加
struts.i18n.encoding=gbk
或
在struts2-core-2.0.8.jar 包中路径为struts2-core-2.0.8\org\apache\struts2 有一个default.properties
文件
把struts.i18n.encoding=utf-8改为struts.i18n.encoding=gbk 或者在struts.xml里面改
这样在action中取到的参数不用自己手工转码 了。
--------------------------------------------------------------------------------
struts 2.0的标志(tag)介绍介绍常用标志前,我想先从总体上,对struts 1.x与struts 2.0的标志库(tag
library)作比较。 struts 1.x struts 2.0
分类 将标志库按功能分成html、tiles、logic和bean等几部分 严格上来说,没有分类,所有标志都在uri为
“/struts-tags”命名空间下,不过,我们可以从功能上将其分为两大类:非ui标志和ui标志
表达式语言(expression languages) 不支持嵌入语言(el) ognl、jstl、groovy和velcity
以上表格,纯属个人总结,如有所不足或错误,请不吝指正
好了,我要开始介绍“常用”(这里所谓的“常用”,是指在已往工作中使用struts里经常用到的)的标志了。
要在jsp中使用struts 2.0标志,先要指明标志的引入。通过在jsp的代码的顶部加入以下代码可以做到这点。
< prefix="s" uri="/struts-tags" %>
非ui标志
if、elseif和else
描述:
执行基本的条件流转。
参数:
名称 必需 默认 类型 描述 备注
test 是 boolean 决定标志里内容是否显示的表达式 else标志没有这个参数
id 否 object/string 用来标识元素的id。在ui和表单中为html的id属性
例子:
<%@ page contenttype="text/html; charset=utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
iterator
描述:
用于遍历集合(java.util.collection)或枚举值(java.util.iterator)。
参数:
名称 必需 默认 类型 描述
status 否 string 如果设置此参数,一个iteratorstatus的实例将会压入每个遍历的堆栈
value 否 object/string 要遍历的可枚举的(iteratable)数据源,或者将放入新列表(list)的对象
id 否 object/string 用来标识元素的id。在ui和表单中为html的id属性
例子:
<%@ page contenttype="text/html; charset=utf-8" %>
<%@ page import="java.util.list" %>
<%@ page import="java.util.arraylist" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
list list = new arraylist();
list.add("max");
list.add("scott");
list.add("jeffry");
list.add("joe");
list.add("kelvin");
request.setattribute("names", list);
%>
i18n
描述:
加载资源包到值堆栈。它可以允许text标志访问任何资源包的信息,而不只当前action相关联的资源包。
参数:
名称 必需 默认 类型 描述
value 是 object/string 资源包的类路径(如com.xxxx.resources.appmsg)
id 否 object/string 用来标识元素的id。在ui和表单中为html的id属性
例子:
helloworld=hello wrold!
例3 classes\ applicationmessages.properties
<%@ page contenttype="text/html; charset=utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
include
描述:
包含一个servlet的输出(servlet或jsp的页面)。
参数:
名称 必需 默认 类型 描述
value 是 string 要包含的jsp或servlet
id 否 object/string 用来标识元素的id。在ui和表单中为html的id属性
例子:
<%@ page contenttype="text/html; charset=utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
param
描述:
为其他标签提供参数,比如include标签和bean标签. 参数的name属性是可选的,如果提供,会调用component的方法
addparameter(string, object), 如果不提供,则外层嵌套标签必须实现unnamedparametric接口(如texttag)。
value的提供有两种方式,通过value属性或者标签中间的text,不同之处我们看一下例子:
blue
(a)参数值会以string的格式放入statck.
(b)该值会以java.lang.object的格式放入statck.
参数:
名称 必需 默认 类型 描述
name 否 string 参数名
value 否 string value表达式
id 否 object/string 用来标识元素的id。在ui和表单中为html的id属性
例子:
请参考例4。
set
描述:
set标签赋予变量一个特定范围内的值。当希望给一个变量赋一个复杂的表达式,每次访问该变量而不是复杂的表达式
时用到。其在两种情况下非常有用: 复杂的表达式很耗时 (性能提升) 或者很难理解 (代码可读性提高)。
参数:
名称 必需 默认 类型 描述
name 是 string 变量名字
scope 否 string 变量作用域,可以为application, session, request, page, 或action.
value 否 object/string 将会赋给变量的值
id 否 object/string 用来标识元素的id。在ui和表单中为html的id属性
例子:
请参考例1。
text
描述:
支持国际化信息的标签。国际化信息必须放在一个和当前action同名的resource bundle中,如果没有找到相应
message,tag body将被当作默认message,如果没有tag body,message的name会被作为默认message。
参数:
名称 必需 默认 类型 描述
name 是 string 资源属性的名字
id 否 object/string 用来标识元素的id。在ui和表单中为html的id属性
例子:
请参考例3。
url
描述:
该标签用于创建url,可以通过"param"标签提供request参数。
当includeparams的值时'all'或者'get', param标签中定义的参数将有优先权,也就是说其会覆盖其他同名参数的值
。
参数: 略
例子:
<%@ page contenttype="text/html; charset=utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
property
描述:
得到'value'的属性,如果value没提供,默认为堆栈顶端的元素。
参数:
名称 必需 默认 类型 描述
default 否 string 如果属性是null则显示的default值
escape 否 true booelean 是否escape html
value 否 栈顶 object 要显示的值
id 否 object/string 用来标识元素的id。在ui和表单中为html的id属性
例子:
请参考例2。
--------------------------------------------------------------------------------
ui标志ui标志又可以分为表单ui和非表单ui两部分。表单ui部分基本与struts 1.x相同,都是对html表单元素的包装
。不过,struts 2.0加了几个我们经常在项目中用到的控件如:datepicker、doubleselect、timepicker、
optiontransferselect等。因为这些标志很多都经常用到,而且参数也很多,要在一篇文章详细说明并非易事。
需要深入了解这些标志的朋友,可以到以下查看以下网址:
webwork2文档中文化计划(中文)
tag developers guide(英文)
本文有相当的内容也来自这两处。
--------------------------------------------------------------------------------
struts 2.0的action讲解http://www.blogjava.net/max/archive/2006/10/25/77157.html
当请求helloworld.action发生时,struts运行时(runtime)根据struts.xml里的action映射集(mapping),实例化
tutoiral.helloworld类,并调用其execute方法。当然,我们可以通过以下两种方法改变这种默认调用。这个功能
(feature)有点类似struts 1.x中的lookupdispathaction。
在classes/sturts.xml中新建action,并指明其调用的方法;
访问action时,在action名后加上“!xxx”(xxx为方法名)。
现方法一,在classes/sturts.xml中加入下面代码:
通过上面的两个例子,细心的朋友应该可能会发现classes/tutorial/helloworld.java中action方法(execute和
aliasaction)返回都是success。这个属性变量我并没有定义,所以大家应该会猜到它在actionsupport或其父类中定
义。没错,success在接口com.opensymphony.xwork2.action中定义,另外同时定义的还有error, input, login,
none。
此外,我在配置action时都没有为result定义名字(name),所以它们默认都为success。值得一提的是struts 2.0中
的result不仅仅是struts 1.x中forward的别名,它可以实现除forward外的很激动人心的功能,如将action输出到
freemaker模板、velocity模板、jasperreports和使用xsl转换等。这些都过result里的type(类型)属性
(attribute)定义的。另外,您还可以自定义result类型。
下面让我们来做一个velocity模板输出的例子,首先在classes/struts.xml中新建一个action映射(mapping),将其
result类型设为velocity,如以下代码所示:
新建helloworld.vm,内容如下所示:
很多时候我的同事会问我:“如果我要取得servlet api中的一些对象,如request、response或session等,应该怎么
做?这里的execute不像struts 1.x的那样在参数中引入。”开发web应用程序当然免不了跟这些对象打交道。在
strutx 2.0你可以有两种方式获得这些对象:非ioc(控制反转inversion of control)方式和ioc方式。
非ioc方式
要获得上述对象,关键struts 2.0中com.opensymphony.xwork2.actioncontext类。我们可以通过它的静态方法
getcontext()获取当前action的上下文对象。 另外,org.apache.struts2.servletactioncontext作为辅助类
(helper class),可以帮助您快捷地获得这几个对象。
httpservletrequest request = servletactioncontext.getrequest();
httpservletresponse response = servletactioncontext.getresponse();
httpsession session = request.getsession();
如果你只是想访问session的属性(attribute),你也可以通过actioncontext.getcontext().getsession()获取或添
加session范围(scoped)的对象。
ioc方式
要使用ioc方式,我们首先要告诉ioc容器(container)想取得某个对象的意愿,通过实现相应的接口做到这点。具体
实现,请参考例6 iocservlet.java。
package tutorial;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import javax.servlet.http.httpsession;
import org.apache.struts2.servletactioncontext;
import com.opensymphony.xwork2.actioncontext;
import com.opensymphony.xwork2.actionsupport;
publicclass noniocservlet extends actionsupport {
private string message;
public string getmessage() {
return message;
}
@override
public string execute() {
actioncontext.getcontext().getsession().put("msg", "hello world from session!");
httpservletrequest request = servletactioncontext.getrequest();
httpservletresponse response = servletactioncontext.getresponse();
httpsession session = request.getsession();
stringbuffer sb =new stringbuffer("message from request: ");
sb.append(request.getparameter("msg"));
sb.append("
response buffer size: ");
sb.append(response.getbuffersize());
sb.append("
session id: ");
sb.append(session.getid());
message = sb.tostring();
return success;
}
}例6 classes/tutorial/noniocservlet.java
package tutorial;
import java.util.map;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import javax.servlet.http.httpsession;
import org.apache.struts2.interceptor.servletrequestaware;
import org.apache.struts2.interceptor.servletresponseaware;
import org.apache.struts2.interceptor.sessionaware;
import com.opensymphony.xwork2.actioncontext;
import com.opensymphony.xwork2.actionsupport;
publicclass iocservlet extends actionsupport implements sessionaware, servletrequestaware,
servletresponseaware {
private string message;
private map att;
private httpservletrequest request;
private httpservletresponse response;
public string getmessage() {
return message;
}
publicvoid setsession(map att) {
this.att = att;
}
publicvoid setservletrequest(httpservletrequest request) {
this.request = request;
}
publicvoid setservletresponse(httpservletresponse response) {
this.response = response;
}
@override
public string execute() {
att.put("msg", "hello world from session!");
httpsession session = request.getsession();
stringbuffer sb =new stringbuffer("message from request: ");
sb.append(request.getparameter("msg"));
sb.append("
response buffer size: ");
sb.append(response.getbuffersize());
sb.append("
session id: ");
sb.append(session.getid());
message = sb.tostring();
return success;
}
}例6 classes/tutorial/iocservlet.java
<%@ page contenttype="text/html; charset=utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags"%>
--------------------------------------------------------------------------------
在src文件夹中加入struts.properties文件,内容如下:
struts.custom.i18n.resources=globalmessages
struts 2.0有两个配置文件,struts.xml和struts.properties都是放在web-inf/classes/下。
struts.xml用于应用程序相关的配置
struts.properties用于struts 2.0的运行时(runtime)的配置
在src文件夹中加入globalmessages_en_us.properties文件,内容如下:
helloworld=hello world!
在src文件夹中加入globalmessages_zh_cn.properties文件,内容如下:
helloworld=你好,世界!
在webcontent文件夹下加入helloworl.jsp文件,内容如下:
<%@ page contenttype="text/html; charset=utf-8"%>
< prefix="s" uri="/struts-tags"%>
2.0中有下面几种方法:
使用全局的资源文件,方法如上例所示。这适用于遍布于整个应用程序的国际化字符串,它们在不同的包(package)
中被引用,如一些比较共用的出错提示;
使用包范围内的资源文件。做法是在包的根目录下新建名的package.properties和package_xx_xx.properties文件。
这就适用于在包中不同类访问的资源;
使用action范围的资源文件。做法为action的包下新建文件名(除文件扩展名外)与action类名同样的资源文件。它
只能在该action中访问。如此一来,我们就可以在不同的action里使用相同的properties名表示不同的值。例如,在
actonone中title为“动作一”,而同样用title在actiontwo表示“动作二”,节省一些命名工夫;
使用
介绍》。在您使用这一方法时,请注意
际化字符串都会在名为xxxxx资源文件查找,如果找不到,struts 2.0就会输出默认值(国际化字符串的名字)。
上面我列举了四种配置和访问资源的方法,它们的范围分别是从大到小,而struts 2.0在查找国际化字符串所遵循的
是特定的顺序,如图3所示:
图3 资源文件查找顺序图
假设我们在某个childaction中调用了gettext("user.title"),struts 2.0的将会执行以下的操作:
查找childaction_xx_xx.properties文件或childaction.properties;
查找childaction实现的接口,查找与接口同名的资源文件myinterface.properties;
查找childaction的父类parentaction的properties文件,文件名为parentaction.properties;
判断当前childaction是否实现接口modeldriven。如果是,调用getmodel()获得对象,查找与其同名的资源文件;
查找当前包下的package.properties文件;
查找当前包的父包,直到最顶层包;
在值栈(value stack)中,查找名为user的属性,转到user类型同名的资源文件,查找键为title的资源;
查找在struts.properties配置的默认的资源文件,参考例1;
输出user.title。
参数化国际化字符串
许多情况下,我们都需要在动行时(runtime)为国际化字符插入一些参数,例如在输入验证提示信息的时候。在
struts 2.0中,我们通过以下两种方法做到这点:
在资源文件的国际化字符串中使用ognl,格式为${表达式},例如:
validation.require=${gettext(filename)} is required
使用java.text.messageformat中的字符串格式,格式为{ 参数序号(从0开始), 格式类形(number | date | time
| choice), 格式样式},例如:
validation.between=date must between {0, date, short} and {1, date, short}
在显示这些国际化字符时,同样有两种方法设置参数的值:
使用标志的value0、value1...valuen的属性,如:
使用param子元素,这些param将按先后顺序,代入到国际化字符串的参数中,例如:
让用户方便地选择语言
开发国际化的应用程序时,有一个功能是必不可少的——让用户快捷地选择或切换语言。在struts 2.0中,通过
actioncontext.getcontext().setlocale(locale arg)可以设置用户的默认语言。不过,由于这是一个比较普遍的应
用场景(scenario),所以struts 2.0为您提供了一个名i18n的拦截器(interceptor),并在默认情况下将其注册到
拦截器链(interceptor chain)中。它的原理为在执行action方法前,i18n拦截器查找请求中的一个名
为"request_locale"的参数。如果其存在,拦截器就将其作为参数实例化locale对象,并将其设为用户默认的区域
(locale),最后,将此locale对象保存在session的名为“ww_trans_i18n_locale”的属性中。
下面,我将提供一完整示例演示它的使用方法。
package tutorial;
import java.util.hashtable;
import java.util.locale;
import java.util.map;
publicclass locales {
public map
map
locales.put("american english", locale.us);
locales.put("simplified chinese", locale.china);
return locales;
}
}tutorial/locales.java
< prefix="s" uri="/struts-tags"%>
弄清楚struts-config.xml中各项元素的作用,对于我们构建web项目有莫大的好处。
(data-sources?,form-beans?,global-exceptions?,global-forwards?,action-mappings?,controller?,message-resources*,plug-in*)
>
以上8个元素,下面一一描述:
1. date-sources元素
date-sources元素用来配置应用程序所需要的数据源。java语言提供了javax.sql.datesource接口,所有数据源必须实现该接口。如下配置:
………………
在action中访问方式如:
javax.sql.datasource datasource;
java.sql.connection myconnection;
try
{
datasource = getdatasource(request);
myconnection = datasource.getconnection();
}
…………
如果是多数据源,可用如下配置:
………………
………………
访问方式:datasource = getdatasource(request,"a");
2. form-beans元素
该元素主要用来配置表单验证的类。它包含如下属性:
1. classname:一般用得少,指定和form-bean无素对应的配置类,默认为org.apache.struts.config.formbeanconfig,如果自定义,则必须扩展formbeanconfig类。可有可无。
2. name:actionform bean的惟一标识。必须。
3. type:actionform的完整类名。必须。
如下所示:
type="com.ha.login">
如果是动态action formbean,还必须配置form-bean元素的form-property子元素。它包含四个属性,上面三个,还有一个initial 元素:以字符串的形式设置表单字段的初始值,如果没有设置该属性,则是基本类型为0,如果是对象则为null。可有可无。如下所示:
type="com.ha.login">
3. global-exceptions元素
该元素主要配置异常处理,它的exception子元素代表全局的异常配置。struts采取配置的方式来处理异常。它用来设置java异常和异常处理类org.apache.struts.action.exceptionhandler之间的映射。它有七个属性,如下所示:
1. classname:指定和exception元素对应的配置类,默认为:org.apache.struts.config.exceptionconfig。可有可无。
2. handler:指定异常得理类,默认为:org.apache.struts.action.exceptionhandler。可有可无
3. key:指定在resource bundle中描述该异常的消息key
4. path:指定当异常发生时的转发路径。
5. scope:指定actionmessages实例的存放范围,可选值包括:request和session,默认为request。可有可无。
6. type:指定所需处理异常类的名字,必须。
7. bundle:指定resource bundle
如下所示:
path="/error.jsp"
scope="request"
type="com.hn.tree"
/>
4. global-forwards元素
该元素主要用来声明全局的转发关系,它具有以下四个属性:
1. classname:和forward元素对应的配置类,默认为:org.apache.struts.action.actionforward。可有可无。
2. contextrelative:此项为true时,表时path属性以"/"开头,相对于当前上下文的url,默认为false.可有可无。
3. name:转发路径的逻辑名.必填。
4. path:转发或重定向的url,当contextrelative=false时,url路径相对于当前应用(application),当为ture时,表示url路径相对于当前上下文(context)。
5. redirect:当此项为ture时,表示执行重定向操作。当此项为false时表示转向操作。默认为false。
如下所示:
5. action-mappings元素
描述从特定的请求路径到相应的action类的映射。它具有以下几个属性:
1. attribute:设置和action关联的actionform bean在request和session范围内的key。如:form bean存在于request范围内,此项设为“mybenas”,则在request.getattribute("mybenas")就可以返回该bean的实例。
2. classsname:和action元素对应的配置元素,默认为:org.apache.struts.action.actionmapping.
3. forward:转发的url路径。
4. include:指定包含的url路径。
5. input:输入表单的url路径,当表单验证失败时,将把请求转发到该url。
6. name:指定和action关联的action formbean的名字,该名字必须在form-bean定义过。
7. path:指定访问action的路径,以“/”开头,无扩展名。
8. parameter:指定actgion的配置参数,在action类的execute()方法中,可以调用actionmapping对象的getparameter()方法来读取该配置参数。
9. roles:指定允许调用该action的安全角色,多个角色之间用,隔开,在处理请求时,requestprocessor会根据该配置项来决定用户是否有权限调用action权限。
10. scope:指定actionform bean的存在范围,可选取为request和session,默认为session。
11. type:指定action类的完整类名。
12. unknown:如果此项为true,表示可以处理用户发出的所有无效的action url,默认为false;
13. validate:指定是否要调用action formbean的validate方法,默认值为ture.
注:forward、include、type属性只能选中其中一项。
如下:
name="a1"
scope="request"
validate="true"
input="/b.jsp">
注:此中的forward是指局部的转发路径。global-forwards表示全局的转发路径。
6. controller元素
该元素用于配置actionservlet。它具有以下属性。
1. buffersize:指定上载文件的输入缓冲大小,可选,默认为4096
2. classname:指定和controller元素对应的配置类,默认为org.apache.struts.config.controllerconfig
3. conenttype:字符编码,如果在action和jsp网页中设置了,则覆盖该设置。
4. locale:指定是否把locale对象保存到当前用户的session中,默认值为false.
5. processorclass:指定负责请求的java类完整路径。
6. tempdir:指定处理文件的临时工作目录,如果此项没有设置,将采用servlet容器为web应用分配的临时工作目录。
7. nochache:如果为true:在响应结果中将加入特定的头参数:pragma,cache-control和expise,防止页面被保存在客户端的浏览器中,默认为false
如下:
locale="true"
processorclass="con.ok"/>
7. message-resources元素
主要配置本地化消息文本,它具有以下属性。
1. classname:和message-resources元素对应的配置类,默认为org.apache.struts.config.messageresourcesconfig。
2. factory:指定消息资源的工厂类,默认为:org.apache.struts.util.propertymessageresourcesfactory类
3. key:指定resource bundle存放的servletcontext对象中时采用的属性key,默认由globals.messages_key定义的字符串常量,只允许一个resource bundle采用默认的属性key。
4. null:指定messagesources类如何处理未知消息的key,如果为true,则返回空字符串,如果为false,则返回相关字串,默认为false
5. prameter:指定messagesources的资源文件名,如果为:a.b.applicationresources,则实际对应的文件路径为:web-inf/classes/a/b/applicationresources.properties.
如:
访问为:
其中,zxj表法,messagesource资源文件中的一个字符串。
8. plugin-in元素
配置struts的插件,属性如下:
1. classname:指定的struts插件类,必须实现org.apache.struts.action.plugiin接口。如:
后记,多模块的配置,可以供多个应用应用不同的struts-config.xml
(转载于:)
struts.configuration
the org.apache.struts2.config.configuration implementation class
org.apache.struts2.config.configuration接口名
struts.configuration.files
a list of configuration files automatically loaded by struts
struts自动加载的一个配置文件列表
struts.configuration.xml.reload
whether to reload the xml configuration or not
是否加载xml配置(true,false)
struts.continuations.package
the package containing actions that use rife continuations
含有actions的完整连续的package名称
struts.custom.i18n.resources
location of additional localization properties files to load
加载附加的国际化属性文件(不包含.properties后缀)
struts.custom.properties
location of additional configuration properties files to load
加载附加的配置文件的位置
struts.devmode
whether struts is in development mode or not
是否为struts开发模式
struts.dispatcher.parametersworkaround
whether to use a servlet request parameter workaround necessary for some versions of weblogic
(某些版本的weblogic专用)是否使用一个servlet请求参数工作区(parametersworkaround)
struts.enable.dynamicmethodinvocation
allows one to disable dynamic method invocation from the url
允许动态方法调用
struts.freemarker.manager.classname
the org.apache.struts2.views.freemarker.freemarkermanager implementation class
org.apache.struts2.views.freemarker.freemarkermanager接口名
struts.i18n.encoding
the encoding to use for localization messages
国际化信息内码
struts.i18n.reload
whether the localization messages should automatically be reloaded
是否国际化信息自动加载
struts.locale
the default locale for the struts application
默认的国际化地区信息
struts.mapper.class
the org.apache.struts2.dispatcher.mapper.actionmapper implementation class
org.apache.struts2.dispatcher.mapper.actionmapper接口
struts.multipart.maxsize
the maximize size of a multipart request (file upload)
multipart请求信息的最大尺寸(文件上传用)
struts.multipart.parser
the org.apache.struts2.dispatcher.multipart.multipartrequest parser implementation for a multipart request (file upload)
专为multipart请求信息使用的org.apache.struts2.dispatcher.multipart.multipartrequest解析器接口(文件上传用)
struts.multipart.savedir
the directory to use for storing uploaded files
设置存储上传文件的目录夹
struts.objectfactory
the com.opensymphony.xwork2.objectfactory implementation class
com.opensymphony.xwork2.objectfactory接口(spring)
struts.objectfactory.spring.autowire
whether spring should autowire or not
是否自动绑定spring
struts.objectfactory.spring.useclasscache
whether spring should use its class cache or not
是否spring应该使用自身的cache
struts.objecttypedeterminer
the com.opensymphony.xwork2.util.objecttypedeterminer implementation class
com.opensymphony.xwork2.util.objecttypedeterminer接口
struts.serve.static.browsercache
if static content served by the struts filter should set browser caching header properties or not
是否struts过滤器中提供的静态内容应该被浏览器缓存在头部属性中
struts.serve.static
whether the struts filter should serve static content or not
是否struts过滤器应该提供静态内容
struts.tag.altsyntax
whether to use the alterative syntax for the tags or not
是否可以用替代的语法替代tags
struts.ui.templatedir
the directory containing ui templates
ui templates的目录夹
struts.ui.theme
the default ui template theme
默认的ui template主题
struts.url.http.port
the http port used by struts urls
设置http端口
struts.url.https.port
the https port used by struts urls
设置https端口
struts.url.includeparams
the default includeparams method to generate struts urls
在url中产生 默认的includeparams
struts.velocity.configfile
the velocity configuration file path
velocity配置文件路径
struts.velocity.contexts
list of velocity context names
velocity的context列表
struts.velocity.manager.classname
org.apache.struts2.views.velocity.velocitymanager implementation class
org.apache.struts2.views.velocity.velocitymanager接口名
struts.velocity.toolboxlocation
the location of the velocity toolbox
velocity工具盒的位置
struts.xslt.nocache
whether or not xslt templates should not be cached
是否xslt模版应该被缓存
为避免重复文件名
formfile file = theform.getthefile();
string filename= file.getfilename();
int i = filename.lastindexof(".");
if(i != -1)
{
filename = filename.substring(i);
}else
{
filename = ".bin";
}
filename = new date().gettime() filename;
最后别忘了file.destroy();
其他的就用struts里面自带的例子搞定.
inputstream stream = file.getinputstream();
outputstream bos = new fileoutputstream(pathmydir filename);
int bytesread = 0;
byte[] buffer = new byte[8192];
while ((bytesread = stream.read(buffer, 0, 8192)) != -1) {
bos.write(buffer, 0, bytesread);
}
bos.close();
stream.close();
trackback: http://tb.blog.csdn.net/trackback.aspx?postid=250969
一、简介
struts-menu是一组从基于xml的配置文件中生成多种样式的菜单的jsp tags,并且可以结合api开发通过数据库生成的动态菜单。struts-menu支持国际化和多种权限控制。
二、运行环境
windows 2000 professional
jdk 1.4.2_03
eclipse 3.1
tomcat 5.0.28
tomcat plugin 3.1beta
struts 1.2.7
commons-lang 2.1
commons-collections 3.1
struts-menu 2.3
mysql 4.1.10a-nt
三、下载与安装
1:从下载j2sdk,当前1.4.x系列的最新版本为1.4.2_08
2:从下载eclipse,当前最新版本为3.1正式版
3:从下载tomcat,当前5.x系列的最新版本为5.0.28
4:从下载eclipse的tomcat插件,对应eclipse3.1x的最新版本为3.1beta
5:从下载struts,当前最新版本为1.2.7
6:从下载commons-lang,当前最新版本为2.1,下载commons-collections,当前最新版本为3.1
7:从下载struts menu,当前最新版本为2.3
8:从下载mysql数据库,4.x系列的最新版本是4.1.12a
9:mysql、jdk、eclipse、tomcat和tomcatplugin的安装及配置请参考相关资料
四、运行示例程序
1:安装好tomcat后,解压缩struts-menu-2.3.zip,将struts-menu.war释放到tomcat安装目录下的webapps下,运行tomcat
2:在地址栏输入
五、安装与配置
1:在eclipse中新建tomcat项目,context为/mymenu,subdirectory为/web
2:在项目目录下面新建lib目录和web目录及web-inf,在web/web-inf目录下新建web.xml,内容如下:
public "-//sun microsystems, inc.//dtd web application 2.3//en"
"">
3:解压缩struts-1.2.7.zip,将压缩包中的lib目录下所有的8个jar释放到lib目录中,将5个tld文件释放到web\web-inf目录中,在web\web-inf目录中新建struts-config.xml,内容如下:
"-//apache software foundation//dtd struts configuration 1.2//en"
"">
4:解压缩struts-menu-2.3.zip,将压缩包中的jstl-1.0.6.jar、standard-1.0.6.jar、struts-menu-2.3.jar释放到lib目录中,将压缩包中的struts-menu.tld、struts-menu-el.tld释放到web\web-inf目录中,解压缩commons-lang-2.1.zip,将commons-lang-2.1.jar解压缩到lib目录中,注意,在struts-menu的文档中没有看到需要这个包,但是没有这个包却无法成功加载。在web\web-inf目录中新建menu-config.xml,内容如下:
5:将第四步的示例程序中的struts-menu应用目录下的images、scripts、styles三个目录中的内容复制到web目录下
6:你的目录结构应该类似如下:
%project_home%\classes
%project_home%\lib
%project_home%\lib\antlr.jar
%project_home%\lib\commons-beanutils.jar
%project_home%\lib\commons-digester.jar
%project_home%\lib\commons-fileupload.jar
%project_home%\lib\commons-lang-2.1.jar
%project_home%\lib\commons-logging.jar
%project_home%\lib\commons-validator.jar
%project_home%\lib\jakarta-oro.jar
%project_home%\lib\jstl-1.0.6.jar
%project_home%\lib\standard-1.0.6.jar
%project_home%\lib\struts.jar
%project_home%\lib\struts-menu-2.3.jar
%project_home%\src
%project_home%\src\log4j.properties
%project_home%\src\application.properties
%project_home%\src\application_zh_cn.properties
%project_home%\web
%project_home%\web\images\...
%project_home%\web\scripts\...
%project_home%\web\styles\...
%project_home%\web\web-inf
%project_home%\web\web-inf\menu-config.xml
%project_home%\web\web-inf\struts-bean.tld
%project_home%\web\web-inf\struts-config.xml
%project_home%\web\web-inf\struts-html.tld
%project_home%\web\web-inf\struts-logic.tld
%project_home%\web\web-inf\struts-menu.tld
%project_home%\web\web-inf\struts-menu-el.tld
%project_home%\web\web-inf\struts-nested.tld
%project_home%\web\web-inf\struts-tiles.tld
%project_home%\web\web-inf\web.xml
六、实战struts-menu
1:使用配置文件实现静态菜单
新建jsp文件web/static-menu.jsp,内容如下:
<%@ page contenttype="text/html; charset=gbk" %>
<%@ taglib uri="struts-menu" prefix="menu" %>
运行tomcat,在ie地址栏输入查看
2:实现中文化
> 在src\application_zh_cn.properties中增加下面的内容,unicode可以通过jdk自带的native2ascii工具得到:
#门户网站
menu.doorsite=\u95e8\u6237\u7f51\u7ad9
#雅虎
menu.yahoo=\u96c5\u864e
#雅虎凯发k8网页登录首页
menu.yahooindex=\u96c5\u864e\u9996\u9875
#雅虎邮件
menu.yahoomail=\u96c5\u864e\u90ae\u4ef6
#搜狐
menu.sohu=\u641c\u72d0
#新浪
menu.sina=\u65b0\u6d6a
> 在src\application.properties中增加下面的内容:
#门户网站
menu.doorsite=doorsite
#雅虎
menu.yahoo=yahoo
#雅虎凯发k8网页登录首页
menu.yahooindex=yahoo index
#雅虎邮件
menu.yahoomail=yahoo mail
#搜狐
menu.sohu=sohu
#新浪
menu.sina=sina
> 修改menu-config.xml文件
重起tomcat,在ie地址栏输入查看
3:结合数据库实现动态菜单
> 新建数据myexamples:
create database myexamples
> 新建数据库表menu_item:
create table menu_item (
id bigint not null,
parent_name varchar(30),
name varchar(30),
title varchar(30),
titlecn varchar(30),
description varchar(50),
location varchar(255),
target varchar(10),
onclick varchar(100),
onmouseover varchar(100),
onmouseout varchar(100),
image varchar(50),
altimage varchar(30),
tooltip varchar(100),
roles varchar(100),
page varchar(255),
width varchar(5),
height varchar(5),
forward varchar(50),
action varchar(50),
primary key (id)
)
> 插入测试数据:
insert into menu_item
(id, parent_name, name, title, titlecn, location)
values
(1,null,'databasemenu','database menu','数据库动态菜单',null),
(2,'databasemenu','yahoo','yahoo mail','雅虎邮件','http://mail.yahoo.com'),
(3,'databasemenu','javablogs','javablogs','java博客','http://javablogs.com'),
(4,null,'standalonemenu','standalone menu','独立的菜单','http://www.sohu.com')
> 将数据库驱动程序放到lib目录中,并加入到build path,如mysql的数据库驱动mysql-connector-java-3.1.8-bin.jar,解压缩commons-collections-3.1.zip,将commons-collections-3.1.jar释放到lib目录,并加入build path
> 新建一个struts的action,代码如下:
package cn.appex.menu;
import java.io.unsupportedencodingexception;
import java.sql.connection;
import java.sql.drivermanager;
import java.sql.preparedstatement;
import java.sql.resultset;
import java.sql.sqlexception;
import java.util.arraylist;
import java.util.hashmap;
import java.util.listresourcebundle;
import java.util.map;
import com.mysql.jdbc.driver;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import javax.servlet.http.httpsession;
import net.sf.navigator.menu.menucomponent;
import net.sf.navigator.menu.menurepository;
import net.sf.navigator.menu.permissionsadapter;
import org.apache.struts.action.action;
import org.apache.struts.action.actionform;
import org.apache.struts.action.actionforward;
import org.apache.struts.action.actionmapping;
public class menuaction extends action {
public actionforward execute(actionmapping mapping, actionform form,
httpservletrequest request, httpservletresponse response)
throws exception {
buildmenurepository(request);
buildmenuresourcebundle(request);
buildmenupermissions(request);
return (mapping.findforward("success"));
}
/**
* 创建菜单数据结构
*
* @param request
*/
private void buildmenurepository(httpservletrequest request) {
menurepository repository = new menurepository();
// get the repository from the application scope - and copy the
// displayermappings from it.
menurepository defaultrepository = (menurepository) request
.getsession().getservletcontext().getattribute(
menurepository.menu_repository_key);
repository.setdisplayers(defaultrepository.getdisplayers());
map[] menus = getmenucomponents();
for (int i=0; i < menus.length; i ) {
menucomponent mc = new menucomponent();
map row = menus[i];
string name = (string) row.get("name");
mc.setname(name);
string parent = (string) row.get("parent_name");
system.out.println(name ", parent is: " parent);
if (parent != null) {
menucomponent parentmenu = repository.getmenu(parent);
if (parentmenu == null) {
system.out.println("parentmenu '" parent "' doesn't exist!");
// create a temporary parentmenu
parentmenu = new menucomponent();
parentmenu.setname(parent);
repository.addmenu(parentmenu);
}
mc.setparent(parentmenu);
}
string title = (string) row.get("title");
mc.settitle(title);
string location = (string) row.get("location");
mc.setlocation(location);
string description = (string) row.get("description");
mc.setdescription(description);
repository.addmenu(mc);
}
request.setattribute("examplesrepository", repository);
}
/**
* 从数据库中读取菜单配置信息
*
* @return
*/
private map[] getmenucomponents() {
arraylist list = new arraylist();
connection conn = null;
preparedstatement pstmt = null;
resultset rest = null;
string sql = "select name,parent_name,title,location,description from menu_item order by id";
try {
class.forname("com.mysql.jdbc.driver").newinstance();
conn = drivermanager.getconnection("jdbc:mysql://localhost/myexamples?user=root&password=mywangya&useunicode=true&characterencoding=utf-8");
pstmt = conn.preparestatement(sql);
rest = pstmt.executequery();
while (rest.next()) {
int i = 1;
hashmap map = new hashmap();
map.put("name", rest.getstring(i ));
map.put("parent_name", rest.getstring(i ));
map.put("title", rest.getstring(i ));
map.put("location", rest.getstring(i ));
map.put("description", rest.getstring(i ));
list.add(map);
}
} catch (sqlexception ex) {
ex.printstacktrace();
} catch (instantiationexception e) {
e.printstacktrace();
} catch (illegalaccessexception e) {
e.printstacktrace();
} catch (classnotfoundexception e) {
e.printstacktrace();
} finally {
try {
if (null!=rest) rest.close();
if (null!=pstmt) pstmt.close();
if (null!=conn) conn.close();
} catch (sqlexception e) {
e.printstacktrace();
}
}
return (map[]) list.toarray(new hashmap[0]);
}
/**
* 构造菜单权限
*
* @param request
*/
private void buildmenupermissions(httpservletrequest request) {
permissionsadapter permession = new permissionsadapter() {
public boolean isallowed(menucomponent menu) {
// 名称等于standalonemenu的菜单不显示
return !"standalonemenu".equalsignorecase(menu.getname());
}
};
request.setattribute("examplespermession", permession);
}
/**
* 构造菜单显示标题
*
* @param request
*/
private void buildmenuresourcebundle(httpservletrequest request) {
menuresourcebundle resourcebundle = new menuresourcebundle();
request.setattribute("examplesbundle", resourcebundle);
}
/**
* menuresourcebundle树状菜单国际语言显示
*
* @author wenbin.zhang
*
*/
class menuresourcebundle extends listresourcebundle {
private arraylist list = new arraylist();
public menuresourcebundle() {
connection conn = null;
preparedstatement pstmt = null;
resultset rest = null;
string sql = "select title,titlecn from menu_item order by id";
try {
class.forname("com.mysql.jdbc.driver").newinstance();
conn = drivermanager.getconnection("jdbc:mysql://localhost/myexamples?user=root&password=mywangya&useunicode=true&characterencoding=utf-8");
pstmt = conn.preparestatement(sql);
rest = pstmt.executequery();
while (rest.next()) {
int i = 1;
string[] message = new string[2];
message[0] = rest.getstring(i );
try {
message[1] = new string(rest.getstring(i ).getbytes("latin1"), "gbk");
} catch (unsupportedencodingexception e) {
e.printstacktrace();
}
if (message[0] != null && message[1] != null) {
list.add(message);
}
}
} catch (sqlexception ex) {
ex.printstacktrace();
} catch (instantiationexception e) {
e.printstacktrace();
} catch (illegalaccessexception e) {
e.printstacktrace();
} catch (classnotfoundexception e) {
e.printstacktrace();
} finally {
try {
if (null!=rest) rest.close();
if (null!=pstmt) pstmt.close();
if (null!=conn) conn.close();
} catch (sqlexception e) {
e.printstacktrace();
}
}
}
public object[][] getcontents() {
return (string[][]) list.toarray(new string[0][0]);
}
}
}
> 将struts-config.xml文件的
> 新建jsp文件web/dynamic-menu.jsp,内容如下:
<%@ page contenttype="text/html; charset=gbk" %>
<%@ taglib uri="struts-menu" prefix="menu" %>
没有使用bundle和权限控制:
使用bundle, 没有使用权限控制:
使用bundle和权限控制:
七、关于struts-menu配置文件和api的使用方法,请参考附录中的官方网站
附:
struts-menu官方网站:
数据库驱动的动态菜单:
trackback:
下载struts menu, 解压其中的示例包(struts-menu里面有些库没有提供,但示例里面有) 步骤
1,新建一个tomcat工程
2,添加webproject支持
3,增加struts支持
4,增加jstl支持
5, 拷贝必要的jar库文件到dbmenuweb-inflib log4j-1.2.8.jar velocity-1.4.jar velocity-tools-view-1.0.jar struts-menu-2.3.jar
6,创建menu-config.xml文件在dbmenuweb-inf目录。内容如下:
8,拷贝必要的文件
images/*.* scripts/ menuexpandable.js xtree.js styles/ menuexpandable.css global.css xtree.css templates/xtree.html dbmenuweb-infclassesglobalmacros.vm (这个文件好像必须要最后拷贝,否则会自动没了why???)
10, 拷贝tld文件到dbmenuweb-inf
struts-menu.tld
struts-menu-el.tld
11, 不知道什么原因,需要修改web.xml文件中的version=2.3
web.xml中增加
7,修改struts-config.xml 文件,增加如下部分
11,创建数据库
仿造如下代码创建数据库
12,填写数据库
trackback: http://tb.blog.csdn.net/trackback.aspx?postid=640825
一、简介
struts-menu是一组从基于xml的配置文件中生成多种样式的菜单的jsp tags,并且可以结合api开发通过数据库生成的动态菜单。struts-menu支持国际化和多种权限控制。
二、运行环境
windows 2000 professional
jdk 1.4.2_03
eclipse 3.1
tomcat 5.0.28
tomcat plugin 3.1beta
struts 1.2.7
commons-lang 2.1
commons-collections 3.1
struts-menu 2.3
mysql 4.1.10a-nt
三、下载与安装
1:从下载j2sdk,当前1.4.x系列的最新版本为1.4.2_08
2:从下载eclipse,当前最新版本为3.1正式版
3:从下载tomcat,当前5.x系列的最新版本为5.0.28
4:从下载eclipse的tomcat插件,对应eclipse3.1x的最新版本为3.1beta
5:从下载struts,当前最新版本为1.2.7
6:从下载commons-lang,当前最新版本为2.1,下载commons-collections,当前最新版本为3.1
7:从下载struts menu,当前最新版本为2.3
8:从下载mysql数据库,4.x系列的最新版本是4.1.12a
9:mysql、jdk、eclipse、tomcat和tomcatplugin的安装及配置请参考相关资料
四、运行示例程序
1:安装好tomcat后,解压缩struts-menu-2.3.zip,将struts-menu.war释放到tomcat安装目录下的webapps下,运行tomcat
2:在地址栏输入
五、安装与配置
1:在eclipse中新建tomcat项目,context为/mymenu,subdirectory为/web
2:在项目目录下面新建lib目录和web目录及web-inf,在web/web-inf目录下新建web.xml,内容如下:
public "-//sun microsystems, inc.//dtd web application 2.3//en"
"">
3:解压缩struts-1.2.7.zip,将压缩包中的lib目录下所有的8个jar释放到lib目录中,将5个tld文件释放到web\web-inf目录中,在web\web-inf目录中新建struts-config.xml,内容如下:
"-//apache software foundation//dtd struts configuration 1.2//en"
"">
4:解压缩struts-menu-2.3.zip,将压缩包中的jstl-1.0.6.jar、standard-1.0.6.jar、struts-menu-2.3.jar释放到lib目录中,将压缩包中的struts-menu.tld、struts-menu-el.tld释放到web\web-inf目录中,解压缩commons-lang-2.1.zip,将commons-lang-2.1.jar解压缩到lib目录中,注意,在struts-menu的文档中没有看到需要这个包,但是没有这个包却无法成功加载。在web\web-inf目录中新建menu-config.xml,内容如下:
5:将第四步的示例程序中的struts-menu应用目录下的images、scripts、styles三个目录中的内容复制到web目录下
6:你的目录结构应该类似如下:
%project_home%\classes
%project_home%\lib
%project_home%\lib\antlr.jar
%project_home%\lib\commons-beanutils.jar
%project_home%\lib\commons-digester.jar
%project_home%\lib\commons-fileupload.jar
%project_home%\lib\commons-lang-2.1.jar
%project_home%\lib\commons-logging.jar
%project_home%\lib\commons-validator.jar
%project_home%\lib\jakarta-oro.jar
%project_home%\lib\jstl-1.0.6.jar
%project_home%\lib\standard-1.0.6.jar
%project_home%\lib\struts.jar
%project_home%\lib\struts-menu-2.3.jar
%project_home%\src
%project_home%\src\log4j.properties
%project_home%\src\application.properties
%project_home%\src\application_zh_cn.properties
%project_home%\web
%project_home%\web\images\...
%project_home%\web\scripts\...
%project_home%\web\styles\...
%project_home%\web\web-inf
%project_home%\web\web-inf\menu-config.xml
%project_home%\web\web-inf\struts-bean.tld
%project_home%\web\web-inf\struts-config.xml
%project_home%\web\web-inf\struts-html.tld
%project_home%\web\web-inf\struts-logic.tld
%project_home%\web\web-inf\struts-menu.tld
%project_home%\web\web-inf\struts-menu-el.tld
%project_home%\web\web-inf\struts-nested.tld
%project_home%\web\web-inf\struts-tiles.tld
%project_home%\web\web-inf\web.xml
六、实战struts-menu
1:使用配置文件实现静态菜单
新建jsp文件web/static-menu.jsp,内容如下:
<%@ page contenttype="text/html; charset=gbk" %>
<%@ taglib uri="struts-menu" prefix="menu" %>
运行tomcat,在ie地址栏输入查看
2:实现中文化
> 在src\application_zh_cn.properties中增加下面的内容,unicode可以通过jdk自带的native2ascii工具得到:
#门户网站
menu.doorsite=\u95e8\u6237\u7f51\u7ad9
#雅虎
menu.yahoo=\u96c5\u864e
#雅虎凯发k8网页登录首页
menu.yahooindex=\u96c5\u864e\u9996\u9875
#雅虎邮件
menu.yahoomail=\u96c5\u864e\u90ae\u4ef6
#搜狐
menu.sohu=\u641c\u72d0
#新浪
menu.sina=\u65b0\u6d6a
> 在src\application.properties中增加下面的内容:
#门户网站
menu.doorsite=doorsite
#雅虎
menu.yahoo=yahoo
#雅虎凯发k8网页登录首页
menu.yahooindex=yahoo index
#雅虎邮件
menu.yahoomail=yahoo mail
#搜狐
menu.sohu=sohu
#新浪
menu.sina=sina
> 修改menu-config.xml文件
重起tomcat,在ie地址栏输入查看
3:结合数据库实现动态菜单
> 新建数据myexamples:
create database myexamples
> 新建数据库表menu_item:
create table menu_item (
id bigint not null,
parent_name varchar(30),
name varchar(30),
title varchar(30),
titlecn varchar(30),
description varchar(50),
location varchar(255),
target varchar(10),
onclick varchar(100),
onmouseover varchar(100),
onmouseout varchar(100),
image varchar(50),
altimage varchar(30),
tooltip varchar(100),
roles varchar(100),
page varchar(255),
width varchar(5),
height varchar(5),
forward varchar(50),
action varchar(50),
primary key (id)
)
> 插入测试数据:
insert into menu_item
(id, parent_name, name, title, titlecn, location)
values
(1,null,'databasemenu','database menu','数据库动态菜单',null),
(2,'databasemenu','yahoo','yahoo mail','雅虎邮件','http://mail.yahoo.com'),
(3,'databasemenu','javablogs','javablogs','java博客','http://javablogs.com'),
(4,null,'standalonemenu','standalone menu','独立的菜单','http://www.sohu.com')
> 将数据库驱动程序放到lib目录中,并加入到build path,如mysql的数据库驱动mysql-connector-java-3.1.8-bin.jar,解压缩commons-collections-3.1.zip,将commons-collections-3.1.jar释放到lib目录,并加入build path
> 新建一个struts的action,代码如下:
package cn.appex.menu;
import java.io.unsupportedencodingexception;
import java.sql.connection;
import java.sql.drivermanager;
import java.sql.preparedstatement;
import java.sql.resultset;
import java.sql.sqlexception;
import java.util.arraylist;
import java.util.hashmap;
import java.util.listresourcebundle;
import java.util.map;
import com.mysql.jdbc.driver;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import javax.servlet.http.httpsession;
import net.sf.navigator.menu.menucomponent;
import net.sf.navigator.menu.menurepository;
import net.sf.navigator.menu.permissionsadapter;
import org.apache.struts.action.action;
import org.apache.struts.action.actionform;
import org.apache.struts.action.actionforward;
import org.apache.struts.action.actionmapping;
public class menuaction extends action {
public actionforward execute(actionmapping mapping, actionform form,
httpservletrequest request, httpservletresponse response)
throws exception {
buildmenurepository(request);
buildmenuresourcebundle(request);
buildmenupermissions(request);
return (mapping.findforward("success"));
}
/**
* 创建菜单数据结构
*
* @param request
*/
private void buildmenurepository(httpservletrequest request) {
menurepository repository = new menurepository();
// get the repository from the application scope - and copy the
// displayermappings from it.
menurepository defaultrepository = (menurepository) request
.getsession().getservletcontext().getattribute(
menurepository.menu_repository_key);
repository.setdisplayers(defaultrepository.getdisplayers());
map[] menus = getmenucomponents();
for (int i=0; i < menus.length; i ) {
menucomponent mc = new menucomponent();
map row = menus[i];
string name = (string) row.get("name");
mc.setname(name);
string parent = (string) row.get("parent_name");
system.out.println(name ", parent is: " parent);
if (parent != null) {
menucomponent parentmenu = repository.getmenu(parent);
if (parentmenu == null) {
system.out.println("parentmenu '" parent "' doesn't exist!");
// create a temporary parentmenu
parentmenu = new menucomponent();
parentmenu.setname(parent);
repository.addmenu(parentmenu);
}
mc.setparent(parentmenu);
}
string title = (string) row.get("title");
mc.settitle(title);
string location = (string) row.get("location");
mc.setlocation(location);
string description = (string) row.get("description");
mc.setdescription(description);
repository.addmenu(mc);
}
request.setattribute("examplesrepository", repository);
}
/**
* 从数据库中读取菜单配置信息
*
* @return
*/
private map[] getmenucomponents() {
arraylist list = new arraylist();
connection conn = null;
preparedstatement pstmt = null;
resultset rest = null;
string sql = "select name,parent_name,title,location,description from menu_item order by id";
try {
class.forname("com.mysql.jdbc.driver").newinstance();
conn = drivermanager.getconnection("jdbc:mysql://localhost/myexamples?user=root&password=mywangya&useunicode=true&characterencoding=utf-8");
pstmt = conn.preparestatement(sql);
rest = pstmt.executequery();
while (rest.next()) {
int i = 1;
hashmap map = new hashmap();
map.put("name", rest.getstring(i ));
map.put("parent_name", rest.getstring(i ));
map.put("title", rest.getstring(i ));
map.put("location", rest.getstring(i ));
map.put("description", rest.getstring(i ));
list.add(map);
}
} catch (sqlexception ex) {
ex.printstacktrace();
} catch (instantiationexception e) {
e.printstacktrace();
} catch (illegalaccessexception e) {
e.printstacktrace();
} catch (classnotfoundexception e) {
e.printstacktrace();
} finally {
try {
if (null!=rest) rest.close();
if (null!=pstmt) pstmt.close();
if (null!=conn) conn.close();
} catch (sqlexception e) {
e.printstacktrace();
}
}
return (map[]) list.toarray(new hashmap[0]);
}
/**
* 构造菜单权限
*
* @param request
*/
private void buildmenupermissions(httpservletrequest request) {
permissionsadapter permession = new permissionsadapter() {
public boolean isallowed(menucomponent menu) {
// 名称等于standalonemenu的菜单不显示
return !"standalonemenu".equalsignorecase(menu.getname());
}
};
request.setattribute("examplespermession", permession);
}
/**
* 构造菜单显示标题
*
* @param request
*/
private void buildmenuresourcebundle(httpservletrequest request) {
menuresourcebundle resourcebundle = new menuresourcebundle();
request.setattribute("examplesbundle", resourcebundle);
}
/**
* menuresourcebundle树状菜单国际语言显示
*
* @author wenbin.zhang
*
*/
class menuresourcebundle extends listresourcebundle {
private arraylist list = new arraylist();
public menuresourcebundle() {
connection conn = null;
preparedstatement pstmt = null;
resultset rest = null;
string sql = "select title,titlecn from menu_item order by id";
try {
class.forname("com.mysql.jdbc.driver").newinstance();
conn = drivermanager.getconnection("jdbc:mysql://localhost/myexamples?user=root&password=mywangya&useunicode=true&characterencoding=utf-8");
pstmt = conn.preparestatement(sql);
rest = pstmt.executequery();
while (rest.next()) {
int i = 1;
string[] message = new string[2];
message[0] = rest.getstring(i );
try {
message[1] = new string(rest.getstring(i ).getbytes("latin1"), "gbk");
} catch (unsupportedencodingexception e) {
e.printstacktrace();
}
if (message[0] != null && message[1] != null) {
list.add(message);
}
}
} catch (sqlexception ex) {
ex.printstacktrace();
} catch (instantiationexception e) {
e.printstacktrace();
} catch (illegalaccessexception e) {
e.printstacktrace();
} catch (classnotfoundexception e) {
e.printstacktrace();
} finally {
try {
if (null!=rest) rest.close();
if (null!=pstmt) pstmt.close();
if (null!=conn) conn.close();
} catch (sqlexception e) {
e.printstacktrace();
}
}
}
public object[][] getcontents() {
return (string[][]) list.toarray(new string[0][0]);
}
}
}
> 将struts-config.xml文件的
> 新建jsp文件web/dynamic-menu.jsp,内容如下:
<%@ page contenttype="text/html; charset=gbk" %>
<%@ taglib uri="struts-menu" prefix="menu" %>
没有使用bundle和权限控制:
使用bundle, 没有使用权限控制:
使用bundle和权限控制:
七、关于struts-menu配置文件和api的使用方法,请参考附录中的官方网站
附:
struts-menu官方网站:
数据库驱动的动态菜单:
trackback: http://tb.blog.csdn.net/trackback.aspx?postid=496331
struts menu应用是一个jsp标记的集合,支持从xml文件生成各种不同菜单系统。struts menu 2.0进行了重构,使用velocity templates定义菜单。
要从struts menu1.x升级到2.x,需要做如下改变:
l 修改标记库声明的uri,去掉“1.2”
<%@ taglib uri="http://struts-menu.sf.net/tag" prefix="menu" %>
l 修改
l 修改menu-config.xml文件,使用新的包名“net.sf.navigator”
l 下载struts-menu分发包
l 解压缩到本地目录
l 下载并安装tomcat或其它java servlet容器
l 将struts-menu.war文件拷贝到tomcat服务器的webapps目录下,启动服务器
l 浏览
struts menu可以很方便得集成到struts应用中,也将能够集成到其它非struts的应用中。下面是继承标记库的步骤。
你所需要做的就是将struts-menu.jar文件拷贝到web-inf/lib目录下,并在jsp页面中使用标记的uri以声明标记库。
对于struts menu 2.1,还需要将jakarta的standard tag library jar拷贝到web-inf/lib目录下。
l 将struts-menu.jar文件拷贝到web-inf/lib目录下
l 在struts-config.xml文件中添加
l 在web-inf/menu-config.xml文件中声明菜单属性。下面是一个示例:
详细情况请参考例子应用的web-inf目录下的menu-config.xml文件,并修改该文件以适应自己的应用。如果要了解所有相关属性,请参考menubase类的标准文档。
l 在jsp页面中添加标记库的声明
<%@ taglib uri="http://struts-menu.sf.net/tag" prefix="menu" %>
l 在jsp页面中添加标记库代码以生成菜单
bundle="org.apache.struts.action.message">
其中,name="tabbedmenu"是在menu-config.xml文件中定义的。如下:
要使用可定制的velocity模板生成菜单,需要将velocity集成到web应用中。具体步骤如下:
l 确保menu-config.xml文件有如下定义:
l 将velocity的相关jar文件拷贝到web-inf/lib目录下
l 将globalmacros.vm文件添加到web-inf/classes目录下
l 在jsp页面中,修改为name="velocity",并将config属性指到一个文件(如config="/templates/tabs.html"),如果文件在web-inf/classes目录下,就是config="tabs.html"。
3.1. 在使用菜单访问jsp时抛出异常:
org.apache.jasper.jasperexception: could not obtain the menu repository
解决方法:
检查struts-config.xml文件,确保添加如下plug-in设置
3.2. 如何基于角色隐藏/显示菜单项
先在jsp页面中添加属性permissions="rolesadapter"到
3.3. 基于数据库的动态菜单
action 类:
• struts1要求action类继承一个抽象基类。struts1的一个普遍问题是使用抽象类编程而不是接口。
• struts 2 action类可以实现一个action接口,也可实现其他接口,使可选和定制的服务成为可能。struts2提供一个actionsupport基类去实现 常用的接口。action接口不是必须的,任何有execute标识的pojo对象都可以用作struts2的action对象。
线程模式:
• struts1 action是单例模式并且必须是线程安全的,因为仅有action的一个实例来处理所有的请求。单例策略限制了struts1 action能作的事,并且要在开发时特别小心。action资源必须是线程安全的或同步的。
• struts2 action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)
servlet 依赖:
• struts1 action 依赖于servlet api ,因为当一个action被调用时httpservletrequest 和 httpservletresponse 被传递给execute方法。
• struts 2 action不依赖于容器,允许action脱离容器单独被测试。如果需要,struts2 action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问httpservetrequest 和 httpservletresponse的必要性。
可测性:
• 测试struts1 action的一个主要问题是execute方法暴露了servlet api(这使得测试要依赖于容器)。一个第三方扩展--struts testcase--提供了一套struts1的模拟对象(来进行测试)。
• struts 2 action可以通过初始化、设置属性、调用方法来测试,“依赖注入”支持也使测试更容易。
捕获输入:
• struts1 使用actionform对象捕获输入。所有的actionform必须继承一个基类。因为其他javabean不能用作actionform,开发者经常创建多余的类捕获输入。动态bean(dynabeans)可以作为创建传统actionform的选择,但是,开发者可能是在重新描述(创建)已经存在的javabean(仍然会导致有冗余的javabean)。
• struts 2直接使用action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。action属性能够通过web页面上的taglibs访问。struts2也支持actionform模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种modeldriven 特性简化了taglib对pojo输入对象的引用。
表达式语言:
• struts1 整合了jstl,因此使用jstl el。这种el有基本对象图遍历,但是对集合和索引属性的支持很弱。
• struts2可以使用jstl,但是也支持一个更强大和灵活的表达式语言--"object graph notation language" (ognl).
绑定值到页面(view):
• struts 1使用标准jsp机制把对象绑定到页面中来访问。
• struts 2 使用 "valuestack"技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。valuestack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。
类型转换:
• struts 1 actionform 属性通常都是string类型。struts1使用commons-beanutils进行类型转换。每个类一个转换器,对每一个实例来说是不可配置的。
• struts2 使用ognl进行类型转换。提供基本和常用对象的转换器。
校验:
• struts 1支持在actionform的validate方法中手动校验,或者通过commons validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
• struts2支持通过validate方法和xwork校验框架来进行校验。xwork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性
action执行的控制:
• struts1支持每一个模块有单独的request processors(生命周期),但是模块中的所有action必须共享相同的生命周期。
• struts2支持通过拦截器堆栈(interceptor stacks)为每一个action创建不同的生命周期。堆栈能够根据需要和不同的action一起使用。
本文引用地址:
其实,struts 1.x在此部分已经做得相当不错了。它极大地简化了我们程序员在做国际化时所需的工作,例如,如果您要输出一条国际化的信息,只需在代码包中加入file-name_xx_xx.properties(其中file-name为默认资源文件的文件名),然后在struts-config.xml中指明其路径,再在页面用
不过,所谓“没有最好,只有更好”。struts 2.0并没有在这部分止步,而是在原有的简单易用的基础上,将其做得更灵活、更强大。
下面让我们看一个例子——helloworld。这个例子演示如何根据用户浏览器的设置输出相应的helloworld。
struts 2.0有两个配置文件,struts.xml和struts.properties都是放在web-inf/classes/下。
|
在此想和大家分享一个不错的编写properties文件的eclipse插件(plugin),有了它我们在编辑一些简体中文、繁体中文等unicode文本时,就不必再使用native2ascii编码了。您可以通过eclipse中的软件升级(software update)安装此插件,步骤如下: 1、展开eclipse的help菜单,将鼠标移到software update子项,在出现的子菜单中点击find and install;
2、在install/update对话框中选择search for new features to install,点击next; 3、在install对话框中点击new remote site; 4、在new update site对话框的name填入“propedit”或其它任意非空字符串,在url中填入http://propedit.sourceforge.jp/eclipse/updates/; 5、在site to include to search列表中,除上一步加入的site外的其它选项去掉,点击finsih; 6、在弹出的updates对话框中的select the features to install列表中将所有结尾为“3.1.x”的选项去掉(适用于eclipse 3.2版本的朋友); 7、点击finish关闭对话框; 8、在下载后,同意安装,再按提示重启eclipse,在工具条看到形似vi的按钮表示安装成功,插件可用。此时,eclpise中所有properties文件的文件名前有绿色的p的图标作为标识。 |
之所以说struts 2.0的国际化更灵活是因为它可以能根据不同需要配置和获取资源(properties)文件。在struts 2.0中有下面几种方法:
上面我列举了四种配置和访问资源的方法,它们的范围分别是从大到小,而struts 2.0在查找国际化字符串所遵循的是特定的顺序,如图3所示:
假设我们在某个childaction中调用了gettext("user.title"),struts 2.0的将会执行以下的操作:
许多情况下,我们都需要在动行时(runtime)为国际化字符插入一些参数,例如在输入验证提示信息的时候。在struts 2.0中,我们通过以下两种方法做到这点:
开发国际化的应用程序时,有一个功能是必不可少的——让用户快捷地选择或切换语言。在struts 2.0中,通过actioncontext.getcontext().setlocale(locale arg)可以设置用户的默认语言。不过,由于这是一个比较普遍的应用场景(scenario),所以struts 2.0为您提供了一个名i18n的拦截器(interceptor),并在默认情况下将其注册到拦截器链(interceptor chain)中。它的原理为在执行action方法前,i18n拦截器查找请求中的一个名为"request_locale"的参数。如果其存在,拦截器就将其作为参数实例化locale对象,并将其设为用户默认的区域(locale),最后,将此locale对象保存在session的名为“ww_trans_i18n_locale”的属性中。
下面,我将提供一完整示例演示它的使用方法。
上述代码的原理为,langselector.jsp先实例化一个locales对象,并把对象的map类型的属性locales赋予下拉列表(select) 。如此一来,下拉列表就获得可用语言的列表。大家看到langselector有
可能大家会问为什么一定要通过action来访问页面呢? 你可以试一下不用action而直接用jsp的地址来访问页面,结果会是无论你在下拉列表中选择什么,语言都不会改变。这表示不能正常运行的。其原因为如果直接使用jsp访问页面,struts 2.0在web.xml的配置的过滤器(filter)就不会工作,所以拦截器链也不会工作。 |
言归正传,interceptor(以下译为拦截器)是struts 2的一个强有力的工具,有许多功能(feature)都是构建于它之上,如国际化、,等。
拦截器,在aop(aspect-oriented programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是aop的一种实现策略。
在webwork的中文文档的解释为——拦截器是动态拦截action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。
谈到拦截器,还有一个词大家应该知道——拦截器链(interceptor chain,在struts 2中称为拦截器栈interceptor stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
struts 2的拦截器实现相对简单。当请求到达struts 2的servletdispatcher时,struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器,如图1所示。
图1 拦截器调用序列图
struts 2已经为您提供丰富多样的,功能齐全的拦截器实现。大家可以到struts2-all-2.0.1.jar或struts2-core-2.0.1.jar包的struts-default.xml查看关于默认的拦截器与拦截器链的配置。
在本文使用是struts 2的最新发布版本2.0.1。需要下载的朋友请点击以下链接: |
以下部分就是从struts-default.xml文件摘取的内容: