struts2 --明哥讲解


先说点废话:有人问我Struts2,hibernate,spring的运行机制,这个.....额......忘记了,我这么回答。因为公司一直在用SSH,但是Struts2的运行机制是什么我是真的不知道,我一直在想会用就可以了,管它为什么1+1会等于2?如果我要用1+1等于2就解决运算的问题就先要去知道应该怎么去证明那或许我这一辈子都得郁闷到死。但是,所谓欲加之罪何患无辞,所谓死牛角尖都是这么钻的,给自己找理由满地都是。认真去考虑,不懂得原理的人,没读过源码甚至于不了解框架基本结构的人是做不了软件平台研发的,做项目可以,会用就足够了,可是想要搭建工资自己的平台,写公司自己的架构,势必要去认识和熟知其运行机制,另外一个不懂得运行原理的人谁能指望你去写出多优化的代码呢?除非你就老死在初级程序员这个层次上了。
好了切入正题:
struts1与struts2有什么区别呢,本来想说说但后来了解了下情况就不说了,因为struts1除了以前遗留项目之外已经被淘汰了,所以也就无所谓区别了,现在市面上,公司里凡是用的找struts的基本上都是two了。作为一个软件工程师最让人自豪的就是使用的总是最先进的技术,最让人头疼的同样是老出新技术,等你五六十岁脑子不打转了还得学。现在公司面试基本上已经不会再去问struts1的内容了。
Struts2的运行机制我们拿tomcat做服务器,首先浏览器通过URL向服务器发出请求,tomcat就收到请求会检查你的请求是对应于哪个web application哪个项目,接着tomcat将请求交给对应的web application进行处理;web application接受到请求会方位web.xml文件,通过filter过滤URL,接着通过配置的filter-class:StrutsPrepareAndExecuteFilter来查找对应的struts.xml,然后在此xml中找到对应namespace再找到对应的action name,通过action class去找到对应的CLASS,交给execute或者指定的方法去处理(这里无论你写不写class它都会走后台,写了走你写的,不写走默认的actionSupport的execute)在业务处理完成之后根据返回值去找struts.xml的result对应的jsp文件。这就是基本的struts2的运行机制。
注意:原则上一次回话一个session都应该调用单独的自己的action,若是同一个只有一个action,多线程并发访问,问题可想而知,不解释。struts2这一点做的很好,当然结合上spring就更好了。
运行机制知道了,为了解决同志们以及我自己在搭建struts2环境时不必再去查文档找google看视频下面我用比较简单的方式来做一下struts2环境的搭建,若下次再用到了各位只需一步一步来就可以了,这些都是经鄙人亲身测试并敲出来的,木有问题:
环境:jdk1.5,jre1.6,eclipse,xp系统struts2 jar包2.0.14.jar

一、引包

Src下建立struts.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstrutsPUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<!--

<package name="example"namespace="/example" extends="struts-default">

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

<result>/example/HelloWorld.jsp</result>

</action>

<action name="Login_*" method="{1}" class="example.Login">

<result name="input">/example/Login.jsp</result>

<result type="redirect-action">Menu</result>

</action>

<action name="*" class="example.ExampleSupport">

<result>/example/{1}.jsp</result>

</action>

-->

<!--热加载开发模式下修改配置文件后无需重启服务器valuetrue-->

<constantname="struts.devMode"value="true"></constant>

<!-- package标签name用来解决action重名的情况,namespace设置访问路径http://localhost:8080/struts2_zym_01/zzz/Hello.action这里的HelloWorld.jsp也必须放在ZZZ的目录下(jar包在2.0.1.4以上的貌似不用)namespace可以不写默认为””,这里的namenamespace一般为功能名称,比如用户功能就起名为user两个都是user

-->

<packagename="default"namespace="/zzz"extends="struts-default">

<!--请求Hello是所要执行的类class执行方法为execute但返回success时跳转到HelloWorld.jsp界面,d当然并不一定非得是success可以自定义-->

<actionname="Hello"class="com.struts2.zymaction.IndexAction1"method=”methodName”>

<resultname="success">HelloWorld.jsp</result>

</action>

<!-- Add actions here -->

</package>

</struts>

注意:当action标签不写class属性时默认会执行一个xword.jar包内的ActionSupper类,这里面同样有个execute方法,返回的是true,当resule标签不写name属性时默认name”success”

三、将struts.xml配置进web.xml

<filter>

<filter-name>struts2</filter-name>

<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

</filter>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

四:编写执行类

此执行类就是第三部Action标签Class所对应的类

packagecom.struts2.zymaction;

importcom.opensymphony.xwork2.ActionSupport;

//这里的类可以自定义,当然最好还是继承ActionSupport(此类属于//xwork.jar),这个类又实现了Action接口,当然此类也可以自行实现// Action,Action只定义了一个方法execute

//它里面有一批定义好的方法,用起来比较方便

publicclassIndexAction1extendsActionSupport {

publicStringexecute(){

return"success";

}

}

方法调用与Action配置

()对所请求方法的调用:(1)在action中配置:execute方法只是默认执行,如果要让其执行指定方法可以加上属性method=”methodName”,但要记得这个方法也得返回一个String类型。

2DMI动态调用:在类INdexAction1中添加这么一个方法

publicString add(){

returnSUCCESS;

}

要调用此方法请求地址可以这样写:http://localhost:8080/struts2_zym_01/zzz/Hello!add.action这样就可以指定调用add方法。这样比在action中配置更具有灵活性。如果只有一个Action但有多个可供调用的方法是在action标签中添加method明显不具合理性

()使用通配符对标签Action进行配置

作用:简化配置,前提:遵循规范优于配置的原则

(1)下面是一段使用简单通配符进行的标签配置

<packagename="index"namespace="/index"extends="struts-default">

<!--通配符配置下面action属性nameindex*所以访问的时候必须是/indexXXXX,属性method=”{1}”是说/index后面的XXXX将赋给第一个*(这里不能理解为类中的第几个方法),并且XXXX是所要请求的Action类里面的名字为XXXX的方法;返回结果后所指定的JSPindex{1}.jsp中的{1}也是一样的道理,结果将跳向indexXXXX.JSP

比如我访问:http://localhost:8080/struts2_zym_01/index/indexindexAdd.action

Struts2将调用IndexAction2类里面的indexAdd方法并且成功返回后讲转向

indexindexAdd.jps

-->

<actionname="index*"class="com.struts2.zymaction.IndexAction2"method="{1}">

<resultname="success">index{1}.jsp</result>

</action>

</package>

IndexAction2:

packagecom.struts2.zymaction;

importcom.opensymphony.xwork2.ActionSupport;

publicclassIndexAction2extendsActionSupport {

publicString indexAdd(){

returnSUCCESS;

}

publicString indexShow(){

returnSUCCESS;

}

}

对应的JSP文件

请求URLhttp://localhost:8080/struts2_zym_01/index/indexindexAdd.action或者

http://localhost:8080/struts2_zym_01/index/indexindexShow.action

(2)下面是多个通配符的配置

Struts.xmlaction配置

<packagename="dept"namespace="/dept"extends="struts-default">

<!--通配符配置二这里action的属性name结构是*_*method属性为{2}意思是说我将请求一个结构为XXXX_MMMM.action的地址,并且在对应的DeptAction类里面调用名称为第二个*所表示名称为MMMM的方法,成功返回后将跳转至XXXX_MMMM.JSP-->

<actionname="*_*"class="com.struts2.zymaction.DeptAction"method="{2}">

<resultname="success">{1}_{2}.jsp</result>

</action>

</package>

DeptAction

packagecom.struts2.zymaction;

importcom.opensymphony.xwork2.ActionSupport;

publicclassDeptActionextendsActionSupport {

publicString add(){

returnSUCCESS;

}

publicString show(){

returnSUCCESS;

}

}

JPS

注意:如果配置了两个action标签,一个name确定,一个使用通配符,如果两者发生冲突将调用name明确的方法。例如,一个为name=”dept_add”另一个name=”dept_*”那么在请求/dept_add.action时将调用第一个。

使用通配符在命名规则一致的条件下,配置将更为简练。

struts2的参数传递与接收

一、参数传递与接收一----使用属性:

http://localhost:8080/struts2_zym_01//deptActionParam/deptparam.action?DeptNo=20&DeptName=zym

后台Action接受参数的方式

定义两个常量:DeptName和DeptNo写get set方法即可

如下:

packagecom.struts2.zymaction;

importcom.opensymphony.xwork2.ActionSupport;

publicclassDeptActionParamextendsActionSupport {

privateStringDeptName;

privateStringDeptNo;

publicString execute(){

System.out.println("deptNo="+DeptNo);

System.out.println("deptName="+DeptName);

returnSUCCESS;

}

publicString getDeptName() {

returnDeptName;

}

publicvoidsetDeptName(String deptName) {

DeptName= deptName;

}

publicString getDeptNo() {

returnDeptNo;

}

publicvoidsetDeptNo(String deptNo) {

DeptNo= deptNo;

}

}

注意:这里从后台取名是通过参数传递的名称,其实常量名称无所谓,可随便定义但是getset后面的名称必须与传递参数的名称一致。

二、参数传递与接收二:----使用域对象(DomainModel:

几个实体类:值对象VO(value Object)、数据对象:DO(data Object)数据传输对象:DTO(Data Tranfer Object ),一个东西,名称不一样而已,这里我们使用VO值对象。

一个简单用户注册的例子:

struts.xml配置

<packagename="parambyvo"namespace="/parambyvo"extends="struts-default">

<actionname="regist">

<result>regist_page.jsp</result>

</action>

<actionname="userparambyvo"class="com.struts2.zymaction.UserActionByVo">

<resultname="success">regist_success.jsp</result>

</action>

</package>

请求:http://localhost:8080/struts2_zym_02/parambyvo/regist.action

跳转到regist_page.jsp界面

regist_page.jsp代码:

<%@pagelanguage="java"import="java.util.*"pageEncoding="GB18030"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<!DOCTYPEHTMLPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<basehref="<%=basePath%>">

<title>My JSP 'regist_page.jsp' starting page</title>

<metahttp-equiv="pragma"content="no-cache">

<metahttp-equiv="cache-control"content="no-cache">

<metahttp-equiv="expires"content="0">

<metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">

<metahttp-equiv="description"content="This is my page">

<!--

<linkrel="stylesheet" type="text/css"href="styles.css">

-->

<scripttype="text/javascript">

functionregistFun(){

varuserName = document.all("userName").value;

varpassWord = document.all("passWord").value;

//注意传参方式userAction类里面的User对象,userNamepassWord是其属性window.location.href="<%=basePath%>parambyvo/userparambyvo!add.action?"

+"user.userName="+userName+"&user.passWord="+passWord;

}

</script>

</head>

<body>

userName:<inputtype="text"id="userName"name="userName"value=""size="20"><br>

passWord:<inputtype="password"id="passWord"name="passWord"value=""size="20"><br>

<inputtype="button"value="regist"onclick="registFun()">

</body>

</html>

VOUser

packagecom.struts2.zymvo;

publicclassUser {

privateStringuserName;

privateStringpassWord;

publicString getUserName() {

returnuserName;

}

publicvoidsetUserName(String userName) {

this.userName= userName;

}

publicString getPassWord() {

returnpassWord;

}

publicvoidsetPassWord(String passWord) {

this.passWord= passWord;

}

}

Action类:UserActionByVo

packagecom.struts2.zymaction;

importcom.opensymphony.xwork2.ActionSupport;

importcom.struts2.zymvo.User;

publicclassUserActionByVoextendsActionSupport {

privateUseruser;

publicUser getUser() {

returnuser;

}

publicvoidsetUser(User user) {

this.user= user;

}

publicString add(){

System.out.println("userName:"+user.getUserName());

System.out.println("passWord:"+user.getPassWord());

returnSUCCESS;

}

}

这里与传参接参一不同,Action不再是属性而是一个对象

regist_success.jsp

<body>

注册成功<br>

</body>

三、传参接参三:

Action实现位于xwork包的ModelDriven接口,并不常用,不介绍。

参数传递的编码问题

解决方法一:struts.xml中添加标签(这个标签适用于2.0.1.7之后的版本)

<constant name=””struts.i18n.encoding value=”GBK”></constant><!-- internationalization国际化-->

解决方法二:在web.xml配置过滤器

解决方法三:在spring中配置

数据校验

Action中编写校验代码

if(user.getUserName().length()>6){

this.addFieldError("userName","the length ofuserName is to long!!");

this.addFieldError("userName","check two same userName Param!!");

this.addFieldError("userName1","check two same userName Param1!!");

this.addFieldError("userName2","check two same userName Param2!!");

returnERROR;

}

if("admin".equals(user.getUserName())){

this.addFieldError("userName"," the name can't be admin ");

returnERROR;

}

JSP错误显示标签:

<%@tagliburi="/struts-tags"prefix="s"%>

<s:fielderror>

<!--param标签的textAction传递的参数名称-->

<s:param>userName</s:param>

</s:fielderror>

<s:fielderror>

<!-- Example 2: display field errors only for 'userName1' and 'userName2'-->

<s:paramvalue="%{'userName1'}"/>

<s:paramvalue="%{'userName2'}"/>

</s:fielderror>

***************************************************

<br>

<!--由于以上的标签已经被添加了样式,修改起来比较麻烦,为了只得到错误信息的值而有了下面的代码,查看值栈value stack使用最下面的debug标签-->

<!--取得值栈中属性为errorsvalue这里的errorsstruts2定义好的-->

<s:propertyvalue="errors"/><br>

<!--取得值栈中errorspropertiesuserNamevalue-->

<s:propertyvalue="errors.userName"/><br>

<!--取第几个value -->

<s:propertyvalue="errors.userName[0]"/><br>

<s:debug></s:debug>

好了 ,就先就写这么多,至于标签和其他的以后有时间有心情再补充。过两天写spring最后来hibernate,此外还会写基于IE的ajax以及jquery的ajax,ssh的整合,myeclipse的常用功能和配置,oracle的常用函数,存储过程的简单开发等。哪里错了或者不合适同志们快告诉我,免得出去丢人

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值