??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲人成在线精品,国产精品亚洲二区在线观看,亚洲一级毛片免费在线观看http://www.tkk7.com/fuhoujun/category/34967.htmlzh-cnSat, 04 Oct 2008 07:38:11 GMTSat, 04 Oct 2008 07:38:11 GMT60JSON与struts2 http://www.tkk7.com/fuhoujun/archive/2008/10/04/232324.html付厚?/dc:creator>付厚?/author>Sat, 04 Oct 2008 06:45:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232324.htmlhttp://www.tkk7.com/fuhoujun/comments/232324.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232324.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232324.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232324.html提供的一个插件包Q可以把Action中的数据?/span>JSON做个装然后q回?/span>

它会整?/span>action中的变量转化?/span>JSON数据(根对象在JSON中数据添加一?/span>”root”标识)。如果要使用它,Action必须遵@以下几点Q?/span>

1.       q回的页面类型中”content-type”必须?/span>”application/json”.(q个已经Internet Community采用).

2.       JSON内容必须是符合格式要求的.

3.       Action?/span>field必须?/span>public?/span>setҎ.(是不是没?/span>setҎ׃会将fieldd?/span>JSON数据中,有待验证).

4.       它支持的cd?/span>: 基本cd(int,long...String), Date, List, Map, Primitive Arrays, 其它class, 对象数组.

5.       ?/span>JSON中Q何的Object会被装?/span>list?/span>map中,数据会被装E?/span>LongQ如果是含有的数据则会被装E?/span>DoubleQ数l会被封装程List.

下面l出JSON的数据格?/span>:

{

   "doubleValue": 10.10,

   "nestedBean": {

      "name": "Mr Bean"

   },

   "list": ["A", 10, 20.20, {

      "firstName": "El Zorro"

   }],

   "array": [10, 20]

}

说明:

a.       q个插g支持以下几个注释:

注释?/span>

?/span>

默认?/span>

序列?/span>

反序列化

name

配置JSON?/span>name

empty

yes

no

serialize

?/span>serialization?/span>

true

yes

no

deserialize

?/span>deserialization?/span>

true

no

yes

format

格式?/span>Date字段

"yyyy-MM-dd'T'HH:mm:ss"

yes

yes

可以通过配置来显C指攑֜JSON?/span>fieldQ其中有个自q验证规则需要研I?/span>.

<!-- Result fragment -->

<result type="json">

 <param name="excludeProperties">

    login.password,

    studentList.*".sin

 </param>

</result>

<!-- Interceptor fragment -->

<interceptor-ref name="json">

 <param name="enableSMD">true</param>

 <param name="excludeProperties">

    login.password,

    studentList.*".sin

 </param>

</interceptor-ref>

b.       根对?/span>

 <result type="json">

 <param name="root">

    person.job

 </param>

</result>

也可以用拦截器配置操作父对?/span>

<interceptor-ref name="json">

 <param name="root">bean1.bean2</param>

</interceptor-ref>

c.       ?/span>JSON数据用注释封?/span>

如果wrapWithComments讄?/span>true(默认gؓfalse)Q则生成?/span>JSON数据会变成这P

/* {

   "doubleVal": 10.10,

   "nestedBean": {

      "name": "Mr Bean"

   },

   "list": ["A", 10, 20.20, {

      "firstName": "El Zorro"

   }],

   "array": [10, 20]

} */

q样做可以避?/span>js中一些潜在的风险Q用时需?/span>:

Var responseObject = eval("("+data.substring(data.indexOf(""/"*")+2, data.lastIndexOf(""*"/"))+")");

d.       父类

“root”对象中父cȝfield不会默认存放?/span>JSON数据中,如果不想q样做,需要在配置时指?/span>ignoreHierarchy?/span>false:

<result type="json">

 <param name="ignoreHierarchy">false</param>

</result>

e.       枚Dcd

默认处理枚DcdӞ会被处理?/span>JSON数据?/span>name{于枚D?/span>value?/span>value{于枚D?/span>name.

public enum AnEnum {

     ValueA,

     ValueB

 }

 JSON: "myEnum":"ValueA"

如果在处理枚丄型时Q在xml中配|了enumAsBeanQ则会被当作一?/span>Bean处理Q在JSON数据中会有一个特别的属?/span>”_name”name().q个枚D中的所有属性都会被处理.

public enum AnEnum {

     ValueA("A"),

     ValueB("B");

     private String val;

     public AnEnum(val) {

        this.val = val;

     }

     public getVal() {

        return val;

     }

   }

 JSON: myEnum: { "_name": "ValueA", "val": "A" }

Xml中配|?/span>:

<result type="json">

 <param name="enumAsBean">true</param>

</result>

f.        例子

a)         Action

import java.util.HashMap;

import java.util.Map;

import com.opensymphony.xwork2.Action;

public class JSONExample {

    private String field1 = "str";

    private int[] ints = {10, 20};

    private Map map = new HashMap();

    private String customName = "custom";

    //'transient' fields are not serialized

    private transient String field2;

    //fields without getter method are not serialized

    private String field3;

    public String execute() {

        map.put("John", "Galt");

        return Action.SUCCESS;

    }

    public String getField1() {

        return field1;

    }

    public void setField1(String field1) {

        this.field1 = field1;

    }

    public int[] getInts() {

        return ints;

    }

    public void setInts(int[] ints) {

        this.ints = ints;

    }

    public Map getMap() {

        return map;

    }

    public void setMap(Map map) {

        this.map = map;

    }

    @JSON(name="newName")

    public String getCustomName() {

        return this.customName;

    }

}

b)        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="example" extends="json-default">

     <action name="JSONExample" class="example.JSONExample">

        <result type="json"/>

     </action>

 </package>

</struts>

q里有两个地斚w要注?/span>:

1)      需要?/span>json-default?/span>

2)      <result>{定义

c)         JSON数据

 { 

   "field1" : "str",

   "ints": [10, 20],

   "map": {

       "John":"Galt"

   },

   "newName": "custom"

}

d)        JSON RPC

JSON插g可以?/span>js中调?/span>actionҎQ返回执行结果。这个已l在dojo中有了实玎ͼ可以?/span>Simple Method Definition调用q程服务。来一L看下面的例子Q?/span>

首先写一?/span>ActionQ?/span>

package smd;

import com.googlecode.jsonplugin.annotations.SMDMethod;

import com.opensymphony.xwork2.Action;

public class SMDAction {

    public String smd() {

        return Action.SUCCESS;

    }

    @SMDMethod

    public Bean doSomething(Bean bean, int quantity) {

        bean.setPrice(quantity * 10);

        return bean;

    }

}

e)         Ҏ必须?/span>SMDMethod加上注解Q这h能被q程调用Qؓ了安全因素。这个方法会产生一?/span>bean对象Q实C改h格的功能?/span>Action被添加上SMD注解会生成一?/span>SMDQ同时参C会被加上SMDMethodParameter注解。像你所看到的,Action中定义了一个空ҎQ?/span>smd。这个方法是作ؓSimple Method Definition (定义class中提供的服务)Q在struts.xml配置<result>时?/span>type属性gؓ”json”?/span>

下面?/span>bean的定义:

package smd;

public class Bean {

    private String type;

    private int price;

    public String getType() {

        return type;

    }

    public void setType(String type) {

        this.type = type;

    }

    public int getPrice() {

        return price;

    }

    public void setPrice(int price) {

        this.price = price;

    }

}

Xml文g:

<package name="RPC" namespace="/nodecorate" extends="json-default">

    <action name="SMDAction" class="smd.SMDAction" method="smd">

        <interceptor-ref name="json">

            <param name="enableSMD">true</param>

        </interceptor-ref>

        <result type="json">

             <param name="enableSMD">true</param>

        </result>

    </action>

</package>

q里需要注意一?/span>:” enableSMD”q个必须?/span>interceptor?/span>result都要配置.

Js代码:

<s:url id="smdUrl" namespace="/nodecorate" action="SMDAction" />

<script type="text/javascript">

    //load dojo RPC

    dojo.require("dojo.rpc.*");

    //create service object(proxy) using SMD (generated by the json result)

    var service = new dojo.rpc.JsonService("${smdUrl}");

    //function called when remote method returns

    var callback = function(bean) {

        alert("Price for " + bean.name + " is " + bean.price);

    };

    //parameter

    var bean = {name: "Mocca"};

    //execute remote method

    var defered = service.doSomething(bean, 5);

    //attach callback to defered object

    defered.addCallback(callback);

</script>

JsonService会发Z个请求到action加蝲SMDQ同时远E方法会q回一?/span>JSON对象Q这个过E是Dojol?/span>action中的Ҏ创徏了一?/span>Proxy。因是异步调用过E,当远E方法执行的时候,它会q回一个对象到callbackҎ中?/span>

f)         代理的对?/span>

当用的注解不是l承?/span>JavaQ可能你使用代理会出C些问题。比如:当你使用aop拦截你的action的时候。在q种情况下,q个插g不会自动发现注解的方法。ؓ了避免这U情况发生,你需要在xml中配|?/span>ignoreInterfaces?/span>falseQ这h件会自己查找注解的所有接口和父类?/span>

注意Q这个参数只有在Action执行的过E是通过注解来运行的时候才应该设ؓfalse?/span>

<action name="contact" class="package.ContactAction" method="smd">

   <interceptor-ref name="json">

      <param name="enableSMD">true</param>

      <param name="ignoreInterfaces">false</param>

   </interceptor-ref>

   <result type="json">

      <param name="enableSMD">true</param>

      <param name="ignoreInterfaces">false</param>

   </result>

   <interceptor-ref name="default"/>

</action>



]]>
struts2中结合json的?/title><link>http://www.tkk7.com/fuhoujun/archive/2008/10/04/232318.html</link><dc:creator>付厚?/dc:creator><author>付厚?/author><pubDate>Sat, 04 Oct 2008 06:19:00 GMT</pubDate><guid>http://www.tkk7.com/fuhoujun/archive/2008/10/04/232318.html</guid><wfw:comment>http://www.tkk7.com/fuhoujun/comments/232318.html</wfw:comment><comments>http://www.tkk7.com/fuhoujun/archive/2008/10/04/232318.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/fuhoujun/comments/commentRss/232318.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/fuhoujun/services/trackbacks/232318.html</trackback:ping><description><![CDATA[     摘要: http://prototype.conio.net/dist/ 下蝲(对Ajax支持的prototype--js函数?Q? prototype-1.4.0.js ? prototype-1.4.0.tar.gz   http://code.google.com/p/jsonplugin/downloads/list 下蝲(Struts2...  <a href='http://www.tkk7.com/fuhoujun/archive/2008/10/04/232318.html'>阅读全文</a><img src ="http://www.tkk7.com/fuhoujun/aggbug/232318.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/fuhoujun/" target="_blank">付厚?/a> 2008-10-04 14:19 <a href="http://www.tkk7.com/fuhoujun/archive/2008/10/04/232318.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2中的雉|与CoCQConvention over ConfigrationQ?/title><link>http://www.tkk7.com/fuhoujun/archive/2008/10/04/232312.html</link><dc:creator>付厚?/dc:creator><author>付厚?/author><pubDate>Sat, 04 Oct 2008 06:08:00 GMT</pubDate><guid>http://www.tkk7.com/fuhoujun/archive/2008/10/04/232312.html</guid><wfw:comment>http://www.tkk7.com/fuhoujun/comments/232312.html</wfw:comment><comments>http://www.tkk7.com/fuhoujun/archive/2008/10/04/232312.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/fuhoujun/comments/commentRss/232312.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/fuhoujun/services/trackbacks/232312.html</trackback:ping><description><![CDATA[<strong>关键? Struts2 COC</strong> <div id="m688y6m" class="blog_content">摘要Q介lStruts2中的雉|(Zero ConfigurationQ,以及如何用COC来更好地化Struts2的配|。在W一章,我用Maven来创Z个v炚w目;W二章,以该目ZQ讲解如何用Struts2的零配置Q第三章Q论q第二章中的实现方式的缺P然后讲解如何使用COC来改q这些缺Pq进一步简化Struts2的配|。附件是q篇文章用到的示例代码?br /> <br /> <h2>一、从零开?/h2> q里Q我徏立一个新的示例项目,作ؓ讲解的v炏V我使用JDK 6、Maven 2、Eclipse 3.3来徏立这个示例,如果读者对Maven2不熟也没关系Q这只是个示例?br /> 首先Q运行下边的命oQ?br />                 mvn archetype:create -DgroupId=demo.struts -DartifactId=demo-struts-coc -DarchetypeArtifactId=maven-archetype-webapp<br /> q会建立如下的目录结构:<demo-struts-coc><br />  |- POM.xml<br />  |- src<br />      |- main<br />          |- resources<br />          |- webapp<br />              |- index.jsp<br />              |- WEB-INF<br />                  |- web.xml<br /> 然后我们在src/main目录下新Z个名为java的目录,用来攄java代码。在src下徏立test目录Qƈ在test目录下徏立java目录Q用来放|测试代码。另外,我这个示例不想用JSPQ所以我src/main/webapp目录下的index.jsp改ؓindex.html?br /> 现在Q需要配|该目要用到哪些lib。在POM.xml中加入struts2-coreQ?br /> </demo-struts-coc> <div id="468oq4c" class="code_title">xml 代码</div> <div id="uqwc4wk" class="dp-highlighter"> <div id="8ygkgum" class="bar"> </div> <ol class="dp-xml"> <li id="cy4cgs8" class="alt"><span><span id="wg844a4" class="tag"><</span><span id="cmsc4g4" class="tag-name">dependency</span><span id="8444owm" class="tag">></span><span>  </span></span> <li id="8gy4kk4" class=""><span>    <span id="qayea44" class="tag"><</span><span id="s8o48k4" class="tag-name">groupId</span><span id="g8cqcm4" class="tag">></span><span>org.apache.struts</span><span id="cyi8u4y" class="tag"></</span><span id="iug8wy4" class="tag-name">groupId</span><span id="8ugm4ce" class="tag">></span><span>  </span></span> <li id="kmg44oa" class="alt"><span>    <span id="so4qs4c" class="tag"><</span><span id="ggio444" class="tag-name">artifactId</span><span id="cm8ko6u" class="tag">></span><span>struts2-core</span><span id="k8kmiue" class="tag"></</span><span id="8c4e4wg" class="tag-name">artifactId</span><span id="wgayo4a" class="tag">></span><span>  </span></span> <li id="m48so8u" class=""><span>    <span id="ey4ae4i" class="tag"><</span><span id="6ka444c" class="tag-name">version</span><span id="84y4ccs" class="tag">></span><span>2.0.9</span><span id="owi4ems" class="tag"></</span><span id="icw6k88" class="tag-name">version</span><span id="i8oysk4" class="tag">></span><span>  </span></span> <li id="48m4m44" class="alt"><span><span id="u4kwgig" class="tag"></</span><span id="8cws8u4" class="tag-name">dependency</span><span id="8k48oek" class="tag">></span><span>  </span></span> </li> </ol> </div> <br /> 另外Q我惛_Eclipse里用jetty来启动项目ƈq行试Q所以在POM.xml中再加入jetty、jetty-util、servlet-api{的依赖Q详情见附g?br /> 我希望用Eclipse来作个项目的IDEQ所以,我在命o行状态下Q进入这个项目所在的目录Q运行:<br />                 mvn eclipse:eclipse<br /> 然后使用Eclipse导入q个目。如果你是第一ơ用Eclipse导入用Maven生成的项目,那你需要在Eclipse里配|一个名叫M2_REPO的VariableQ指向你的Maven 2的repository目录。缺省情况下Q它应该位于${user.home}/.m2/repository?br /> OKQ现在我们已l可以在Eclipse中进行工作了?br /> 修改src/main/webapp/WEB-INF/web.xmlQ加入struts2的FilterDispatcherq设|filter-mapping。在q个CZ中我url-pattern设ؓ"/app/*"Q也是_url的匹配是Z路径来做的。这只是我的个h喜好而已Q你也可以将它设?*"?br /> 既然是在讲struts2的零配置Q当然是可以不要M配置文g的。但是ؓ了更好地q行“配置”Q我q是建立了struts.xml文gQ在src/main/resources目录下)。我不喜Ƣurl最后都有个action后缀Q现在,我在struts.xml中配|struts.action.extensionQ将q个后缀LQ?br /> <div id="sc4cwcs" class="code_title">xml 代码</div> <div id="u4ceoy4" class="dp-highlighter"> <div id="ym8mo4o" class="bar"> </div> <ol class="dp-xml"> <li id="644kui4" class="alt"><span><span id="iku44g6" class="tag"><</span><span id="4m44cqs" class="tag-name">struts</span><span id="4y88aa4" class="tag">></span><span>  </span></span> <li id="6e4c8qs" class=""><span>    <span id="84imw4m" class="tag"><</span><span id="4ua44mw" class="tag-name">constant</span><span> </span><span id="g44o4m4" class="attribute">name</span><span>=</span><span id="s44ycuw" class="attribute-value">"struts.action.extension"</span><span> </span><span id="gmk8k44" class="attribute">value</span><span>=</span><span id="6qec4q4" class="attribute-value">""</span><span> </span><span id="8c4g4m4" class="tag">/></span><span>  </span></span> <li id="m8ugqkm" class="alt"><span><span id="k8ac444" class="tag"></</span><span id="8i84yg4" class="tag-name">struts</span><span id="ymou4ik" class="tag">></span><span>  </span></span> </li> </ol> </div> <br /> 然后我在src/test/java下徏立demo/RunJetty.java文gQmainҎ如下Q?br /> <div id="6w4wiy4" class="code_title">java 代码</div> <div id="co84ewy" class="dp-highlighter"> <div id="ggsgcsk" class="bar"> </div> <ol class="dp-j"> <li id="g84gi4k" class="alt"><span><span id="84kmy4q" class="keyword">public</span><span> </span><span id="aaec4y4" class="keyword">static</span><span> </span><span id="qa84qwm" class="keyword">void</span><span> main(String[] args) </span><span id="6ge8o44" class="keyword">throws</span><span> Exception {  </span></span> <li id="oy84884" class=""><span>    Server server = <span id="m8miaa4" class="keyword">new</span><span> Server(</span><span id="omaw4cm" class="number">8080</span><span>); </span><span id="eeykom8" class="comment">//也可以改成其它端?/span><span>  </span></span> <li id="cwqs8ia" class="alt"><span>    File rootDir = <span id="8ao484q" class="keyword">new</span><span> File(RunJetty.</span><span id="cwia8is" class="keyword">class</span><span>.getResource(</span><span id="8ma4e4g" class="string">"/"</span><span>).getPath()).getParentFile().getParentFile();  </span></span> <li id="6i8ueuw" class=""><span>    String webAppPath = <span id="6e6m8kq" class="keyword">new</span><span> File(rootDir, </span><span id="c4cmgem" class="string">"src/main/webapp"</span><span>).getPath();  </span></span> <li id="6s44gou" class="alt"><span>    <span id="8w444gu" class="keyword">new</span><span> WebAppContext(server, webAppPath, </span><span id="c648iiy" class="string">"/"</span><span>);  </span></span> <li id="oycm8c4" class=""><span>    server.start();  </span> <li id="6sqkeka" class="alt"><span>}  </span> </li> </ol> </div> <br /> 现在Q在Eclipse里运行或调试q个RunJetty.javaQ用览器打开http://localhost:8080/看看吧。如果不出问题,应该可以讉K到webapp目录下的index.html了。有了JettyQ你q在用MyEclipse或其它插件么Q?br /> <br /> <h2>二、零配置</h2> 首先要澄清一点,q里说的雉|ƈ不是一炚w|都没有Q只是说配置很少而已?br /> Struts2Q我只用qStruts 2.0.6?.0.9Q不清楚其它版本是否支持雉|)引入了零配置的新Ҏ,元数据可以通过规则和注解来表达QA "Zero Configuration" Struts application or plugin uses no additional XML or properties files. Metadata is expressed through convention and annotation.<br /> 目前Q这个新Ҏ还在测试阶D,但经q一D|间的使用Q我觉得q个Ҏ已l可用。下面我讲一下如何用它?br /> 1. Actions的定?br /> 以前需要在xml配置文g中配|Action的name和classQ如果用零配置Q所带来的一个问题就是如何定位这些Action。我们需要在web.xml中找到struts2的filter的配|,增加一个名为actionPackages的init-paramQ它的值是一个以逗号分隔的Java包名列表Q比如:demo.actions1,demo.actions2。struts2会扫描q些包(包括q些包下边的子包Q,在这些包下,所有实CAction接口的或者是cd?#8220;Action”l尾的类都会被检查到Qƈ被当做Action?br /> 以前Q我们写Action必须要实现Action接口或者承ActionSupport。但是,上面提到的类名以"Action"l尾的类q不需要这样做Q它可以是一个POJOQStruts2支持POJO ActionQ?br /> 下面是actionPackages的配|示例:<br /> <div id="qsu84uc" class="code_title">xml 代码</div> <div id="4kqi8qe" class="dp-highlighter"> <div id="uu8qs44" class="bar"> </div> <ol class="dp-xml"> <li id="6wkwyw4" class="alt"><span><span id="i4gi44s" class="tag"><</span><span id="qy4wyg6" class="tag-name">filter</span><span id="6mceqw4" class="tag">></span><span>  </span></span> <li id="c4cewm4" class=""><span>  <span id="kcya4y4" class="tag"><</span><span id="y84osyi" class="tag-name">filter-name</span><span id="yiugq84" class="tag">></span><span>struts2</span><span id="suwgkys" class="tag"></</span><span id="oy4augq" class="tag-name">filter-name</span><span id="woa84io" class="tag">></span><span>  </span></span> <li id="8koysy4" class="alt"><span>  <span id="8gk4wce" class="tag"><</span><span id="qau8ym4" class="tag-name">filter-class</span><span id="e4u4w4y" class="tag">></span><span>org.apache.struts2.dispatcher.FilterDispatcher</span><span id="8wkmyo4" class="tag"></</span><span id="8g444mu" class="tag-name">filter-class</span><span id="qik4m44" class="tag">></span><span>  </span></span> <li id="4o4i4om" class=""><span>  <span id="ii64aaa" class="tag"><</span><span id="6g84i4q" class="tag-name">init-param</span><span id="m8k48i4" class="tag">></span><span>  </span></span> <li id="8q4y48q" class="alt"><span>    <span id="6qoy4g4" class="tag"><</span><span id="e8c4qgo" class="tag-name">param-name</span><span id="ck8wg4u" class="tag">></span><span>actionPackages</span><span id="6km4iy4" class="tag"></</span><span id="84gamk4" class="tag-name">param-name</span><span id="8s4c4qg" class="tag">></span><span>  </span></span> <li id="cmo8s4c" class=""><span>    <span id="e4cwy4c" class="tag"><</span><span id="8cegagg" class="tag-name">param-value</span><span id="8sc4ouc" class="tag">></span><span>demo.actions1,demo.actions2</span><span id="a4y4cqq" class="tag"></</span><span id="keoa8oe" class="tag-name">param-value</span><span id="c8cw4kk" class="tag">></span><span>  </span></span> <li id="ce44ou4" class="alt"><span>  <span id="444k4yo" class="tag"></</span><span id="8y44c4w" class="tag-name">init-param</span><span id="yq8ce4q" class="tag">></span><span>  </span></span> <li id="ouo8ig4" class=""><span><span id="iac8wm8" class="tag"></</span><span id="is4o4kq" class="tag-name">filter</span><span id="a8cmwm4" class="tag">></span><span>  </span></span> </li> </ol> </div> <br /> 2. CZ<br /> 现在我们建立demo.actions1.app.person和demo.actions2.app.group两个包,在demo.actions1.app.person包下建立ListPeopleAction.javaQ在demo.actions2.app.group下徏立ListGroupAction.java。作为示例,q两个类只是包含一个executeҎQ返?success"?error"Q其它什么都不做Q?br /> <div id="keqm4c4" class="code_title">java 代码</div> <div id="64444qq" class="dp-highlighter"> <div id="6m44888" class="bar"> </div> <ol class="dp-j"> <li id="4keg84i" class="alt"><span><span id="cyqkiy6" class="keyword">public</span><span> String execute() {  </span></span> <li id="8oy8ckc" class=""><span>    <span id="k4i4ki8" class="keyword">return</span><span> </span><span id="w4eg8ms" class="string">"success"</span><span>;  </span></span> <li id="8wikq4k" class="alt"><span>}  </span> </li> </ol> </div> <br /> 在Filter的配|中Q我指定actionPackages为demo.actions1,demo.actions2Q当pȝ启动ӞStruts2׃在这两个包下扫描到demo.actions1.app.person.ListPeopleAction和demo.actions2.app.group.ListGroupAction?br /> <br /> 3. Action and Package name<br /> Struts2扫描到Action后,从actionPackages指定的包开始,子包名会成ؓq个Action的namespaceQ而Action的name则由q个Action的类名决定。将cd首字母小写,如果cd以Actionl尾Q则L"Action"后缀QŞ成的名字是q个Action的名字。在如上所q的CZ中,actionPackages指定为demo.actions1,demo.actions2Q那么你可以q样讉Kdemo.actions1.app.person.ListPeopleActionQ?br />                 http://localhost:8080/app/person/listPeople<br /> <br /> 4. Results<br /> Struts2是通过"Result"?Results"两个cȝ别的annotations来指定Results的?br /> 作ؓCZQ我们在webapp目录下徏两个html文gQsuccess.html和error.htmlQ随便写点什么内定w可以。现在假设我们访?app/person/listPeopleӞ或Actionq回successp{到success.html面Q若是errorp{到error.html面Q这只需要在ListPeopleActioncM加上一D|解就可以了:<br /> <div id="6woic44" class="code_title">java 代码</div> <div id="s4k4484" class="dp-highlighter"> <div id="ceyak8u" class="bar"> </div> <ol class="dp-j"> <li id="84mysqq" class="alt"><span><span id="a8is4ie" class="annotation">@Results</span><span>({  </span></span> <li id="84cw4cs" class=""><span>    <span id="qaueiik" class="annotation">@Result</span><span>(name=</span><span id="oyke448" class="string">"success"</span><span>, type=NullResult.</span><span id="kugakcu" class="keyword">class</span><span>, value = </span><span id="uuk44qe" class="string">"/success.html"</span><span>, params = {}),  </span></span> <li id="6i4k44s" class="alt"><span>    <span id="skwgiyy" class="annotation">@Result</span><span>(name=</span><span id="ic8ok4e" class="string">"error"</span><span>, type=NullResult.</span><span id="4au44cc" class="keyword">class</span><span>, value = </span><span id="uugaucq" class="string">"/error.html"</span><span>, params = {})  </span></span> <li id="iak44mk" class=""><span>})  </span> <li id="8umgk4k" class="alt"><span><span id="ooiuoe8" class="keyword">public</span><span> </span><span id="kkeg4e4" class="keyword">class</span><span> ListPeopleAction {  </span></span> <li id="key4c44" class=""><span>    <span id="44mgs4i" class="keyword">public</span><span> String execute() {  </span></span> <li id="eo84ca8" class="alt"><span>        <span id="kuoa44k" class="keyword">return</span><span> </span><span id="6k4448k" class="string">"success"</span><span>;  </span></span> <li id="8iamom4" class=""><span>    }  </span> <li id="844qsy8" class="alt"><span>}  </span> </li> </ol> </div> <br /> 同上Q我们给ListGroupAction也加上注解?br /> 现在Q我们已l完成了一个零配置的示例。我们ƈ没有在xml文g里配|ListPeopleAction和ListGroupActionQ但它们已经可以工作了!<br /> 用Eclipseq行RunJettyQ然后用览器访问http://localhost:8080/app/person/listPeople和http://localhost:8080/app/group/listGroup看看Q是不是正是success.htmlQ或error.htmlQ的内容Q?br /> <br /> 5. Namespaces<br /> 如上所qͼnamespace由包名所形成Q但我们可以使用"Namespace"注解来自己指定namespace?br /> <br /> 6. Parent Package<br /> q个配置用得较少。Struts2提供一?ParentPackage"注解来标识Action应该是属于哪个package?br /> <br /> <h2>三、用COC</h2> 如上所qͼStruts2用注解来实现雉|。然而,q不是我喜欢的方式。在我看来,q不q是配|从XML格式换成了注解方式,q不是真的零配置。而且Q这U方式也未必比XML形式的配|更好。另外,对元数据的修改必然会D目的重新编译和部v。还有,现在的Struts2版本g对Result注解中的params的处理有些问题?br /> 其实QStruts2的actionPackages配置已经使用了COCQ那Z么不能ؓResults也实现COCQ从而去除这些每个Action都要写的注解Q?br /> 在严谨的目中,package、action的名U和面的\径、名UC定存在着某种关系。比如,面的\径可能和package是对应的Q页面的名称可能和action的名U是对应的,或是Ҏ某种法则q算得到。我们知道webwork2和struts2有个配置叫global-results。我们ؓ什么不能根据这些对应规则写个ResultQ将它配到global-results中,从而真正免去result的配|?<br /> 事实上,我推荐Struts2的用者只用Struts2输出XML或JSONQ放弃UIQ页面这层还是用标准的HTML、CSS和一些JSlg来展现。许多h反映Struts2慢,实QStruts2是慢Q很慢!慢在哪儿Q很大一部分因素是UIq层引v的,特别是用了q多的Struts2的tagQƈ使用了ajax theme。但是,如果我们攑ּ了Struts2的笨拙的UIQResult只输出XML或JSONQUI则用标准的HTML+CSSQ用JSlgQDOJO、Adobe Spry Framework、YUI-Ext{)来操作Struts2的输出数据,情况会如何Q我们会得到一个高性能、高可配的、UI和应用服务器的职责分割更为明、合理的、更易于静态化部v的开发组合?br /> q似乎是阉割了Struts2Q但是这样阉割过的Struts2摆脱了性能低下的包袱,更轻、更C化?br /> 有些扯远了,a归正传,不管是让Struts2输出XML或JSONQ还是输出页面,我们都有办法Ҏ目的规则写一个ResultQ将它配到global-results中,从而大大减Result的配|?br /> 假设我们让Struts2只输出JSONQ有个jsonplugin可以做这件事。用JsonResultӞ不再需要知道页面的位置、名U等信息Q它仅仅是数据输出,那么我们可以将q个Result配成全局的,大部分Action不再需要Result的配|?br /> 作ؓCZQ我假设我的例子中输出的两个html面Qsuccess.html和error.htmlQ是JSONQ我们看看怎么免去我例子中的两个Action的Result注解?br /> 首先Q我们删去ListPeopleAction和ListGroupAction两个Action的注解,q修改struts.xml文gQ加入:<br /> <div id="aceya84" class="code_title">xml 代码</div> <div id="yac84ao" class="dp-highlighter"> <div id="k4a4444" class="bar"> </div> <ol class="dp-xml"> <li id="ewyk4q4" class="alt"><span><span id="sugics8" class="tag"><</span><span id="k8sc4qy" class="tag-name">package</span><span> </span><span id="4s4uoeq" class="attribute">name</span><span>=</span><span id="i4y4mcs" class="attribute-value">"demo-default"</span><span> </span><span id="wgiugec" class="attribute">extends</span><span>=</span><span id="i44s44k" class="attribute-value">"struts-default"</span><span id="seoi8ye" class="tag">></span><span>  </span></span> <li id="yesuoeu" class=""><span><span id="4i4uwwc" class="tag"><</span><span id="8qycgme" class="tag-name">global-results</span><span id="6ewa4w4" class="tag">></span><span>  </span></span> <li id="8ugq8gu" class="alt"><span><span id="u4kewwc" class="tag"><</span><span id="s8cw4cs" class="tag-name">result</span><span> </span><span id="64eoiy4" class="attribute">name</span><span>=</span><span id="s4ueq4s" class="attribute-value">"success"</span><span id="8w4s4gg" class="tag">></span><span>/success.html</span><span id="swico8s" class="tag"></</span><span id="uuoq8gu" class="tag-name">result</span><span id="8wa84ki" class="tag">></span><span>  </span></span> <li id="ys844s4" class=""><span><span id="6ake48e" class="tag"></</span><span id="g4cmqg8" class="tag-name">global-results</span><span id="8ikoggq" class="tag">></span><span>  </span></span> <li id="88eyk48" class="alt"><span><span id="qimegwi" class="tag"></</span><span id="ww8au4w" class="tag-name">package</span><span id="suey8e4" class="tag">></span><span>  </span></span> </li> </ol> </div> <br /> <font color="#ff0000">误住这只是一个示例,Z方便Q我没在目中加入jsonplugin来作真实的演C,我只是假设这个success是json输出Q读者可以自行用jsonplugin来作实验?/font><br /> <br /> 现在Q离成功不远了,但是目仍然不能正常q行。我们的Actionq回successQ但q不会匹配到global-results中配|。ؓ什么呢Q因为,我们q里是把global-results配置?demo-default"q个package下的Q而Struts2ҎactionPackages扑ֈ的Action不会匚w到这个package上。解军_法也很简单,q记得上面讲到的Parent Package吧?lAction加个注解Q指定ParentPackage?demo-default"。但q样可不是我喜欢的,其实有更好的办法Q我们在struts.xml中加个constant好了:<br /> <div id="iameq8s" class="code_title">xml 代码</div> <div id="c4suyow" class="dp-highlighter"> <div id="8m8qs4k" class="bar"> </div> <ol class="dp-xml"> <li id="q8y4w4o" class="alt"><span><span id="yq4c4ay" class="tag"><</span><span id="q84o4e4" class="tag-name">constant</span><span> </span><span id="8aug4mc" class="attribute">name</span><span>=</span><span id="8qseqg4" class="attribute-value">"struts.configuration.classpath.defaultParentPackage"</span><span> </span><span id="iey4ci4" class="attribute">value</span><span>=</span><span id="qim44sq" class="attribute-value">"demo-default"</span><span> </span><span id="u8i4o44" class="tag">/></span><span>  </span></span> </li> </ol> </div> <br /> 现在Q大功告成!q行RunJetty来测试下吧!你可以访?app/person/listPeopleQ可以访?app/group/listGroupQ而所有的配置仅仅是web.xml和struts.xml中的几行Q我们的Java代码中也没有加注解。如果再加上几百个Action呢?配置仍然p几行?br /> 可是Q某些Action实需要配|怎么办?对这些ActionQ你可以加注解,也可以针对这些Action来写些XML配置。一个项目中Q大部分Action的配|是可以遵从一定规则的Q可以用规则来化配|,只有部分需要配|,q就是COC?br /> <br /> </div> <img src ="http://www.tkk7.com/fuhoujun/aggbug/232312.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/fuhoujun/" target="_blank">付厚?/a> 2008-10-04 14:08 <a href="http://www.tkk7.com/fuhoujun/archive/2008/10/04/232312.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts2中的标签http://www.tkk7.com/fuhoujun/archive/2008/10/04/232308.html付厚?/dc:creator>付厚?/author>Sat, 04 Oct 2008 06:02:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232308.htmlhttp://www.tkk7.com/fuhoujun/comments/232308.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232308.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232308.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232308.htmlstruts2.0的标{ֺQ简?
用过struts1.x的h都知道,标签库有html、bean、logic、tilesQ?br /> 而struts2.0里的标签却没有分c,只用在jsp头文件加?br /> <%@ taglib prefix="s" uri="/struts-tags" %>
p使用struts2.0的标{ֺ

下面׃l下每个标签的用法(有错h正)Q?/p>

AQ?/p>

<s:a href=""></s:a>-----链接,cM于html里的<a></a>
<s:action name=""></s:action>-----执行一个view里面的一个action
<s:actionerror/>-----如果action的errors有值那么显C出?br /> <s:actionmessage/>-----如果action的message有值那么显C出?br /> <s:append></s:append>-----d一个值到listQ类glist.add();
<s:autocompleter></s:autocompleter>-----自动完成<s:combobox>标签的内容,q个是ajax

BQ?br /> <s:bean name=""></s:bean>-----cM于struts1.x中的QJavaBean的?/p>

CQ?br /> <s:checkbox></s:checkbox>-----复选框
<s:checkboxlist list=""></s:checkboxlist>-----多选框
<s:combobox list=""></s:combobox>-----下拉?br /> <s:component></s:component>-----囑փW号

DQ?br /> <s:date/>-----获取日期格式
<s:datetimepicker></s:datetimepicker>-----日期输入?br /> <s:debug></s:debug>-----昄错误信息
<s:div></s:div>-----表示一个块Q类ghtml?lt;div></div>
<s:doubleselect list="" doubleName="" doubleList=""></s:doubleselect>-----双下拉框

EQ?br /> <s:if test=""></s:if>
<s:elseif test=""></s:elseif>
<s:else></s:else>-----q?个标{一起用,表示条g判断

FQ?br /> <s:fielderror></s:fielderror>-----昄文g错误信息
<s:file></s:file>-----文g上传
<s:form action=""></s:form>-----获取相应form的?/p>

GQ?br /> <s:generator separator="" val=""></s:generator>----?lt;s:iterator>标签一起?/p>

HQ?br /> <s:head/>-----?lt;head></head>里用,表示头文件结?br /> <s:hidden></s:hidden>-----隐藏?/p>

IQ?br /> <s:i18n name=""></s:i18n>-----加蝲资源包到值堆?br /> <s:include value=""></s:include>-----包含一个输出,servlet或jsp面
<s:inputtransferselect list=""></s:inputtransferselect>-----获取form的一个输?br /> <s:iterator></s:iterator>-----用于遍历集合

LQ?br /> <s:label></s:label>-----只读的标{?/p>

MQ?br /> <s:merge></s:merge>-----合ƈ遍历集合出来的?/p>

OQ?br /> <s:optgroup></s:optgroup>-----获取标签l?br /> <s:optiontransferselect doubleList="" list="" doubleName=""></s:optiontransferselect>-----左右选择?/p>

PQ?br /> <s:param></s:param>-----为其他标{提供参?br /> <s:password></s:password>-----密码输入?br /> <s:property/>-----得到'value'的属?br /> <s:push value=""></s:push>-----value的值push到栈?从而property标签的能够获取value的属?/p>

RQ?/p>

<s:radio list=""></s:radio>-----单选按?br /> <s:reset></s:reset>-----重置按钮


SQ?br /> <s:select list=""></s:select>-----单选框
<s:set name=""></s:set>-----赋予变量一个特定范围内的?br /> <s:sort comparator=""></s:sort>-----通过属性给list分类
<s:submit></s:submit>-----提交按钮
<s:subset></s:subset>-----为遍历集合输出子?/p>

TQ?br /> <s:tabbedPanel id=""></s:tabbedPanel>-----表格?br /> <s:table></s:table>-----表格
<s:text name=""></s:text>-----I18n文本信息
<s:textarea></s:textarea>-----文本域输入框
<s:textfield></s:textfield>-----文本输入?br /> <s:token></s:token>-----拦截?br /> <s:tree></s:tree>-----?br /> <s:treenode label=""></s:treenode>-----树的l构

UQ?br /> <s:updownselect list=""></s:updownselect>-----多选择?br /> <s:url></s:url>-----创徏url



]]>
Struts用户指南http://www.tkk7.com/fuhoujun/archive/2008/10/04/232306.html付厚?/dc:creator>付厚?/author>Sat, 04 Oct 2008 05:59:00 GMThttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232306.htmlhttp://www.tkk7.com/fuhoujun/comments/232306.htmlhttp://www.tkk7.com/fuhoujun/archive/2008/10/04/232306.html#Feedback0http://www.tkk7.com/fuhoujun/comments/commentRss/232306.htmlhttp://www.tkk7.com/fuhoujun/services/trackbacks/232306.html 1.1 Model-View-Controller (MVC) 设计模式
FIXME - 需要一个对该模式一般性的介绍。(译注Q可以参考机械工业出版社的《设计模式》。)
1.2 MVC概念映射到Strutslg?br /> Struts 的体pȝ构实CModel-View-Controller设计模式的概念,它将q些概念映射到web应用E序的组件和概念?
q一体系l构中每个主要的lg都将在下面做详细的讨论?

1.3 Model: pȝ状态和商业逻辑JavaBeans
ZMVC的系l中?Model 部分可以l分Z个概?-- pȝ的内部状? 能够改变状态的行ؓ。用语法术语来说Q我们可以把状态信息当作名词(事物Q,把行为当作动词(事物状态的改变Q?
通常说来Q你的应用程序将pȝ内部的状态表CZؓ一l一个或多个的JavaBeansQ用属性(propertiesQ来表示状态的l节。依赖于你的应用E序的复杂度Q这些beans可以是自包含的(以某U方式知道怎样怹C存它们的状态信息)Q或者可以是正面的(facadesQ,知道当被h时怎样从外部数据源Q例如数据库Q中取得信息。Entity EJBs通常也用来表C内部状态?

大型应用E序l常系l可能的商业逻辑行ؓ表示为可以被l护状态信息的beans调用的方法。D个例子,你有一个ؓ每个当前用户保存在session中的购物车beanQ里面是表示当前用户军_购买物品的属性。这个bean有一个checkOut()Ҏ用来验证用户的信用卡Q将定单发给库房以选择货品和出货。别的系l分别地表示同样的行为,或许使用Session EJBs?

在一些小型应用程序中Q同L行ؓ又可能嵌入到作ؓController一部分?Action cM。这在逻辑非常单或者ƈ不想要在其它环境中重用这些商业逻辑时是恰当的。Struts框架支持所有这些方法,但徏议将商业逻辑Q?#8220;做什?#8221;Q和 Action c(“军_做什?#8221;Q分d?

1.4 View: JSP面和表C组?br /> ZStruts的应用程序中?View 部分通常使用JSP技术来构徏。JSP面包含UCؓ“模版文本”的静态HTMLQ或XMLQ文本,加上插入的基于对Ҏ行ؓ标记解释的动态内宏VJSP环境包括了其用途由JSP规范来描q的一套标准的行ؓ标记Q例?<jsp:useBean> 。另外,q有一个用来定义你自己标记的标准机Ӟq些自定义的标记l织?#8220;定制标记?#8221;中?
Struts包括了一个广阔的便于创徏用户界面Qƈ且充分国际化的定制标记库Q与作ؓpȝ Model 部分一部分的ActionForm beans妙地相互配合。这些标记的使用在后面做详l讨论?

除了JSP面和其包含的行为及定制标记Q商业对象经帔R要能够基于它们在被请求时的当前状态将自己处理成HTMLQ或XMLQ。从q些对象处理q的输出可以很容易地使用 <jsp:include> 标准行ؓ标记包括在结果的JSP面中?

1.5 Controller: ActionServlet和ActionMapping
应用E序?Controller 部分集中于从客户端接收请求(典型情况下是一个运行浏览器的用PQ决定执行什么商业逻辑功能Q然后将产生下一步用L面的责Q委派l一个适当的Viewlg。在Struts中,controller的基本组件是一?ActionServlet cȝservlet。这个servlet通过定义一l映(由Java接口 ActionMapping 描述Q来配置。每个映定义一个与所h的URI相匹配的路径和一?Action c(一个实?Action 接口的类Q完整的cdQ这个类负责执行预期的商业逻辑Q然后将控制分派l适当的Viewlg来创建响应?
Struts也支持用包含有q行框架所必需的标准属性之外的附加属性的 ActionMapping cȝ能力。这允许你保存特定于你的应用E序的附加信息,同时仍可利用框架其余的特性。另外,Struts允许你定义控制将重定向到的逻辑名,q样一个行为方法可以请?#8220;主菜?#8221;面QD例)Q而不需要知道相应的JSP面的实际名字是什么。这个功能极大地帮助你分L刉辑Q下一步做什么)和显C逻辑Q相应的面的名U是什么)?

2. 创徏Modellg
2.1 概述
你用到的应用E序的需求文档很可能集中于创建用L面。然而你应该保证每个提交的请求所需要的处理也要被清楚的定义。通常说来QModel lg的开发者集中于创徏支持所有功能需求的JavaBeanscR一个特D应用要求的beans的精特性依赖于具体需求变化会非常的大Q但是它们通常可以分成下面讨论的几U类型。然而,首先?#8220;范围”概念做一个简短的回顾是有用的Q因为它与beans有关?
2.2 JavaBeans和范?br /> 在一个基于web的应用程序中QJavaBeans可以被保存在Qƈ从中讉KQ一些不?#8220;属?#8221;的集合中。每一个集合都有集合生存期和所保存的beans可见度的不同的规则。ȝ说来Q定义生存期和可见度的这些规则被叫做q些beans?范围 。JSP规范中用以下术语定义可选的范围Q在圆括号中定义servlet API中的{h物)Q?
page - 在一个单独的JSP面中可见的BeansQ生存期限于当前h。(service()Ҏ中的局部变量) request - 在一个单独的JSP面中可见的BeansQ也包括所有包含于q个面或从q个面重定向到的页面或servlet。(Request属性)
session - 参与一个特定的用户session的所有的JSP和servlet都可见的BeansQ跨一个或多个h?Session属性)
application - 一个web应用E序的所有JSP面和servlet都可见的Beans。(Servlet context属性)
C同一个web应用E序的JSP面和servlets׃n同样一lbean集合是很重要的。例如,一个bean作ؓ一个request属性保存在一个servlet中,pq样Q?
MyCart mycart = new MyCart(...);
request.setAttribute("cart", mycart);
立卌q个servlet重定向到的一个JSP面使用一个标准的行ؓ标记看到Q就象这P
<jsp:useBean id="cart" scope="request"
class="com.mycompany.MyApp.MyCart"/>
2.3 ActionForm Beans
Struts框架通常假定你已lؓ每一个你的应用程序中h的输入创Z一?ActionForm beanQ即一个实C ActionForm 接口的类Q。如果你在你?ActionMapping 配置文g中定义了q样的beansQ见“创徏Controllerlg”Q,Struts的controller servlet在调用适当?Action Ҏ前将自动Z执行如下的服务:
用适当的关键字查用Lsession中是否有适当的类的bean的一个实例?
如果没有q样的session范围的beanQ自动徏立一个新的beanq添加到用户的session中?
Ҏ个名字对应于bean中的一个属性的h参数Q调用相应的setҎ。这个操作类g当你以通配W?#8220;*”选择所有属性用标准的JSP行ؓ标记 <jsp:setProperty> ?
更新的ActionForm bean在被调用时将被传递给Actoncȝperform()ҎQ以使这些D够立即生效?
当你在写你的ActionForm beansӞC以下的原则:
ActionForm 接口本n不需要特D的实现Ҏ。它是用来标识这些特定的beans在整个体pȝ构中的作用。典型情况下Q一个ActionForm bean只包括属性的getҎ和setҎQ没有商业逻辑?
通常在一个ActionForm bean中只有很的输入验证逻辑。这Lbeans存在的主要理由是保存用户为相关的表单所输入的大部分q期?-- 甚至在错误被到?-- q样同样的页面可以被重徏Q伴随有一l出错信息,q样用户仅仅需要纠正错误的字段。用戯入的验证应该?Action cM执行Q如果是很简单的话)Q或者在适当的商业逻辑beans中执行?
为每个表单中出现的字D定义一个属性(用相关的getXxx()和setXxx()ҎQ。字D名和属性名必须按照JavaBeans的约定相匚w。例如,一个名?username 的输入字D将引v setUsername() Ҏ被调用?
你应该注意一?#8220;表单”在这里讨论时的意义ƈ不必d应于用户界面中的一个单独的JSP面。在很多应用E序中一?#8220;表单”Q从用户的观点)延臛_个页面也是很q_的。想想看Q例如,通常在安装新的应用程序时使用的导航安装程序的用户界面。Struts鼓励你定义一个包含所有字D属性的单独的ActionForm bean。不字D实际上是显C在哪个面上。同LQ同一表单的不同的面应该提交到相同的ActioncR如果你늅q个Q在大多数情况下Q页面设计者可以重新组l不同页面中的字D而不需要改变处理逻辑?
2.4 pȝ状态Beans
pȝ的实际状态通常表示Zl一个或多个的JavaBeansc,其属性定义当前状态。例如,一个购物Rpȝ包括一个表C物R的beanQ这个bean为每个单独的购物者维护,q个bean中包括(在其它事物之中)一l购物者当前选择购买的项目。分别地Q系l也包括保存用户信息Q包括他们的信用卡和送货地址Q、可获得目的目录和它们当前库存水^的不同的beans?
对于规模的pȝQ或者对于不需要长旉保存的状态信息,一l系l状态beans可以包含所有系l曾l经历的特定l节的信息。或者经常是Q系l状态beans表示怹保存在一些外部数据库中的信息Q例如CustomerBean对象对应于表 CUSTOMERS 中的特定的一行)Q在需要时从服务器的内存中创徏或清除。在大规模应用程序中QEntity EJBs也用于这U用途?

2.5 商业逻辑Beans
你应该把你的应用E序中的功能逻辑装成对为此目的设计的JavaBeans的方法调用。这些方法可以是用于pȝ状态beans的相同的cȝ一部分Q或者可以是在专门执行商业逻辑的独立的cM。在后一U情况下Q你通常需要将pȝ状态beans传递给q些Ҏ作ؓ参数处理?
Z代码最大的可重用性,商业逻辑beans应该被设计和实现为它们不知道自己被执行于web应用环境中。如果你发现在你的bean中你必须import一?javax.servlet.* c,你就把这个商业逻辑捆绑在了web应用环境中。考虑重新l织事物使你?Action c(Controllerd的一部分Q在下面描述Q翻译所有从HTTPh中请求被处理为对你的商业逻辑beans属性setҎ调用的信息,然后可以发出一个对 execute() 的调用。这L一个商业逻辑cd以被重用在除它们最初被构造的web应用E序以外的环境中?

依赖于你的应用程序的复杂度和范围Q商业逻辑beans可以是与作ؓ参数传递的pȝ状态beans交互作用的普通的JavaBeansQ或者用JDBC调用讉K数据库的普通的JavaBeans。而对于较大的应用E序Q这些beansl常是有状态或无状态的EJBs?

2.6 题外? 讉K关系数据?br /> 很多web应用E序利用一个关pL据库Q通过一个JDBC driver讉KQ来保存应用E序相关的永久数据。其它应用程序则使用Entity EJBs来实现这个目的,他们委派EJBs自己来决定怎样l护怹状态。如果你是用EJBs来实现这个目的,늅EJB规范中描q的客户端设计模式?
对于Z直接数据库访问的web应用E序Q一个普通的设计问题是当需要访问低层数据库时怎样产生一个适当的JDBCq接对象。解册个问题有几种Ҏ -- 以下原则描述了推荐的一U方法:

创徏或得C个允怸l数据库q接被多个用户共享的ConnectionPoolcRStrutsQ当前)没有包括q样的一个类Q但是有很多q样的类可以得到?
当应用程序初始化Ӟ在应用程序展开QdeploymentQ描q符中定义一个有一?#8220;启动时加?#8221;值的servlet。我们将把这个servlet叫做 启动 servlet。在大多数情况下Q这个servlet不需要处理Q何的hQ所以没有一?<servlet-mapping> 会指向它?
在启动servlet?init() Ҏ中,配置q初始化一个ConnectionPoolcȝ实例Q将其保存ؓ一个servlet context属性(从JSP的观点看{同于一个application范围的beanQ。通常Z传递给启动servlet初始化参数来配置联接~冲池是很方便的?
在启动servlet?destroy() Ҏ中,包含了释放联接缓冲池所打开的联接的逻辑。这个方法将在servlet容器l束q个应用E序的时候被调用?
?Action c需要调用一个需要数据库联接的商业逻辑bean中的ҎQ例?#8220;insert a new customer”Q时Q将执行下面的步骤:
个web应用E序从servelt context属性中得到一个联接缓冲池对象?
调用联接~冲池对象的 open() Ҏ来得C个在 Action c调用中使用的联接?
调用商业逻辑bean中合适的ҎQ将数据库联接对象作Z个参C递给它?
调用分配的联接中?close() ҎQ这引赯个联接ؓ了以后其它请求的重用被返回到~冲池中?
一个通常的编E错误是忘记了把数据库联接返回给~冲池,q将最l导致用完所有的联接。一定要信 Action cȝ逻辑Lq回联接Q甚臛_商业逻辑bean抛出一个违例时?
늅上面推荐的设计模式意味着你能够编写你的商业逻辑c而不需要担心它们怎样得到一个JDBC联接来?- 单地在Q何需要访问数据库的方法中包含一个Connection参数。当你的商业逻辑cd一个web应用E序中被利用Ӟ分配和释N当的联接是 Action cȝ责Q。当你用相同的商业逻辑cLQ例如,在一个批处理工作中,提供一个适当的联接是那个应用E序的责任(q不需要从~冲池中获得Q因为大多数批处理工作运行于一个单U程环境中)?
3. 创徏Viewlg
3.1 概述
q一章集中于创徏应用E序中的 View lg的Q务,主要使用JSP技术徏立。特别的QStruts除了提供了与输入表单的交互外q提供了建立国际化应用程序的支持。几个其它的与View相关的主题也被简单地讨论?
3.2 国际化消?br /> 几年之前Q应用程序开发者能够考虑C仅支持他们本国的只用一U语aQ或者有时候是两种Q和通常只有一U数量表现方式(例如日期、数字、货币|的居民。然而,Zweb技术的应用E序的爆炸性增长,以及这些应用程序展开在Internet或其它被q泛讉K的网l之上,已经在很多情况下使得国家的边界E化到不可见。这U情况{变成ZU对于应用程序支持国际化Q经常被U做“i18n”Q因?8是字?#8220;i”和字?#8220;n”之间的字母个敎ͼ和本地化的需求?
Struts建立于Javaq_之上为徏立国际化和本地化的应用程序提供帮助。需要熟悉的关键概念是:

Locale - 基础的支持国际化的JavacL java.util.Locale 。每?Locale 代表一个特别的国家和语a选择Q加上一个可选的语言变量Q,以及一套格式假定,例如数字和日期等{?
ResourceBundle - java.util.ResourceBundle cL供支持多U语a消息的基本工兗查看文档中关于ResourceBundle cM及你的JDK版本的文档包中关于国际化的更多内宏V?
PropertyResourceBundle - 一?ResourceBundle cȝ标准实现允许你用与初始化properties文g同样?#8220;name=value”语法来定义资源。这对于使用为用于一个web应用E序的消息准备资源包是非常方便的Q因些消息通常都是面向文本的?
MessageFormat - java.text.MessageFormat cd怽使用q行时指定的参数替换一个消息字W串中的一部分Q在q种情况下,是一个从一个资源包得到的消息)。这在你创徏一个句子的场合中是有用的,但是词会以不同的语言按照不同的顺序出现。消息中的占位符字符串{0}用第一个运行时参数替换Q{1}用第二个q行时参数替换,以此cL?
MessageResources - Struts的类 org.apache.struts.util.MessageResources 使你能够一套资源包视做一个数据库Qƈ且允怽Z个特定的LocaleQ通常是与当前用户相对应)h一个特定的消息Q而不是ؓ服务器运行在其中的缺省的Localeh消息?
对于一个国际化的应用程序,늅JDK文档包中国际化文档所描述的步骤来创徏一个包含每U语a的消息的属性文件。下面D一个例子说明?
假设你的源代码徏立在?com.mycompany.mypackage 中,因此它保存于一个叫做(相对于你的源目录Qcom/mycompany/mypackage 的目录中。ؓ创徏一个叫?com.mycompany.mypackage.MyResources 的资源包Q你应该在目?com/mycompany/mypackage 中创Z列文Ӟ

MyResources.properties - 包含你的服务器的~省语言的消息。如果你的缺省语a是英语,你可能有一个这L条目Q?
prompt.hello=Hello
MyResources_xx.properties - 包含ISO语言~程?#8220;xx”Q查看ResourceBundle的Java文档面得到一个当前列表的联接Q的同样的消息。对于上面的消息的法语版Q你可以有这个条目:
prompt.hello=Bonjour
你可以有你需要的L多的语言的资源包文g?br /> 当你在web应用E序展开描述W中配置controller servletӞ你需要在一个初始化参数中定义的一件事是应用程序的资源包的基础名。在上述的情况中Q这应该?com.mycompany.mypackage.MyResources ?
3.3 表单和FormBean的交?br /> 大部分web开发者曾l用HTML的标准性能来徏立表单,例如使用 <input> 标记。用户希望交互程序具有一定的行ؓQ这些期待中的一个与错误处理有关 -- 如果用户出现一个错误,应用E序应该允许他们仅仅修改需要修改的部分 -- 而不需要重新敲入当前页面或表单中的M其它信息?
使用标准的HTML和JSP~程来完全实现这个期望是单调而繁重的。D例来_一个用户名字段的输入元素看h可以象是q样Q在JSP中)

<input type="text" name="username"
value="<%= loginBean.getUsername() %>">
q很难敲对,会把没有~程概念的HTML开发者搞p涂Qƈ且会在HTML~辑器中造成问题。取而代之的是,Struts提供了一U全面的ZJSP 1.1的定制标记库功能的机制来建立表单。上面的情况使用Struts处理后将象是q样Q?
<struts:text name="username"/>
没有必要再显式地涉及C中获得初始值的JavaBean。这由框架自动处理?
3.3.1 使用Struts建立表单
一个完整的注册表单演CStruts相对于直接用HTML和标准的JSP功能怎样极大地减M处理表单的痛苦。考虑以下UCؓlogon.jsp的页面(来自Struts的例子程序)Q?



<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts.tld" prefix="struts" %>

<html>
<head>
<title><struts:message key="logon.title"/></title>
<body bgcolor="white">

<struts:errors/>

<struts:form action="logon.do" name="logonForm"
type="org.apache.struts.example.LogonForm"/>
<table border="0" width="100%">
<tr>
<th align="right">
<struts:message key="prompt.username"/>
</th>
<td align="left">
<struts:text name="username" size="16"/>
</td>
</tr>
<tr>
<th align="right">
<struts:message key="prompt.password"/>
</th>
<td align="left">
<struts:password name="password" size="16"/>
</td>
</tr>
<tr>
<td align="right">
<struts:submit>
<struts:message key="button.submit"/>
</struts:submit>
</td>
<td align="right">
<struts:reset>
<struts:message key="button.reset"/>
</struts:reset>
</td>
</tr>
</table>
</struts:form>

</body>
</html>

下面的条目基于这个例子演C在Struts中处理表单的关键的特性:
taglib指o告诉JSP面~译器从哪里扑ֈStruts标记库的 标记库描q符 。在q种情况下,我们使用struts作ؓ前缀来标识来自这个库中的标记Q但是可以用Q何你想用的前~?
q个面使用了几?message 标记来从一个包含有q个应用E序所有资源的 MessageResources 对象中查扑֛际化的消息字W串。ؓ了让q个面能够工作Q以下的消息关键字必dq些资源中被定义Q?
logon.title - 注册面的标?
prompt.username - 一?“Username:” 提示字符?
prompt.password - 一?“Password:” 提示字符?
button.submit - “Submit”按钮的标{?
button.reset - “Reset”按钮的标{?
当用h册时Q应用程序可以在用户的session中保存一?Locale 对象。这?Locale 用来选择适当语言的消息。这使得l用户一个切换语a的可选项实现h变的Ҏ?-- 仅仅改变保存?Locale 对象Q所有的消息׃自动切换?
errors 标记昄׃个商业逻辑lg保存的Q何出错消息,或者如果没有出错消息保存就什么都没有。这个标记将在下面做深入的描q?
form 标记Z指定的属性对一个HTML <form> 元素q行处理。它也将所有在q个表单中的字段与一个保存在关键?logonForm 下的session范围的FormBean相关联。这个bean用来为所有的h与bean中的属性名匚w的名字的输入字段提供初始倹{如果适当的bean没有扑ֈQ一个新的bean会被自动徏立,使用指定的Javacd?
text 标记对一个类型ؓ“text”的HTML <input> 元素q行处理。在q种情况下,占据览器屏q的字符位置的数字也被指定。当面被执行时Q是相对应的bean?username 属性的当前|也就?getUsername() 的返回|?
password 标记使用ҎcM。不同之处是当用h入他们的口o时浏览器回应星号字W,而不是输入倹{?
submit ?reset 标记在表单低部生成相应的按钮。每个按钮的文本标签使用 message 标记建立Q同时带有提C,q样q些值就是国际化的?
3.3.2 输入字段cd支持
Struts为所有以下类型的输入字段定义了标讎ͼ带有与其相应的参考信息的联接?
checkboxes
hidden 字段
password 输入字段
radio 按钮
reset 按钮
select 列表和嵌入的
options
submit 按钮
text 输入字段
textareas
在所有情况下Q一个字D|记都必须嵌套在一?form 标记中,q样字段才知道用哪个bean来初始化昄的倹{?
3.3.3 其它有用的表C标?br /> 在Struts的标记库中有几个其它的标记对于徏立用L面是有帮助的Q?
enumerate Z个指定集合的每个元素重复一ơ标CQ可以是一个EnumerationQ一个HashtableQ一个Vector或一个对象数l)?
getProperty 从指定的bean中得到指定的属性,q且在本面的其余部分作Z个page范围的bean存在。这是访问一个被 enumerate 使用的集合的方便的方法?
ifAttributeExists 只有在一个指定的属性存在于一个指定的范围中时才对标记体求倹{?
ifAttributeMissing 只有在一个指定的属性不存在于一个指定的范围中时才对标记体求倹{?
ifParameterEquals 只有在一个指定的h参数h一个指定的值时才对标记体求倹{?
ifParameterNotEquals 只有在一个指定的h参数不具有一个指定的值或者不存在时才ҎC求倹{?
ifParameterNotNull 只有在一个指定的h参数包含在这个请求中q且长度大于0时才ҎC求倹{?
ifParameterNull 只有在一个指定的h参数不包含在q个h中或者长度等?时才ҎC求倹{?
iterate Z个指定集合中的每个元素重复一ơ标CQ可以是一个CollectionQ一个IteratorQ一个MapQ或者一个对象数l)。这个标记在Java2环境中代替了 enumerate 标记?
link 生成一个超联接Q当没有cookie支持时自动应用URL~程来维护session状态?
parameter 处理指定h参数的|适当地过滤HTML中有Ҏ含义的字W?
property 昄一个表单中命名的bean属?-- 在属性应该是只读时用这个标记而不?text 标记?
3.3.4 自动表单验证
除了上面描述的表单和bean的交互外Q如果你的bean知道怎样验证它接收的输入字段QStrutsq提供一U附加的机制。ؓ了利用这个特性,使你的beancd?ValidatingActionForm 接口Q而不?ActionForm 接口。一?ValidatingActionForm 增加了一个附加的Ҏ{֐Q?
public String[] validate()
对于一个被controller servlet在bean属性已l组装但是在相应的行为类?perform() Ҏ被调用之前调用的ҎQvalidate() Ҏ有以下可选项Q?
执行适当的验证发现没有错?-- q回 null 或者一个非0长度字符串数l,q且controller servletl调用适当?Action cȝ perform() Ҏ?
执行适当的验证发现有错误 -- q回一个内容ؓ应该被显C的出错消息关键字(q入应用E序的MessageResources 包)的字W串数组。controller servlet作为适合?<struts:errors> 标记使用的请求属性保存这个数l,q且控刉定向回输入表单(p?ActionMapping ?inputForm 属性标识)?
正如以前提到的,q个Ҏ完全是可选的。如果你的form bean 仅仅实现?ActionForm 接口Qcontroller servlet假设Q何请求的验证由actioncd成?
3.4 其它的表C技?br /> 管你的应用E序的外表和感觉可以完全Z标准的JSP能力和Struts的定制标记库构徏Q你也应该考虑展开其它改进lg重用、减管理负担或者减出错的技术。在下面的部分讨论几个可选的技术?
3.4.1 特定于应用程序的定制标记
在用Struts库提供的定制标记之外Q很Ҏ建立特定于你创徏的应用程序的标记来帮助徏立用L面。Struts包括的例子程序用建立以下仅用于实现这个应用程序的标记演示了这个原则:
checkLogon - 查一个特D的会话对象的存在,如果不存在将控制重定向到注册面。这是用来捕捉这L情况Q用户在你的应用E序执行的中间把一个页面做成书{ƈ且试图蟩q注册,或者用L会话时?
linkSubscription - Z个详l的定单面生成一个超联接Q它需要的d键字gZ个请求属性传递。这在列Z一个用L关的定单q提供编辑或删除定单的联接时使用?
linkUser - Z个用L一个具体的面生成一个超联接Q它它需要的d键字gZ个请求属性传递?
q些标记的源代码?src/example 目录中,在包 org.apache.struts.example 里,q带有一些其它的用在q个应用E序中的JavacR?
3.4.2 有包含文件的面lg
在一个JSP文gQ包含定制标记和beans用来讉Kh的动态数据)中创建完整的表示是一U非常普通的设计ҎQ在Struts包括的例子程序中被采用。然而很多应用程序要求在单独一个页面中昄你的应用E序的多个逻辑上独立的部分?
举例来说Q一个入口应用程序可以在入口的主面上有一些或者全部以下的功能Q?

讉Kq个入口的一个搜索引擎?
一个或更多?#8220;提供新闻”的显C,含有按照用户的注册信息定制的感兴的标题?
讉K与这个入口相关的讨论的主题?
如果你的入口提供免费邮g帐号Q还要有一?#8220;邮g{待”的提C?
如果你能够将工作划分开Q分配不同的开发者去做不同的片段Q那么这个站点不同片D늚开发就会更加简单。然后,你可以用JSP技术的 include 能力来将q些片段l合q一个单独的面。有两种 include 可用Q依赖于你希望输出的l合发生在什么时_
include 指o Q?lt;%@ include file="xxxxx" %>Q在JSP面被编译时处理。它用于包括不需要在h时改变的HTML代码。它把包括进来的文本当作静态文本,很象C或C++中的 #include 指o?
include 行ؓ Q?lt;jsp:include page="xxxxx" flush="true" />Q在h时处理,q且是由服务器透明处理。这意味着你可以通过把它嵌套在一个类似ifParameterEquals的标C有条件地执行include ?
3.4.3 囄处理lg
一些应用程序要求动态生成图片,p一个股市报告站点的h图一栗通常使用两种不同的方法来实现q个需求:
处理一个执行一个servleth的URL的超联接。这个servlet用一个图象库来生成图片,讄适当的contentcdQ例?image/gifQ,q且图片的字节发送回览器。浏览器׃象从一个静态文件中接收到的一hC图片?
处理HTML代码需要下载一个创求的图象的Java applet。你可以通过为在处理的代码中的这个applet讄适当的初始化参数配置q个图象Q或者你可以让这个applet与服务器建立自己联接来接收这些参数?
4. 创徏Controllerlg
4.1 概述
现在我们理解了怎样构造你的应用程序的Model和ViewlgQ现在是集中?Controller lg的时候了。Struts包括一个实现映一个请求URIC个行为类的主要功能的servlet。因此你的与Controller有关的主要责LQ?
为每一个可能接收的逻辑h写一?Action c(也就是,一?Action 接口的实玎ͼ
写一个定义类名和与每个可能的映射相关的其它信息的 ActionMapping c(也就是,一?ActionMapping 接口的实玎ͼ
写行为映配|文Ӟ用XMLQ用来配|controller servlet?
Z的应用程序更新web应用E序展开描述W文Ӟ用XMLQ用来包括必需的Strutslg?
l你的应用程序添加适当的Strutslg?
4.2 Actionc?br /> Action 接口定义一个单一的必ȝ一?Action cd现的ҎQ就象下面这P
public ActionForward perform(ActionServlet servlet,
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException;
一?Action cȝ目标是处理这个请求,然后q回一个标识JSP面?ActionForward 对象Q控制应该重定向q个JSP面以生成相应的响应。在 Model 2 设计模式中,一个典型的 Action cd在它?perform() Ҏ中实C面的逻辑Q?
验证用户session的当前状态(例如Q检查用户已l成功地注册Q。如?Action cd现没有注册存在,h应该重定向到昄用户名和口o用于注册的JSP面。应该这样做是因为用户可能试图从“中间”Q也是Q从一个书{)q入你的应用E序Q或者因为session已经时q且servlet容器创徏了一个新的session?
如果验证q没有发生(׃使用一个实?ValidatingActionForm 接口的form beanQ,验证q个 form bean 的属性是必须的。如果发C个问题,当作一个请求属性保存合适的出错信息关键字,然后控刉定向回输入表单这样错误可以被U正?
执行要求的处理来处理q个hQ例如在数据库里保存一行)。这可以用嵌?Action cLw的代码来完成,但是通常应该调用一个商业逻辑bean的一个合适的Ҏ来执行?
更新用来创Z一个用L面页面的服务器端对象Q典型情况下是request范围或session范围beansQ定义你需要在多长旉内保持这些项目可获得Q?
q回一个标识生成响应的JSP面的适当?ActionForward 对象Q基于新q更新的beans。典型情况下Q你通过在你接收到的 ActionMapping 对象Q如果你使用一个局部于与这个映上的逻辑名)或者在controller servlet 本nQ如果你使用一个全局于应用程序的逻辑名)上调?findForward() 得到一个对q样一个对象的引用?
当ؓ Action cȝE时要记住的设计要点包括以下q些Q?
controller servlet仅仅创徏一个你?Action cȝ实例Q用于所有的h。这样你需要编写你?Action cM其能够在一个多U程环境中正运行,p你必d全地~写一个servlet?service() Ҏ一栗?
帮助U程安全~程的最重要的原则就是在你的 Action cM仅仅使用局部变量而不是实例变量。局部变量创Z一个分配给Q由你的JVMQ每个请求线E的栈中Q所以没有必要担心会׃n它们?
管不应该,代表你的pȝ中Model部分的的beans仍有可能抛出q例。你应该在你?perform() Ҏ的逻辑中捕捉所有这Lq例Qƈ且通过执行以下语句它们记录在应用E序的日志文件中Q包括相应的栈跟t信息)Q?
servlet.log("Error message text", exception);
作ؓ一个通用的规则,分配很少的资源ƈ在来自同一个用P在用Lsession中)的请求间保持它们会导致可伸羃性的问题。你应该在将控制重定向到适当的Viewlg前努力释放这L资源Q例如数据库联接Q?-- 甚至在你调用的一个bean抛出了一个违例时?
另外Q你会惌防止出现非常大的 Action cR最单的实现途径是将你的功能逻辑嵌入?Action cLw,而不是将其写在独立的商业逻辑beans中。除了 Action c难于理解和l护外,q种Ҏ也得难于重用这些商业逻辑代码Q因Z码被嵌入C个组ӞAction c)中ƈ被捆l运行于web应用E序环境中?
包括在Struts中的例子E序某种E度上g怺q个设计原则Q因为商业逻辑本n是嵌入到 Action cM的。这应该被看作是在这个样本应用程序设计中的一个bugQ而不是一个Struts体系l构中的固有Ҏ,或者是一个值得仿效的方法?

4.3 ActionMapping实现
Z成功地运行,Struts的controller servlet需要知道关于每个URI该怎样映射C个适当?Action cȝ几g事。需要了解的知识装在一个叫?ActionMapping 的Java接口中,它有以下属性:
actionClass - 用于q个映射?Action cd整的Javacd。第一ơ一个特定的映射被用,一个这个类的实例将被创建ƈZ后重用而保存?
formAttribute - session范围的bean的名字,当前的这个映的 ActionForm 被保存在q个bean之下。如果这个属性没有被定义Q没?ActionForm 被用?
formClass - 用于q个映射?ActionForm cd整的Javacd。如果你在用对form beans的支持,q个cȝ一个实例将被创建ƈ保存Q在当前的用户会话中Q?
path - 匚w选择q个映射的请求的URI路径。看下面如何匚w的例子?
Struts在一个叫?ActionMappingBase 的类中包括了一?ActionMapping 接口的方便的实现。如果你不需要ؓ你自q映射定义M附加的属性,管把这个类作ؓ你的 ActionMapping cd了,向下面部分描述的那样配|。然而,定义一?ActionMapping 实现Q多半是扩展 ActionMappingBase c)来包含附加的属性也是可能的。controller servlet知道怎样自动配置q些定制属性,因ؓ它用Struts的Digester模块来读配置文g?
包括在Struts的例子程序中Q这个特性用来定义两个附加的属性:

failure - 如果ActioncL到它接收的输入字段的一些问题,控制应该被重定向到的上下文相关的URI。典型情况下是请求发向的JSP面名,它将引v表单被重新显C(包含Actionc设|的出错消息和大部分最q的来自ActionForm bean的输入|?
success - 如果ActioncL功执行请求的功能Q控制应该被重定向到的上下文相关的URI。典型情况下是准备这个应用程序的会话的下一个页面的JSP面名?
使用q两个额外的属性,例子E序中的 Action cd乎完全独立于面设计者用的实际的JSP面名。这个页面可以在重新设计时被重命名,然而几乎不会媄响到 Action cLw。如?#8220;下一?#8221;JSP面的名字被编码到 Action cMQ所有的q些cM需要被修改?
4.4 Action映射配置文g
controller servlet怎样知道你想要得到的映射Q写一个简单地初始化新?ActionMapping 实例q且调用所有适当的setҎ的小的JavacL可能的(但是很麻烦)。ؓ了ɘq个处理单些QStruts包括一个Digester模块能够处理一个想得到的映的ZXML的描qͼ同时创徏适当的对象。看 API 文档 以获得关于Digester更多的信息?
开发者的责Q是创Z个叫?action.xml 的XML文gQƈ且把它放在你的应用程序的WEB-INF目录中。(注意q个文gq不需?DTDQ因为实际用的属性对于不同的用户可以是不同的Q最外面的XML元素必须?lt;action-mappings>Q在q个元素之中是嵌入的0个或更多?<action> 元素 -- 每一个对应于你希望定义的一个映?

来自例子E序?action.xml 文g包括“注册”功能的以下映条目,我们用来说明q个需求:




<action-mappings>

<forward name="logon" path="/logon.jsp"/>

<action path="/logon"
actionClass="org.apache.struts.example.LogonAction"
formAttribute="logonForm"
formClass="org.apache.struts.example.LogonForm"
inputForm="/logon.jsp">
<forward name="success" path="/mainMenu.jsp"/>
</action>

</action-mappings>

p你所看到的,q个映射匚w路径 /logon Q实际上Q因Z子程序用扩展匹配,你在一个JSP面指定的请求的URIl束?logon.doQ。当接收C个匹配这个\径的hӞ一?LogonAction cȝ实例被创徏Q仅仅在W一ơ)q被使用。controller servlet在关键?logonForm 下查找一个session范围的beanQ如果需要就为指定的cd建ƈ保存一个bean?
q个 action 元素也定义了一个逻辑?#8220;success”Q它?LogonAction cM被用来标识当一个用h功注册时使用的页面。象q样使用一个逻辑名允许将 action c隔MM׃重新设计位置而可能发生的面名改变?

q是W二个在M action 之外宣告?forward 元素Q这样它可以被所有的action全局地获得。在q个情况下,它ؓ注册面定义了一个逻辑名。当你调?mapping.findForward() 时在你的 action 代码中,Struts首先查找q个action本地定义的逻辑名。如果没有找刎ͼStruts会自动ؓ你查扑օ局定义的逻辑名?

4.5 Web应用E序展开描述W?br /> 讄应用E序最后的步骤是配|应用程序展开描述W(保存在文件WEB-INF/web.xml中)以包括所有必需的Strutslg。作Z个指南用例子程序的展开描述W,我们看到下面的条目需要被创徏或修攏V?
4.5.1 配置Action Servlet实例
d一个条目定义action servlet本nQ同时包括适当的初始化参数。这样一个条目看h象是q样Q?




<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-p
aram>
<param-name>application</param-name>
<param-value>org.apache.struts.example.ApplicationResources</param-value>
</init-param>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/action.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>mapping</param-name>
<param-value>org.apache.struts.example.ApplicationMapping</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

controller servlet支持的初始化参数在下面描qͼ拯?ActionServlet cȝ Javadocs 。方括号描述如果你没有ؓ那个初始化参数提供一个值时假设的缺省倹{?
application - 应用E序资源包基cȝJavacd。[NONE].
config - 包含配置信息的XML资源的上下文相关的\径。[/WEB-INF/action.xml]
debug - q个servlet的调试别,它控制记录多信息到日志中。[0]
digester - 我们?initMapping() 中利用的Digester的调试别,它记录到System.out而不是servlet的日志中。[0]
forward - 使用的ActionForward实现的Javacd。[org.apache.struts.action.ActionForward]
mapping - 使用的ActionMapping实现的Javacd。[org.apache.struts.action.ActionMappingBase]
nocache - 如果讄?trueQ增加HTTP头信息到所有响应中使浏览器对于生成或重定向到的M响应不做~冲。[false]
null - 如果讄?trueQ设|应用程序资源得如果未知的消息关键字被使用则返?null。否则,一个包括不Ƣ迎的消息关键字的出错消息将被返回。[true]
4.5.2 配置Action Servlet映射
有两U通常的方法来定义被controller servlet处理的URL -- 前缀匚w和扩展匹配。每U方法的一个适当的映条目将在下面被描述?
前缀匚w意思是你想让所有以一个特D值开_在上下文路径部分之后Q的URL传递给q个servlet。这样一个条目看h可以象是q样Q?

<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/execute/*</url-pattern>
</servlet-mapping>
它意味着一个匹配前面描q的 /logon 路径的请求的URL看v来象是这P
http://www.mycompany.com/myapplication/execute/logon
q里 /myapplicationis 是你的应用程序展开所在的上下文\径?
另一斚wQ扩展映基于URL以一个跟着定义的一l字W的句点l束的事实而将URL匚w到action servlet 。例如,JSP处理servlet映射?*.jsp 模式q样它在每个JSP面h时被调用。ؓ了?*.do 扩展Q它意味着“做某件事”Q映条目看h应该象是q样Q?

<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
q且一个匹配以前描q的 /logon 路径的请求的URI可以看v来象是这P
http://www.mycompany.com/myapplication/logon.do
4.5.3 配置Struts标记?br /> 下一步,你必L加一个定义Struts标记库的条目。这个条目看h应该象是q样Q?
<taglib>
<taglib-uri>/WEB-INF/struts.tld</taglib-uri>
<taglib-location>/WEB-INF/struts.tld</taglib-location>
</taglib>
它告诉JSPpȝ到哪里去找这个库的标记库描述W(在你的应用程序的WEB-INF目录Q而不是在外部互联|上的某个地方)?
4.5.4 dStrutslgC的应用程序中
Z在你的应用程序运行时使用StrutsQ你必须?struts.tld 文g拯C?WEB-INF 目录Q将 struts.jar 文g拯C?WEB-INF/lib ??



]]>
վ֩ģ壺 Ľղ2021| ĻȫĻ| ޹av| 91þ޹˾Ʒɫ| ˹ƷŮëƬѲ| ɫse01Ƶ| Ʒһ24Ƶ| aëƬ| avպaɫͷ| ޵Ӱѹۿ| AVþþƷ| պ߹ۿƵ| ͹Ƶ| þþwwwëƬ| 91þþƷһ| ͵Ƶѹۿ| Ļѿ| պӰ߹ۿַ| AVһһ| ݺɫþþ޾Ʒ| һɪ| ŷ㽶ۺ| ŮƵ| þþ뾫Ʒպ˳ | ۺУ԰ɫ| ƵƵ| ͵޾Ʒ| þþþAV| þþƷAV뽿ɫ| þþƷavĻ| AVһ | yellowƵѿ| ƬѸ߿| һһͰһƵ| VA߹ۿ| þƷƵ| һëƬһֱӹۿ| ɫӴӴƷѹۿ| VAѾƷ| һƬѿ| ůůձ|