blogjava-凯发k8网页登录http://www.blogjava.net/i369/category/18051.html北极心空zh-cnwed, 28 may 2008 18:14:27 gmtwed, 28 may 2008 18:14:27 gmt60当jsonplugin遇到cglibhttp://www.blogjava.net/i369/articles/203608.html芦苇芦苇wed, 28 may 2008 10:26:00 gmthttp://www.blogjava.net/i369/articles/203608.htmlhttp://www.blogjava.net/i369/comments/203608.htmlhttp://www.blogjava.net/i369/articles/203608.html#feedback0http://www.blogjava.net/i369/comments/commentrss/203608.htmlhttp://www.blogjava.net/i369/services/trackbacks/203608.htmljsonplugin在分析类结构并序列化时,对于cglig动态生成的类也是按照一般类来看待的。这就导致了如下的问题:

在一个应用中,某些情况下,一个服务类返回的实体并不是原有实体类的对象,而是cglib动态生成的子类。例如使用hibernate的时候,某些情况下dao返回的是entityclassname$$enhancerbycglib$$ac21e这样的类的对象。hibernate在这个子类中添加了hibernatelazyinitializer等等的附加属性。由于jsonplugin并不区分类和动态生成的类,所以也会试图序列化hibernatelazyinitializer属性,从而导致出现如下的异常: java.sql.sqlexception: positioned update not supported.
 at com.mysql.jdbc.resultset.getcursorname(resultset.java:1800)

另外,cglib生成的类,某些方法上的@json标记奇怪的丢失了。导致标记了@json(serialize=false)的属性也被序列化。

在网上查了很久没有发现相关的文章,所以无奈就自己动手修改jsonplugin的代码了。

类:com.googlecode.jsonplugin.jsonwriter,修改bean()方法:

 1     private void bean(object object) throws jsonexception {
 2         this.add("{");
 3 
 4         beaninfo info;
 5 
 6         try {
 7             class clazz = object.getclass();
 8 
 9             info = ((object == this.root) && this.ignorehierarchy) ? introspector
10                     .getbeaninfo(clazz, clazz.getsuperclass())
11                     : introspector.getbeaninfo(clazz);
12 
13             propertydescriptor[] props = info.getpropertydescriptors();
14 
15             boolean hasdata = false;
16             for (int i = 0; i < props.length; i) {
17                 propertydescriptor prop = props[i];
18                 string name = prop.getname();
19                 method accessor = prop.getreadmethod();
20                 method baseaccessor = null//这里增加一个临时变量作为真实希望序列化的属性的accessor方法引用
21                 if (clazz.getname().indexof("$$enhancerbycglib$$"> -1) {  //如果是cglib动态生成的类
22                     try {
23                         //下面的逻辑是根据cglib动态生成的类名,得到原本的实体类名
24                         //例如 entityclassname$$enhancerbycglib$$ac21e这样
25                         //的类,将返回的是entityclassname这个类中的相应方法,若
26                         //获取不到对应方法,则说明要序列化的属性例如hibernatelazyinitializer之类
27                         //不在原有实体类中,而是仅存在于cglib生成的子类中,此时baseaccessor
28                         //保持为null
29                         baseaccessor = class.forname(
30                                 clazz.getname().substring(0,
31                                         clazz.getname().indexof("$$")))
32                                 .getdeclaredmethod(accessor.getname(),
33                                         accessor.getparametertypes());
34                     } catch (exception ex) {
35                         log.debug(ex.getmessage());
36                     }
37                 }
38                 else    //若不是cglib生成的类,那么要序列化的属性的accessor方法就是该类中的方法。
39                     baseaccessor = accessor;
40 
41                 //这个判断,根据上面的逻辑,使得仅存在于cglib生成子类中的属性跳过json序列化
42                 if (baseaccessor != null) {    
43                     
44                     //下面的json annotation的获取也修改为从baseaccessor获取,这样避免了
45                     //由于cglib生成子类而导致某些方法上的json annotation丢失导致处理不该
46                     //序列化的属性
47                     json json = baseaccessor.getannotation(json.class);
48                     if (json != null) {
49                         if (!json.serialize())
50                             continue;
51                         else if (json.name().length() > 0)
52                             name = json.name();
53                     }
54 
55                     //ignore "class" and others
56                     if (this.shouldexcludeproperty(clazz, prop)) {
57                         continue;
58                     }
59                     string expr = null;
60                     if (this.buildexpr) {
61                         expr = this.expandexpr(name);
62                         if (this.shouldexcludeproperty(expr)) {
63                             continue;
64                         }
65                         expr = this.setexprstack(expr);
66                     }
67                     if (hasdata) {
68                         this.add(',');
69                     }
70                     hasdata = true;
71 
72                     object value = accessor.invoke(object, new object[0]);
73                     this.add(name, value, accessor);
74                     if (this.buildexpr) {
75                         this.setexprstack(expr);
76                     }
77                 }
78             }
79         } catch (exception e) {
80             throw new jsonexception(e);
81         }
82 
83         this.add("}");
84     }

这样修改之后,原有类中不能存在的属性将不会被序列化,同时,由于不检查生成的类的方法上的json标记,而是检查原有类上的标记,这样避免了由于cglib导致的annotation丢失的问题。

在此依然向诸位询问是否jsonplugin有处理这样的情况的方法。

芦苇 2008-05-28 18:26
]]>
[translation]json与struts2[转]http://www.blogjava.net/i369/articles/203606.html芦苇芦苇wed, 28 may 2008 10:20:00 gmthttp://www.blogjava.net/i369/articles/203606.htmlhttp://www.blogjava.net/i369/comments/203606.htmlhttp://www.blogjava.net/i369/articles/203606.html#feedback0http://www.blogjava.net/i369/comments/commentrss/203606.htmlhttp://www.blogjava.net/i369/services/trackbacks/203606.html阅读全文

芦苇 2008-05-28 18:20
]]>
[译]struts menu开发向导 [转]http://www.blogjava.net/i369/articles/188258.html芦苇芦苇mon, 24 mar 2008 07:31:00 gmthttp://www.blogjava.net/i369/articles/188258.htmlhttp://www.blogjava.net/i369/comments/188258.htmlhttp://www.blogjava.net/i369/articles/188258.html#feedback0http://www.blogjava.net/i369/comments/commentrss/188258.htmlhttp://www.blogjava.net/i369/services/trackbacks/188258.html

一、从1.x升级到2.x需要做以下事情:
1、改变你的taglib声明中的uri。
 <% at taglib uri="" prefix="menu" %>
2、改变,使用新的包名"net.sf.navigator." 。
 
3、改变你的menu-config.xml文件,使用新的包名"net.sf.navigator." 。
     type="net.sf.navigator.displayer.simplemenudisplayer"/>

二、快速开始:
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设置。
 
        value="/web-inf/menu-config.xml"/>
 

3、你将需要在你的应用程序的/web-inf/menu-config.xml文件中定义你的菜单,这里提供一个简单的片断:
 


  
  
 

  更多全面的例程,请查看应用程序的web/web-inf目录中的menu-config.xml文件,你可以截取一段作为你需要的菜单。完整的属性列表,可以查看menubase class's javadocs()。
4、在你的jsp文件的顶部加入taglib声明:
 <% at taglib uri="" prefix="menu" %>
5、在你的jsp文件中要放置菜单的位置加入taglib代码:
     bundle="org.apache.struts.action.message">
  
  
 

  属性name="tabbedmenu"被定义在menu-config.xml文件的顶部:
     type="net.sf.navigator.displayer.tabbedmenudisplayer"/>

(译注:其实到此步即可在你的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定义:
       type="net.sf.navigator.displayer.velocitymenudisplayer"/>
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载入:
 
 
     net.sf.navigator.menu.menucontextlistener
 

或者如果你使用spring,甚至更容易。仅仅需要加入下面的部分到你的applicationcontext.xml文件中:
 
  
     /web-inf/menu-config.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开发项目,请参考此份开发向导()。



芦苇 2008-03-24 15:31
]]>
strus 2的新表单标志的使用 [转]http://www.blogjava.net/i369/articles/183622.html芦苇芦苇tue, 04 mar 2008 02:30:00 gmthttp://www.blogjava.net/i369/articles/183622.htmlhttp://www.blogjava.net/i369/comments/183622.htmlhttp://www.blogjava.net/i369/articles/183622.html#feedback0http://www.blogjava.net/i369/comments/commentrss/183622.htmlhttp://www.blogjava.net/i369/services/trackbacks/183622.html

 struts 2为大家提供了不少常用的很酷的表单标志,简化了我们程序员的工作。不过,由于这些都是新标志,大家可能在使用上还存在不少疑问。本文将就朋友们的回复、留言或email上的问题,分别对这些酷标志进行讲述。

表单标志使用小技巧

struts 2的表单标志在输出(render)html时,使用了模板的概念,增加了复杂性(因为它不像struts 1.x的表单标志,它通常都是一个标志对应html的一个元素),因此大家在使用时,需要一些技巧:

  1. struts 2的ui标志的表单标志默认是以表格布局,按钮是右对齐的。如果你不喜欢此风格,你可以简单地将标志的“theme”属性设为“simple”,然后用以往的做法自已布局表单元素(注意:此法有利有弊,弊就是当你将“theme”属性设为“simple”时,表单标志以最简单方式输出html,所以你可能失去一些默认输出提供的便利,如:友好的错误信息的显示,或客户端的表单验证等)。当然更好的做法是通过css或自定义主题(theme)然后应用到整个应用程序,这样可以获得一致的页面风格,加强用户体验(我会在以后的文章对此进行讲解);
  2. 当你在页面上加入某些标志(如:等)时,应该通过action来访问页面,而不是通过*.jsp的url直接访问。

下面我将分别对这些标志进行讲述:

1、

大家对的最大的疑问可能是:“如何在默认情况下,选中某些checkbox?”

答案其实很简单,只需要将其“value”属性设为你的要选中的值,如以代码所示:

<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   
<title>struts 2 cool tags - <s:checkboxlist/ >title>
   
<s:head />
head>
<body>    
   
<h2><s:checkboxlist/>h2>
   
<s:form action="store">
       
<s:checkboxlist name="skills1" 
                        label
="skills 1" 
                        list
="{ 'java', '.net', 'ror', 'php' }" 
                        value
="{ 'java', '.net' }"/>
       
<s:checkboxlist name="skills2" 
                        label
="skills 2" 
                        list
="#{ 1:'java', 2: '.net', 3: 'ror', 4: 'php' }" 
                        listkey
="key" 
                        listvalue
="value" 
                        value
="{ 1, 2, 3 }"/>
   
s:form>
body>
html>
清单1 webcontent/checkboxlist.jsp

分布运行应用程序,在浏览器中键入:,出现如下图所示页面:

checkboxlist.jsp页面
清单2 checkboxlist.jsp页面

2、

大家看struts 2的showcase的例子,的用法如下所示:

    <s:doubleselect
           
tooltip="choose your state"
            label
="state"
            name
="region" list="{'north', 'south'}"
            value
="'south'"
            doublevalue
="'florida'"
            doublelist
="top == 'north' ? {'oregon', 'washington'} : {'texas', 'florida'}" 
            doublename
="state"
            headerkey
="-1"
            headervalue
="---------- please select ----------"
            emptyoption
="true"/>
清单3 showcase中

很多朋友问:“上面的‘list’属性只有两个值,如果我有三个或更多的值,‘doublelist’属性应该如何设定呢?”

我建议的做法是先定义一个map类型的对象,键为“list”的集合,值则为“doublelist”的集合,然后“doublelist”的ognl写成“#mymap[top]”,如以下代码所示:

<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   
<title>struts 2 cool tags - <s:doubeselect/ >title>
   
<s:head />
head>
<body>    
   
<h2><s:doubleselect/>h2>
   
<s:form action="store">
       
<s:set name="foobar" 
               value
="#{'java': {'spring', 'hibernate', 'struts 2'}, '.net': {'linq', ' asp.net 2.0'}, 'database': {'oracle', 'sql server', 'db2', 'mysql'}}"/>
       
<s:doubleselect list="#foobar.keyset()"
                          doublename
="technology" 
                          doublelist
="#foobar[top]" 
                          label
="technology"/>
   
s:form>
body>
html>
清单4 webcontent/doubleselect.jsp

分布运行应用程序,在浏览器中键入:,出现如下图所示页面:

doubleselect.jsp页面
清单5 doubleselect.jsp页面

3、

这个标志可能大家不常用,不过本人认为它还是挺有用的。在使用struts 1.x时,因为跳转通常是用forward(而不是redirect)实现的,所以当用户完成请求后,按“f5”刷新页面时,就会重新提交上次的请求,这样经常会出错。要解决这个问题,可以帮你忙。

实现原理

在页面加载时,产生一个guid(globally unique identifier,全局唯一标识符)值的隐藏输入框如:

<input type="hidden" name="struts.token.name" value="struts.token"/>
<input type="hidden" name="struts.token" value="bxpnndg6bb11zxhpi4e106cz5k7vnmhr"/>
清单6 的html输出

同时,将guid放到会话(session)中;在执行action之前,“token”拦截器将会话token与请求token比较,如果两者相同,则将会话中的token删除并往下执行,否则向actionerrors加入错误信息。如此一来,如果用户通过某种手段提交了两次相同的请求,两个token就会不同。

具体实现

首先看一下action的代码:

package tutorial;

import com.opensymphony.xwork2.actionsupport;

publicclass cooltagaction extends actionsupport {    
   
privatestaticfinallong serialversionuid =6820659617470261780l;
   
   
private string message;
       
   
public string getmessage() {
       
return message;
   }


   
publicvoid setmessage(string message) {
       
this.message = message;
   }

   
   @override
   
public string execute() {
       system.out.println(
"executing action, your message is " message);
       
return success;
   }
   
}
清单7 src/tutorial/cooltagaction.java

以上代码一目了然,再看看jsp的写法:

%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags"%>

doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   
<title>struts 2 cool tags - <s:token/ >title>
   
<s:head />
head>
<body>    
   
<h2><s:token/>h2>
   
<s:actionerror />
   
<s:form action="token">
       
<s:textfield name="message" label="message"/>
       
<s:token />
       
<s:submit />
   
s:form>
body>
html>
清单8 webcontent/token.jsp

jsp也很简单,就是加入标志。接下来是actoin配置的xml片段:

xml version="1.0" encoding="utf-8"?>

doctype struts public
    "-//apache software foundation//dtd struts configuration 2.0//en"
    "http://struts.apache.org/dtds/struts-2.0.dtd"
>

<struts>
   
<package name="struts2_cool_tags_demo" extends="struts-default">
       
<action name="token" class="tutorial.cooltagaction">
           
<interceptor-ref name="defaultstack"/>
           
<interceptor-ref name="token"/>
           
<result name="invalid.token">/token.jspresult>                        
           
<result>/token.jspresult>
       
action>
       
<action name="*">
           
<result>/{1}.jspresult>
       
action>
   
package>
struts>
清单9 src/struts.xml

以上xml片段值注意的是加入了“token”拦截器和“invalid.token”结果,因为“token”拦截器在会话token与请求token不一致时,将会直接返回“invalid.token”结果。

发布运行应用程序,在浏览器中键入:,出现如下图所示页面:

正常显示的token.jsp页面
清单10 正常显示的token.jsp页面

随便填点东西并提交页面,一切正常返回以上页面,然后按“f5”刷新页面,在弹出的对话框中点击“retry”,出现如下图所示页面:

重复提交出错显示
清单11 重复提交出错显示

4、

这几个标志的使用相对简单,所以我想小举一例即可,以下是jsp的代码:

doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   
<title>struts 2 cool tags - otherstitle>
   
<s:head />
head>
<body>    
   
<h2>othersh2>
   
<s:form action="store">
       
<s:datetimepicker name="birthday" label="birthday"/>
       
<s:updownselect
           
label = "favourite countries"
            list
="#{'england':'england', 'america':'america', 'germany':'germany'}"
            name
="prioritisedfavouritecountries"
            headerkey
="-1"
            headervalue
="--- please order them accordingly ---"
            emptyoption
="true"/>
       
<s:optiontransferselect            
           
label="favourite cartoons characters"
            name
="leftsidecartooncharacters" 
            lefttitle
="left title"
            righttitle
="right title"
            list
="{'popeye', 'he-man', 'spiderman'}" 
            multiple
="true"
            headerkey
="headerkey"
            headervalue
="--- please select ---"
            emptyoption
="true"
            doublelist
="{'superman', 'mickey mouse', 'donald duck'}" 
            doublename
="rightsidecartooncharacters"
            doubleheaderkey
="doubleheaderkey"
            doubleheadervalue
="--- please select ---" 
            doubleemptyoption
="true"
            doublemultiple
="true"/>
   
s:form>
body>
html>
清单12 webcontent\others.jsp页面

发布运行应用程序,在浏览器中键入:,出现如下图所示页面:


清单13 其它表单标志页面

总结

struts 2在标志上的确比struts 1.x丰富了许多,同时模板机制也给程序员带来不少方便(如果你不太喜欢个性化的风格)。另外,struts 2还有一些ajax(如等)的标志和非表单的ui标志(如等),我会在以后的文章中讲述其使用。


原作者:http://www.blogjava.net/max/archive/2007/05/18/118442.html

芦苇 2008-03-04 10:30
]]>
转换器(converter)——struts 2.0中的魔术师(struts2中数据批量保存)[转别人的]http://www.blogjava.net/i369/articles/183607.html芦苇芦苇tue, 04 mar 2008 01:25:00 gmthttp://www.blogjava.net/i369/articles/183607.htmlhttp://www.blogjava.net/i369/comments/183607.htmlhttp://www.blogjava.net/i369/articles/183607.html#feedback0http://www.blogjava.net/i369/comments/commentrss/183607.htmlhttp://www.blogjava.net/i369/services/trackbacks/183607.html阅读全文

芦苇 2008-03-04 09:25
]]>
struts 1.x中批量封装对象http://www.blogjava.net/i369/articles/183603.html芦苇芦苇tue, 04 mar 2008 01:19:00 gmthttp://www.blogjava.net/i369/articles/183603.htmlhttp://www.blogjava.net/i369/comments/183603.htmlhttp://www.blogjava.net/i369/articles/183603.html#feedback0http://www.blogjava.net/i369/comments/commentrss/183603.htmlhttp://www.blogjava.net/i369/services/trackbacks/183603.html阅读全文

芦苇 2008-03-04 09:19
]]>
struts2 strus.xml中result类型及含义http://www.blogjava.net/i369/articles/169286.html芦苇芦苇fri, 21 dec 2007 05:04:00 gmthttp://www.blogjava.net/i369/articles/169286.htmlhttp://www.blogjava.net/i369/comments/169286.htmlhttp://www.blogjava.net/i369/articles/169286.html#feedback0http://www.blogjava.net/i369/comments/commentrss/169286.htmlhttp://www.blogjava.net/i369/services/trackbacks/169286.html一个提交到服务器的处理通常可以分为两个阶段,第一个阶段查询服务器状态(查询或者更新数据库),第二个阶段选择一个合适的结果页面其返回给用户(这里要讲的result的内容)。

 

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标签内部,所以上述代码的最简单的写法为:

/thankyou.jsp

 

我们也可以定义多个不同的result

 /hello/result.jsp

 /hello/error.jsp

 /hello/input.jsp

上述代码的含义为,名字为hello的action有三个返回结果,并且都是dispatcher类型(默认类型),这三个返回值的名字分别为success(默认值),error,input,对应的页面的路径分别为/hello/result.jsp,/hello/error.jsp,/hello/input.jsp。

 

有些时候我们需要一个定义在全局的result,这个时候我们可以在package内部定义全局的result,例如:

 /error.jsp

 /error.jsp

 logon!input

 

动态返回结果

有些时候,只有当action执行完璧的时候我们才知道要返回哪个结果,这个时候我们可以在action内部定义一个属性,这个属性用来存储action执行完璧之后的result值,例如:

private string nextaction; 

public string getnextaction() {

    return nextaction;

}

 

在strutx.xml配置文件中,我们可以使用${nextaction}来引用到action中的属性,通过${nextaction}表示的内容来动态的返回结果,例如:

 ${nextaction}

 

上述action的execute方法返回next的时候,还需要根据nextaction的属性来判断具体定位到哪个action。

 

在strutx.xml配置文件中,我们可以使用method=""来设置调用类的哪个方法,这样就可以在一个java类中使用不同的方法来实现不同的功能,就无需每个功能写一类了,例如:

      /success.jsp



芦苇 2007-12-21 13:04
]]>
struts2拦截器的使用 (详解)http://www.blogjava.net/i369/articles/162407.html芦苇芦苇thu, 22 nov 2007 08:58:00 gmthttp://www.blogjava.net/i369/articles/162407.htmlhttp://www.blogjava.net/i369/comments/162407.htmlhttp://www.blogjava.net/i369/articles/162407.html#feedback1http://www.blogjava.net/i369/comments/commentrss/162407.htmlhttp://www.blogjava.net/i369/services/trackbacks/162407.html  

芦苇 2007-11-22 16:58
]]>
struts 2中的ognl [转]http://www.blogjava.net/i369/articles/162409.html芦苇芦苇thu, 22 nov 2007 08:58:00 gmthttp://www.blogjava.net/i369/articles/162409.htmlhttp://www.blogjava.net/i369/comments/162409.htmlhttp://www.blogjava.net/i369/articles/162409.html#feedback0http://www.blogjava.net/i369/comments/commentrss/162409.htmlhttp://www.blogjava.net/i369/services/trackbacks/162409.htmlstruts 2中的ognl
本人是一个el(expression language,以下译为表达式语言)的支持者。因为我对<% %>写法极为反感,忘记了在那本书上看到的一句话——“使用标志(tag)的一个目的就是避免在jsp页面中出现过多的<%%>的语句,使页面与后台代码分离。”

表达式语言主要有以下几大好处:

避免(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=""
     xmlns:xsi=""
     xsi:schemalocation=" ">

     struts 2 ognl
    
    
         struts-cleanup
        
             org.apache.struts2.dispatcher.actioncontextcleanup
        

    

    
    
         struts-cleanup
         /*
    

    
    
         struts2
        
             org.apache.struts2.dispatcher.filterdispatcher
        

    

    
         struts2
         /*
    

    
         index.html
    

清单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 session;
     private servletcontext application;
     private list books;
            
     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 getbooks() {
         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">

     struts ognl demo

    
    

访问ognl上下文和action上下文


    

parameters:


    

request.username:


    

session.username:


    

application.username:


    

attr.username:


    

    

用于过滤和投影(projecting)集合


    

books more than $35


    

            
                
  • - $

  •         

        

    

the price of "code complete, second edition" is:


    

    

构造map


    
    

the value of key "foo1" is



清单3 webcontent/ognl.jsp
以上代码值得注意的是“”,因为“books.{?#this.title=='code complete, second edition'}.{price}”返回的值是集合类型,所以要用“[索引]”来访问其值。

最后是struts 2的配置文件struts.xml,内容如下:

     "-//apache software foundation//dtd struts configuration 2.0//en"
     "">


    
    
        
             /ognl.jsp
        
        
    

清单4 src/struts.xml

发布运行应用程序,结果如下所示:


清单5 示例运行结果1

“%”符号的用途是在标志的属性为字符串类型时,计算ognl表达式的值。例如在ognl.jsp中加入以下代码:



    

%的用途


    


    

清单6 演示%用途的代码片段
刷新页面,结果如下所示:

清单7 示例运行结果2

“$”有两个主要的用途

用于在国际化资源文件中,引用ognl表达式,例子请参考《在struts 2.0中国际化(i18n)您的应用程序》
在struts 2配置文件中,引用ognl表达式,如
                         
             listphotos.action?albumid=${albumid}
        
清单8 演示$用途的代码片段
总结
ognl是一种功能很大的表达式语言,熟悉它可以使我们的开发变得更快捷。



芦苇 2007-11-22 16:58
]]>
struts2 ognl 与 jsp2.1 el 的冲突问题http://www.blogjava.net/i369/articles/162318.html芦苇芦苇thu, 22 nov 2007 03:13:00 gmthttp://www.blogjava.net/i369/articles/162318.htmlhttp://www.blogjava.net/i369/comments/162318.htmlhttp://www.blogjava.net/i369/articles/162318.html#feedback0http://www.blogjava.net/i369/comments/commentrss/162318.htmlhttp://www.blogjava.net/i369/services/trackbacks/162318.html 由于 nio 带来的性能提升,tomcat6 不能被忽略。

办法1:





改用-------------------------------------------------------------


这样 jsp2.1 el 就不会有问题了。

办法2: 对于旧的程序,不愿意改了,可以向后兼容


必须用 servlet 2.5 xsd.
2.5" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">



true



或者在页面中
<%@page  language="java" deferredsyntaxallowedasliteral="true" %>

办法3 :不用 jsp2.1 el

>
>
> *.jsp
> true
>

>



我现在的疑问
在一个页面中采用两个 el 引擎,是否会对性能造成一定影响?
较小。



















西津渡 ,

webwork ognl的list集合与jsp el 冲突问题解决     
将: 

<ww:radio list="#{"d":"草稿箱","s":"直接发表"}"    name="saveposition">ww:radio>

改:

<ww:radio list="#@java.util.hashmap@{"d":"草稿箱","s":"直接发表"}"    name="saveposition">ww:radio> 


芦苇 2007-11-22 11:13
]]>
struts2与struts1对比http://www.blogjava.net/i369/articles/157718.html芦苇芦苇fri, 02 nov 2007 04:07:00 gmthttp://www.blogjava.net/i369/articles/157718.htmlhttp://www.blogjava.net/i369/comments/157718.htmlhttp://www.blogjava.net/i369/articles/157718.html#feedback0http://www.blogjava.net/i369/comments/commentrss/157718.htmlhttp://www.blogjava.net/i369/services/trackbacks/157718.htmlstruts2与struts1对比

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时,

action2
/*

把/*改成*.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" %>


hello world!





将该文件拷贝到步骤1中制作的目录struts2\example中。
4.制作java文件helloworld.java

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


http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi=""
    xsi:schemalocation=" -

app_2_4.xsd"
    version="2.4">

struts blank


struts2
org.apache.struts2.dispatcher.filterdispatcher


struts2
/*


index.html


将该文件拷贝到步骤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"
"">



/example/helloworld.jsp




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" %>


   
        condition flow
   
   
       

condition flow

           
       
        " />
       
            max's file here
       

       
            scott's file here
       

       
            other's file here
       
       
   

例1 condition.jsp

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);
%>

   
        iterator
   
   
       

names:


       
       

                               
                   
                       
  1. white

  2.                

                   
                       

  3.                

               

           

   

例2 iterator.jsp

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" %>



   
        internationization
   
   
       


           
               
           

       


   

例3 i18n.jsp

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" %>



   
        iterator
   
   
       

interator page


       
            max
       

       

i18n


       
   

例4 include.jsp

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" %>


   
        url
   
   
       

url

           
       

       
            max
       
       
        if\elseif\else
   

例5 url.jsp

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中加入下面代码:

   /helloworld.jsp
例2 classes/struts.xml中alaishelloworld action的配置
通过上面的两个例子,细心的朋友应该可能会发现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
例3 classes/struts.xml中vmhelloworld action的配置

新建helloworld.vm,内容如下所示:

 
    velocity
   
 
 
   

message rendered in velocity: $message


 
例3 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"%>


    hello world!


   


       
       
message from session:
   



例6 servlet.jsp


    /servlet.jsp


    /servlet.jsp

 


--------------------------------------------------------------------------------
在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"%>


    hello world


   


   




资源文件查找顺序
之所以说struts 2.0的国际化更灵活是因为它可以能根据不同需要配置和获取资源(properties)文件。在struts

2.0中有下面几种方法:

使用全局的资源文件,方法如上例所示。这适用于遍布于整个应用程序的国际化字符串,它们在不同的包(package)

中被引用,如一些比较共用的出错提示;
使用包范围内的资源文件。做法是在包的根目录下新建名的package.properties和package_xx_xx.properties文件。

这就适用于在包中不同类访问的资源;
使用action范围的资源文件。做法为action的包下新建文件名(除文件扩展名外)与action类名同样的资源文件。它

只能在该action中访问。如此一来,我们就可以在不同的action里使用相同的properties名表示不同的值。例如,在

actonone中title为“动作一”,而同样用title在actiontwo表示“动作二”,节省一些命名工夫;
使用标志访问特定路径的properties文件。使用方法请参考我早前的文章《常用的struts 2.0的标志(tag)

介绍》。在您使用这一方法时,请注意标志的范围。在之间,所有的国

际化字符串都会在名为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 getlocales() {
        map locales =new hashtable(2);
        locales.put("american english", locale.us);
        locales.put("simplified chinese", locale.china);
        return locales;
    }
}tutorial/locales.java

< prefix="s" uri="/struts-tags"%>



" name="langform"
    style="background-color: powderblue; padding-top: 4px; padding-bottom: 4px;">
    language:         list="#locales.locales" listkey="value"    listvalue="key"
        value="#session_locale == null ? locale : #session_locale"
        name="request_locale" id="langselecter"
        onchange="langselecter_onchanged()" theme="simple"/>
langselector.jsp
上述代码的原理为,langselector.jsp先实例化一个locales对象,并把对象的map类型的属性locales赋予下拉列表(

select) 。如此一来,下拉列表就获得可用语言的列表。大家看到langselector有标志和一段javascript脚

本,它们的作用就是在用户在下拉列表中选择了后,提交包含“reqeust_locale”变量的表单到action。在打开页面

时,为了下拉列表的选中的当前区域,我们需要到session取得当前区域(键为“ww_trans_i18n_locale”的属性),

而该属性在没有设置语言前是为空的,所以通过值栈中locale属性来取得当前区域(用户浏览器所设置的语言)。

你可以把langselector.jsp作为一个控件使用,方法是在jsp页面中把它包含进来,代码如下所示:

value="/langselector.jsp"/>
在例1中的hellloworld.jsp中后加入上述代码,并在struts.xml中新建action,代码如下:

    /helloworld.jsp

或者,如果你多个jsp需要实现上述功能,你可以使用下面的通用配置,而不是为每一个jsp页面都新建一个action。

    /{1}.jsp

分布运行程序,在浏览器的地址栏中输入,出现图4所示页

面:

图3 helloworld.action

在下拉列表中,选择“american english”,出现图5所示页面:

图4 helloworld.action
可能大家会问为什么一定要通过action来访问页面呢?
你可以试一下不用action而直接用jsp的地址来访问页面,结果会是无论你在下拉列表中选择什么,语言都不会改变。

这表示不能正常运行的。其原因为如果直接使用jsp访问页面,struts 2.0在web.xml的配置的过滤器(filter)就不

会工作,所以拦截器链也不会工作。



芦苇 2007-11-02 12:07
]]>
深入了解struts中的struts-config.xml http://www.blogjava.net/i369/articles/151217.html芦苇芦苇tue, 09 oct 2007 00:50:00 gmthttp://www.blogjava.net/i369/articles/151217.htmlhttp://www.blogjava.net/i369/comments/151217.htmlhttp://www.blogjava.net/i369/articles/151217.html#feedback0http://www.blogjava.net/i369/comments/commentrss/151217.htmlhttp://www.blogjava.net/i369/services/trackbacks/151217.html深入了解struts中的struts-config.xml 

 弄清楚struts-config.xml中各项元素的作用,对于我们构建web项目有莫大的好处。是struts的根元素,它主要有8个子元素,dtd定义如下:

(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的完整类名。必须。
如下所示:

         name="loign"
      type="com.ha.login">
  


  如果是动态action formbean,还必须配置form-bean元素的form-property子元素。它包含四个属性,上面三个,还有一个initial 元素:以字符串的形式设置表单字段的初始值,如果没有设置该属性,则是基本类型为0,如果是对象则为null。可有可无。如下所示:

         name="loign"
      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
如下所示:

         key="global.error.invalidlogin"
      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属性只能选中其中一项。
如下:
    type="zxj.okbean"
    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
如下:
  contenttype="text/html;charset="utf-8""
  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接口。如:
  classname="a.b.c.">
  

 后记,多模块的配置,可以供多个应用应用不同的struts-config.xml

(转载于:)



芦苇 2007-10-09 08:50
]]>
struts2访问隐藏的request和session http://www.blogjava.net/i369/articles/135780.html芦苇芦苇fri, 10 aug 2007 05:12:00 gmthttp://www.blogjava.net/i369/articles/135780.htmlhttp://www.blogjava.net/i369/comments/135780.htmlhttp://www.blogjava.net/i369/articles/135780.html#feedback1http://www.blogjava.net/i369/comments/commentrss/135780.htmlhttp://www.blogjava.net/i369/services/trackbacks/135780.html在struts1.*中,要想访问request、response以及session等servlet对象是很方便的,因为它们一直是作为形参在各个方法之间进行传递的,而在struts2中我们就很难看到它们的芳踪了,因为我们获得表单中的值都是通过预先设置好了的get方法来得到的,那么如果有些参数我们必须通过request.getparametre或者session.getattribute来得到,那么应该怎么做呢?按照max的教程上的说法,可以分为两种:ioc方式和非ioc方式,如何理解这两种方式的区别呢?ioc是spring里面的特征之一,字面意思是反转控制,说白了就是依赖注入,比方说类a依赖类b,那么就主动的给a注入一个类b的对象,下面看一下这两种方法的具体实现。
1.非ioc方式
这种方式主要是利用了com.opensymphony.xwork2.actioncontext类以及org.apache.struts2.servletactioncontext类,具体的方法如下所示。
获得request对象:
ahttpservletrequest request = servletactioncontext.getrequest ();
b.actioncontext ct= actioncontext.getcontext()
   httpservletrequest request=
(httpservletrequest)ct.get(servletactioncontext.http_request);
获得session对象:
在struts2中底层的session都被封装成了map类型,我们称之为sessionmap,而平常我们所说的session则是指httpsession对象,具体的获得方法如下所示。
a.map session=actioncontext.getsession();
b.map session=(map)actioncontext.getcontext().get(actioncontext.session);
得到这个sessionmap之后我们就可以对session进行读写了,如果我们想得到原始的httpsession可以首先得到httpservletrequest对象,然后通过request.getsession()来取得原始的httpsession对象。一般情况下sessionmap已经可以完成所有的工作,我们不必再去碰底层的session了。
2.ioc方式
这种方式相对来说变化就比较少了,具体流程如下所示。
获得request对象:
第一步:让action实现servletrequestaware接口
第二步:在action中声明一个httpservletrequest类型的实例变量
第三步:在action中实现servletrequestaware接口的setservletrequest方法,实现方式很简单,如下所示。
         private httpservletrequest request;
publicvoid setservletrequest(httpservletrequest request) {
            this.request = request;
    }
获得session对象(注意,此时的sessionsessionmap类型)
第一步:让action实现sessionaware接口
第二步:在action中声明一个httpservletrequest类型的实例变量
第三步:在action中实现sessionaware接口的setsession方法,实现方式很简单,如下所示。
         private map session;
publicvoid setsession(map session) {
            this. session = session;
    }
 trackback: http://tb.blog.csdn.net/trackback.aspx?postid=1721226


芦苇 2007-08-10 13:12
]]>
struts2的struts.properties配置文件详解 http://www.blogjava.net/i369/articles/135778.html芦苇芦苇fri, 10 aug 2007 05:07:00 gmthttp://www.blogjava.net/i369/articles/135778.htmlhttp://www.blogjava.net/i369/comments/135778.htmlhttp://www.blogjava.net/i369/articles/135778.html#feedback0http://www.blogjava.net/i369/comments/commentrss/135778.htmlhttp://www.blogjava.net/i369/services/trackbacks/135778.html          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模版应该被缓存 



芦苇 2007-08-10 13:07
]]>
webwork深入浅出http://www.blogjava.net/i369/articles/135461.html芦苇芦苇thu, 09 aug 2007 05:15:00 gmthttp://www.blogjava.net/i369/articles/135461.htmlhttp://www.blogjava.net/i369/comments/135461.htmlhttp://www.blogjava.net/i369/articles/135461.html#feedback0http://www.blogjava.net/i369/comments/commentrss/135461.htmlhttp://www.blogjava.net/i369/services/trackbacks/135461.html阅读全文

芦苇 2007-08-09 13:15
]]>
用struts上传文件时创建目录以及把文件上传到指定的目录 http://www.blogjava.net/i369/articles/134640.html芦苇芦苇mon, 06 aug 2007 02:56:00 gmthttp://www.blogjava.net/i369/articles/134640.htmlhttp://www.blogjava.net/i369/comments/134640.htmlhttp://www.blogjava.net/i369/articles/134640.html#feedback0http://www.blogjava.net/i369/comments/commentrss/134640.htmlhttp://www.blogjava.net/i369/services/trackbacks/134640.html在action里面取得路径:
string pathmydir = this.getservlet().getservletcontext().getrealpath("/uploads/");

file targetfolder = new file(pathmydir);
        if (targetfolder.isfile() || !targetfolder.exists())
       {
            targetfolder.mkdir();
       }

为避免重复文件名
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



芦苇 2007-08-06 10:56
]]>
struts-menu使用指南 http://www.blogjava.net/i369/articles/134616.html芦苇芦苇mon, 06 aug 2007 02:30:00 gmthttp://www.blogjava.net/i369/articles/134616.htmlhttp://www.blogjava.net/i369/comments/134616.htmlhttp://www.blogjava.net/i369/articles/134616.html#feedback0http://www.blogjava.net/i369/comments/commentrss/134616.htmlhttp://www.blogjava.net/i369/services/trackbacks/134616.html

 一、简介
  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"
    "
">


  my example application -- vinton lee
     
 
 
    action
    org.apache.struts.action.actionservlet
   
      config
      /web-inf/struts-config.xml
   

    1
 

 
   
 
 
    action
    *.do
 

 
 
 
 
    index.jsp
 

 
 
    struts-bean
    /web-inf/struts-bean.tld
 

 
    struts-html
    /web-inf/struts-html.tld
 

 
    struts-logic
    /web-inf/struts-logic.tld
 

 
    struts-nested
    /web-inf/struts-nested.tld
 

 
    struts-tiles
    /web-inf/struts-tiles.tld
 

 
 
 
 
    struts-menu
    /web-inf/struts-menu.tld
 

 

  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,内容如下:

 
                     type="net.sf.navigator.displayer.dropdownmenudisplayer"/>
                     type="net.sf.navigator.displayer.simplemenudisplayer"/>
                     type="net.sf.navigator.displayer.coolmenudisplayer"/>
                     type="net.sf.navigator.displayer.coolmenudisplayer4"/>
                     type="net.sf.navigator.example.permissionsformmenudisplayer"/>
                     type="net.sf.navigator.displayer.listmenudisplayer"/>
                     type="net.sf.navigator.displayer.tabbedmenudisplayer"/>
                     type="net.sf.navigator.displayer.velocitymenudisplayer"/>
 

 
   
      
           http://www.yahoo.com.cn"/>
           http://cn.mail.yahoo.com"/>
      
       http://www.sohu.com"/>
       http://www.sina.com.cn"/>
   
 

  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" %>

    bundle="org.apache.struts.action.message">
   

  运行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文件部分:
 
   
      
           http://www.yahoo.com.cn"/>
           http://cn.mail.yahoo.com"/>
      
       http://www.sohu.com"/>
       http://www.sina.com.cn"/>
   
 

  重起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和权限控制:

   
   


  重起tomcat,在地址栏输入

七、关于struts-menu配置文件和api的使用方法,请参考附录中的官方网站


附:
struts-menu官方网站:

数据库驱动的动态菜单:




trackback:




芦苇 2007-08-06 10:30
]]>
使用struts-menu_详细实现动态菜单http://www.blogjava.net/i369/articles/124651.html芦苇芦苇sat, 16 jun 2007 06:59:00 gmthttp://www.blogjava.net/i369/articles/124651.htmlhttp://www.blogjava.net/i369/comments/124651.htmlhttp://www.blogjava.net/i369/articles/124651.html#feedback0http://www.blogjava.net/i369/comments/commentrss/124651.htmlhttp://www.blogjava.net/i369/services/trackbacks/124651.html准备工作:

 

下载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目录。内容如下:

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"/>
  
displayers>
  
menuconfig>

 

 

 

   <plug-in classname="net.sf.navigator.menu.menuplugin">
      
<set-property property="menuconfig"
        value
="/web-inf/menu-config.xml"/>
   
plug-in>

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中增加

<context-param>
        
<param-name>javax.servlet.jsp.jstl.fmt.localizationcontextparam-name>
        
<param-value>trackerresparam-value>
    
context-param>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

7,修改struts-config.xml 文件,增加如下部分

11,创建数据库

 

       仿造如下代码创建数据库

    <sql:update>
        
create table menu_item (
           id bigint 
not null
,
           parent_name 
varchar(30
),
           name 
varchar(30
),
           title 
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)
        )
sql:update>

12,填写数据库

 

 

 

 



trackback: http://tb.blog.csdn.net/trackback.aspx?postid=640825



芦苇 2007-06-16 14:59
]]>
struts-menu使用指南 http://www.blogjava.net/i369/articles/124649.html芦苇芦苇sat, 16 jun 2007 06:58:00 gmthttp://www.blogjava.net/i369/articles/124649.htmlhttp://www.blogjava.net/i369/comments/124649.htmlhttp://www.blogjava.net/i369/articles/124649.html#feedback0http://www.blogjava.net/i369/comments/commentrss/124649.htmlhttp://www.blogjava.net/i369/services/trackbacks/124649.html

一、简介
  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"
    "
">


  my example application -- vinton lee
     
 
 
    action
    org.apache.struts.action.actionservlet
   
      config
      /web-inf/struts-config.xml
   

    1
 

 
   
 
 
    action
    *.do
 

 
 
 
 
    index.jsp
 

 
 
    struts-bean
    /web-inf/struts-bean.tld
 

 
    struts-html
    /web-inf/struts-html.tld
 

 
    struts-logic
    /web-inf/struts-logic.tld
 

 
    struts-nested
    /web-inf/struts-nested.tld
 

 
    struts-tiles
    /web-inf/struts-tiles.tld
 

 
 
 
 
    struts-menu
    /web-inf/struts-menu.tld
 

 

  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,内容如下:

 
                     type="net.sf.navigator.displayer.dropdownmenudisplayer"/>
                     type="net.sf.navigator.displayer.simplemenudisplayer"/>
                     type="net.sf.navigator.displayer.coolmenudisplayer"/>
                     type="net.sf.navigator.displayer.coolmenudisplayer4"/>
                     type="net.sf.navigator.example.permissionsformmenudisplayer"/>
                     type="net.sf.navigator.displayer.listmenudisplayer"/>
                     type="net.sf.navigator.displayer.tabbedmenudisplayer"/>
                     type="net.sf.navigator.displayer.velocitymenudisplayer"/>
 

 
   
      
           http://www.yahoo.com.cn"/>
           http://cn.mail.yahoo.com"/>
      
       http://www.sohu.com"/>
       http://www.sina.com.cn"/>
   
 

  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" %>

    bundle="org.apache.struts.action.message">
   

  运行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文件部分:
 
   
      
           http://www.yahoo.com.cn"/>
           http://cn.mail.yahoo.com"/>
      
       http://www.sohu.com"/>
       http://www.sina.com.cn"/>
   
 

  重起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和权限控制:

   
   


  重起tomcat,在地址栏输入

七、关于struts-menu配置文件和api的使用方法,请参考附录中的官方网站


附:
struts-menu官方网站:

数据库驱动的动态菜单:




trackback: http://tb.blog.csdn.net/trackback.aspx?postid=496331



芦苇 2007-06-16 14:58
]]>
struts menu中文文档综述 http://www.blogjava.net/i369/articles/124650.html芦苇芦苇sat, 16 jun 2007 06:58:00 gmthttp://www.blogjava.net/i369/articles/124650.htmlhttp://www.blogjava.net/i369/comments/124650.htmlhttp://www.blogjava.net/i369/articles/124650.html#feedback2http://www.blogjava.net/i369/comments/commentrss/124650.htmlhttp://www.blogjava.net/i369/services/trackbacks/124650.html1.       overview

 

struts menu应用是一个jsp标记的集合,支持从xml文件生成各种不同菜单系统。struts menu 2.0进行了重构,使用velocity templates定义菜单。

blogjava-凯发k8网页登录

要从struts menu1.x升级到2.x,需要做如下改变:

l         修改标记库声明的uri,去掉“1.2

<%@ taglib uri="http://struts-menu.sf.net/tag" prefix="menu" %>

l         修改,使用新的包名“net.sf.navigator

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,还需要将jakartastandard 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"标记中;然后在menu-config.xml文件中加入允许看到此菜单项的角色列表,角色之间以逗号分隔。

 

 

 

 

 

3.3.        基于数据库的动态菜单



芦苇 2007-06-16 14:58
]]>
ajax、struts、spring的无缝结合http://www.blogjava.net/i369/articles/111968.html芦苇芦苇thu, 19 apr 2007 08:03:00 gmthttp://www.blogjava.net/i369/articles/111968.htmlhttp://www.blogjava.net/i369/comments/111968.htmlhttp://www.blogjava.net/i369/articles/111968.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111968.htmlhttp://www.blogjava.net/i369/services/trackbacks/111968.html阅读全文

芦苇 2007-04-19 16:03
]]>
struts2与struts1的对比 http://www.blogjava.net/i369/articles/111965.html芦苇芦苇thu, 19 apr 2007 08:00:00 gmthttp://www.blogjava.net/i369/articles/111965.htmlhttp://www.blogjava.net/i369/comments/111965.htmlhttp://www.blogjava.net/i369/articles/111965.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111965.htmlhttp://www.blogjava.net/i369/services/trackbacks/111965.html来源:struts2开发组 翻译:tianxinet(胖猴)

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一起使用。


本文引用地址:




芦苇 2007-04-19 16:00
]]>
struts2的struts.properties配置文件详解http://www.blogjava.net/i369/articles/111964.html芦苇芦苇thu, 19 apr 2007 07:59:00 gmthttp://www.blogjava.net/i369/articles/111964.htmlhttp://www.blogjava.net/i369/comments/111964.htmlhttp://www.blogjava.net/i369/articles/111964.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111964.htmlhttp://www.blogjava.net/i369/services/trackbacks/111964.htmlstruts.action.extension
          the url extension to use to determine if the request is me for a struts action 
           用url扩展名来确定是否这个请求是被用作struts action,其实也就是设置 action的后缀,例如login.do的'do'字。

.configuration
          the org.apache.2.config.configuration implementation class
            org.apache.2.config.configuration接口名

.configuration.files
          a list of configuration files automatically loaded by struts 
           自动加载的一个配置文件列表

.configuration..reload
          whether to reload the xml configuration or not
           是否加载配置(true,false)

.continuations.package
           the package containing actions that use rife continuations
           含有actions的完整连续的package名称

.custom.i18n.resources
          location of additional localization properties files to load 
           加载附加的国际化属性文件(不包含.properties后缀)

.custom.properties
          location of additional configuration properties files to load
           加载附加的配置文件的位置


.devmode
          whether struts is in development mode or not
           是否为开发模式

.dispatcher.parametersworkaround
          whether to use a servlet request parameter workaround necessary for some versions of weblogic
            (某些版本的专用)是否使用一个servlet请求参数工作区(parametersworkaround)

.enable.dynamicmethodinvocation
          allows one to disable dynamic method invocation from the url
            允许动态方法调用

.freemarker.manager.classname
          the org.apache.2.views.freemarker.freemarkermanager implementation class 
           org.apache.2.views.freemarker.freemarkermanager接口名

.i18n.encoding
          the encoding to use for localization messages
           国际化信息内码

.i18n.reload
          whether the localization messages should automatically be reloaded
           是否国际化信息自动加载 

.locale
          the default locale for the struts application
           默认的国际化地区信息

.mapper.class
          the org.apache.2.dispatcher.mapper.actionmapper implementation class
            org.apache.2.dispatcher.mapper.actionmapper接口

.multipart.maxsize
          the maximize size of a multipart request (file upload)
           multipart请求信息的最大尺寸(文件上传用) 

.multipart.parser
          the org.apache.2.dispatcher.multipart.
          multipartrequest parser implementation for a multipart request (file upload) 
          专为multipart请求信息使用的org.apache.2.dispatcher.multipart.multipartrequest解析器接口(文件上传用)


.multipart.savedir
          the directory to use for storing uploaded files 
           设置存储上传文件的目录夹

.objectfactory
          the com.opensymphony.xwork2.objectfactory implementation class
           com.opensymphony.xwork2.objectfactory接口()

.objectfactory..autowire
          whether spring should autowire or not
           是否自动绑定spring

.objectfactory..useclasscache
          whether spring should use its class cache or not
           是否应该使用自身的cache 

.objecttypedeterminer
          the com.opensymphony.xwork2.util.objecttypedeterminer implementation class
            com.opensymphony.xwork2.util.objecttypedeterminer接口

.serve.static.browsercache
  if static content served by the struts filter should set browser caching header properties or not 
           是否过滤器中提供的静态内容应该被浏览器缓存在头部属性中

.serve.static
          whether the struts filter should serve static content or not 
           是否过滤器应该提供静态内容

.tag.altsyntax
          whether to use the alterative syntax for the tags or not 
           是否可以用替代的语法替代tags

.ui.templatedir
          the directory containing ui templates
           ui templates的目录夹 

.ui.theme
          the default ui template theme
           默认的ui template主题

.url.http.port
          the http port used by struts urls
           设置http端口

.url.https.port
          the https port used by struts urls 
           设置https端口

.url.includeparams
          the default includeparams method to generate struts urls 
          在url中产生 默认的includeparams


.velocity.configfile
          the velocity configuration file path
           velocity配置文件路径

.velocity.contexts
          list of velocity context names
           velocity的context列表


.velocity.manager.classname
          org.apache.2.views.velocity.velocitymanager implementation class
           org.apache.2.views.velocity.velocitymanager接口名

.velocity.toolboxlocation
          the location of the velocity toolbox
           velocity工具盒的位置 
.xslt.nocache
          whether or not xslt templates should not be cached
           是否xslt模版应该被缓存

请记住本文永久地址:



芦苇 2007-04-19 15:59
]]>
在struts 2.0中国际化(i18n)您的应用程序 http://www.blogjava.net/i369/articles/111922.html芦苇芦苇thu, 19 apr 2007 05:34:00 gmthttp://www.blogjava.net/i369/articles/111922.htmlhttp://www.blogjava.net/i369/comments/111922.htmlhttp://www.blogjava.net/i369/articles/111922.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111922.htmlhttp://www.blogjava.net/i369/services/trackbacks/111922.html国际化是商业系统中不可或缺的一部分,所以无论您学习的是什么web框架,它都是必须掌握的技能。

其实,struts 1.x在此部分已经做得相当不错了。它极大地简化了我们程序员在做国际化时所需的工作,例如,如果您要输出一条国际化的信息,只需在代码包中加入file-name_xx_xx.properties(其中file-name为默认资源文件的文件名),然后在struts-config.xml中指明其路径,再在页面用标志输出即可。

不过,所谓“没有最好,只有更好”。struts 2.0并没有在这部分止步,而是在原有的简单易用的基础上,将其做得更灵活、更强大。

国际化hello world

下面让我们看一个例子——helloworld。这个例子演示如何根据用户浏览器的设置输出相应的helloworld。

  1. 在eclipse创建工程配置开发和运行环境(如果对这个步骤有问题,可以参考我早前的文章《为struts 2.0做好准备》)。
  2. 在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)的配置
  3. 在src文件夹中加入globalmessages_en_us.properties文件,内容如下:
    helloworld=hello world!
  4. 在src文件夹中加入globalmessages_zh_cn.properties文件,内容如下:
    helloworld=你好,世界!
    在此想和大家分享一个不错的编写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的图标作为标识。
  5. 在webcontent文件夹下加入helloworl.jsp文件,内容如下:
    <%@ page  contenttype="text/html; charset=utf-8"%>
    <%@taglib prefix="s" uri="/struts-tags"%>
    <html>
    <head>
       
    <title>hello worldtitle>
    head>
    <body>
       
    <h2><s:text name="helloworld"/>h2>
       
    <h2><s:property value="%{gettext('helloworld')}"/>h2>
    body>
    html>
  6. 发布运行应用程序,在浏览器地址栏中输入 ,出现图1所示页面。
    图1 中文输出
    图1 中文输出
  7. 将浏览器的默认语言改为“英语(美国)”,刷新页面,出现图2所示页面。
    图2 英文输出
    图2 英文输出
上面的例子的做法,与struts 1.x的做法相似,似乎并不能体现struts 2.0的优势。不过,我在上面的例子用了两种方法来显示国际化字符串,其输出是相同的。其实,这就是struts 2.0的一个优势,因为它默认支持el,所示我们可以用gettext方法来简洁地取得国际化字符串。另外更普遍的情况——在使用ui表单标志时,gettext可以用来设置label属性,例如:
<s:textfield name="name" label="%{gettext('username')}"/>

资源文件查找顺序

之所以说struts 2.0的国际化更灵活是因为它可以能根据不同需要配置和获取资源(properties)文件。在struts 2.0中有下面几种方法:

  1. 使用全局的资源文件,方法如上例所示。这适用于遍布于整个应用程序的国际化字符串,它们在不同的包(package)中被引用,如一些比较共用的出错提示;
  2. 使用包范围内的资源文件。做法是在包的根目录下新建名的package.properties和package_xx_xx.properties文件。这就适用于在包中不同类访问的资源;
  3. 使用action范围的资源文件。做法为action的包下新建文件名(除文件扩展名外)与action类名同样的资源文件。它只能在该action中访问。如此一来,我们就可以在不同的action里使用相同的properties名表示不同的值。例如,在actonone中title为“动作一”,而同样用title在actiontwo表示“动作二”,节省一些命名工夫;
  4. 使用标志访问特定路径的properties文件。使用方法请参考我早前的文章《常用的struts 2.0的标志(tag)介绍》。在您使用这一方法时,请注意标志的范围。在之间,所有的国际化字符串都会在名为xxxxx资源文件查找,如果找不到,struts 2.0就会输出默认值(国际化字符串的名字)。

上面我列举了四种配置和访问资源的方法,它们的范围分别是从大到小,而struts 2.0在查找国际化字符串所遵循的是特定的顺序,如图3所示:

图3 资源文件查找顺序图
图3 资源文件查找顺序图

假设我们在某个childaction中调用了gettext("user.title"),struts 2.0的将会执行以下的操作:

  1. 查找childaction_xx_xx.properties文件或childaction.properties;
  2. 查找childaction实现的接口,查找与接口同名的资源文件myinterface.properties;
  3. 查找childaction的父类parentaction的properties文件,文件名为parentaction.properties;
  4. 判断当前childaction是否实现接口modeldriven。如果是,调用getmodel()获得对象,查找与其同名的资源文件;
  5. 查找当前包下的package.properties文件;
  6. 查找当前包的父包,直到最顶层包;
  7. 在值栈(value stack)中,查找名为user的属性,转到user类型同名的资源文件,查找键为title的资源;
  8. 查找在struts.properties配置的默认的资源文件,参考例1;
  9. 输出user.title。

参数化国际化字符串

许多情况下,我们都需要在动行时(runtime)为国际化字符插入一些参数,例如在输入验证提示信息的时候。在struts 2.0中,我们通过以下两种方法做到这点:

  1. 在资源文件的国际化字符串中使用ognl,格式为${表达式},例如:
    validation.require=${gettext(filename)} is required
  2. 使用中的字符串格式,格式为{ 参数序号(从0开始), 格式类形(number | date | time | choice), 格式样式},例如:
    validation.between=date must between {0, date, short} and {1, date, short}
在显示这些国际化字符时,同样有两种方法设置参数的值:
  1. 使用标志的value0、value1...valuen的属性,如:
    <s:text name="validation.required" value0="user name"/>
  2. 使用param子元素,这些param将按先后顺序,代入到国际化字符串的参数中,例如:
    <s:text name="validation.required">
       
    <s:param value="user name"/>
    s:text>

让用户方便地选择语言

开发国际化的应用程序时,有一个功能是必不可少的——让用户快捷地选择或切换语言。在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<string, locale> getlocales() {
       map
<string, locale> locales =new hashtable<string, locale>(2);
       locales.put(
"american english", locale.us);
       locales.put(
"simplified chinese", locale.china);
       
return locales;
   }

}
tutorial/locales.java

<%@taglib prefix="s" uri="/struts-tags"%>
<script type="text/javascript">

script>
<s:set name="session_locale" value="#session['ww_trans_i18n_locale']"/>
<s:bean id="locales" name="tutorial.locales"/>
<form action="get" encode="true"/>" name="langform" 
    style="background-color: powderblue; padding-top: 4px; padding-bottom: 4px;">
    language:
<s:select label="language" 
        list
="#locales.locales" listkey="value"    listvalue="key"
        value
="#session_locale == null ? locale : #session_locale"
        name
="request_locale" id="langselecter" 
        onchange
="langselecter_onchanged()" theme="simple"/>
form>
langselector.jsp

上述代码的原理为,langselector.jsp先实例化一个locales对象,并把对象的map类型的属性locales赋予下拉列表(select) 。如此一来,下拉列表就获得可用语言的列表。大家看到langselector有标志和一段javascript脚本,它们的作用就是在用户在下拉列表中选择了后,提交包含“reqeust_locale”变量的表单到action。在打开页面时,为了下拉列表的选中的当前区域,我们需要到session取得当前区域(键为“ww_trans_i18n_locale”的属性),而该属性在没有设置语言前是为空的,所以通过值栈中locale属性来取得当前区域(用户浏览器所设置的语言)。

你可以把langselector.jsp作为一个控件使用,方法是在jsp页面中把它包含进来,代码如下所示:
<s:include value="/langselector.jsp"/>

在例1中的hellloworld.jsp中后加入上述代码,并在struts.xml中新建action,代码如下:
<action name="helloworld">
   
<result>/helloworld.jspresult>
action>

或者,如果你多个jsp需要实现上述功能,你可以使用下面的通用配置,而不是为每一个jsp页面都新建一个action。
<action name="*">
   
<result>/{1}.jspresult>
action>

分布运行程序,在浏览器的地址栏中输入,出现图4所示页面:
图3 helloworld.action
图3 helloworld.action

在下拉列表中,选择“american english”,出现图5所示页面:
图3 helloworld.action
图4 helloworld.action
可能大家会问为什么一定要通过action来访问页面呢?
你可以试一下不用action而直接用jsp的地址来访问页面,结果会是无论你在下拉列表中选择什么,语言都不会改变。这表示不能正常运行的。其原因为如果直接使用jsp访问页面,struts 2.0在web.xml的配置的过滤器(filter)就不会工作,所以拦截器链也不会工作。
posted on 2006-11-01 19:06 max 阅读(3247) 评论(30)    所属分类: struts 2.0系列


芦苇 2007-04-19 13:34
]]>
常用的struts 2.0的标志(tag)介绍 http://www.blogjava.net/i369/articles/111921.html芦苇芦苇thu, 19 apr 2007 05:33:00 gmthttp://www.blogjava.net/i369/articles/111921.htmlhttp://www.blogjava.net/i369/comments/111921.htmlhttp://www.blogjava.net/i369/articles/111921.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111921.htmlhttp://www.blogjava.net/i369/services/trackbacks/111921.html阅读全文

芦苇 2007-04-19 13:33
]]>
在struts 2中实现文件上传 http://www.blogjava.net/i369/articles/111918.html芦苇芦苇thu, 19 apr 2007 05:29:00 gmthttp://www.blogjava.net/i369/articles/111918.htmlhttp://www.blogjava.net/i369/comments/111918.htmlhttp://www.blogjava.net/i369/articles/111918.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111918.htmlhttp://www.blogjava.net/i369/services/trackbacks/111918.html阅读全文

芦苇 2007-04-19 13:29
]]>
在struts 2中实现crud http://www.blogjava.net/i369/articles/111917.html芦苇芦苇thu, 19 apr 2007 05:28:00 gmthttp://www.blogjava.net/i369/articles/111917.htmlhttp://www.blogjava.net/i369/comments/111917.htmlhttp://www.blogjava.net/i369/articles/111917.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111917.htmlhttp://www.blogjava.net/i369/services/trackbacks/111917.html阅读全文

芦苇 2007-04-19 13:28
]]>
struts 2.0的action讲解 http://www.blogjava.net/i369/articles/111913.html芦苇芦苇thu, 19 apr 2007 05:24:00 gmthttp://www.blogjava.net/i369/articles/111913.htmlhttp://www.blogjava.net/i369/comments/111913.htmlhttp://www.blogjava.net/i369/articles/111913.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111913.htmlhttp://www.blogjava.net/i369/services/trackbacks/111913.html阅读全文

芦苇 2007-04-19 13:24
]]>
为struts 2.0做好准备http://www.blogjava.net/i369/articles/111909.html芦苇芦苇thu, 19 apr 2007 05:19:00 gmthttp://www.blogjava.net/i369/articles/111909.htmlhttp://www.blogjava.net/i369/comments/111909.htmlhttp://www.blogjava.net/i369/articles/111909.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111909.htmlhttp://www.blogjava.net/i369/services/trackbacks/111909.html阅读全文

芦苇 2007-04-19 13:19
]]>
struts 2的基石——拦截器(interceptor) http://www.blogjava.net/i369/articles/111907.html芦苇芦苇thu, 19 apr 2007 05:17:00 gmthttp://www.blogjava.net/i369/articles/111907.htmlhttp://www.blogjava.net/i369/comments/111907.htmlhttp://www.blogjava.net/i369/articles/111907.html#feedback0http://www.blogjava.net/i369/comments/commentrss/111907.htmlhttp://www.blogjava.net/i369/services/trackbacks/111907.html首先,要跟大家道个歉,前一阵子为给客户个一个demo,忙得不可开交,所以很久没有更新blog。提到这个demo我想顺便跟大家分享一下心得——如果大家希望快速开发,一个类似struts 2这样的简单方便的web框架必不可少。我们在开发demo使用的还是struts 1.2.8,而且没有不使用任何el(表达式语言),导致页面出现无数类似“<%= ((integer) request.getattribute("xx")).intvalue()%6 %>”的代码。struts 1.x的form bean的麻烦使得有部分同事直接使用request.getparameter(string arg),继而引入另一种麻烦。诸如此类的问题,在demo这样时间紧迫的项目凸显了struts 1.x对快速开发的无能为力。不过没办法,由于我们项目中的几个资深员工除了struts 1.x外,对其它的web框架似乎不大感兴趣。

言归正传,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 拦截器调用序列图
图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文件摘取的内容:

< interceptor name ="alias" class ="com.opensymphony.xwork2.interceptor.aliasinterceptor" />
< interceptor name ="autowiring" class ="com.opensymphony.xwork2.spring.interceptor.actionautowiringinterceptor" />
< interceptor name ="chain" class ="com.opensymphony.xwork2.interceptor.chaininginterceptor" />
< interceptor name ="conversionerror" class ="org.apache.struts2.interceptor.strutsconversionerrorinterceptor" />
< interceptor name ="createsession" class ="org.apache.struts2.interceptor.createsessioninterceptor"


芦苇 2007-04-19 13:17
]]>
网站地图