struts2快速上手(附例子)(例子已修改)

[size=large][b][color=red]实在对不起,上次写的例子有些匆忙,有些小的细节没有注意到,现在已经修改[/color][/b][/size]
注:附件的例子用eclipse直接导入就能跑了:)

[size=xx-large]一、MVC思想及其优势[/size]
MVC思想将一个应用分成三个部分:Model(模型)、View(视图)、Controller(控制器)。这三个部分以最少的耦合协同工作,从而提高应用的可扩展性及可维护性。
MVC特点:1、多个视图对应一个模型。2、模型返回的数据与显示逻辑分离,模型数据可以应用任何显示技术,例如JSP,Velocity,或者生成Excel。3、应用被分成三层,降低了各层之间的耦合,提高可扩展性。4、MVC更符合软件工程思想,不同的层各司其职。

[size=x-large]二、struts2概述[/size]
虽然Struts2号称是一个全新的框架,但这仅仅是相对Struts 1而言。Struts 2 与Struts 1相比,确实有很多革命性的改进,但它并不是新发布的新框架,而是在另一个赫赫有名的框架:WebWork基 础上发展起来的。从某种程度上来讲,Struts2没有继承Struts 1的血统,而是继承WebWork的血统。或者说,WebWork衍生出了Struts2,而不是Struts 1衍生了Struts2。因为Struts2是WebWork的升级,而不是一个全新的框架,因此稳定性、性能等各方面都有很好的保证:而且吸收了 Struts 1和WebWork两者的优势,因此,是一个非常值得期待的框架。
Apache Struts2是一个优雅的,可扩展的JAVA EE web框架。框架设计的目标贯穿整个开发周期,从开发到发布,包括维护的整个过程。
Apache Struts 2即是之前大家所熟知的WebWork 2。在经历了几年的各自发展后,WebWork和Struts社区决定合二为一,也即是Struts 2
[size=xx-large]三、MVC框架的比较[/size]
Struts1
缺点:
1、 支持的表示层技术单一
Struts1只支持JSP视图技术,当然,通过某些不自然的整合可以支持velocity等技术。
2、 struts与servlet API严重耦合,难于测试
比如说:如果要对struts1的Action的execute进行测试的时候,该方法有四个参数:ActionMapping、ActionForm、HttpServletRequest和HttpServletResponse,初始化这四个参数比较困难,尤其是HttpServletRequest和HttpServletResponse两个参数,因为这两个参数通常由容器进行注入的。如果脱离web服务器,Action的测试是很困难的。
3、 struts1的侵入性太大
一个Action中包含了大量的strutsAPI,比如ActionMapping、ActionForm、ActionForwad。这种侵入式的设计最大的弱点在于:切换框架会相当困难,代码复用较低,不利于重构,对struts的依赖太严重。
[size=large]SpringMVC [/size]
优点:
对覆盖绑定(overriding binding)、验证(validation)等提供生命周期管理与许多表示层技术/框架无缝集成:JSP/JSTL、Tiles、Velocity、FreeMarker、Excel、XSL、PDF等便于测试——归功于IoC。
缺点:大量的XML配置文件太过灵活——没有公共的父控制器没有内置的Ajax支持。

[size=large]Struts 2 [/size]
(如果需要用到request的话,可以用
HttpServletResponse response = ServletActionContext.getResponse();
HttpServletRequest request = ServletActionContext.getRequest();

优点:架构简单——易于扩展,标记库很容易利用FreeMarker或者Velocity来定制基于控制器或者基于页面的导航
缺点:文档组织得很差,对新特征过分关注,通过Google搜索到的大多是Struts 1.x的文档。
[size=xx-large]四、Struts2的大致处理流程:[/size]
[img]http://zhaoshg.iteye.com/upload/picture/pic/34223/bc1ce044-ebda-37b2-90de-2fc3893e5f35.png[/img]
当接收到一个httprequest ,
a) 当外部的httpservletrequest到来时
b) 初始到了servlet容器 传递给一个标准的过滤器链
c) FilterDispatecher会去查找相应的ActionMapper,如果找到了相应的ActionMapper它将会将控制权限交给ActionProxy
d) ActionProxy将会通过ConfigurationManager来查找配置struts.xml
i. 下一步将会 通过ActionInvocation来负责命令模式的实现(包括调用一些拦截Interceptor框架在调用action之前)
ii. Interceptor做一些拦截或者初始的工作
e) 一旦action返回,会查找相应的Result
f) Result类型可以是 jsp或者freeMark 等
g) 这些组件和ActionMapper一起返回给请求的url(注意拦截器的执行顺序)
h) 响应的返回是通过我们在web.xml中配置的过滤器
i) 如果ActionContextCleanUp是当前使用的,则FilterDispatecher将不会清理sreadlocal ActionContext;如果ActionContextCleanUp不使用,则将会去清理sreadlocals。

[size=xx-large]五、Struts2的使用(例子)[/size]
[size=x-large]Ⅰ、基本用法[/size]
 1、jsp页面编辑
 2、Action编写
 3、(xml,properties)文件的配置
 [b][color=red]Attention:[/color][/b]
在配置action时候,跳转页面
<result name="suc">/Menu.jsp?un=${userName}</result>:正确
<result name="suc">/Menu.jsp?un={2}</result>:正确
<result type="redirect-action">Menu?un=${userName}</result>:错误
redirect-action 是重定向,是服务器让浏览器重新发送一个请求过去,这时候request的参数肯定会丢失的(象servlet里,response.sendRedirect("url"))
struts2 默认是dispatcher,这个是服务器端转向,在服务器端执行,(象servlet里,request.getRequestDispatcher("url").forword(request,response))
[size=x-large]Ⅱ、整合Ioc[/size]
 修改WEB-INF\web.xml文件
加入这个

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>

主要是加入Spring的ContextLoaderListener监听器,方便Spring与Web容器交互。
 修改Struts.properties文件,告知Struts 2运行时使用Spring来创建对象(如Action等),内容如下:
struts.objectFactory = spring
 再下来,遵循Spring的原则——面向接口编程
 然后,配置Spring的applicationContext.xml(位于WEB-INF下)文件
 [b][color=red]Attention:[/color][/b]
Struts 2会为每一个请求创建一个Action对象,所以在定义DemoAction时,使用singleton="false"。这样Spring就会每次都返回一个新的DemoAction对象了;
因为IocDemoServiceImpl被配置为默认的scope(也即是singleton,唯一的),所以在实现时应保证其线程安全。
 接下来,在classes/struts.xml中配置Action
 [b][color=red]Attention[/color][/b]
这里的Action和平常不同的就是class属性,它对应于Spring所定义的bean的id,而不是它的类全名。
我的例子里面有,其中Login没有使用Spring,Register使用了Spring,大家可以对比一下

[size=x-large]Ⅲ、拦截器(这里可以参考http://zhaoshg.iteye.com/blog/356511的文章)[/size]
[img]http://zhaoshg.iteye.com/upload/picture/pic/34221/a38f9a47-ec81-3434-a9eb-a476a27cc555.jpg[/img]
拦截器的工作原理如上图,每一个Action请求都包装在一系列的拦截器的内部。拦截器可以在Action执行直线做相似的操作也可以在Action执行直后做回收操作。
每一个Action既可以将操作转交给下面的拦截器,Action也可以直接退出操作返回客户既定的画面。
[size=large]使用已有的拦截器[/size]
 1.在使用拦截器的时候,在Action里面最后必须一定要引用struts2自带的拦截器缺省堆栈defaultStack, (例子里我是引用了struts2自带的token拦截器)
 2.在struts.xml里面定义全局的配置设置
 3.struts-action.xml里面配置Action
 4.你的拦截器可以正常工作了!!
[size=large]如何自定义一个拦截器[/size]
 1.自定义一个实现Interceptor接口(或者继承自AbstractInterceptor)的类。
Interceptor接口声明了三个方法:
	public interface Interceptor extends Serializable {  
void destroy();
void init();
String intercept(ActionInvocation invocation) throws Exception;
}

Init方法在拦截器类被创建之后,在对Action镜像拦截之前调用
Destroy方法在拦截器被垃圾回收之前调用,用来回收init方法初始化的资源。
Intercept是拦截器的主要拦截方法,如果需要调用后续的Action或者拦截器,只需要在该方法中调用invocation.invoke()方法即可,在该方法调用的前后可以插入Action调用前后拦截器需要做的方法。如果不需要调用后续的方法,则返回一个String类型的对象即可,例如Action.SUCCESS。
另外AbstractInterceptor提供了一个简单的Interceptor的实现,这个实现为:
public abstract class AbstractInterceptor implements Interceptor {  
public void init() {
}
public void destroy() {
}
public abstract String intercept(ActionInvocation invocation) throws Exception;
}

在不需要编写init和destroy方法的时候,只需要从AbstractInterceptor继承而来,实现intercept方法即可。
 2.在strutx.xml中注册上一步中定义的拦截器。

<interceptors>
<interceptor name="login" class="example.CheckLoginInterceptor"/>
<interceptor-stack name="teamwareStack">
<interceptor-ref name="login"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>


 3.在需要使用的Action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的Action都被这个拦截器拦截。
 4.可以将多个拦截器合并在一起作为一个堆栈调用,当一个拦截器堆栈被附加到一个Action的时候,要想Action执行,必须执行拦截器堆栈中的每一个拦截器。

 [color=red]Attention[/color][b][/b]
拦截器执行的顺序按照定义的顺序执行,例如:

<interceptor-stack name="xaStack">
<interceptor-ref name="1Interceptor"/>
<interceptor-ref name="2Interceptor"/>
<interceptor-ref name="3Interceptor"/>
<interceptor-ref name="4Interceptor"/>
</interceptor-stack>


的执行顺序为:
1. 1Interceptor
2. 2Interceptor
3. 3Interceptor
4. 4Interceptor
5. MyAction1
6. MyAction2 (chain)
7. MyPreResultListener
8. MyResult (result)
9. 4Interceptor
10. 3Interceptor
11. 2Interceptor
12. 1Interceptor

[size=large]一个最常见的例子:防止刷新后表单重复提交[/size]
[color=red]我的例子里面有,Login是不带拦截器的,而register则附带了Token拦截器,大家可以比较一下[/color]
Token Interceptor
这个拦截器可以保证一个令牌对应一个请求。确保后退按钮和两次提交不会产生不希望的效果。 例如你可以使用这个来防止粗心的用户在在线商店点了两下"结帐"按钮。这个拦截器使用了非常简单的机制来处理非法令牌:返回一个invliad.token的结果,这样你就可以在action配置中做映射了。
具体做法是在你的jsp页面的form里面加上
<s:token > </s:token>
你要先访问到这个jsp页面,来给token初始的值,这样当你提交的时候,才能匹配上,了解一下token的原理吧:刚进入jsp页面的时候,struts2会生成一个tokenid的字符串,然后存入session。当你点击提交按钮的时候,struts2把页面的tokenid回传到struts2的拦截器里,看看是否一样,一样的话,就在给tokenid赋个新值,然后传回表单,当你再点击提交或者刷新的时候,又执行上面的过程,结果session中的tokenid和表单中的不一样,就出错,你这么配置

<action name="login” class="example.Login” singleton=false>
<interceptor-ref name="token"/>
<interceptor-ref name="defaultStack"/><!—这里要加上struts2的默认拦截器栈—>
<result name="invalid.token" > /repeatRefresh.jsp</result>
<result name="input" > /Login.jsp</result>
<result name="success" type="dispatcher" > /menu.jsp</result>
</action>


上面的invalid.token默认是不一致时候的result,这样就返回到repeatRefresh.jsp页面,你在这里给出提示,比如:不能重复提交等等
别忘了在你的页面的form里加上 <s:token > </s:token>,你可以查看源代码,就能找到tokenid的值


[size=x-large]Ⅳ、使用validate方法或者Validation框架验证数据[/size]
[size=large]使用validate方法:[/size]

在Struts2中最简单的验证数据的方法是使用validate。我们从ActionSupport类的源代码中可以看到,ActionSupport类实现了一个Validateable接口。这个接口只有一个validate方法。如果Action类实现了这个接口,Struts2在调用execute方法之前首先会调用这个方法,我们可以在validate方法中验证,如果发生错误,可以根据错误的level选择字段级错误,还是动作级错误。并且可使用addFieldError或addActionError加入相应的错误信息,如果存在Action或Field错误,Struts2会返回“input”(这个并不用开发人员写,由Struts2自动返回),如果返回了“input”Struts2就不会再调用execute方法了。如果不存在错误信息,Struts2在最后会调用execute方法。
这两个add方法和ActionErrors类中的add方法类似,只是add方法的错误信息需要一个ActionMessage对象,比较麻烦。除了加入错误信息外,还可以使用addActionMessage方法加入成功提交后的信息。当提交成功后,可以显示这些信息。
以上三个add方法都在ValidationAware接口中定义,并且在ActionSupport类中有一个默认的实现。其实,在ActionSupport类中的实现实际上是调用了ValidationAwareSupport中的相应的方法,也就是这三个add方法是在ValidationAwareSupport类中实现的,代码如下:


private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
public void addActionError(String anErrorMessage)
{ validationAware.addActionError(anErrorMessage);
}
public void addActionMessage(String aMessage)
{
validationAware.addActionMessage(aMessage);
}
public void addFieldError(String fieldName, String errorMessage)
{
validationAware.addFieldError(fieldName, errorMessage);
}


具体的代码例子里面有(Login.java 里面)。
[size=large]另外一种办法是使用Validation框架[/size]
编写验证规则配置文件
这是一个基于XML的配置文件,和struts1.x中的validator框架的验证规则配置文件类似。但一般放到和要验证的.class文件在同一目录下,而且配置文件名要使用如下两个规则中的一个来命名:
<ActionClassName>-validation.xml
<ActionClassName>-<ActionAliasName>-validation.xml
其中<ActionAliasName>就是struts.xml中<ation>的name属性值。在例子中我们使用第一种命名规则。例子中都是Type="requiredstring",意思是必须输入信息。还有其他的类型,比如说如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="age">
<field-validator type="int">
<param name="min">0</param>
<param name="max">100</param>
<message>
必须在0至100之间
</message>
</field-validator>
</field>
</validators>


这个文件使用了这个规则:int(确定整型范围)。关于其他更详细的验证规则,请访问http://struts.apache.org/2.0.11.1/docs/validation.html查看。
[b][color=red]两种方式的对比:[/color][/b]
Validate方法:直接写在Action里面,不用配置xml文件;在如果验证N个表单元素(input之类),如果有一个没有通过验证,就直接返回,后面的就不验证了。只打印一个不合格提示
Validation框架:可以部分写在Action里面,有些不用写都可以,但是每一个Action都要对应一个xml文件;在如果验证N个表单元素(input之类),是全部验证完毕之后再返回。会打印出每一个不合格提示。


[size=x-large]Ⅶ:struts与AJAX[/size]
在当今——Web 2.0概念铺天盖地的Internet环境下,简易的AJAX集成对于一个成功的WEB框架来说是不可或缺的。因此,Struts 2其中的一个重要的功能(Feature)就是“First-class AJAX support - Add interactivity and flexibility with AJAX tags that look and feel just like standard Struts tags(大意:一流的AJAX支持——通过AJAX标志增加互动性和灵活性,而且使用这些AJAX标志与普通的Struts标志同样简单)”
现在已经有了Struts 2的JSON插件,可以到http://code.google.com/p/jsonplugin/downloads/list下载JSON插件的JAR包,并将其加入你的工程。
如果只是简单的应用,我们只要用PrintWriter out 把需要的js代码带出来就可以了。如果真的需要很复杂的AJAX应用,请看http://zhaoshg.iteye.com/admin/blogs/356222这篇文章就可以了。

[size=x-large][b][color=red]下载例子说明:[/color][/b][/size]
其实例子里面有用的只是Login和Register,就这两个例子我说明一下:
Login是最普通的:没有拦截器,没有使用validation框架,也没有使用Spring的IOC。
Register刚好相反:有Token拦截器(放刷新),使用了Validation框架,使用了IOC。
大家可以比较一下。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值