本文档包括了
(1)首先加入jar包(最小jar组合)
(1) 在web.xml中注册Struts2
这是一个前控制器作用是提供一个统一的入口,所有的请求都先经过前控制器就是这里,然后由他在做进一步处理
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(2) 编写后控制器Action类
编写Action类需要一个无参构造函数,控制器方法名字任意,但不能带参数,并且返回值类型必须是String
(3) 配置Action类编写src/struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<!--
dtd:文件类型声明,约束文件的标签规格
Struts 配置文件,配置Action类
package:配置文件的包,将配置文件进行分包放置管理
name= "nyist" 包名,之后定义的每一个包,名字都不一样就和类的包一样
extends="struts-default" 继承了
namespace :是Action的访问前缀,即要访问namespace 为“/a” 的包中的name为"hello" 的Action
http://localhost:8080/项目名/a/hello.action
作用:在namespace 的支持下,较彻底的将配置文件分模块管理了
-->
<struts>
<package name="nyist" extends="struts-default" namespace="/a">
<!-- 配置Action
name ="hello" 等价于Servlet中的url-pattern
即在访问的时候我们需要加入/hello 自己定义的
class ="com.nyist.action.HelloWorldaction" 即是Action的全限定名
method = "abc" 即method表示的是我们需要访问该Action的abc此方法,因为方法是自定义的所以很大的空间命名,所以我们需要指定我们访问的是那个方法
-->
<action name="hello" class="com.nyist.action.HelloWorldaction" method="abc">
<!--<result name="helloOK">
abc方法返回的值 helloOK,然后进行view视图的调用,反义到index.jsp
-->
<result name="helloOK">/index.jsp</result>
</action>
</package>
</struts>
(4) 方法参数接收问题
Struts 框架集合了很好的参数接收问题。我们只需要在我们所要访问的那个Action类中定义我们访问时候使用的jsp文件中出现的我们需要传递的值的名称例如
<input type="text" name="name"/> name这个属性名称。我们只需要在action类定义一个私有属性,并进行get/set方法。然后struts就进行自我封装。所以我们在本类取我们传递过来的值得时候就只需要访问我们的私有属性即可例如:
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
System.out.println(name+"===="+age+"====");
这样就相当的简单了,不需要我们使用HttpRequest 进行访问了
List<对象>也行
Date等和基本属性
(5) 转发与重定向
<!--
dispatcher:请求转发:type的默认值转发到JSP
redirect : 重定向到JSP
redirectAction :重定向到Action
chain: 转发到Action
-->
例如:
<result name="paramOK" type="dispatcher">/index.jsp</result>
注意:我们转发或者跳转到一个action中的时候,我们需要声明,转发或者跳转action的位置,即namespace(包的namespace,注意/ 不能少)和name(你自己在定义那个action的时候的name)。但是如果跳转双方都在一个package中,那么namespace可以省略,即默认是在当前包中跳转例如:(原跳转,和改良后的)(redirectAction 重定向到Action 和上面的转发到Action中相似就是将chain 改为redirectAction 即可)
例如:
为了防止重复提交我们选取重定向(当action做的是增删改的操作的时候我们需要使用重定向(redirectAction),当操作查询的时候我们使用转发(chain))
(6) 全局跳转
全局跳转:抽取一个package 中的重复的result(例如错误) 简化配置,
:每个全局跳转(<result>) 都是在当前的包中的所有的Action 之间共享的。注意:全局跳转,只存在于一个包中,不存在不同包中的。全局跳转需要放在action之前
例如:
<global-results>
<result name="">/error.jsp</result>
</global-results>
(8)Action 的创建模式:非单例模式,每个请求都独享一个Action的实例对象
例如:UserAction{
}
请求一次:new UserAction()
再请求一次:new UserAction()
再再请求一次:new UserAction()
Servlet :单例模式
(9) Action的生命周期:一个请求,请求到来的时候创建,请求结束的时候就销毁
(10)Action的创建方式:
1)public class ClassName{(pojo)建议使用
方法
}
2)public class ClassName extends ActionSupport{ (ActionSupport是Action的实现类是一个适配器)
方法
}
3) public class ClassName implements Action{
方法
}
注意:Action中的默认执行方法:
Public String execute(){
。。。。。。
Return 。。;
}
即如果配置中<action name=”XX” class =”XX”></action> 没有定义method属性,则默认执行execute 方法
(11)多方法控制
<!-- 多方法控制:
在一个Action中定义多个不同实现不同作用的方法,
然后进行在.xml 文件中进行配置,配置原则就是多个action 对应了多个方法class相同,
method 对应不同的方法名,已经之后的不同的方法返回值
-->
<!-- 静态调用 -->
<!--
<action name="manyfuns" class="com.nyist.action.ManyFunction" method="fun1">
<result name="fun1">/fun1.jsp</result>
</action>
<action name="manyfuns1" class="com.nyist.action.ManyFunction" method="fun2">
<result name="fun2">/fun2.jsp</result>
</action>
<action name="manyfuns2" class="com.nyist.action.ManyFunction" method="fun3">
<result name="fun3">/fun3.jsp</result>
</action>
-->
<!--
动态调用:name="manyfuns_* 中*是通配符 ,匹配任意一个或者多个字符
/manyfuns_fun1
/manyfuns_fun2
/manyfuns_fun3
.......
method="{1}" 中的{1} 是一个占位符,此位置会填充【*】号当前匹配的位置
每个请求到来时* 都可以匹配到不同的内容
此时的url是:
http://localhost:8080/StrutsDemo/manyfuns_fun1(调用fun1)
http://localhost:8080/StrutsDemo/manyfuns_fun2(调用fun2)
http://localhost:8080/StrutsDemo/manyfuns_fun1(调用fun3)
-->
<action name="manyfuns_*" class="com.nyist.action.ManyFunction" method="{1}">
<result name="fun1">/fun1.jsp</result>
<result name="fun2">/fun2.jsp</result>
<result name="fun3">/fun3.jsp</result>
</action>
(12)(数据处理机制=ognl + 值栈 +struts标签)
作用:
OGNL(对象图导航语言)
:寻址,取值
:独立的组件(ognl.jar)
: 取值来源:根(任何一个对象成为ognl的根对象)和上下文(任何一个Map都可以成为ognl的上下文)
: 为ognl指定【根对象】或【上下文】,之后ognl即可以从中取值
:从根对象取值语法
1》Ognl.getValue(‘属性名’,下文, 根)
2》从根中取出其中的数组属性中的值(可以通过强转和属性[index] 进行取出)
3》从根中取出其中对象属性的属性值是(可以通过强转和对象属性名.对象的属性名)
如下面,addr是User的对象属性,为city和id是对象属性的类属性
4》 如果取出的值是Map 可以通过【.key】获取对应的value
: 从上下文取值
1》 从上下文中取值,通过【key】获取对应的value(注意:从上下文取值的时ognl表达式要以#开头)
2》 如果要取出的值是数组的话那么就第一个参数就使用”#你存的key[index]”
String [] hobbys = new String[]{"111","222","333"};
map.put("hobby",hobbys);
String hobby1 = (String) Ognl.getValue("#hobby[0]", map,new Object());
String hobby2 = (String) Ognl.getValue("#hobby[2]", map,new Object());
3》 如果要取出的值是对象的话那么第一个参数就使用”#存储对象的名字 . 你要获取的对象的属性名”
例如:
User u = new User(1,"zhangsan");
map.put("usr", u);
Integer id = (Integer) Ognl.getValue("#usr.id",map,new Object());
String name = (String) Ognl.getValue("#usr.name", map, new Object());
System.out.println(id + "===" + name);
4》 如果要取出的值是对象集合的话那么分为三种集合Map集合那么在取值的时候就可以第一个参数使用”#存储集合的名字.key.对象属性” ,如果是List集合的话那么就是和数组相似“#存储list集合的名子[索引].对象属性”
ArrayList<User> list = new ArrayList<User>();
list.add(u);
list.add(u1);
map.put("list", list);
//List 集合取值
Integer id1 = (Integer) Ognl.getValue("#list[1].id", map,new Object());
System.out.println(id1);
5》 升级
调用取出数据类型中的所有的公开的方法
Integer n = (Integer)Ognl.getValue("#usr.name.length()", map, new Object());
运算(算术运算,,逻辑运算)
赋值
6》 setValue() 设置
=====================================================
值栈:struts 提供的一个域,用于存储数据(传值的媒介实现Action到jsp的数据传输,通信)
1》 在Action中向值栈存入数据
*需要OGNL找到对应位置,将数据存入
2》 在JSP中从值栈中获取数据
*需要OGNL找到对应位置,将数据取出
3》 值栈:获取方式
//获取值栈对象ServletActionContext.getRequest();
ValueStack vs = ActionContext.getContext().getValueStack();
//向OGNL指向的位置取值
vs.findValue("OGNL");
//向OGNL 指向的位置存值
vs.setValue("ognl", );
vs.findValue(“#request.name”) //request.getAttribate(“name”)
vs.findValue(“#session.age”) // session.getAttribute(‘age’)
vs.setValue(“#request.age”,20);//request.setAttribute(“age”,20)
vs.setValue(“#session.name”,”zhang”),//session.setAttribute(“name”,”zhang”);
4》 值栈的内部存储结构(Context 区域)
l Context 区域:本质是MAP
Key value
“request” mapr ===》等价于request作用于的底层的Map
“session” Maps ===》等价于session作用于的底层的Map
“application” Mapa ===》等价于application(servletContext)的作用域
l 等价: 数据严格同步
l 通过Context区域,可以统一的通过ValueStack操作三大作用于(request,session,application);等价的findValue(),setValue()函数进行上下文取值和设置
l
5》 实际案例
Action—>JSP
Action 存数据
Struts处理(使用的是重定向到JSP)
JSP取值(使用Struts标签)
6》 值栈的内部存储结构(Root区域)
l Root区域:本质上ArrayList,具有栈(Stack)的特点
1》 root区域中【存放当前请求的Action实例对象和s标签遍历时候的临时值】
2》 root 区域中的元素为OGNL的根对象
3》 即当前的Action实例对象为OGNL的根对象
4》 由于本对象就是OGNL的根对象,那么在赋值的时候很方便,直接进行this.属性=你传递过来的值
例如:下面使用的转发到jsp中,所以我们不需要使用session进设置在JSP中使用
注意:
通过Root区域,Struts2提供了全新的数据传输介质:根对象(Action), 但是由于根对象的生命周期仅为一个请求,所以通过根对象进行传值 的话只能使用转发。不能使用跳转
根对象基本代替了请求作用域(request)去完成一个请求内部的数据 传递(Action——>JSP)
l
7》 Struts标签(jsp使用时需要导入库文件<%@taglib uri="/struts-tags" prefix="s"%> 这样才能使用Struts的标签)
l 获取数据(取单值)
<s:property value="OGNL"/>(OGNL表示的是action转入到该jsp页面是创建的名称例如:
或者是Root区域的特殊实现
比如第一个的结果jsp中取值就是
第二个取值就是)
l 分支判断 (<s:elseif test=""></s:elseif> <s:else></s:else> )
实例:
l 遍历(List集合)
(1)ROOT区域遍历
<s:iterator value="#session.users">
<s:property value="id"/>
<s:property value="name"/>
<s:property value="age"/>
<br/>
</s:iterator>
注意:遍历过程中,每次遍历到的当前元素,都会被压入栈的Root区域中,成为Root区域的栈顶元素,以及OGNL高级别
(2)上下文遍历
<s:iterator value="#session.users" var="usr">
<s:property value="#usr.id"/>
<s:property value="#usr.name"/>
<s:property value="#usr.age"/>
<br/>
</s:iterator>
注意:遍历过程中,每次都以【a】为key,以当前遍历的元素为value存入Context中
(3) 相当于for
<s:iterator begin="1" end="10" var="i">
<s:property value="#i"/>
<br/>
</s:iterator>
(4)遍历实例:
l 动态获取项目名:(使用<s:url value=””/ > 标签会自动补全项目名)
<a href="<s:url value=‘/index.jsp‘/>">跳转</a>
<a
href=‘<s:url value="/fun"></s:url>‘>飞</a>
8》