如果提供了全局页面的result的同时,在action中还有一个同名的result,例如上述例子,在action中还有一个name=”success” 的result,那么就依据就近原则,执行action内部的result进行跳转
全局页面的应用场景: 1)错误页面跳转 2)如果没有登录,避免访问某些页面,跳转到登录页面;
跳转的分类:
* 跳转到jsp页面 * 跳转到其他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>以上方式可以拿到页面交过来的数据,但是还只是零散的数据,并没有封装成对象。而且还要考虑一个隐患,如果页面提交过来的数据太多,我们还需要写很多的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>