(3)在Action中用request、session、application和前端简单数据、对象数据传递到后端
一、在Action中用request、session、application
public class LoginAction2 extends ActionSupport implements RequestAware,SessionAware, ApplicationAware {
/*
* ActionContext只是设置设置数据,获取数据
* struct2提供一种简单使用session的方式,使用SessionAware接口来访问存储于ActionContext中的数据,该接口通过使用IoC/DI来为Action注入session Map,就
* 可以在程序中直接使用这个map操作数据了。
* 类似的,有RequestAware来获取包装请求对象的attribute中的值的Map
* 有ApplicationAware来获取包装请求对象的ServletContext对象的attribute中的值的Map
* 有ParameterAware来获取包装请求对象的参数中的值的Map
*/
/*
* ActionContext仅仅是获取数据,实际开发是不够的,有时,希望根据功能需要,在Action中必须能获取servlet相关的api,比如要操作cookie,这个时候需要ServletActionContext
*也有ServletResponseAware
*/
/*
* ActionContext与ServletActionContext有些重复,都能获取到web对象的数据,通常ActionContext主要负责值的操作
* ServletActionContext:主要负责获取servlet对象。
* 优先使用ActionContext,当其功能不能满足时,采用ServletActionContext
*/
private Map<String, Object> request;
private Map<String, Object> session;
private Map<String, Object> application;
//DI dependency injection
//IoC inverse of control
public String execute() {
request.put("r1", "r1");
session.put("s1", "s1");
application.put("a1", "a1");
return SUCCESS;
}
@Override
public String execute1() throws Exception {
// TODO Auto-generated method stub
System.out.println("用户名为:"+username);
ActionContext c=ActionContext.getContext();
c.getSession().put("username", "session中的username");
c.getApplication().put("account", "application中的account");
/*
* 使用ActionContext来访问Session中的数据,在struct2中,在程序里面访问的是Map,而非HttpSession
* 原因:struct2框架与web相关的很多对象重新进行了包装,比如HttpSession对象就被包装在了一个Map对象中,里面存放着Session中的数据,提供这个map给Action使用
* 而不用Action直接和底层的HttpSession打交道,也正是因为框架的包装,让Action可以完全的和web层解耦
* 注意:ActionContext不能在普通的Java应用程序中使用。因为ActionContext包装的都是Web的数据,若没有web的环境和相应的数据,会抛出异常。
* 访问其他web对象的值也是与此类似的,访问的都是包装的map。
* 若想要在普通的Java应用中运行并测试Action,可以使用SessionAware 的方式来访问HttpSession。
*/
return "success";
}
public void setApplication(Map arg0) {
// TODO Auto-generated method stub
this.application=arg0;
}
public void setSession(Map arg0) {
// TODO Auto-generated method stub
this.session=arg0;
}
public void setRequest(Map arg0) {
// TODO Auto-generated method stub
this.request=arg0;
}
在jsp页面中可以用jsp取request、session、application中的数据,也可以用OGNL表达式取数据。
<s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br />
<s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br />
<s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br />
二、前端的数据能够传递到后端,在最终页面能够取到Action中的数据,在struct2中理解很简单,就是在一次请求(是dispatcher无论有多少转向),Action中的私有字段信息存放在值栈中,这个值栈保留到请求的结果页面。
①简单数据传递
一个简单的jsp页面:向后端传递参数,注意这个参数必须是Action中有的私有字段,而且不能是request、session、application(测试这些都不能在Action中获取到,但是可以将这些数据给前端)
而且这里的${type}:可以将Action中的私有字符串字段可以在result的结果页面名中使用。而且可以作为paramater(redirect)或者Value Stack Contents中(dispatcher)数据。
下面的例子是根据用户的选择,进入不同的页面。
jsp
向结果传参数<br/>
<a href="user/user?type=1">传参数</a><!-- 请求的时候传的值,过滤器可以接收,则action可以接收,并将其放入值栈中
并且可以在<result></result>中接收到,从而传给下一个页面。 -->
<a href="user/user1?type=1">传参数</a>
struct.xml
<action name="user1" class="com.front.action.UserAction">
<result > <!-- type="redirect" -->
/user_success1.jsp?t=${type}<!-- 是要将action中的属性传给下一个页面,在redirect(两次请求中),不再公用一个值栈,在显示页面,
是个新的值栈,没有action存在,就没有属性名、值,不能通过<s:property value="type"/>得到其值,因为没有这个属性。
但是<s:property value="#parameters.t"/>可以得到,t=1相当于参数传过去了
-->
<!-- 深刻理解什么叫一次请求(forward)、两次请求(redirect) -->
</result>
</action>
Action
public class UserAction extends ActionSupport {
private int type;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return "success";
}
}
②考虑一种情况,用户登录,登录成功进入主页面,登录失败到登录界面,可以用
<!--这种方式,理解简单,对于用刀只是简化操作,其实也没简化多少-->
<result name="success">/mainFrame.jsp </result>
<result name="error">/>/login.jsp </result>
也可以用①中的思想,定义一个私有变量,然后根据查询数据库的结果对这个变量赋值,然后在result页面用${}
<!--首先,要有登录界面-->
<action name="user" class="com.front.action.UserAction">
<result>
${r}
</result>
</action>
Action中
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
if(用户名、密码正确) r="/user_success.jsp";//通过用户动态传过来的type来决定用哪个r,这个r也是action中,
//当调用这个类创建对象时,就会将r改变,已经产生值栈而struct.xml返回结果result,${r}就能读取这个值栈,动态返回页面
else r="/user_error.jsp";
return "success";
}
private String r;
public String getR() {
return r;
}
public void setR(String r) {
this.r = r;
}
③向后端传入一个对象,这种只要根据简单类型应该怎么办,自定义类型相似。
User类
//这里简写model:User 注意要有get、set方法。
注册表单jsp
<input type="text" name="user.name" />//1中简单数据通过?传到Action中(?可以在超链接中,也可以在表单提交处)
当要传入后端是个对象时,用Action类中相应对象(在本Action中是对象是user,注意在Action中 user对象也要有getset方法)
即对象名.属性。这样传到后端,就应该在Action中有个对象user在接收。
struct.xml(比如用户注册,添加用户,成功添加数据库后跳转到添加成功的页面)
<action name="user_add" class="com.front.action.UserAction">
<result>
/user_add_success.jsp
</result>
</action>
Action
public class UserAction extends ActionSupport {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
//添加到数据库操作,省略
System.out.println("接收的用户名"+user.getName());
return SUCCESS;
}
}