一、跳转的页面的分类 – 全局页面和局部页面
- 局部页面 – 在action的内部声明的
在action内部自己定义的页面称之为局部页面。 也就是一个action跑自己的页面去。
<!-- 配置action -->
<struts>
<package name="demo" extends="struts-default" >
<action name="demo_*" class="com.itheima.test.ActionDemo3" method="{1}">
<result type="redirect">/other.jsp</result>
</action>
</package>
</struts>
- 全局页面
有点像java里面的全局变量
<!-- 配置action -->
<struts>
<package name="demo" extends="struts-default">
//这个是全局页面 。 可以让多个action都指向这个地址
<global-results>
<result name="success"> /other.jsp</result>
</global-results>
<action name="demo_*" class="com.itheima.test.ActionDemo3"
method="{1}">
</action>
</package>
</struts>
如果提供了全局页面的result的同时,在action中还有一个同名的result,例如上述例子,在action中还有一个name=”success” 的result,那么就依据就近原则,执行action内部的result进行跳转
全局页面的应用场景:
1)错误页面跳转
2)如果没有登录,避免访问某些页面,跳转到登录页面;
二、结果跳转
跳转的分类:
* 跳转到jsp页面
* 跳转到其他Action
* 其他跳转,例如跳转到网络资源等等。
1、跳转jsp页面
- 请求转发跳转 – type=”dispatcher”
其实不写type , 默认采用的就是请求转发跳转
<result name="success" type="dispatcher">/success02.jsp</result>
- 重定向跳转 – type=”redirect”
<result name="success" type="redirect">/success02.jsp</result>
- 如果要给页面带数据, 一般都是用请求转发去跳转。 因为重定向无法带数据过去。
- 请求转发会在地址栏上显示请求的地址 ,第一次请求的地址。
2、跳转Action
跳转action没有什么默认的说法, 如果不写type 默认就是dispatcher , 但是这个dispatcher只能跳转页面,不能跳转action,它会把后面给的地址看成是一个页面,从而产生错误
- 请求转发跳转action
<result name="success" type="chain">actionDemo02_add02</result>
- 重定向跳转
<result name="success" type="redirectAction">actionDemo02_add02</result>
注意:
1)跳转的result后面的action的名字不能包含package的名字,只能够写真正的action的名字,如果package加了namespace当然要加上,不然就只写写action的名字。因为package只是拿来区分的,并不需要在跳转的时候加上包名
2)跳转Action一般采用什么跳转。
一般采用重定向跳转redirectAction。 因为重定向跳转,会抛弃掉第一个action的执行结果以及它的执行参数。如果使用请求转发跳转,会把第一个action的参数以及结果都带到第二个Action上,有可能影响第二个action的执行结果。
3)如果一个action方法里面有返回值,但是没有配置result的话,那跳转的时候就要报错
以后如果哪一个方法不想跳转结果,建议采用返回none常量这种方式,而不适用void的写法。
public class ActionDemo3 extends ActionSupport {
public String add(){
System.out.println("add方法执行了~~~~");
return NONE;
}
}
4)如果要跳转action,一定要写type,如果不写的话默认是type=’dispatcher’,但是dispatcher是跳转页面的,不能够跳转action,他会把后面写的地址看成是页面,完成跳转失败
注意:跳转action的时候不能够写/开头
其他跳转:
Stream Result,可以看看Struts给的文档的index.xml中的说明
JSON Result
以json为例子:
1)导入jar包:struts2-json-plugin-2.3.32.jar
2)编写类:
list需要为全局变量
需要提供一个get方法
public class JsonTest extends ActionSupport {
List<User> list ;
public List<User> getList(){
return list;
}
public String test(){
list = new ArrayList<User>();
System.out.println("执行到这里了,日志");
for(int i=1;i<6;i++){
User user = new User();
user.setId(i);
user.setUsername("张三"+i);
list.add(user);
}
return "success";
}
}
3)配置struts.xml
<struts>
<package name="json" extends="json-default">
<action name="json_*" class="com.itheima.test.JsonTest"
method="{1}">
<result name="success" type="json">
<param name="root">list</param>
</result>
</action>
</package>
</struts>
三、获取表单数据
1. 获取零散数据
所谓的获取零散数据,就是我们得到页面的数据之后,还得手动封装成一个实体对象
- 使用ActionContext类获取
翻译过来是Action的上下文,通过它可以获取到有关Action的信息
ActionContext:就是包含了action的一切信息,都在这个对象的身上;
actionContexct只提供了拿getParameters提取这个map的方法
缺点:这个ActionContext无法获取单个参数
public void test01(){
ActionContext context = ActionContext.getContext();
Map<String, Object> map = context.getParameters();
System.out.println(map);
for (String key : map.keySet()) {
System.out.println(key+":"+Arrays.toString((String[])map.get(key)));
}
}
- 使用ServletActionContext获取
该类是ActionContext的子类,所以功能上应该稍微有扩展。 该类不仅可以获取数据,它还提供了获取response对象 、 request对象、servletContext对象当然它也能得到它父类对ActionContext
其实这个类本质上就是让我们回到了原来的servlet的处理方式处理页面传递的数据
public void test01(){
HttpServletRequest request = ServletActionContext.getRequest();
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username:"+username);
System.out.println("password:"+password);
}
- 使用实现接口方式获取
这种方式其实和第二种方式一样。唯一的不同只是这种方式获取request对象是采用实现接口的方式获取。 大家获取参数的手法都是通过request获取的。
public class GetParameters extends ActionSupport implements ServletRequestAware{
HttpServletRequest request;
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public String test01() {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username:"+username);
System.out.println("password:"+password);
return NONE;
}
}
2. 封装表单数据成对象
- 属性封装
只要在action上声明全局变量,并且提供set方法, struts会自动对这些变量进行赋值。但是有一个要求: 这个全局变量的名字必须和 页面的标签 name属性值 一致。
action :
public class ActionDemo extends ActionSupport {
private String username;
private String password;
//1. 声明全局变量
//2. 提供set方法 --struts框架会调用set方法对我们的全局变量进行赋值。
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
以上方式可以拿到页面交过来的数据,但是还只是零散的数据,并没有封装成对象。而且还要考虑一个隐患,如果页面提交过来的数据太多,我们还需要写很多的set方法,并且最后还要自己封装成实体对象。
Action :
//属性封装,直接封装成实体
public class ActionDemo02 extends ActionSupport {
private User user ;
//set方法的本意是: 赋值对象。 注意:现在这个user并没有new出来对象 。
// 1. 先new一个user对象 调用setUser方法,让我们的这个user指向了曾经new出来的对象
public void setUser(User user) {
this.user = user;
}
//因为要赋值的话,需要得到这个user对象,然后调用user.setXXX()
public User getUser() {
return user;
}
}
页面:
用户名:<input type="text" name="user.username"><br>
密码:<input type="password" name="user.password"><br>
模型驱动封装【重点掌握】
让Action实现接口ModelDriven
实现方法 getModel ,并在里面返回要封装的对象。
public class ActionDemo extends ActionSupport implements ModelDriven<User>{
private User user ;
public String add() {
System.out.println("user2222==="+user);
return NONE;
}
@Override
public User getModel() {
//一定要在返回user对象之前 new出来user
if(user == null){
user = new User();
}
return user;
}
}
这个模型驱动是怎么封装数据的。 — 是通过拦截器封装的。
封装集合数据 – 比较类似于属性封装的封装成为实体
一般这种情况只有在批量操作的时候才会出现,比如:批量添加用户Action :
private List<User> list;
public void setList(List<User> list) {
this.list = list;
}
public List<User> getList() {
return list;
}
页面:
用户名:<input type="text" name="list[0].username"><br>
密码:<input type="password" name="list[0].password"><br>
<br>-------------------------------<br>
用户名:<input type="text" name="list[1].username"><br>
密码:<input type="password" name="list[1].password"><br>
---------------------------------------------------------------------
下面是Map集合
private Map<String , User> map ;
public void setMap(Map<String, User> map) {
this.map = map;
}
public Map<String, User> getMap() {
return map;
}
页面
用户名:<input type="text" name="map['aa'].username"><br>
密码:<input type="password" name="map['aa'].password"><br>
<br>-------------------------------<br>
用户名:<input type="text" name="map['bb'].username"><br>
密码:<input type="password" name="map['bb'].password"><br>