使用Struts2框架实现用登录的功能,使用struts2标签和ognl表达式简化了试图的开发,并且利用struts2提供的特性对输入的数据进行验证,以及访问ServletAPI时实现用户会话跟踪,其简单的程序运行流程图如下
Struts2的Action类很有意思,你可以使用3种方式来实现具体的Action类:
- 让你的Action类继承自ActionSupport类(项目中最常用这种方式,因为ActionSupport类中定义了很多帮助方法)
- 让你的Action类实现Action接口
- 使用POJO的方式来实现,只要Action类中有一个返回值为String的execute方法就好了(这种方式使Action类最容易被测试)
以上三种Action的实现方式都可以被struts2框架自动识别,如果你在struts.xml里面配置了一个action块但是没有配置action类的路径,这样框架默认使用ActionSupport来处理请求。
但是在实际使用struts2的过程中我发现了一个问题,一个Action只有一个execute方法来处理一类请求,如果我开发的某块功能有100个不同的请求那我岂不是要写100个Action类,每个类实现一个execute方法,这样虽然满足了一个类一个责任的设计原则,但是会不会造成“类爆炸”?后来看了struts2的文档才知道,其实我们可以使用struts2灵活的通配符配置来达到减少action类的目的:
方式一:
继承ActionSupport类,如果使用了数据校验功能,则必须继承ActionSupport。上面那个Action类就是继承了ActionSupport类。
方式二:
实现Action接口,实现execute()方法
package lps.servletAPI; import com.opensymphony.xwork2.Action; import javax.xml.registry.infomodel.User; public class LoginThirdActionContextAction implements Action { private User user; @Override public String execute() throws Exception { return null; } }
方式三:
:既不继承ActionSupport也不实现Action接口.(ActionSupport实现了Action接口)
public class UserAction3 { private String userName; public void setUserName(String userName) { this.userName = userName; } public String login(){ System.out.println("UserAction3.login()"+":"+userName); return "success"; } }
Struts2的result结果集
Struts2的Action处理用户请求后,返回一个普通字符串-------逻辑视图名,必须在Struts.xml文件中完成逻辑图
和物理视图资源的映射,才可以让系统转到实际的视图资源。
结果就是告诉Struts2框架,当Action处理结果时,系统下一步做什么。当Action返回一个普通的字符串时,系统下一步做什么。
Struts2通过在struts.xml文件中使用<result…/>元素来配置结果。根据<result…/>元素所在位置的不同,struts2提供了两种结果:
(1) 局部结果:将<result…/>作为<action…/>元素的子元素配置。
(2) 全局结果:将<result…/>作为<global-result…/>元素的子元素配置。
首先来介绍一下局部结果,局部结果是通过在<action../>元素中指定<result…/>元素来配置的,一个<action…/>元素可以有多个<result…/>元素。这表示一个Action可以对应多个结果。
<!--登陆的action--> <action name="login" class="lps.demo.LoginAction"> <result name="success"> /success.jsp </result> <result name="login"> /login.jsp </result> </action>
(1) location:该参数指定了该逻辑视图对应的实际视图资源。
(2) parse:该参数指定是否允许在实际视图名字中使用OGNL表达式,该参数默认值为true。如果设置该参数值为false,则不允许在实际视图名中使用表达式。通常无需修改该属性值。因为通常无需指定parse参数的值。
<action name="login" class="lps.demo.LoginAction"> <result name="login"> /login.jsp </result> </action>
以下Struts2支持处理结果类型为转载☞:https://blog.csdn.net/fujiakai/article/details/51897533
struts2支持的处理结果类型
Struts2内建支持结果类型如下:
(1) chain结果类型:Action链式处理的结果类型。
(2) chart结果类型:用于整合JFreeChart的结果类型。
(3) dispatcher结果类型:用于FreeMarker整合的结果类型。
(4) httpheader结果类型:用于控制特殊的HTTP行为的结果类型。
(5) jasper结果类型:用于JasperReports整合的结果类型。
(6) jsf结果类型:用于与JSF整合的结果类型。
(7) redirect结果类型:用于直接跳转到其他URL的结果类型。
(8) redirect-action结果类型:用于制直接跳转到其他Action的结果类型。
(9) stream结果类型:用于向浏览器返回一个InputStream(一般用于文件下载)。
(10) tiles结果类型:用于与Tiles整合的结果类型。
(11) velocity结果类型:用于与Velicity整合的结果类型。
(12) xslt结果类型:用于与XML/XSLT整合的结果类型。
(13) plaintext结果类型:用于显示某个页面的原始代码的结果类型。
---------------------
堆栈ValueStack
valueStack是struts2的值栈空间,是struts2存储数据的空间
Strut2的Action类通过属性可以获得所有请求相关的值,要在Action类中声明与参数同名的属性或者以类名小写加属性名如:user.name,就可以获得这些参数值,在Struts2调用Action类的Action方法(默认是execute方法)之前,就会为相应的Action属性赋值。这项功能Struts2要依赖于ValueStack对象来实现,每个Action类的对象实例会拥有一个ValueStack对象,这个对象贯穿整个Action的生命周期,
当Struts2接收到一个请求后,会先建立Action类的对象实例,但并不会立即调用Action方法,而是先将Action类的相应属性放到ValueStack实现类ONGLValueStack对象root对象的顶层节点。只是所有的属性值都是默认的值,如String类型的属性值为null,int类型的属性值为0等。在处理完上述工作后,Struts 2就会调用拦截器链中的拦截器,这些拦截器会根据用户请求参数值去更新ValueStack对象顶层节点的相应属性的值,最后会传到Action对象,并将ValueStack对象中的属性值,赋给Action类的相应属性。当调用完所有的拦截器后,才会调用Action类的Action方法。ValueStack会在请求开始时被创建,请求结束时消亡
值栈ValueStack
为什么进行类型转换
在基于HTTP协议的Web应用中
客户端请求的所有内容都以文本编码方式传输到服务器端,服务器端的编程语言却有着丰富的数据类型
Servlet中,类型转换工作由开发者自己完成,eg
3.valueStack底层相关的数据结构
CompoundRoot是继承了Arraylist的集合,里面存放Action的实例、代理对象、自定义对象(Student)等数据。