??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产区男人本色,日韩亚洲人成网站,亚洲免费福利视频 http://m.tkk7.com/jackybu/category/1614.html<a ><b><font color=red>共有<script src=http://fastonlineusers.com/online.php?d=jackybu.blogjava.net></script>人在同时阅读此Blog</font></b></a> zh-cn Tue, 27 Feb 2007 23:04:23 GMT Tue, 27 Feb 2007 23:04:23 GMT 60 Dreamweaver和Struts的整? http://m.tkk7.com/jackybu/articles/10313.html?/dc:creator>?/author>Wed, 17 Aug 2005 02:46:00 GMT http://m.tkk7.com/jackybu/articles/10313.html http://m.tkk7.com/jackybu/comments/10313.html http://m.tkk7.com/jackybu/articles/10313.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/10313.html http://m.tkk7.com/jackybu/services/trackbacks/10313.html
Dreamweaver和Struts的整?/TD>
使用Struts开发web应用是非常有吸引力的Q在昄层我们通常采用jspQ当然我们编辑网|首选工具就是DreamweaverQ而Dreamweaver不能识别Struts的标记库Q在做网设计时通常带来不小ȝ(ch)Q没有代码提C和所见即所得的界面。下面我们将提供一个方案来解决q个问题?/P>
1 首先在Dreamweaver中导入Struts的标{ֺQ这样在~写代码时可以出现动态代码提C。点几Z编辑|标签库…”,在“标{ֺ~辑器”导入Struts的taglib文gQ在q些标签用于在JSP文g上?/P>
2 下蝲“Animalsgroup Struts taglibs Translator”,该插件可以将以Struts的一些标C囑Ş方式昄出来Q当前支持html和bean标签?/P>
点击此处 下蝲插g?/P>
下蝲后用“Macromedia扩展理器”安装该插g?/P>
3 创一个jsp文gQ导入相应的Struts的taglib声明Q进行设计吧。html的标{֏以显C啦Q和普通的设计完全一P不过没有属性栏Q你需要通过更改代码来达到显C的效果?/P>
ȝQ用以上方法,实可以l网设计者带来不便利,lg可以直接昄Q方便我们的修改。其实有一ƾDreamweaver的Struts插gQ功能更强大Q你可在http://www.fwasi.com 查找到该插g的信息,不过是收费的?/P>
]]> Struts常见异常信息和解x?/title> http://m.tkk7.com/jackybu/articles/9766.html?/dc:creator>?/author>Thu, 11 Aug 2005 01:05:00 GMT http://m.tkk7.com/jackybu/articles/9766.html http://m.tkk7.com/jackybu/comments/9766.html http://m.tkk7.com/jackybu/articles/9766.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/9766.html http://m.tkk7.com/jackybu/services/trackbacks/9766.html 1、“No bean found under attribute key XXX?BR>在struts-config.xml里定义了一个ActionFormQ但type属性指定的cM存在Qtype属性的值应该是Formcȝ全名。或者是Q在Action的定义中Qname或attribute属性指定的ActionForm不存在?/P>
2、“Cannot find bean XXX in any scope?BR>在Action里一般会(x)request.setAttribute()一些对象,然后在{向的jsp文g里(用tag或request.getAttribute()Ҏ(gu)Q得到这些对象ƈ昄出来。这个异常是说jsp要得C个对象,但前面的Action里ƈ没有对象设|到requestQ也可以是session、servletContextQ里?BR>可能是名字错了,h查jsp里的tag的一般是name属性,或getAttribute()Ҏ(gu)的参数|或者是Action逻辑有问题没有执行setAttribute()Ҏ(gu)先转向了?BR>q有另外一个可能,Ua(b)是jsp文g的问题,例如<logic:iterate>?x)指定一个id|然后在@环里<bean:write>使用q个g为name的|如果q两个g同,也会(x)出现此异常。(都是一个道理,request里没有对应的对象。)(j)
3、“Missing message for key "XXX"?BR>~少所需的资源,(g)查ApplicationResources.properties文g里是否有jsp文g里需要的资源Q例如:(x)
<bean:message key="msg.name.prompt"/>
q行代码?x)找msg.name.prompt资源Q如果AppliationResources.properties里没有这个资源就?x)出现本异常。在使用多模块时Q要注意在模块的struts-config-xxx.xml里指定要使用的资源文件名Uͼ否则当然什么资源也找不刎ͼq也是一个很Ҏ(gu)犯的错误?/P>
4、“No getter method for property XXX of bean teacher?BR>q条异常信息说得很明白,jsp里要取一个bean的属性出来,但这个beanq没有这个属性。你应该(g)查jsp中某个标{property属性的倹{例如下面代码中的cade应该改ؓ(f)code才对Q?/P>
<bean:write name="teacher" property="cade" filter="true"/>
5、“Cannot find ActionMappings or ActionFormBeans collection?BR>待解冟?/P>
6、“Cannot retrieve mapping for action XXX?BR>?jsp?lt;form>标签里指定action='/XXX'Q但q个Actionq未在struts-config.xml里设|过?/P>
7、HTTP Status 404 - /xxx/xxx.jsp Forward的path属性指向的jsp面不存在,h查\径和模块Q对于同一模块中的Action转向Qpath中不应包含模块名Q模块间转向Q记住用contextRelative="true"?/P>
8、没有Q何异怿息,昄I白面 可能是Action里用的forward与struts-config.xml里定义的forward名称不匹配?/P>
9、“The element type "XXX" must be terminated by the matching end-tag "XXX".?BR>q个是struts-config.xml文g的格式错误,仔细(g)查它是否是良构的xml文gQ关于xml文g的格式这里就不赘qC?/P>
10、“Servlet.init() for servlet action threw exception?BR>一般出现这U异常在后面?x)显CZ个关于ActionServlet的异常堆栈信息,其中指出了异常具体出现在代码的哪一行。我曄遇到的一ơ提C如下:(x)
java.lang.NullPointerException at org.apache.struts.action.ActionServlet.parseModuleConfigFile(ActionServlet.java:1003) at org.apache.struts.action.ActionServlet.initModuleConfig(ActionServlet.java:955)
决问题,先下载struts的源码包Q然后在ActionServlet.java的第1003行插入断点,q对各变量进行监视。很丢hQ我竟然把struts-config.xml文g弄丢了,因此出现了上面的异常Q应该是和CVS同步时不心删除的?/P>
11、“Resources not defined for Validator?BR>q个是利用Validator插g做验证时可能出现的异常,q时你要(g)查validation.xml文gQ看里面使用的资源是否确实有定义Qform的名U是否正,{等?/P>
上面q些是我在用Struts做项目时遇到q的问题Q其中一些曾困绕我不时_(d)其实大部分都是自׃l心造成的。希望这文章能对你的开发有所帮助QƈƢ迎l箋补充?/P>
]]> Struts 中bean:present使用Ҏ(gu) 选择?techyang ?Blog http://m.tkk7.com/jackybu/articles/9764.html?/dc:creator>?/author>Thu, 11 Aug 2005 01:04:00 GMT http://m.tkk7.com/jackybu/articles/9764.html http://m.tkk7.com/jackybu/comments/9764.html http://m.tkk7.com/jackybu/articles/9764.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/9764.html http://m.tkk7.com/jackybu/services/trackbacks/9764.html 在JSP面头部一定要加上相应?lt;%@ taglib {标讎ͼ否则无法实现。我开始时是忘了?lt;%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %> Q而导致无论是使用 present q是 notPresent Q网中都显C用L(fng)陆页面。:(x)Q。在jsp面实现代码Q?/P>
<%@ page language="java"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>
<logic:notPresent name="userid" scope="session">
// q里是登陆表单代?/P>
</logic:notPresent>
<logic:present name="userid" scope="session">
<bean:write key="userid" /> //昄session中的用户id QuseridQ?/P>
</logic:present>
在Struts的action?execute Ҏ(gu)里面可以q样定义session变量Q?/P>
String userId="123456";
request.getSession(true).setAttribute("userid",userId);
Q注Qrequest.getSeesion(booleanQ,q个Ҏ(gu)里面传了一个boolean|q个值如果是trueQ那么如果当前的request的session不可用,那么创建新的会(x)话,如果存在p回当前的?x)话。如果参数是falseQ那么在request的当前会(x)话不存在的时候就q回null。)(j)
]]> 深入Struts 1.1 http://m.tkk7.com/jackybu/articles/9765.html?/dc:creator>?/author>Thu, 11 Aug 2005 01:04:00 GMT http://m.tkk7.com/jackybu/articles/9765.html http://m.tkk7.com/jackybu/comments/9765.html http://m.tkk7.com/jackybu/articles/9765.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/9765.html http://m.tkk7.com/jackybu/services/trackbacks/9765.html
王和?/FONT>
2003 q?8 ?02 ?/P>
作ؓ(f)ZMVC模式的Web应用最l典框架QStruts已经正式推出?.1版本Q该版本在以往版本的基上,提供了许多激动h心的新功能。本文就带你走qStruts 1.1L入地了解q些功能?/BLOCKQUOTE>
说明Q?/B>希望本文的读者能有一定的Struts使用基础?
Model 2
Struts是基于Model 2之上的,而Model 2是经典的MVCQ模型-视图Q控制器Q模型的Web应用变体Q这个改变主要是׃|络应用的特?-HTTP协议的无状态性引L(fng)。Model 2的目的和MVC一P也是利用控制器来分离模型和视图,辑ֈ一U层间松散耦合的效果,提高pȝ灉|性、复用性和可维护性。在多数情况下,你可以将Model 2与MVC{同h?/P>
下图表示一个基于Java技术的典型|络应用Q从中可以看出Model 2中的各个部分是如何对应于Java中各U现有技术的?/P>
在利用Model 2之前Q我们是把所有的表示逻辑和业务逻辑都集中在一P比如大杂烩似的JSPQ,有时也称q种应用模式为Model 1QModel 1的主要缺点就是紧耦合Q复用性差以及(qing)l护成本高?/P>
Struts 1.1 和Model 2
既然Struts 1.1是基于Model 2之上Q那它的底层机制也就是MVCQ下面是Struts 1.1中的MVC实现C意图:(x)
图解说明Q其中不同颜色代表MVC的不同部分:(x)U色Q控制器Q、Ԍ模型Q和l色Q视图)(j)
首先Q控制器QActionServletQ进行初始化工作Q读取配|文Ӟstruts-config.xmlQ,Z同的Struts模块初始化相应的ModuleConfig对象。比如配|文件中的Action映射定义都保存在ActionConfig集合中。相应地有ControlConfig集合、FormBeanConfig集合、ForwardConfig集合和MessageResourcesConfig集合{?/P>
提示Q?/B>模块是在Struts 1.1中新提出的概念,在稍后的内容中我们将详细介绍Q你现在可以单地把模块看作是一个子pȝQ它们共同组成整个应用,同时又各自独立。Struts 1.1中所有的处理都是在特定模块环境中q行的。模块的提出主要是ؓ(f)了解决Struts 1.0中单配置文g的问题?
控制器接收HTTPhQƈ从ActionConfig中找出对应于该请求的Action子类Q如果没有对应的ActionQ控制器直接请求{发给JSP或者静态页面。否则控制器请求分发至具体Actionc进行处理?/P>
在控制器调用具体Action的executeҎ(gu)之前QActionForm对象利用HTTPh中的参数来填充自己(可选步骤,需要在配置文g中指定)(j)。具体的ActionForm对象应该是ActionForm的子cd象,它其实就是一个JavaBean。此外,q可以在ActionFormcM调用validateҎ(gu)来检查请求参数的合法性,q且可以q回一个包含所有错误信息的ActionErrors对象。如果执行成功,ActionForm自动这些参C息以JavaBeanQ一般称之ؓ(f)form beanQ的方式保存在Servlet Context中,q样它们可以被其它Action对象或者JSP调用?/P>
Struts这些ActionForm的配|信息都攑֜FormBeanConfig集合中,通过它们Struts能够知道针对某个客户h是否需要创建相应的ActionForm实例?/P>
Action很简单,一般只包含一个executeҎ(gu)Q它负责执行相应的业务逻辑Q如果需要,它也q行相应的数据检查。执行完成之后,q回一个ActionForward对象Q控制器通过该ActionForward对象来进行{发工作。我们主张将获取数据和执行业务逻辑的功能放到具体的JavaBean当中Q而Action只负责完成与控制有关的功能。遵循该原则Q所以在上图中我Action对象归ؓ(f)控制器部分?/P>
提示Q?/B>其实在Struts 1.1中,ActionMapping的作用完全可以由ActionConfig来替代,只不q由于它是公共API的一部分以及(qing)兼容性的问题得以保留。ActionMapping通过l承ActionConfig来获得与其一致的功能Q你可以{同地看待它们。同理,其它例如ActionForward与ForwardConfig的关pM是如此?
下图l出了客L(fng)从发求到获得响应整个q程的图解说明?/P>
下面我们来详细地讨Z下其中的每个部分Q在q之前,先来了解一下模块的概念?/P>
模块
我们知道Q在Struts 1.0中,我们只能在web.xml中ؓ(f)ActionServlet指定一个配|文Ӟq对于我们这些网上的教学例子来说当然没什么问题,但是在实际的应用开发过E中Q可能会(x)有些ȝ(ch)。因多开发h员都可能同时需要修攚w|文Ӟ但是配置文g只能同时被一个h修改Q这栯定会(x)造成一定程度上的资源争夺,势必?x)?jing)响开发效率和引v开发h员的抱怨?/P>
在Struts 1.1中,Z解决q个q行开发的问题Q提Z两种解决Ҏ(gu)Q?
多个配置文g的支?
模块的支?
支持多个配置文gQ是指你能够为ActionServlet同时指定多个xml配置文gQ文件之间以逗号分隔Q比如Struts提供的MailReader演示例子中就采用该种Ҏ(gu)?/P>
<!-- Action Servlet Configuration -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml, /WEB-INF/struts-config-registration.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
q种Ҏ(gu)可以很好地解决修改冲H的问题Q不同的开发h员可以在不同的配|文件中讄自己的Action、ActionForm{等Q当然不是说每个开发h员都需要自q配置文gQ可以按照系l的功能模块q行划分Q。但是,q里q是存在一个潜在的问题Q就是可能不同的配置文g之间?x)生冲H,因ؓ(f)在ActionServlet初始化的时候这几个文g最l还是需要合q到一L(fng)。比如,在struts-config.xml中配|了一个名为success?lt;forward>Q而在struts-config-registration.xml中也配置了一个同L(fng)<forward>Q那么执行v来就?x)生冲H?/P>
Zd解决q种冲突QStruts 1.1中引q了模块QModuleQ的概念。一个模块就是一个独立的子系l,你可以在其中q行L所需的配|,同时又不必担心和其它的配|文件生冲H。因为前面我们讲q,ActionServlet是将不同的模块信息保存在不同的ModuleConfig对象中的。要使用模块的功能,需要进行以下的准备工作Q?/P>
1、ؓ(f)每个模块准备一个配|文?/P>
2、配|web.xml文gQ通知控制?/P>
军_采用多个模块以后Q你需要将q些信息告诉控制器,q需要在web.xml文gq行配置。下面是一个典型的多模块配|:(x)
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>config/customer</param-name>
<param-value>/WEB-INF/struts-config-customer.xml</param-value>
</init-param>
<init-param>
<param-name>config/order</param-name>
<param-value>/WEB-INF/struts-config-order.xml</param-value>
</init-param>
要配|多个模块,你需要在原有的一?lt;init-param>Q在Struts 1.1中将其对应的模块UCؓ(f)~省模块Q的基础之上Q增加模块对应的<init-param>。其?lt;param-name>表示为config/XXX的Ş式,其中XXX为对应的模块名,<param-value>中还是指定模块对应的配置文g。上面这个例子说明该应用有三个模块,分别是缺省模块、customer和orderQ它们分别对应不同的配置文g?/P>
3、准备各个模块所需的ActionForm、Action和JSP{资?/P>
但是要注意的是,模块的出C同时带来了一个问题,卛_何在不同模块间进行{发?有两U方法可以实现模块间的{发,一U就是在<forward>Q全局或者本圎ͼ(j)中定义,另外一U就是利用org.apache.struts.actions.SwitchAction?/P>
下面是一个全局的例子:(x)
...
<struts-config>
...
<global-forwards>
<forward name="toModuleB"
contextRelative="true"
path="/moduleB/index.do"
redirect="true"/>
...
</global-forwards>
...
</struts-config>
可以看出Q只需要在原有的path属性前加上模块名,同时contextRelative属性置为true卛_。此外,你也可以?lt;action>中定义一个类似的本地<forward>?/P>
<action-mappings>
<!-- Action mapping for profile form -->
<action path="/login"
type="com.ncu.test.LoginAction"
name="loginForm"
scope="request"
input="tile.userLogin"
validate="true">
<forward name="success" contextRelative="true" path="/moduleA/login.do"/>
</action>
</action-mappings>
如果你已l处在其他模块,需要{回到~省模块Q那应该cM下面q样定义Q即模块名ؓ(f)I?/P>
<forward name="success" contextRelative="true" path="/login.do"/>
此外Q你也可以用org.apache.struts.actions.SwitchActionQ例如:(x)
...
<action-mappings>
<action path="/toModule"
type="org.apache.struts.actions.SwitchAction"/>
...
</action-mappings>
...
ActionServlet
我们首先来了解MVC中的控制器。在Struts 1.1中缺省采用ActionServletcL充当控制器。当然如果ActionServlet不能满你的需求,你也可以通过l承它来实现自己的类。这可以?WEB-INF/web.xml中来具体指定?/P>
要掌握ActionServletQ就必须了解它所扮演的角艌Ӏ首先,ActionServlet表示MVCl构中的控制器部分,它需要完成控制器所需的前端控制及(qing)转发h{职责。其ơ,ActionServlet被实Cؓ(f)一个专门处理HTTPh的ServletQ它同时hservlet的特炏V在Struts 1.1中它主要完成以下功能Q?
接收客户端请?
Ҏ(gu)客户端的URI请求映到一个相应的Actionc?
从请求中获取数据填充Form BeanQ如果需要)(j)
调用Actioncȝexecute()Ҏ(gu)获取数据或者执行业务逻辑
选择正确的视囑֓应客?
此外QActionServletq负责初始化和清除应用配|信息的d。ActionServlet的初始化工作在initҎ(gu)中完成,它可以分Z个部分:(x)初始化ActionServlet自n的一些信息以?qing)每个模块的配置信息。前者主要通过initInternal、initOther和initServlet三个Ҏ(gu)来完成?/P>
我们可以?WEB-INF/web.xml中指定具体的控制器以?qing)初始参敎ͼ׃版本的变化以及(qing)Struts 1.1中模块概늚引进Q一些初始参数被废弃或者移入到/WEB-INF/struts-config.xml中定义。下面列出所有被废弃的参敎ͼ相应地在web.xml文g中也不鼓励再使用?/P>
application
bufferSize
content
debug
factory
formBean
forward
locale
mapping
maxFileSize
multipartClass
nocache
null
tempDir
ActionServletҎ(gu)不同的模块来初始化ModuleConfigc,q在其中以XXXconfig集合的方式保存该模块的各U配|信息,比如ActionConfigQFormBeanConfig{?/P>
初始化工作完成之后,ActionServlet准备接收客户h。针Ҏ(gu)个请求,Ҏ(gu)process(HttpServletRequest request, HttpServletResponse response)被调用。该Ҏ(gu)指定具体的模块,然后调用该模块的RequestProcessor的processҎ(gu)?/P>
protected void process(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
RequestUtils.selectModule(request, getServletContext());
getRequestProcessor(getModuleConfig(request)).process(request, response);
}
RequestProcessor包含了Struts控制器的所有处理逻辑Q它调用不同的processXXXҎ(gu)来完成不同的处理。下表列出其中几个主要的Ҏ(gu)Q?/P>
Ҏ(gu)
功能
processPath
获取客户端的h路径
processMapping
利用路径来获得相应的ActionMapping
processActionForm
初始化ActionFormQ如果需要)(j)q存入正的scope?/TD>
processActionCreate
初始化Action
processActionPerform
调用Action的executeҎ(gu)
processForwardConfig
处理Actionq回的ActionForward
ActionForm
对于ActionForm你可以从以下几个斚w来理解它Q?
ActionForm表示HTTPH体中的数据Q可以将其看作是模型和视囄中介Q它负责保存视图中的数据供模型或者视图用。Struts 1.1文档中把它比作HTTP和Action之间的防火墙Q这体现了ActionFormh的过滤保护的作用Q只有通过ActionForm验证的数据才能够发送到Action处理?
ActionForm是与一个或多个ActionConfig兌的JavaBeanQ在相应的action的executeҎ(gu)被调用之前,ActionForm?x)自动利用请求参数来填充自己Q初始化属性)(j)?
ActionForm是一个抽象类Q你必须通过l承来实现自qcR?
ActionForm首先利用属性的getter和setterҎ(gu)来实现初始化Q初始化完毕后,ActionForm的validateҎ(gu)被调用,你可以在其中来检查请求参数的正确性和有效性,q且可以错误信息以ActionErrors的Ş式返回到输入H体。否则,ActionForm被作ؓ(f)参数传给action的executeҎ(gu)以供使用?/P>
ActionForm bean的生命周期可以设|ؓ(f)sessionQ缺省)(j)和requestQ当讄为sessionӞ记得在resetҎ(gu)中将所有的属性重新设|ؓ(f)初始倹{?/P>
׃ActionForm对应于HTTPH体Q所以随着面的增多,你的ActionForm会(x)急速增加。而且可能同一cd面字段会(x)在不同的ActionForm中出玎ͼq且在每个ActionForm中都存在相同的验证代码。ؓ(f)了解册个问题,你可以ؓ(f)整个应用实现一个ActionForm或者至一个模块对应于一个ActionForm?/P>
但是Q聚合的代h(hun)是复用性很差,而且隄护。针对这个问题,在Struts 1.1中提ZDynaActionForm的概c(din)?/P>
DynaActionFormc?/B>
DynaActionForm的目的就是减ActionForm的数目,利用它你不必创徏一个个具体的ActionFormc,而是在配|文件中配置出所需的虚拟ActionForm。例如,在下表中通过指定<form-bean>的type?org.apache.struts.action.DynaActionForm"来创Z个动态的ActionForm--loginForm?/P>
<form-beans>
<form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm">
<form-property name="actionClass" type="java.lang.String"/>
<form-property name="username" type="java.lang.String"/>
<form-property name="password" type="java.lang.String"/>
</form-bean>
</form-beans>
动态的ActionForm的用方法跟普通的ActionForm相同Q但是要注意一炏V普通的ActionForm对象需要ؓ(f)每个属性提供getter和setterҎ(gu)Q以上面的例子而言Q我们需要提供getUsername() ?setUsername()Ҏ(gu)取得和设|username属性,同样地有一Ҏ(gu)法用于取得和讄password属性和actionClass属性?/P>
如果使用DynaActionFormQ它?yu)属性保存在一个HashMapcd象中Q同时提供相应的get(name) ?set(name)Ҏ(gu)Q其中参数name是要讉K的属性名。例如要讉KDynaActionForm中username的|可以采用cM的代码:(x)
String username = (String)form.get("username")Q?
׃值存放于一个HashMap对象Q所以要记得对get()Ҏ(gu)q回的Object对象做强制性类型{换。正是由于这点区别,如果你在Action中非帔RJ地使用ActionForm对象Q徏议还是用普通的ActionForm对象?/P>
在Struts 1.1中,除了DynaActionForm以外Q还提供了表单输入自动验证的功能Q在包org.apache.struts.validator中提供了许多有用的类Q其中最常见的就是DynaValidatorFormcR?/P>
DynaValidatorFormc?/B>
DynaValidatorForm是DynaActionForm的子c,它能够提供动态ActionForm和自动表单输入验证的功能。和使用DynaActionFormcMQ你必须首先在配|文件中q行配置Q?/P>
<form-beans>
<form-bean name="loginForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="actionClass" type="java.lang.String"/>
<form-property name="username" type="java.lang.String"/>
<form-property name="password" type="java.lang.String"/>
</form-bean>
</form-beans>
同时要定义验证的插gQ?/P>
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,
/WEB-INF/validation.xml"/>
</plug-in>
其中的validator.xml和validator-rules.xml分别表示验证定义和验证规则的内容Q可以合q在一P(j)Q比如针对上例中的DynaValidatorFormQ我们有如下验证定义Qvalidator.xmlQ:(x)
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_0.dtd">
<!-- Validation Rules $Id: validation.xml-->
<form-validation>
<!-- ========== Default Language Form Definitions ===================== -->
<formset>
<form name="loginForm">
<field property="username" depends="required, minlength,maxlength">
<arg0 key="prompt.username"/>
<arg1 key="${var:minlength}" name="minlength" resource="false"/>
<arg2 key="${var:maxlength}" name="maxlength" resource="false"/>
<var>
<var-name>maxlength</var-name>
<var-value>16</var-value>
</var>
<var>
<var-name>minlength</var-name>
<var-value>3</var-value>
</var>
</field>
<field property="password" depends="required, minlength,maxlength" bundle="alternate">
<arg0 key="prompt.password"/>
<arg1 key="${var:minlength}" name="minlength" resource="false"/>
<arg2 key="${var:maxlength}" name="maxlength" resource="false"/>
<var>
<var-name>maxlength</var-name>
<var-value>16</var-value>
</var>
<var>
<var-name>minlength</var-name>
<var-value>3</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
从上q定义中Q我们可以看到对于字Dusername有三w证:(x)required, minlength, maxlengthQ意思是该字D不能ؓ(f)I,而且长度??6之间。而validator-rules.xml文g则可以采用Struts提供的缺省文件。注意在<form-bean>中定义的form是如何与validation.xml中的form兌h的。最后,要启动自动验证功能,q需要将Action配置的validate属性设|ؓ(f)true?/P>
<action path="/login"
type="com.ncu.test.LoginAction"
name="loginForm"
scope="request"
input="tile.userLogin"validate="true">
此时QStruts根据xml配置文g中的定义来检验表单输入,q将不符合要求的错误信息输出到页面。但是你可能?x)想Q这个功能虽然好Q可是什么检验都跑到服务器端执行Q效率方面和用户易用性方面是不是有些问题Q你可能?x)怀念v那简单的JavaScript客户端验证?/P>
不用担心Q在Struts 1.1中也支持JavaScript客户端验证。如果你选择了客L(fng)验证Q当某个表单被提交以后,Struts 1.1启动客户端验证,如果览器不支持JavaScript验证Q则服务器端验证被启动,q种双重验证机制能够最大限度地满各种开发者的需要。JavaScript验证代码也是在validator-rules.xml文g中定义的。要启动客户端验证,你必d相应的JSP文g中做如下讄Q?
?lt;html:form>增加onsubmit属?
讄Javascript支持
下表中列Z一JSP文g的示例代码,U字部分为Javascript验证所需代码?/P>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<table bgcolor="#9AFF9A" cellspacing="0" cellpadding="10" border="1" width="100%">
<tr>
<td>
<table cellspacing="0" cellpadding="0" border="0" width="100%">
<tr bgcolor="#696969">
<td align="center">
<font color="#FFFFFF">Panel 3: Profile</font>
</td>
</tr>
<tr>
<td><br>
<html:errors/>
<html:form action="/login.do" focus="username" onsubmit="return validateLoginForm(this);">
<html:hidden property="actionClass"/>
<center>
<table>
<tr>
<td>UserName:</td>
<td><html:text property="username" size="20"/></td>
</tr>
<tr>
<td>Password:</td>
<td><html:password property="password" size="20"/></td>
</tr>
<tr>
<td colspan=2><html:submit property="submitProperty" value="Submit"/></td>
</table>
</center>
</html:form>
<html:javascript formName="loginForm" dynamicJavascript="true" staticJavascript="false"/>
<script language="Javascript1.1" src="staticJavascript.jsp"></script>
</td>
</tr>
</table>
</td>
</tr>
</table>
其中onsubmit的gؓ(f)"return validateLoginForm(this);"Q它的语法ؓ(f)Q?/P>
return validate + struts-config.xml中定义的form-bean名称 + (this);
staticJavascript.jsp的内容ؓ(f)Q?/P>
<%@ page language="java" %>
<%-- set document type to Javascript (addresses a bug in Netscape according to a web resource --%>
<%@ page contentType="application/x-javascript" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html:javascript dynamicJavascript="false" staticJavascript="true"/>
如果validator-rules.xml中定义的基本验证功能不能满你的需求,你可以自己添加所需的验证类型?/P>
Action
我们通过l承ActioncL实现具体的执行类。具体Actioncȝ功能一般都在executeQ以前是performҎ(gu)Q方法中完成Q其中主要涉?qing)到以下几个斚wQ?
辅助ActionFormq行一些表单数据的(g)查?
执行必要的业务逻辑Q比如存取数据库Q调用实体bean{?
更新服务器端的bean数据Q后l对象中可能?x)用到这些数据,比如在JSP中利用bean:write来获得这些数据?
Ҏ(gu)处理l果军_E序的去处,q以ActionForward对象的Ş式返回给ActionServlet?
提示Q?/B>׃在Action和ActionForm中都可以实现验证Ҏ(gu)Q那么如何来安排它们之间的分工呢Q一般来_(d)我们U着MVC分离的原则,也就是视囄的验证工作放在ActionForm来完成,比如输入不能为空Qemail格式是否正确Q利用ValidatorForm可以很轻村֜完成q些工作。而与具体业务相关的验证则攑օAction中,q样可以获得最大ActionForm重用性的可能?
前面我们提到q,我们d业务逻辑执行分离到单独的JavaBean中,而Action只负责错误处理和程控制。而且考虑到重用性的原因Q在执行业务逻辑的JavaBean中不要引用Q何与Web应用相关的对象,比如HttpServletRequestQHttpServletResponse{对象,而应该将其{化ؓ(f)普通的Java对象。关于这一点,可以参考Petstore中WAF框架的实现思\?/P>
此外Q你可能q注意到execute与perform的一个区别:(x)executeҎ(gu)单地掷出Exception异常Q而performҎ(gu)则掷出ServletException和IOException异常。这不是说Struts 1.1在异常处理功能方面弱化了Q而是Z配合Struts 1.1中一个很好的功能--宣称式异常处理机制?/P>
宣称式异常处?/SPAN>
和EJB中的宣称式事务处理概늱|宣称式异常处理其实就是可配置的异常处理,你可以在配置文g中指定由谁来处理ActioncM掷出的某U异常。你可以按照以下步骤来完成该功能Q?
实现org.apache.struts.action.ExceptionHandler的子c,覆盖executeҎ(gu)Q在该方法中处理异常q且q回一个ActionForward对象
在配|文件中配置异常处理对象Q你可以配置一个全局的处理类或者单独ؓ(f)每个Action配置处理c?
下表定义了一个全局的处理类CustomizedExceptionHandlerQ它被用来处理所有的异常?/P>
<global-exceptions>
<exception
handler="com.yourcorp.CustomizedExceptionHandler"
key="global.error.message"
path="/error.jsp"
scope="request"
type="java.lang.Exception"/>
</global-exceptions>
其中具体的参数含义,可以参考ExceptionHandler.java源文件?/P>
taglib
讲完了模型和控制器,接下来我们要涉及(qing)的是视图。视囄角色主要是由JSP来完成,从JSP的规范中可以看出Q在视图层可?折腾"的技术不是很多,主要的就是自定义标记库的应用。Struts 1.1在原有的四个标记库的基础上新增了两个标记?-Tiles和Nested?/P>
其中Tiles除了替代Template的基本模板功能外Q还增加了布局定义、虚拟页面定义和动态页面生成等功能。Tiles强大的模板功能能够ə面获得最大的重用性和灉|性,此外可以l合Tiles配置文g中的面定义和Action的{发逻辑Q即你可以将一个Action转发C个在Tiles配置文g中定义的虚拟面Q从而减页面的数量。比如,下表中的Action定义了一个{发\径,它的l点是tile.userMainQ而后者是你在Tiles配置文g中定义的一个页面?/P>
<!-- ========== Action Mapping Definitions ============================== -->
<action-mappings>
<!-- Action mapping for profile form -->
<action path="/login"
type="com.ncu.test.LoginAction"
name="loginForm"
scope="request"
input="tile.userLogin"
validate="true">
<forward name="success" path="tile.userMain"/>
</action>
</action-mappings>
Tiles配置文gQtiles-defs.xml
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration//EN" "http://jakarta.apache.org/struts/dtds/tiles-config.dtd">
<tiles-definitions>
<!-- ======================================================= -->
<!-- Master definitions -->
<!-- ======================================================= -->
<!-- Page layout used as root for all pages. -->
<definition name="rootLayout" path="/tiles-layouts/rootLayout.jsp">
<put name="titleString" value="CHANGE-ME"/>
<put name="topMenu" value="/tiles-components/topMenu.jsp"/>
<put name="leftMenu" value="/tiles-components/panel1.jsp"/>
<put name="body" value="CHANGE-ME"/>
<put name="footer" value="/tiles-components/footer.jsp"/>
</definition>
<!-- ======================================================= -->
<!-- Page definitions -->
<!-- ======================================================= -->
<!-- User Login page -->
<definition name="tile.userLogin" extends="rootLayout">
<put name="titleString" value="User Login"/>
<put name="body" value="/src/userLogin.jsp"/>
</definition>
<!-- User Main page -->
<definition name="tile.userMain" extends="rootLayout">
<put name="titleString" value="User Main"/>
<put name="body" value="/src/userMain.jsp"/>
</definition>
</tiles-definitions>
而Nested标记库的作用是让以上q些基本标记库能够嵌套用,发挥更大的作用?/P>
Commons Logging 接口
所谓的Commons Logging接口Q是指将日志功能的用与日志具体实现分开Q通过配置文g来指定具体用的日志实现。这样你可以在Struts 1.1中通过l一的接口来使用日志功能Q而不ȝ具体是利用的哪种日志实现Q有点于cMJDBC的功能。Struts 1.1中支持的日志实现包括QLog4JQJDK Logging APIQ?LogKitQNoOpLog和SimpleLog?/P>
你可以按照如下的方式来用Commons Logging接口Q可以参照Struts源文中的许多cd玎ͼ(j)Q?/P>
package com.foo;
// ...
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//...
public class Foo {
// ...
private static Log log = LogFactory.getLog(Foo.class);
// ...
public void setBar(Bar bar) {
if (log.isTraceEnabled()) {
log.trace("Setting bar to " + bar);
}
this.bar = bar;
}
// ...
}
而开启日志功能最单的办法是在WEB-INF/classes目录下添加以下两个文Ӟ(x)
commons-logging.properties文gQ?/P>
# Note: The Tiles framework now uses the commons-logging package to output different information or debug statements.
Please refer to this package documentation to enable it. The simplest way to enable logging is to create two files in
WEB-INF/classes:
# commons-logging.properties
# org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
# simplelog.properties
# # Logging detail level,
# # Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
#org.apache.commons.logging.simplelog.defaultlog=trace
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
simplelog.properties文gQ?/P>
# Logging detail level,
# Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
org.apache.commons.logging.simplelog.defaultlog=fatal
q里我们采用的日志实现是SimpleLogQ你可以在simplelog.properties文g指定日志明细的别:(x)traceQdebugQinfoQwarnQerror和fatalQ从trace到fatal错误U别来高Q同时输出的日志信息也越来越。而这些别是和org.apache.commons.logging.log接口中的Ҏ(gu)一一对应的。这些别是向后包含的,也就是前面的U别包含后面U别的信息?/P>
]]>用Struts上传多个文g的方? 选择?techyang ?Blog http://m.tkk7.com/jackybu/articles/9763.html?/dc:creator>?/author>Thu, 11 Aug 2005 01:03:00 GMT http://m.tkk7.com/jackybu/articles/9763.html http://m.tkk7.com/jackybu/comments/9763.html http://m.tkk7.com/jackybu/articles/9763.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/9763.html http://m.tkk7.com/jackybu/services/trackbacks/9763.html 一。徏立ActionForm
package com.cnehu.struts.form; import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.upload.FormFile; import org.apache.struts.upload.MultipartRequestHandler;
/** * <p> * Title:UpLoadForm * </p> * <p> * Copyright: Copyright (c) 2005 techyang http://blog.csdn.net/techyang * </p> * @author techyang * @version 1.0 */
public class UpLoadForm extends ActionForm { public static final String ERROR_PROPERTY_MAX_LENGTH_EXCEEDED = "org.apache.struts.webapp.upload.MaxLengthExceeded";
protected FormFile theFile; protected FormFile theFile2; public FormFile getTheFile() { return theFile; }
public void setTheFile(FormFile theFile) { this.theFile = theFile; }
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = null; //has the maximum length been exceeded? Boolean maxLengthExceeded = (Boolean) request .getAttribute(MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED); if ((maxLengthExceeded != null) && (maxLengthExceeded.booleanValue())) { errors = new ActionErrors(); errors.add(ERROR_PROPERTY_MAX_LENGTH_EXCEEDED, new ActionError( "maxLengthExceeded")); } return errors;
} /** * @return Returns the theFile2. */ public FormFile getTheFile2() { return theFile2; } /** * @param theFile2 The theFile2 to set. */ public void setTheFile2(FormFile theFile2) { this.theFile2 = theFile2; } }
二。徏立ActionServlet
package com.cnehu.struts.action;
import java.io.*; import javax.servlet.http.*; import org.apache.struts.action.*; import org.apache.struts.upload.FormFile;
import com.cnehu.struts.form.UpLoadForm;
/** * <p> * Title:UpLoadAction * </p> * <p> * Copyright: Copyright (c) 2005 techyang http://blog.csdn.net/techyang * </p> * @author techyang * @version 1.0 */
public class UpLoadAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String encoding = request.getCharacterEncoding(); if ((encoding != null) && (encoding.equalsIgnoreCase("utf-8"))) { response.setContentType("text/html; charset=gb2312");//如果没有指定~码Q编码格式ؓ(f)gb2312 } UpLoadForm theForm = (UpLoadForm) form; FormFile file = theForm.getTheFile();//取得上传的文?BR> FormFile file2=theForm.getTheFile2(); try { /* * 取当前系l\径D:\Tomcat5\webapps\coka\ 其中coka 为当前context */ String filePath = this.getServlet().getServletContext() .getRealPath("/"); InputStream stream = file.getInputStream();//把文件读?BR> ByteArrayOutputStream baos = new ByteArrayOutputStream(); /* * 建立一个上传文件的输出?如果是linuxpȝhUploadFiles后的"\\"换成"/" */ OutputStream bos = new FileOutputStream(filePath + "UploadFiles\\"+file.getFileName()); //D:\Tomcat5\webapps\coka\UploadFiles\DSC01508.JPG /* System.out.println(filePath + "UploadFiles\\"+file.getFileName()); System.out.println(filePath);*/ request.setAttribute("fileName",filePath + "/" + file.getFileName()); 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(); InputStream stream2 = file2.getInputStream();//把文件读?BR> ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); OutputStream bos2 = new FileOutputStream(filePath + "UploadFiles\\"+file2.getFileName());//建立一个上传文件的输出?BR> int bytesRead2 = 0; byte[] buffer2 = new byte[8192]; int i=0; while ((bytesRead2 = stream2.read(buffer2, 0, 8192)) != -1) { bos2.write(buffer2, 0, bytesRead2);//文件写入服务器 } bos2.close(); stream2.close(); } catch (Exception e) { System.err.print(e); } return mapping.findForward("display"); } }
三。徏立上传用的JSP文g upload.jsp
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %> <html:html> <head> <title>用Struts上传文g</title> </head> <body> <html:form action="/uploadsAction" enctype="multipart/form-data"> <html:file property="theFile"/> <html:file property="theFile2"/>
<html:submit/> </html:form> </body> </html:html>
四。配|struts-config.xml文g
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> <data-sources /> <form-beans > <form-bean name="uploadsForm" type="com.cnehu.struts.form.UpLoadForm" /> </form-beans>
<global-exceptions /> <global-forwards > </global-forwards>
<action-mappings > <action name="uploadsForm" type="com.cnehu.struts.action.UpLoadAction" path="/uploadsAction"> <forward name="display" path="/display.jsp" /> </action> </action-mappings> </struts-config>
全文完!
]]> struts 数据源的配置 http://m.tkk7.com/jackybu/articles/9579.html?/dc:creator>?/author>Mon, 08 Aug 2005 08:26:00 GMT http://m.tkk7.com/jackybu/articles/9579.html http://m.tkk7.com/jackybu/comments/9579.html http://m.tkk7.com/jackybu/articles/9579.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/9579.html http://m.tkk7.com/jackybu/services/trackbacks/9579.html 三个需要的E序包:(x)
commons-dbcp-1.2.1.jar
http://apache.linuxforum.net/dist/jakarta/commons/dbcp/binaries/
struts-legacy.jar
http://apache.linuxforum.net/dist/jakarta/struts/struts-legacy/
commons-pool-1.2.jar
http://apache.linuxforum.net/dist/jakarta/commons/pool/binaries/ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "<struts-config> <data-sources> <data-source type="org.apache.commons.dbcp.BasicDataSource"> <set-property property="autoCommit" value="ture"/> <set-property property="description" value="MySQL Data Source"/> <set-property property="driverClassName" value="com.mysql.jdbc.Driver"/> <set-property property="maxCount" value="20"/> <set-property property="mixCount" value="5"/> <set-property property="username" value="root"/> <set-property property="password" value="jacky"/> <set-property property="url" value="jdbc:mysql://localhost:3306/ebooklib"/> </data-source> </data-sources> <form-beans > <form-bean name="logonForm" type="org.apache.struts.action.DynaActionForm"> <form-property name="password" type="java.lang.String" /> <form-property name="username" type="java.lang.String" /> </form-bean>
</form-beans>
<global-exceptions /> <global-forwards /> <action-mappings > <action attribute="logonForm" input="/form/logon.jsp" name="logonForm" path="/logon" scope="request" type="com.yourcompany.struts.action.LogonAction" />
</action-mappings>
<message-resources parameter="com.yourcompany.struts.ApplicationResources" /> </struts-config>
]]> struts下的q问题的解军_?/title> http://m.tkk7.com/jackybu/articles/8880.html?/dc:creator>?/author>Sun, 31 Jul 2005 15:55:00 GMT http://m.tkk7.com/jackybu/articles/8880.html http://m.tkk7.com/jackybu/comments/8880.html http://m.tkk7.com/jackybu/articles/8880.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/8880.html http://m.tkk7.com/jackybu/services/trackbacks/8880.html 1、页面提CZ息ؕ?BR>面的提CZ息来自ApplicationResources_zh.properties 解决Ҏ(gu)Q?BR>(1)所有jsp面均要?BR><%@ page language="java" contentType="text/html; charset=GBK" %> 指出当前面的charset (2)用notepad{工P而不是Eclipse EditorQ编写中文资源文Ӟ比如ApplicationResources_xx.properties。然后用工具native2ascii资源文件中的中文字W{换ؓ(f)GBKQ方法是在DOS?BR> native2ascii -encoding GBK ApplicationResources_xx.properties ApplicationResources_zh.properties 2、提交的中文字符在服务器?JBOSS)q 解决办法Q增加一个filterQ里面将request中的中文转换为GBK public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("GBK"); chain.doFilter(request,response); } 另:(x)关于native2ascii 使ApplicationResources.properties支持中文 建立一个ApplicationResources_ISO.properties文gQ把应用E序用的message都写q去Q然后在dos 下执行这个命令, native2ascii -encoding gb2312 ApplicationResources_ISO.properties ApplicationResources.properties q样׃(x)ISO~码的ApplicationResources转换成GB2312~码的格式了Q同时保存到 ApplicationResources.properties. native2asciiq个工具是jdk自带的一个东东,所以如果path都设定正就可以直接q行了,你可以在 $java_home$/bin下找C?nbsp; 转换后的中文cM于这个样?nbsp; iso 格式?nbsp;Qtj.type=商品车类?nbsp; gb2312格式?nbsp;Qtj.type=\u5546\u54c1\u8f66\u7c7b\u578b 然后在struts-config.xml中设|应用这个资源文?nbsp; <message-resources parameter="com.huahang.tj.ApplicationResources" key="org.apache.struts.action.MESSAGE" /> 开发jsp时在jsp的开头写?lt;%@ page contentType="text/html; charset=gb2312" %>Q将字符集设|?nbsp; 成gb2312可以了?BR> ]]> MyEclipse注册?/title> http://m.tkk7.com/jackybu/articles/7984.html?/dc:creator>?/author>Tue, 19 Jul 2005 06:21:00 GMT http://m.tkk7.com/jackybu/articles/7984.html http://m.tkk7.com/jackybu/comments/7984.html http://m.tkk7.com/jackybu/articles/7984.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/7984.html http://m.tkk7.com/jackybu/services/trackbacks/7984.html 下蝲 ]]> (转蝲)struts中文问题struts国际化问题终极解x? http://m.tkk7.com/jackybu/articles/7983.html?/dc:creator>?/author>Tue, 19 Jul 2005 04:50:00 GMT http://m.tkk7.com/jackybu/articles/7983.html http://m.tkk7.com/jackybu/comments/7983.html http://m.tkk7.com/jackybu/articles/7983.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/7983.html http://m.tkk7.com/jackybu/services/trackbacks/7983.html Java本n支持多国语a~码Q不需要写ME序Q可以很单的实现,U诀是两点Q? 1、所有HTML/JSP面全部采用UTF-8~码 2、客L(fng)览器完全支持UTF-8~码 步骤Q? 1、首先把所有的HTML/JSP的ContentType都设为UTF-8 2、然后对于JSPE序中的非ASCII码提CZ息都不应该写在程序里面,都应该放? application.properties里面l一理? 3、对HTML用native2ascii工具l一做一ơ处理,把HTML中的非ASCII码都转换为Unicode~码? 4、针对不同的语言Q写不同的application.propertiesQ比如说体中文是 application_zh_CN.propertiesQ繁体中文是application_zh_TW.propertiesq样Q然后对q些配置? 息文件同L(fng)native2ascii工具处理一ơ,把非ASCII码统l{为Unicode~码? 5、在Servlet的request.getCharacterEncoding()获得客户端的操作pȝ默认~码Q然后set到Struts 的HTTPSession的Locale中? OKQ现在不同的客户讉KQ就?x)显CZ同的语言版本了。你可以看看此时你的览器的字符集,是 UTF-8。现在你的网站和Google一样了Q嘿嘿,其实你有心的话,看看你的览器访问Google的时候是 什么字W集? 切记Q所有的HTML/JSP都要设ؓ(f)UTF-8~码Q所有的文g中的非ASCII码字W都要用native2ascii工具? 为用ASCII表示的Unicode~码? Struts的中文问题,q实现Struts的国际化Q其实一切ƈ不复杂,下面是具体步骤:(x) 0.遇到的问?q些问题也许不会(x)同时出现) a.中文数据从数据库中到jsp中后变成了"????" b.做好的中文properties文gQ其中的中文value在页面显CZؕ? c.jsp文g中的中文到浏览器后显C时也是qQ徏议不要在jsp文g中输入中文,量攑֜properties文g中)(j) d.由jsp传给bean的中文|再由bean传回面又是q e.当更换本地浏览器的语a选项ӞW(xu)eb应用E序不能自动Ҏ(gu)你的locale选择合适的*.properties文g。导致Web应用E序不能国际化? 1.环境Q? Web服务器:(x) Tomcat 5.0.19 操作pȝQ?Win2000 Server JVM Q?jdk 1.4 ??库:(x) Oracle 8.1.7 开发工P(x) struts studio 5.2 pro for eclipse 2.先将所?.jsp |页中开头处加入 <%@ page language="java" contentType="text/html; charset=utf-8" %> 再设|?lt;html:html locale = "true"> 3.然后~辑好两?.properties文gQ放在classes文g夹下你指定的地方Q这里是攑֜/web-inf/classes/com/wiley 下,它们分别是:(x) ApplicationResources.properties (英文资源文g) ApplicationResources_zh.properties (中文资源文g) 随便用什么工L(fng)写都行啊Q? 4.ApplicationResources_zh.properties转码成gb2312。上面引文说要{成UTF-8Q结果我试了Q不行。{成gb2312p了,操作是? ApplicationResources_zh.properties更名为ApplicationResources_xx.properties 在DOS命o(h)行进入ApplicationResources_xx.properties所在的文g? 使用命o(h)Qnative2ascii -encoding gb2312 ApplicationResources_xx.properties ApplicationResources_zh.properties(至于你ؓ(f)什么会(x)出现“native2ascii不是内部命o(h)”,Q请查其它资料,可能你要讄环境变量Q因Z是jdk的文件夹bin下的一个应用程? 5.接下来配|struts-config.xml,很简单,我们加入Q? <message-resources parameter="com.wiley.ApplicationResources"/> p了; 到此已能解决大多C文问题。如上面所说的a,b,e 现在打开览器,选择菜单Q工兗internet选项》语aQ将“中文-中国[zh-cn]”删掉,d一个“英语-英国[zh-gb]”确定后Q重启Tomcat,输入|址你就?x)发玎ͼ你的面的文本信息就会(x)用的是ApplicationResources.properties (英文资源文g)中的内容。如果换回“中文-中国[zh-cn]”,它就?x)显CApplicationResources_zh.properties (中文资源文g)中的中文内容? 至于问题“c.jsp文g中的中文到浏览器后显C时也是q?你就要用与第4步类似的Ҏ(gu)来重新对*.jsp 文g~码Q这?encoding的参数就要用UTF-8了,如果你用的也是struts studio 5.2 pro for eclipse工具Q这一步就免了。它?x)自动用UTF-8的格式存储? 至于问题“d.由jsp传给bean的中文|再由bean传回面又是q”的解决Q我只是加了个过滤器? 你可以现在web.xml中加入:(x) <filter> <filter-name>Set Character Encoding</filter-name> <filter-class>com.wiley.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>ignore</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <servlet-name>action</servlet-name> </filter-mapping> 然后在你指定的包内加个java文g 我放在了/web-inf/classes/com/wiley 里,下面是源代码Q? /* * XP Forum * * Copyright (c) 2002-2003 RedSoft Group. All rights reserved. * */ package com.huahang.tj.struts.filters; import javax.servlet.*; import java.io.IOException; /** * <p>Filter that sets the character encoding to be used in parsing the * incoming request, either unconditionally or only if the client did not * specify a character encoding. Configuration of this filter is based on * the following initialization parameters:</p> * <ul> * <li><strong>encoding</strong> - The character encoding to be configured * for this request, either conditionally or unconditionally based on * the <code>ignore</code> initialization parameter. This parameter * is required, so there is no default.</li> * <li><strong>ignore</strong> - If set to "true", any character encoding * specified by the client is ignored, and the value returned by the * <code>selectEncoding()</code> method is set. If set to "false, * <code>selectEncoding()</code> is called <strong>only</strong> if the * client has not already specified an encoding. By default, this * parameter is set to "true".</li> * </ul> * * <p>Although this filter can be used unchanged, it is also easy to * subclass it and make the <code>selectEncoding()</code> method more * intelligent about what encoding to choose, based on characteristics of * the incoming request (such as the values of the <code>Accept-Language</code> * and <code>User-Agent</code> headers, or a value stashed in the current * user's session.</p> * * @author <a href="mailto:jwtronics@yahoo.com">John Wong</a> * * @version $Id: SetCharacterEncodingFilter.java,v 1.1 2002/04/10 13:59:27 johnwong Exp $ */ public class SetCharacterEncodingFilter implements Filter { // ----------------------------------------------------- Instance Variables /** * The default character encoding to set for requests that pass through * this filter. */ protected String encoding = null; /** * The filter configuration object we are associated with. If this value * is null, this filter instance is not currently configured. */ protected FilterConfig filterConfig = null; /** * Should a character encoding specified by the client be ignored? */ protected boolean ignore = true; // --------------------------------------------------------- Public Methods /** * Take this filter out of service. */ public void destroy() { this.encoding = null; this.filterConfig = null; } /** * Select and set (if specified) the character encoding to be used to * interpret request parameters for this request. * * @param request The servlet request we are processing * @param result The servlet response we are creating * @param chain The filter chain we are processing * * @exception IOException if an input/output error occurs * @exception ServletException if a servlet error occurs */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Conditionally select and set the character encoding to be used if (ignore || (request.getCharacterEncoding() == null)) { String encoding = selectEncoding(request); if (encoding != null) request.setCharacterEncoding(encoding); } // Pass control on to the next filter chain.doFilter(request, response); } /** * Place this filter into service. * * @param filterConfig The filter configuration object */ public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; this.encoding = filterConfig.getInitParameter("encoding"); String value = filterConfig.getInitParameter("ignore"); if (value == null) this.ignore = true; else if (value.equalsIgnoreCase("true")) this.ignore = true; else if (value.equalsIgnoreCase("yes")) this.ignore = true; else this.ignore = false; } // ------------------------------------------------------ Protected Methods /** * Select an appropriate character encoding to be used, based on the * characteristics of the current request and/or filter initialization * parameters. If no character encoding should be set, return * <code>null</code>. * <p> * The default implementation unconditionally returns the value configured * by the <strong>encoding</strong> initialization parameter for this * filter. * * @param request The servlet request we are processing */ protected String selectEncoding(ServletRequest request) { return (this.encoding); } }//EOC 到此我遇到的中文问题已全部得到解冻Iq从中理解到struts的国际化的深d义?/FONT> ]]> 译-Jakarta Struts介[from Matrix] http://m.tkk7.com/jackybu/articles/4168.html?/dc:creator>?/author>Wed, 11 May 2005 06:45:00 GMT http://m.tkk7.com/jackybu/articles/4168.html http://m.tkk7.com/jackybu/comments/4168.html http://m.tkk7.com/jackybu/articles/4168.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/4168.html http://m.tkk7.com/jackybu/services/trackbacks/4168.html 译作?-Matrix开源技?/A>-Wingc译前的?/FONT> 呵呵Q这是wingcW一ơ真正意义的译技术文章,自己看E文文档和把E文翻译成能读的中文那真是两回事啊Q翻译得不好再所隑օQ?zhn)可别骂wingc?)若有什么地方不通、不爽或不妥Q请?A target=_blank>http://www.onjava.com/pub/a/onjava/2001/09/11/jsp_servlets.html 看原文吧?BR> Web应用开发早期曾l是那么的“简单”,那个时候还只是UHTML面和浏览器Ҏ(gu)而已。由于还涉及(qing)不到动态数据操作和商业应用Q也qM很多ȝ(ch)。但是这L(fng)“简单”只是过g烟,如今我们不得不ؓ(f)复杂的基于Web的商业应用开发采用诸多技术?BR> 本文介l如何利用Strutsq行应用开发的前台整合的开发过E。Struts是一个ؓ(f)开发基于模?Model)Q视?View)Q控制器(Controller)(MVC)模式的应用架构的开源框?译注1)Q是利用Java Servlet和JSP构徏Web应用的一w常有用的技术?BR> 阅读本文需要读者具有以下几斚w的开发经验:(x)JSP、Servlet、自定义标签?custom tag library)和XML。如果读者想补一补自定义标签库的知识Q可以参考作者以前关于这斚w的文章。而本文也是关于介l如何用Strutspd文章的上半部分,本系列暂定分Z下两部分?BR>新手上\注意事项 Struts是一个基于Sun J2EEq_的MVC框架Q主要是采用Servlet和JSP技术来实现的。其最初萌芽于Craig McClanahan的构思,诞生至今也一q有余了(译注2)。现在,Struts是Apache软g基金?x)旗下Jakarta目l的一部分Q其官方|站?IMG src="http://www.matrix.org.cn/images/small/url.gif" align=absMiddle>http://jakarta.apache.org/struts 。由于Struts能充分满_用开发的需求,单易用,敏捷q速,在过ȝ一q中颇受x。Struts把Servlet、JSP、自定义标签和信息资?message resources)整合C个统一的框架中Q开发h员利用其q行开发时不用再自q码实现全套MVC模式Q极大的节省了时_(d)所以说Struts是一个非怸错的应用框架?BR> 目前的Struts 1.0修正版包括完整的文档Q既可以说是用户文档又是开发指导文档。如果读者是JSP新手Q或者对MVC设计模式不是太熟的话Q可能刚上\时会(x)比较慢,不过不用担心Q要怿自己?x)尽快赶上?) 此外Q应该注意到管当前Struts只是1.0版,但已l相当稳定了Q作者从Struts 0.9版就在一个大规模的项目中应用?最q升U到1.0?Q至今还没有遇到什么麻?ch)问题。实际上QStruts在这个要开发复杂用L(fng)面的目中,为我们团队大大的~短了开发时_(d)在此衷心的感谢Struts目团队的所有开发h员?BR> 哦,q有Q如果读者开始上路了Q要知道Struts的邮件列表可是有相当分量的,在这里h可保证能?qing)时跟上Jakarta目的最新动态哦 http://jakarta.apache.org/site/mail.html ?BR>开始上? Struts框架可分Z下四个主要部分,其中三个和MVC模式紧密相关Q?BR> 1、模?Model)Q本质上来说在Struts中Model是一个Actionc?q个?x)在后面详细讨?Q开发者通过其实现商业逻辑Q同时用戯求通过控制?Controller)向Action的{发过E是Z由struts-config.xml文g描述的配|信息的?BR> 2、视?View)QView是由与控制器Servlet配合工作的一整套JSP定制标签库构成,利用她们我们可以快速徏立应用系l的界面?BR> 3、控制器(Controller)Q本质上是一个ServletQ将客户端请求{发到相应的ActioncR?BR> 4、一堆用来做XML文g解析的工具包QStruts是用XML来描q如何自动生一些JavaBean的属性的Q此外Strutsq利用XML来描q在国际化应用的用户提示信息?q样一来就了应用系l的实现多语a支持)?BR> 好,下一步咱们来看看构成q个框架的各个部分以?qing)相互之间是怎样q作的吧Q?BR> 搞定配置?/FONT> 在用Struts之前Q咱们必先设|好JSP服务器,以便让服务器在用戯求时Q知道该如何指定后~的请求{到相应的ControllerQStruts ActionServlet处理Q当?dng)q些配置信息都一般在服务器启动时通过web.xml文gd的。我们可以在web.xml定义多个ControlloerQؓ(f)每一个应用定义一个。一个典型的web.xml文g配置如下Q其中有相应的注释,很好懂的Q在后面讨论Action的时候,我们主要分析strutc-config.xml?BR><web-app> <servlet> <!-- 以下配置信息声明了Struts中的ActionServletQ即一个名为OreillyAction的ServletQ其具体实现为org.apache.struts.action.ActionServlet。在q个配置中还有这个Servlet的两个参敎ͼ(x)debug level和detailQ此处这两个参数的值都设ؓ(f)?Q此外还讄了在启动载入时创Z个实例?BR>--> <servlet-name>OreillyActionServlet</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- 讄所有后~?action的请求,都{发到OreillyActionServlet --> <servlet-mapping> <servlet-name> OreillyActionServlet </servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> <!-- 初始请求页面设|ؓ(f)login.jsp --> <welcome-file-list><welcome-file>login.jsp</welcome-file></welcome-file-list> <!-- 讄Struts的JSP面要用到的标签库和她们的\?BR>--> <taglib> <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib> </web-app>控制?Controller) Controller是这个框架中扮演“交通警察”的角色Q当客户端与服务器有交互动作Ӟ都由Ҏ(gu)控制。ControllerHTTPh包q{发到框架中相应的对象Q这些对象可能是一个JSP面或一个Action?BR> Controller在web.xml中设|ؓ(f)org.apache.struts.action.ActionServlet的一个实例,在本例中Q这个实例就是OreillyActionServlet。在一个完整的控制q程中,也就是处理一个HTTPhӞ在控制过E之初,q个Servlet?x)从一个配|文件struts-config.xml中获取请求与控制动作向对应的配置信息Q这个我们会(x)在后面详l讨论,Controller通过q些配置信息来决定HTTPh该往何处转发Q而这些Action在接收到转发来的h后,实现真正的商业逻辑。我们要注意的非帔R要的一Ҏ(gu)Action对象要能够调用这个ActionServlet的若q方法,通过q个有力的特性,当Action对象在控制过E中请求再向别的Action对象转发?最初的h是由ActionServlet获取Q向Action对象转发Q而Action对象q可以再转发到别的对?Q我们可以将一些需要共享的数据对象通过调用一些方法放入这个Servlet相关的一些标准容器中捎带q去?BR>模型(Model) 所谓Model是在对用户h的整个控制过E中Q真正处理用戯求ƈ保存处理l果的对象,在整个过E中Q我们一般利用JavaBean来把一些信息保存v来以便在各个对象之间传递。因为在框架中,Model对象是真正处理商业逻辑功能的对象,因此也就是框架中应用需求实现相x最大的部分。在Struts的实现里QModel的具体表现Ş式就是ActionForm对象和与其对应的Action对象了。对用户提交表单的数据进行校验,甚至Ҏ(gu)据进行预处理都能在ActionForm中完成。通常的应用中Q一般是一个Model对象和一个请求页面对应的关系Q但也可以一个Model对象对应多个面h。如果struts-config.xml配置文g没有指定一个Model对象对应的ActionQ那么控制器直接把(通过模型对象完成数据装?h转到一个View对象?BR>struts-config.xml 前面多次提到的struts-config.xml配置文g是整个框架的d骨。web.xml文g定义了一个请求到来应向何处{发后Q后面的工作全权由struts-config.xml理控制了。可以说struts-config.xml是整个Struts框架的“扛把子?译注3)Q只有这位“老大”清楚所有请求与动作的映关p,要是他哪里没有搞定或不爽的话Q整个“社团”就什么也摆不q了:)如今的应用系l,XML形式的配|文件越来越多,如果整个pȝ只用一个这L(fng)配置文g的话Q那么保持整个系l的模块化和可维护性都非常的轻松。用配|文件来描述h-动作的控制过E和怺关系Q而不是在代码中将对象之间的调用关pd死,那么都应用系l有变动Ӟ我们只用修改配置文gp了,而不是再重新~译发布E序了?BR> Controller通过struts-config.xml文g的配|信息确定当有请求时应该调用那个对象来处理,从效率的角度出发Q这些信息都是在pȝ启动时读入ƈ存在内存中的。下面我们将讲解一个极短小的struts-config.xml文gQ文件中定义了一个与dh对应的登录动作,h到达后将被{发到com.oreilly.ui.authentication.actions.LoginActionq个Action对象Q该对象处理的结果决定向用户q回的页面。这个例子同时还C了一个Action对象请求{发到别的Action对象Q而例子中另一个返回的对象则是一个View对象Q即我们看到的login.jsp面?BR><?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd" ;> <struts-config> <!-- ========== Action 映射定义 =================== --> <action-mappings> <!-- <action> 属性的说明 --> <!- type - 完整的Action实现cd name - 该Action要用到的ActionForm?BR>path - h该Action的URI validate - 如果本属性ؓ(f)true则在Action动作之前其对应的ActionForm的validateҎ(gu)?x)自动被调用Q一般用以校验用戯入的数据 --> <!-- ~~~~~~~~~~~~~~~~~~~~~ --> <!-- O'Reilly Main Actions --> <!-- ~~~~~~~~~~~~~~~~~~~~~ --> <action path="/Login" type="com.oreilly.ui.authentication.actions.LoginAction"> <forward name="success" path="/DisplayMainPage.action"/> <forward name="failure" path="/login.jsp"/> </action> </action-mappings> </struts-config>视图(View) View对象通常来说都是指的JSP面。Struts框架实际上ƈ没有真正的JSP的要求规范,而是提供了大量的标签库来为开发者更便的JSP整合到Struts框架中。在Struts中通过标签定义方式的JSP面能够用户通过表单输入的数据存入一个JavaBean中,也就是我们前面提到的ActionForm bean。通过Actionc调?自动或手?ActionForm的校验方法来(g)查用戯入的数据Q如果发C合法的数据,再通过Struts的一个通用机制错误信息返回给用户昄?BR> Struts框架提供了若q个标签库,它们有各自不同的用途。由于这些库q可以脱Struts框架单独使用Q这h们也可以在其他系l中试使用q些标签库,它们包括Q?BR> * struts-html - q个标签库用来创建动态的HTML面和表单?BR> * struts-bean - 提供了类似甚xZ<jsp:useBean>中的功能?BR> * struts-logic - 用于在页面输出文本信息时的条件、@环等程的控制?BR> * struts-template - 用于产生有共同风格的动态JSP面模板?BR> 此外Q可定制标签库在Struts中还有一大用处是Q通过资源文g的方式来实现应用pȝ的多语言Ҏ(gu),应用Struts的系l若惛_pȝ中的用户交互信息换一U语a的会(x)很简单,更换一个不同的资源文g可以了?BR>大家都开始应用Struts? Struts框架可能对于大多数开发h员来_(d)是一门比较新的技术。但我们现在已经可以在不的应用pȝ中看到Struts的n׃Q而我们大可在新的应用或正在开发的JSP目中用Struts框架?BR> 例如Q在作者现在正在ؓ(f)客户开发的一个大型数据库应用pȝ中,商业逻辑都是通过EJB来实现的Q用L(fng)面则是JSP面。在struts-config.xml文g中定义了用户输入表单和对应的Actionc,当一个请求发生时Q即用户数据以ActionForm的Ş式封装提交到ActionӞAction先调用ActionForm的校验方法,数据(g)查校验通过后,Action再调用相应的EJB中的Ҏ(gu)来完成数据操作,操作的结果以XML的Ş式返回,XML解析后再攑օ我们数据的封装传递JavaBean Q?nbsp;ActionForm中显C到JSP面里返回用戗?BR> 整个的控制流E?包括Action调用后的不同的返回结?都尽在struts-config.xml中所掌握Q这U“中央集权”的方式非常便于应用程的调整。而不是Servletq是JSP面?甚至在一些n层的应用架构)都无需撰写如何获取昄数据的代码?BR> ׃目前作者所开发的是一个较大型的系l,有很多的JSP面和用戯提交的ActionFormcdQ因此发现Struts的一个麻?ch)的地方Q那是Q我们要为如此多面和ActionForm开发对应的ActioncL完成控制Q因为我们目前JSP和ActionForm与Action是一对一的关pR不q我认ؓ(f)如果在项目前期分析和设计时多下些功夫Q做出更完美一些的设计Ҏ(gu)的话Q这L(fng)情况是可以避免的Q当?dng)在新产品的开发过E中Q想一步就把所有需求弄清楚明白那也是不可能的。我们不是都有这L(fng)l历吗?在开发中的应用系l正一步一步走向成熟的时候,更新和更明确的需求才?x)被提出来。不q,像我们手里这个利用Struts开发了六个月的pȝ也确实少见了Q呵c(din)除去这些非技术因素不谈,Struts框架为我们实现MVC模式节省了大量的旉Qƈ且开发出的系l相当的E_Q可以说是很成熟的品了?BR> 在本pd文章的第二部分,我们把各小D代码集成v来,完成一个完整的Struts应用的实例,希望大家l箋和作者一起学?fn)Struts! Sue Spielman是ONJava.com的副~辑Q主要擅长于JSP和Servlet技术,她还是Switchback Software LLC公司的总裁和高U技术咨询专家?BR> 译注1Q虽然常见将Controller、Model和Viewq三个翻译ؓ(f)对应的“控制器”、“模型”和“视䏀,但L觉在表达上还是有Ơ本意,所以译文中只在需要名词定义的地方三个中文词汇写上,文中其他的发q是保留E文“真w”?BR>译注2Q这?001q??1?没错Q就是?11”当天哦)发的文章啦,要知道文章里的“那时”也是现在的好久之前的时候了?BR>译注3Q原文中此处是用“Vito Corleone”来形容struts-config.xml的,知道唯托.U尼奥尼是谁吗?呵呵Q经典电(sh)影《教父I》和《教父II》里的教父啊Q马?白兰度和|伯?德尼|先后塑造的l典形象Q所以wingc在这里也用了一Ҏ(gu)湖词汇,请勿见怪?BR> 学习(fn)Jakarta StrutsQ第二篇Q?BR> 本文是三学?fn)Struts框架pd文章的第二篇Q原文请?A target=_blank>http://www.onjava.com/pub/a/onjava/2001/10/31/struts2.htmlQ。在本系列的的第一中Q我们大致浏览了Struts框架Q框架的功能以及(qing)框架中应用到的各个模块。而本文,我将利用Struts 1.0为大家演C徏立一个简单的应用Q在W三文章中介l如何利用Struts的标{֜JSP中访问ApplicationResource文g中的信息?BR> 我们在这文章将?x)一步一步的讲解Struts的应用,以这L(fng)形式打开Struts一道道秘的大门,通过q样的过E,怿也能Ȁ起你在应用开发中如何应用Struts的灵感。如果你对Struts的一些术语不是很清楚的话Q可以参考本pd前一对Struts作大体介l的文章?BR> 再次重复一遍,本文需要读者有如下几方面的知识和经验:(x)JSPQServletsQ自定义标签库(Custom Tag librariesQ和XML。此外,在本文中Q我q会(x)用到Jakarta目l其他一些好东东Q比如Tomcathttp://jakarta.apache.org/tomcat/index.html Q实现Java Servlet和JSP官方标准的Servlet容器Q通俗的讲是一个JSP的Web Server啦)(j)和Anthttp://jakarta.apache.org/ant/index.html Q基于Java的自动编译发布工Pq可是好东东啊)(j)?BR> 作ؓ(f)一名一直用前沿技术开发了诸多应用的技术h员,我一直坚信掌握新技术,理解该技术开发的逻辑是至关重要的。但q往往是陷住我们学习(fn)步伐的惔潭,正因如此Q我打算利用Struts开发的一套完整流E作为我们教学的案例。该程的这个案例可谓“麻雀虽小、五脏据全”,你完全可以将q个程应用C手头那些复杂庞大的项目中Q至在我们的大目中应用这个流E效果不错?BR> 有开发复杂商业应用的开发h员都知道Q客L(fng)需求L在不停变q,所以如果有一套规范的开发流E来遵@Q当客户提出新的需求时Q我们至可以明哪些“无理”需求其实是合理可行的。好Q接下里我将在我的这个例子中向各位展C和应用整个程?BR> 本文中的CZ代码是StrutsSample应用中的一部分Q包括build.xml的完整代码可以到此处http://www.onjava.com/onjava/2001/10/31/examples/StrutsPartII.jar 下蝲?BR>Struts开发过E?/FONT> 从Struts发布的版本号可以看出QStruts是个新玩意,Ҏ(gu)好几个部分组成,明智的你如果搞清楚了何时该开发完成合适的部分Q那会(x)更好的利用我们的开发时间。从我所开发的几个利用Struts应用中,我大致ȝ出如下这个比较有效的开发步骤:(x) 1Q明应用需求; 2Q由用户输入和获取数据的角度出发Q明和设计出每一个用L(fng)面; 3Q确定用L(fng)面的q入路径Q?BR>4Q由应用逻辑信息定动作映射?ActionMapping)Q?BR>5Q由设计完成的用L(fng)面开发其所用到的类和应用函敎ͼ 6Q由用户界面中的数据信息开发ActionForm和相应的数据校验Ҏ(gu)Q?BR>7QActionMapping中将?x)被调用相应的Action或{到相应的JSP面Q这一步我们先开发这些ActionQ?BR>8Q开发商业应用逻辑Q就是相应的JavaBean、EJB或其他东东; 9Q开发由ActionMapping定义的系l工作流E完成对应的JSP面Q?BR>10Q完成系l配|文Ӟ(x)struts-config.xml和web.xmlQ?BR>11Q编?试/发布?BR>明确应用需?/FONT> 开发Q何应用系l的W一步就是收集用户需求信息。不一个用户逻辑初看上去多么合理Q但L可能在开发时才发现它比看上去要难得多。所以,拟一份明的用户需求列表,q不只是Z开发的目的Q还能通过该表分析用户需求以定哪些地方可能需要花更多的精力?BR> 在我们这个StrutsSample目中,应用需求就是:(x) 作ؓ(f)一个展CStruts框架应用的完整例子,本示例完成的功能是用L(fng)录。目的只为明Struts的应用,本示例将不会(x)涉及(qing)C般复杂应用系l中可能应用的安全、数据库、EJB开发等{相x术?BR>设计用户界面 q个应用中,包括如下三个用户界面Q?BR>1Q登录界面,用于用户名和密码输入Q?BR>2Q当d用户为合法用h的欢q界面; 3Q当dp|时的错误提示界面?BR> 定用户界面的进入\?/FONT> 1Q登录界面作个应用的默认面Q?BR>2Q欢q界面只有当成功d后才能进入; 3QQ何可能发生错误的面能可以进入错误提C界面;由应用逻辑信息定ActionMapping ActionMapping为整个应用确定的“线路图”,在配|文件struts-config.xml对ActionMappingq行定义Q通过转发hQforwardQ来理顺应用的处理流E,定应用中每个用戯求对应的动作?BR> 通常我们在开发过E中逐步定了ActionMapping所需的信息,开发代码的q程是在由草稿开始一步步完善struts-config.xml的过E。当Actioncd理完用户h后,其返回的的forward是在ActionMapping中定义的一个。一个Actionq回的forward完全有多U可能,管一个Action一般只定义其相关的几个forward。那么,如果有多个Action都可能返回的同一个forwardQ那么就可以其定义为全局转发Qglobal forwardQ。这cM于C中的头文件中全局变量Q如果在struts-config.xml描述信息中,某一个forwardq不是在当前Action描述中定义的而是全局定义的,那么q个全局的将起作用,同样Q一个Action中当前定义的forward覆盖全局定义。在我们所l的q个单实例中Q我们定义了全局forward――“error”,当某Actionq回的forward是“error”这个映,那么Errorpage.jsp面会(x)昄l用P管当前Actionq没有对其定义?BR> 我们l箋不断的开发,目日渐完善Q项目相关的配置文g也会(x)来详l。在下面的例子中Q我们将以StrutsSample中用到的struts-confug.xml文gZQ学?fn)global forward和一个Action中相x的定义。下面定义了一个名为“login”的ActionQ其为com.oreilly.actions.LoginAction的实例,当Action处理用户d成功后将一个名?success"的forwardq回Q用户也׃(x)看到Welcome.jsp面Q如果登录失败,Action返回对应的forward以再昄Login.jspl用P而如果处理过E中发生其他错误QAction返回全局定义的forward――“error”,用户也就?x)看到错误提C页面Errorpage.jsp?BR> <!-- ========== Global Forward 定义 --> <global-forwards> <forward name="login" path="/Login.jsp"/> <forward name="error" path="/Errorpage.jsp"/> </global-forwards> <!-- ========== Action Mapping 定义 --> <action-mappings> <!-- <action>元素的相兛_?nbsp;--> <!-- 以下只列出常用属性,其他请参考org.apache.struts.action.ActionMapping的相x?BR> path - 当前Action对应的用戯求URI路径 type - 实现当前Action的Java class的完整名?BR> name - 当前Action中用到的ActionForm的名字,其具体信息在配置文g其他地方另有详细定义 unknown - 如果该属性设|ؓ(f)trueQ那么就是声明这个Action处理整个应用中所有未扑ֈ相应处理Action的请求,当然Q一个应用系l中也只?x)有一个Action的unknown属性可以设为true scope - Action中所用到的ActionForm的生存期Q可以ؓ(f)“request”或“session”,随着生存期的讄Q该Action也会(x)在相应的旉被创?BR> input - 该Action中相关ActionForm获取用户输入的输入页面,当将ActionForm设ؓ(f)自动验证输入数据Q发C合法数据q回错误Ӟ返回该面 validate - 如果本属性ؓ(f)true则在Action动作之前其对应的ActionForm的validateҎ(gu)?x)自动被调用Q一般用以验证用戯入的数据 forward 元素 - 定义当前Action相关的ActionForward --> <!-- =================== --> <!-- O'Reilly Struts Sample Main Actions --> <!-- =================== --> <action path="/login" type="com.oreilly.actions.LoginAction" name="loginForm" scope="request" input="/Login.jsp"> <forward name="success" path="/Welcome.jsp"/> <forward name="failure" path="/Login.jsp"/> </action> </action-mappings> 在前一文章中Q我们曾说过Qstruts-config.xml是MVC模式的的Controller。在定struts-config.xml中的配置信息Ӟ应该多花些时间精力在上面Q以保证每一个Action定义?qing)其相关定义是符合应用的需求的。如果在目开始没有详l的设计其定义,当将所有代码和配置集成CL(fng)时候,我们不可避免的各部分的代码和配置完全重新l织一遍?BR> 我们当前的例子StrusSample因ؓ(f)只是处理用户dQ所以只需要一个Action。一个应用系l中所要用到的Action的多完全依应用的大而定。一旦整套Action的映完全的定义出来后,我们可以一个一个开发其具体实现的Action和ActionFormc,q渐完成的部分一点一炚w成v来?BR>p计完成的用户界面开发其所用到的类和应用函?/FONT> 所有ActionForm的实现类都是org.apache.struts.ActionForm的子cR一个ActionForm是与面上的输入表单相关联的Q而且ActionForm的实现还可以对用戯入数据的合法性进行验证。作Z个Java BeanQActionForm有Set和GetҎ(gu)Q当一个页面中表单被提交时Q系l将自动调用SetҎ(gu)数据放入ActionForm中,而GetҎ(gu)ؓ(f)在Action中操作这些数据所提供。一般来_(d)处理表单中的所有数据,q进行合法性验证都完全可以交由ActionForm来完成。在应用中,我个h而言Q們于将ActionForm和Action划分C同的包中Q因为当一个页面中要用到几对ActionFrom和ActionӞ都放在一个包内会(x)h的。下面的代码Q就是实例中d面用到的ActionForm的代码?BR> /* * LoginForm.java */ package com.oreilly.forms; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; /** * 验证用户要用到的两个数据 * * username - d用户?BR>* password - 用户密码 * */ public final class LoginForm extends ActionForm { private String userName = null; private String password = null; /** * userName的GetҎ(gu) * @return String */ public String getUserName() { return (userName); } /** * userName的SetҎ(gu) * @param userName */ public void setUserName(String newUserName) { userName = newUserName; } /** * password的GetҎ(gu) * @return String */ public String getPassword() { return (password); } /** * password的SetҎ(gu) * @param password */ public void setPassword(String newPassword) { password = newPassword; } /** * 重置所有数?BR> * * @param mapping 当前的ActionMapping * @param request 当前Server正在处理的HttpServletRequest */ public void reset(ActionMapping mapping, HttpServletRequest request) { userName = null; password = null; } /** * 验证当前HTTPh提交上来的数?BR> * 如果数据验证发现不合法数据,返回一个封?BR> * 所有验证错误的ActionErrors对象 * 如果数据验证通过Q该Ҏ(gu)q回null或者一?BR> * 没有装M验证错误的ActionErrors对象 * * @param mapping 当前的ActionMapping * @param request 当前Server正在处理的HttpServletRequest */ public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors errors = new ActionErrors(); // 当前ActionForm中,只需要检查用戯入的用户名数?BR> if( userName == null || userName.length()==0 ){ errors.add("userName",new ActionError("error.userName.required")); } return (errors); } } 以上的代码,只有两点和一般的Java Bean有所不同。其一是resetҎ(gu)Q方法中讄的值将在表单被reset时反应到其对应的表单上Q即表单项的数据恢复到默认倹{其二是validateҎ(gu)Q是用来验证用户在表单中所输入数据的方法。在当前q个例子中,我们只验证用戯入的用户名。因Z个用户名其对应的密码可能为空Q所以我们的逻辑是验证时不L查密码。验证用户名Q当发现输入的用户名为空ӞҎ(gu)׃(x)产生一个错误对象(ActionErrorQ?BR> 在Struts中用ActionErrors来装载多个错误,从ActionErrorsl尾的那个“s”就可以知道Ҏ(gu)一个ActionError对象的集合。在验证用户输入Ӟ可以验证完表单中所有数据后Q再可能发现的多个错误通过ActionErrorsq回l用Pq样的逻辑应该是想当然的啦Q不可能用户有五个不同的输入错误Q却要分五次提示Q让用户修改提交五遍吧,呵呵?BR> 同时Q要知道在我们这个例子中Q我们将错误信息提示l用h通过ApplicationResource.properties文g。这个文件在Tomcat启动旉过web.xml中的定义个应用所使用。通常每一个应用都在其WEB-INF目录下都有web.xml文g来描q系l,而关于部|应用时具体的结构信息,请参考Tomcathttp://jakarta.apache.org/tomcat/index.html {Server相关的用h册?BR> ApplicationResource.properties文g中可以定义应用中所要用到的提示信息的字W串Q字W串都通过一个键值来唯一定其位|。在我们q个例子中,键值error.userName.required所对应的字W串信息是“A username is required”,在给用户昄错误信息Ӟ也就通过键值确定的错误提示昄该字W串。通过q样的机Ӟ为我们在pȝ中实现多语言提供了便利,该文g中的q些字符串翻译成相应的语aQ我们的pȝ可以实现西班牙语、d语、法语和汉语{等语言的版本了?BR> 下面q些ApplicationResource.properties中的信息对于我们q个单的CZ中已l够用了Q?BR> login.title=Login Struts Sample error.userName.required=A username is required error.login.authenticate=Invalid username/password errors.footer=</ul><hr> errors.header=<h3><font color="red">Page Validation</font></h3>Please correct the following error(s) before contiuing:<ul> applicationResources=Cannot load application resources bundle {0} 面的标题,按钮或其他什么需要文本提C的地方都可以通过q个文g来定义显C用字符丌Ӏ我们将在该pd的最后一文章,也就是后l几个开发步骤中讲解如何通过Struts的标{从q个文g中获取显C用字符丌Ӏ?BR> 学习(fn)Jakarta StrutsQ第三篇Q?BR>本文是三学?fn)Struts框架pd文章的最后一(原文误http://www.onjava.com/pub/a/onjava/2001/11/14/jsp_servlets.html Q?BR>在第一文章《Jakarta Struts介》中Q我大致分析了Struts框架Q讨Z它所能完成的功能Q还?gu)览了组成Struts的各个组成部分。在W二文章《学?fn)Jakarta Struts》中Q我开始详l描q如何利用Struts来构Z个简单应用的q程步骤。而本文章将?x)向大家演示如何ApplicationResource文g中的文本信息Q通过Struts标签在JSP面中显C出来?BR>ActioncLq接Struts架构和应用中业务逻辑代码的桥梁。所以你应该可能让Actioncd巧简单,因ؓ(f)真实应用中的逻辑处理应该是由单独分离出来的逻辑层来完成的。如果你正在从事n层应用的开发,你当然希望层与层之间的接口越单越好。而事实上QActioncM的主要方?perform()"Q?.1中ؓ(f)execute()Q却有点暗示应该在本Ҏ(gu)中做点什么的意思。我们知道,每个Actionc都需要从 org.apache.struts.action.Action l承而来。在型应用中,我们的Actioncd可能只要承org.apache.struts.action.Actionp够了Q而在某些特定的复杂应用中Q我׃我们所实现的ActioncMȝ出来了一些通用Ҏ(gu)。因此,在我看来Q构造一个基cdq些通用Ҏ(gu)的代码实现出来Q让应用中所用到的所有ActioncM直接l承org.apache.struts.action.ActionQ而承这个完成了一些通用Ҏ(gu)的基类以实C码重用,是一个相当不错的设计。我在StrutsSample中就应用了这U方法,构造了q样的一个基c,该基cȝҎ(gu)在完成复杂逻辑的和单{发请求的ActioncM都可以用?BR> package com.oreilly.actions; import java.io.IOException; import java.util.Properties; import java.util.ResourceBundle; import java.util.MissingResourceException; import java.util.Enumeration; import java.util.Properties; import java.rmi.RemoteException; import javax.ejb.EJBHome; import javax.ejb.CreateException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionServlet; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; q个cd是用Struts开发时Q所有Actionc都要承的基类。它把一些通常在实际应用中最有可能被用到的东襉K考虑q来了。就q篇文章而言Q?nbsp;cM一些与Strutsq不是太紧密相关的方法将只做注释而不?x)完整的实现Q而从事开发工作的你,有兴的话,请完成这些方法ƈ应用q个c,ؓ(f)你在实际目中的开发快马加鞭。注意,因ؓ(f)所有的Actionc都要从org.apache.struts.action.Action l承而来Q所以我们的q个cd栗?BR>public abstract class AbstStrutsActionBase extends Action { /** * 定义一些在struts-config.xml中记录在案的 * 全局应用中皆可可通用的forward标识 */ protected static final String SUCCESS = "success"; protected static final String FAILURE = "failure"; protected static final String ERROR = "error"; protected static final String LOGIN = "login"; protected static final String CONFIRM = "confirm"; protected Context jndiContext = null; /** * 默认构造方?BR> */ public AbstStrutsActionBase() { } /** 下面q个查找EJB实例的方法将不会(x)完整实现?BR>一般来_(d)Actioncd该调用实C应用的商务逻辑的EJB?x)话beanQ或仅仅普通JavaBeanQ。在大型目中,开发h员必d清层与层之间的界限。在ActioncMQ我们应该拿到获取含有JNDI信息的环境的实例Q然后通过EJB的JNDI名字L询获取它的home接口。过Eƈ不简单,所以下面这个代码片断只是个l出了必要实现的例子?BR>?nbsp;参数cdStringQ传入的要查询JNDI的名?BR>?nbsp;q回cdObjectQ即查找到的home接口 ?nbsp;如果查找p|Q抛出NamingException异常 ?nbsp;如果获取资源信息p|Q抛出MissingResourceException异常 */ public Object lookup(String jndiName) throws NamingException, MissingResourceException { // 用EJB对象Q通过构徏记录JNDI信息的Properties对象 // 来获得初始环境信?BR> if (jndiContext == null) { ResourceBundle resource = ResourceBundle.getBundle("strutssample.properties"); Properties properties = new Properties(); properties.setProperty( Context.INITIAL_CONTEXT_FACTORY, resource.getString(Context.INITIAL_CONTEXT_FACTORY)); properties.setProperty( Context.PROVIDER_URL, resource.getString(Context.PROVIDER_URL)); properties.setProperty( Context.SECURITY_PRINCIPAL, resource.getString(Context.SECURITY_PRINCIPAL)); properties.setProperty( Context.SECURITY_CREDENTIALS, resource.getString(Context.SECURITY_CREDENTIALS)); jndiContext = new InitialContext(properties); } 注意Q在真正的品中Q我们应该在此处考虑代码的健壮性,代码加入到try/catch块内Qƈ记录所有错误或重要信息到系llog中。而本例中Q我们仅仅把异常往外抛Qƈ假定一定会(x)扑ֈEJB对象的home接口q返回?BR> return (jndiContext.lookup(jndiName)); } ׃Actioncd是由Struts来调用的。所以它的主要方法应该是一个抽象方法,而由每个l承的子cL具体实现Q或者在其中做一些所有Action都会(x)做的通用机制Q例如记录log信息。在本例中,我们一切从Q将其抽象之?BR>?nbsp;参数mappingQ其cd为ActionMappingQ将在本Action做蟩转选择?BR>?nbsp;参数actionFormQ由StrutsҎ(gu)本次HTTPh数据填充完成的ActionForm对象Q可选,如果存在h数据的话Q?BR>?nbsp;参数requestQ此Action所有处理的本次HTTPhQ对象)(j) ?nbsp;参数responseQ此Action输出数据所要用到的HTTP响应Q对象)(j) ?nbsp;如果有I/O错误出现Q则本方法抛出IOException异常 ?nbsp;如果处理时发生servlet异常Q则本方法抛出ServletException异常 ?nbsp;本方法处理完h后按照处理逻辑q回相应的页面导向(对象Q?BR> public abstract ActionForward perform( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException; } 或者让q个抽象Ҏ(gu)更有用一点,那就在里面干点什么吧Q比如像下面q样在其中记录log?BR> { ActionForward forward = null; // 只是单的记录一些提CZ息到servlet log getServlet().log( "AbstStrutsActionBase.perform() [Action Class: " + this.getClass().getName() + " ]"); getServlet().log( "AbstStrutsActionBase.perform() [Form Class : " + (form == null ? "null" : form.getClass().getName()) + " ]"); } 然后Q我们再~写的每个Actionc都应该从AbstStrutsActionBasel承Qƈ依照处理逻辑~写各自的performҎ(gu)。让我们用LoginActionZQ看看具体应该怎么应用吧?BR> package com.oreilly.actions; import java.io.IOException; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionForward; import com.oreilly.forms.LoginForm; /* LoginAction 演CZ个Action如何被Struts架构所调用 在这个例子中Q我们只是简单的演示performҎ(gu)是如何调用、执行ƈq回?BR>*/ public class LoginAction extends AbstStrutsActionBase { 接下来这个是验证用户的方法,本例中没有具体实现。但一个典型的应用Ҏ(gu)是调用JavaBean或者EJB来完成。用来查找EJB的lookupҎ(gu)Q在基类中完成的Q应该在本方法中被调用,其返回一个依据后台数据库验证用户的接口?BR>?nbsp;参数cdStringQ要验证的用户名 ?nbsp;参数cdStringQ密?BR>?nbsp;q回cdbooleanQ如果验证通过为trueQ否则ؓ(f)false public boolean authenticate(String username, String password) { /* 本方法将先做一个查扑֊作,获得验证用户的EJB对象的接口ƈ调用 * ׃本例只演CAction与商务逻辑层是如何交互?nbsp; * 所以具体实C码本例中׃提供?) */ return (true); } 接下来我们在LoginAction中重载基cȝperformҎ(gu)?BR>?nbsp;参数mappingQ其cd为ActionMappingQ将在本Action做蟩转选择?BR>?nbsp;参数actionFormQ由StrutsҎ(gu)本次HTTPh数据填充完成的ActionForm对象Q可选,如果存在h数据的话Q?BR>?nbsp;参数requestQ此Action所有处理的本次HTTPhQ对象)(j) ?nbsp;参数responseQ此Action输出数据所要用到的HTTP响应Q对象)(j) ?nbsp;如果有I/O错误出现Q则本方法抛出IOException异常 ?nbsp;如果处理时发生servlet异常Q则本方法抛出ServletException异常 ?nbsp;本方法处理完h后按照处理逻辑q回相应的页面导向(对象Q?BR> public ActionForward perform( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // 先假定验证失败,那么要导向的forward当然是LOGIN了(见基cd义的全局变量Q?BR> boolean validLogin = false; ActionForward actionForward = mapping.findForward(LOGIN); // 构造出承蝲ActionError对象的容器——errorsQ以备错误出现时可用 ActionErrors errors = new ActionErrors(); // 从由本次h构造的ActionForm中提取出所需要的数据 LoginForm loginForm = (LoginForm)form; String userName = null; String password = null; if (loginForm != null) { userName = loginForm.getUserName(); password = loginForm.getPassword(); validLogin = authenticate(userName, password); } if (validLogin) { // 验证成功了,导向到struts-config.xml中定义的SUCCESS actionForward = mapping.findForward(SUCCESS); // 存点必要的东东到sessionQ以备后?BR> request.getSession(true).setAttribute("USERNAME", userName); } else { errors.add("login", new ActionError("error.login.authenticate")); } // pȝ如果用户界面友好一点,我们应该将错误信息存入request对象?BR> // 然后到页面,通过在Struts的标{显C出?BR> if (!errors.empty()) { saveErrors(request, errors); } // 本Action处理完成Q导向到合适的forward return (actionForward); } } 注意Q这个LoginActioncd是在struts-config.xml中定义的用来处理d事务的一个具体实现。当q个c被载入q有一个对象实例化后,Struts架构׃(x)调用它的performҎ(gu)。这个方法是q样声明的:(x) public ActionForward perform( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException 其中Qmapping是一个记录与此Action对应的forward导向的对象,form对象装由客L(fng)提交的此Action要处理的数据Q还有标准的HttpServletRequest对象和HttpServletResponse对象?BR>有了q些对象的辅助,此Action可以拿到需要的东东利开工了。我们的例子中,要处理的数据主要是用户名和密码,q些都由form对象提供。实现验证功能是本应用的主要业务逻辑Q在Ҏ(gu)中的具体实现应该是去取EJB的相应接口来操作或者直接去拿数据库数据来验证。前面那个AbstStrutsActionBasecM已经实现了一个简单的EJB接口查找动作Q所以如果我们是在开发一个基于EJB实现的系l,它的可重用性就非常Z?BR>由验证方法(authenticate()Q的q回|Action要接着做出合理的动作。如果验证通过Q就要让用户q入正确的页面,那么我们将一些后面可能会(x)用到的信息存入request对象Q译注:(x)准确的讲Q代码中是存Csession对象里,当然session对象是和当前request相关的)(j)Qƈ向Strutsq回successq个forward。这个forward是在struts-config.xml中定义的Q然后由ActionMapping装hQ在Action处理中可以从中拿出合适的forward做ؓ(f)q回倹{如果回头去看看struts-config.xml中的定义Q就?x)知道successq个forward?x)将用户导向至Welcome.jspq个面的。如果验证失败,则将一个错误信息存hQ然后导向到一个错误提C页面显C出来?BR> 开发应用的业务逻辑 在一个真实的应用pȝ中,我们应该业务逻辑层整合进来了。在我们q个例子里,我们应该去开发LoginAction中的authenticaeҎ(gu)所调用到的EJB了。但是正如你所见的Q我们完全可以把q一层暂时屏蔽掉Q而利用Struts把前端部分构建ƈ能够让它跑v来的。我其实相当推崇的是Ҏ(gu)是先应用框架搭建ƈq行hQ然后在开发后台实际的业务逻辑层。在应用框架完全恰当的构v来的时候,后台的开发工作所有做的debug工作也少的多了。而且Q业务逻辑的开发也不是本文所要函概的范围Q所以此处我们略q,不过我相信你现在一定对应用的全局有了M的把握了吧! 开发由ActionMapping定义的系l工作流E,完成对应的JSP面 l于可以所有这些东东整合在一起了。在struts-config.xml配置文g中定义的那些ActionMappingQ我们要完成q些ActionMapping定义用到的JSP面。本例中Q包括Login.jsp、Welcome.jsp和Errorpage.jsp。还有,管我们在本例中都是Action处理完成forward到JSP面Q这在这个简单的例子中是再恰当不q的逻辑程了,而在实际利用Struts开发应用中呢,当然可以从Action forward到其他的Action。我们这个简单的Login.jsp面内容是这L(fng)Q?BR><%@ page language="java" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-form.tld" prefix="form" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <html> <head> <title><bean:message key="login.title"/></title> </head> <body> <html:errors/> <h3>Enter your username and password to login:</h3> <html:form action="login.action" focus="userName" > <html:text property="userName" size="30" maxlength="30"/> <html:password property="password" size="16" maxlength="16" redisplay="false"/> <html:submit property="submit" value="Submit"/> <html:reset/> </html:form> </body> </html> Struts在JSP自定义标{ֺ的基上提供了一套综合各U功能的标签库。利用这些标{ֺ很容易的构徏用户界面了。用这些标{ֺ的好处之一是可以利用其提供的很多附加功能。比如在一般的JSP面的表单里我们可以看到q样常见的HTML片断Q?BR><input type="text" name="userName" value=""> 如果我们使用Struts的标{ֺ的话Q就可以Ҏ(gu)q样子:(x) <html:text property ="userName"> 不过我们得现在页面中先声明Struts标签库的定义?BR> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> 在这个例子中Q我们会(x)用到一些Struts标签Q但我不准备在此详细讲解Struts各种标签库的用法。相信在你不断用Struts搭徏功能复杂的JSP面的过E中Q你会(x)Ҏ(gu)使用q的标签来熟(zhn)的。到那时Q你也将更能体会(x)到Struts标签的益处,利用它们大大的羃短你的开发时间。目前,你可以从Struts Developers Guides了解到更多的l节?BR>在我们这个简单例子中Q有两个重点。其一Q?BR> <title><bean:message key="login.title"/></title> q就是在利用我们前面提到的资源文件ApplicationResource来在面昄信息Q而不是将信息文本编码到我们的应用中?BR>其二Q?BR> <html:errors/> q就是在面中显C出ActionErrors的信息,也就是我们在LoginForm的验证方法和LoginAction中生的报错信息的集合对象?BR>面中的表单Q利用StrutsQ我们将用如下的标签来定义:(x) <html:form action="login.action" focus="userName"> q里的login.actionQ是和struts-config.xml中定义ActionMapping相匹配的。在面标签中这L(fng)定义Q就相关的Action、ActionForm和ActionForward完整的串了v来。当q个用标{֮义的表单提交的时候,Struts中的ActionServlet׃(x)其交由login.action来处理。具体的q程我们下面慢慢深入?BR>在Welcome.jsp中,我们只演C如何将Action中的信息传递到面加以利用的一般机Ӟ(x) <html> <title>Welcome to Struts</title> <body> <p>Welcome <%= (String)request.getSession().getAttribute("USERNAME") %></p> </p>You have logged in successfully!</p> </body> </html> q记得吗Q我们在LoginAction中的perform()Ҏ(gu)中将USERNAME攑ֈ了session中哦?BR> 完成pȝ配置文g 我们已经struts-config.xml谈了好多了。通常Q这个文件中的信息会(x)在开发过E中逐渐完善。但是到了开发过E的最后一部,我们更应该回头去(g)查这个至关重要的配置文gQ以保证万无一失:(x)Action、JSP面q有ActionForm都应该在文g中正的定义。此外,我们q不得不说到web.xml。这个文件是JSP容器Q例如TomcatQ获取应用相关配|的重要文g。我们这个StrutsSample例子所用到的web.xml大致是这L(fng)Q?BR> <?xml version="1.0" encoding="ISO-8859-1"?> <!-- This is the web-app configuration that allow the strutsSample to work under Apache Tomcat. --> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd" ;> <web-app> <servlet> <servlet-name>oreilly</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>application</param-name> <param-value>com.oreilly.ApplicationResources</param-value> </init-param> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>validate</param-name> <param-value>true</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>oreilly</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>Login.jsp</welcome-file> </welcome-file-list> <!-- Struts Tag Library Descriptors --> <taglib> <taglib-uri>/WEB-INF/struts.tld</taglib-uri> <taglib-location>/WEB-INF/struts.tld</taglib-location> </taglib> <taglib> <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib> <taglib> <taglib-uri>/WEB-INF/struts-form.tld</taglib-uri> <taglib-location>/WEB-INF/struts-form.tld</taglib-location> </taglib> </web-app> q里?lt;servlet>标签定义了org.apache.struts.action.ActionServletQ而且在本例中Q我们把q个定义的servlet叫作“oreilly”,q传了两个初始化参数l它Q其一是我们ؓ(f)q个应用所需的显C字W串定义的资源文Ӟ其二是指明struts-config.xml文g的位|。相信你也注意到了,?lt;servlet-mapping>中ؓ(f)q个Servlet指明的相应请求处理串?.actionQ这是和我们在页面中的表单定义的提交的URL是吻合的。也是_(d)我们通过<servlet-mapping>标签告诉TomcatQ所有后~?action的请求都交给“oreilly”这个Servlet来处理。你当然可以指定你喜Ƣ的后缀。在Struts附带的例子中Q你可能?x)看到通常?do做ؓ(f)后缀Q不q我认ؓ(f).action更明一些?lt;welcome-file-list>标签中定义了本应用初始显C页面。最后呢Q我们还要把?x)用到的Struts标签库列在后面?BR> ~译/试/发布 到此为止Q编?试/发布应用之前的所有工作都完成了。用Ant来编译整个应用是相当Ҏ(gu)的。如果你以前没有接触qAntQ那最好把q个研究一下。其实学?fn)和应用Ant来管理一个应用编译环境ƈ不难。我把这个编译应用所要用到的build.xml和例子放C一Pq篇文章所要用到的所有东东,你都可以Ҏ(gu)下蝲Q到时候你到build.xml所在目录简单执行ant命o(h)可以完成编译,q打包成strutsSample.war包。当然要执行antQ你得先M载Ant。将Ant下蝲回来q搭建好环境可能得花十几分钟的时间哦?BR>本应用的目录l构如下Q?BR>StrutsSample根目?BR> *.jsp WEB-INF目录 Struts配置文gQstruts-config.xml, web.xmlQ?BR> classes目录Q还是以JavaE序文g包结构ؓ(f)路径Q?BR> lib目录Qstruts.jarQ?BR> 拿到了应用的war包,我们将它放到Tomcat的webapps路径下,然后启动Tomcat。war包会(x)被自动展开Q此应用的上下文环境也会(x)由Tomcat自动建立h。我们通过web.xml告知Tomcatq个应用所需的其他资源在哪里。现在,我们可以通过http://localhost:8080/strutsSample 来访问我们的应用了。如果没有特别指定的话,Tomcat默认的端口是8080Q我们定义的默认初始面Login.jsp也将昄出来Q现在我们来试试吧?BR> l论 通过本系列的文章Q我们利用Struts从应用需求开始,一步步整个应用搭v来。和普通的JSP技术相比,通过Struts开发的应用涉及(qing)到更多的与之相关的各cLӞ也正是依靠各cLӞ我们才可能构Z个适合开发复杂应用的MVC架构。我们的W一个Struts应用׃如此多的旉Q是Z要弄清楚Struts的各个部分到底是如何工作的?BR>希望本系列Struts文章Q能够帮助你了解Struts是由哪些部分构成的,它们能够完成什么,也希望介l一个比较好的开发流E可供你参考。Struts才诞生不久,我有信心它将成ؓ(f)我们构徏J2EE应用的优U工具?BR> ]]> WebWork 2 : Comparison to Struts http://m.tkk7.com/jackybu/articles/3109.html?/dc:creator>?/author>Mon, 11 Apr 2005 02:33:00 GMT http://m.tkk7.com/jackybu/articles/3109.html http://m.tkk7.com/jackybu/comments/3109.html http://m.tkk7.com/jackybu/articles/3109.html#Feedback 0 http://m.tkk7.com/jackybu/comments/commentRss/3109.html http://m.tkk7.com/jackybu/services/trackbacks/3109.html from:http://www.opensymphony.com/webwork/wikidocs/Comparison%20to%20Struts.html WebWork 2 : Comparison to Struts
This page last changed on Jun 18, 2004 by plightbo .
Feature
Struts
WebWork 1.x
WebWork 2.x
Action classes
Struts requires Action classes to extend an Abstract base class. This shows a common problem in Struts of programming to abstract classes instead of interfaces.
Action classes must implement the webwork.Action Interface. There are other Interfaces which can be implemented for other services, such as storing error messages, getting localized texts, etc. The ActionSupport class implements many of these Interfaces and can act as a base class. WebWork is all written to Interfaces, which allows for plugging in your own implementations.
An Action must implement the com.opensymphony.xwork.Action Interface, with a series of other Interfaces for other services, like in WebWork 1.x. WebWork2 has its own ActionSupport to implement these Interfaces.
Threading Model
Struts Actions must be thread-safe because there will only be one instance to handle all requests. This places restrictions on what can be done with Struts Actions as any resources held must be thread-safe or access to them must be synchronized.
WebWork Actions are instantiated for each request, so there are no thread-safety issues. In practice, Servlet containers generate many throw-away objects per request, and one more Object does not prove to be a problem for performance or garbage collection.
ditto
Servlet Dependency
Struts Actions have dependencies on Servlets because they get the ServletRequest and ServletResponse (not HttpServletRequest and HttpServletResponse, I've been told) when they are executed. This tie to Servlets (although not Http*) is a defacto tie to a Servlet container, which is an unneeded dependency. Servlets may be used outside a Web context, but it's not a good fit for JMS, for instance.
WebWork Actions are not tied to the web or any container. WebWork actions CAN choose to access the request and response from the ActionContext, but it is not required and should be done only when ABSOLUTELY neccessary to avoid tieing code to the Web.
ditto
Testability
Many strategies have sprung up around testing Struts applications, but the major hurdle is the fact that Struts Actions are so tightly tied to the web (receiving a Request and Response object). This often leads people to test Struts Actions inside a container, which is both slow and NOT UNIT TESTING. There is a Junit extension : Struts TestCase (http://strutstestcase.sourceforge.net/ )
WebWork actions can be tested by instantiating your action, setting the properties, and executing them
ditto, but the emphasis on Inversion of Control makes testing even simpler, as you can just set a Mock implementation of your services into your Action for testing, instead of having to set up service registries or static singletons
FormBeans
Struts requires the use of FormBeans for every form, necessitating either a lot of extra classes or the use of DynaBeans, which are really just a workaround for the limitation of requiring FormBeans
WebWork 1.x allows you to have all of your properties directly accessible on your Action as regular Javabeans properties, including rich Object types which can have their own properties which can be accessed from the web page. WebWork also allows the FormBean pattern, as discussed in "WW1:Populate Form Bean and access its value "
WebWork 2 allows the same features as WebWork 1, but adds ModelDriven Actions, which allow you to have a rich Object type or domain object as your form bean, with its properties directly accessible to the web page, rather than accessing them as sub-properties of a property of the Action.
Expression Language
Struts 1.1 integrates with JSTL, so it uses the JSTL EL. This EL has basic object graph traversal, but relatively weak collection and indexed property support.
WebWork 1.x has its own Expression language which is built for accessing the ValueStack. Collection and indexed property support are basic but good. WebWork can also be made to work directly with JSTL using the Filter described in WW1:Using JSTL seamlessly with WebWork
WebWork 2 uses XW:Ognl which is a VERY powerful expression language, with additions for accessing the value stack. Ognl supports very powerful collection and indexed property support. Ognl also supports powerful features like projections (calling the same method on each member of a collection and building a new collection of the results), selections (filtering a collection with a selector expression to return a subset), list construction, and lambda expressions (simple functions which can be reused). Ognl also allows access to static methods, static fields, and constructors of classes. WebWork2 may also use JSTL as mentioned in WW1:Using JSTL seamlessly with WebWork
Binding values into views
Struts uses the standard JSP mechanism for binding objects into the page context for access, which tightly couples your view to the form beans being rendered
WebWork sets up a ValueStack which the WebWork taglibs access to dynamically find values very flexibly without tightly coupling your view to the types it is rendering. This allows you to reuse views across a range of types which have the same properties.
ditto
Type Conversion
Struts FormBeans properties are usually all Strings. Struts uses Commons-Beanutils for type conversion. Converters are per-class, and not configurable per instance. Getting a meaningful type conversion error out and displaying it to the user can be difficult.
WebWork 1.x uses PropertyEditors for type conversion. PropertyEditors are per type and not settable per Action, but field error messages are added to the field error map in the Action to be automatically displayed to the user with the field.
WebWork2 uses Ognl for type conversion with added converters provided for all basic types. Type converters default to these converters, but type conversion can be specified per field per class. Type conversion errors also have a default error message but can be set per field per class using the localization mechanism in WW2 and will be set into the field error messages of the Action.
Modular Before & After Processing
Class hierarchies of base Actions must be built up to do processing before and after delegating to the Action classes, which can lead deep class hierarchies and limitations due to the inability to have multiple inheritance WW:Comparison to Struts#1
Class hierarchies
WebWork 2 allows you to modularize before and after processing in Interceptors. Interceptors can be applied dynamically via the configuration without any coupling between the Action classes and the Interceptors.
Validation
Struts calls validate() on the FormBean. Struts users often use Commons Validation for validation. I don't know a lot about this, so I'll put some questions here: Because FormBean properties are usually Strings, some types of validations must either be duplicated (checking type conversion) or cannot be done? Can Commons Validation have different validation contexts for the same class? (I've been told yes, so that's a good thing) Can Commons Validation chain to validations on sub-objects, using the validations defined for that object properties class?
WebWork1.x calls the validate() method on Actions, which can either do programmatic validations or call an outside validation framework (this is apparently the same as Struts)
WebWork2 can use the validate() method of WebWork and Struts and / or use the XW:Validation Framework , which is activated using an XWork Interceptor. The Xwork Validation Framework allows you to define validations in an XML format with default validations for a class and custom validations added for different validation contexts. The Xwork Validation Framework is enabled via an Interceptor and is therefore completely decoupled from your Action class. The Xwork Validation Framework also allows you to chain the validation process down into sub-properties using the VisitorFieldValidator which will use the validations defined for the properties class type and the validation context.
Control Of Action Execution
As far as I know Struts sets up the Action object for you, and you have very little control over the order of operations. To change them I think you need to write your own Servlet to handle dispatching as you want
The ActionFactory chain controls the order in which an Action is constructed and initialised, but this requires writing a class
The interceptor stacks in WebWork 2 are hugely powerful in this regard. All aspects of Action setup have been moved into Interceptor implementations (ie setting paramters from the web, validation etc), so you can control on a per action basis the order in which they are performed. For example you might want your IOC framework to setup the action before the parameters are set from the request or vice versa - you can thusly control this on a per package or per action basis with interceptor stacks.
Some Stuts users have built the beginnings of an Interceptor framework for Struts (http://struts.sourceforge.net/saif/ ). It currently has some serious limitations (no "around" processing, just before and after) and is not part of the main Struts project ]]>
վ֩ģ壺
97seۺ |
ձƷþþþþþþ |
һһ߹ۿƵ |
99һ |
Ļ |
һþ |
þþ |
ˬָ߳Ƶ |
һĻþ |
һһˬһ߽дƵ |
ҰĻƵ
|
˵Ƶ߹ۿ |
þۺ |
Ů侫 |
ִӲˬִֿƵ |
ұͨӰƬ߲
|
ƬAëƬ |
ŷŮƵ |
ƷߵӰ |
91Ƶ |
һ |
ƷۺϾþ20 |
ٸ͵˾ƷƵ |
պСӰ߹ۿ |
鶹69Ƶ |
߾ƷƵ |
˳ëƬ߲ |
ѹվ߹ۿ |
ҹþþþüŮӰԺ |
ձػɫAAAƬ |
ɫwwwƵ |
ĻAV |
йxxxxxѿƵ |
Ƶ߹ۿһ |
ҹƷһ |
˾Ʒþ |
պݺݾþ͵͵ɫۺ |
պƵһ |
ɫ㽶 |
91ɫŮԴվ |
þƷƷ |