struts2的execute方法中并没有任何参数(相较于servlet的doGet和doPost),不存在任何的servlet API。即Action类没有与任何Servlet API耦合,因此可以脱离Servlet容器环境进行单元测试。
struts2提供以四种下方式访问servlet API:
其中方法1和2保持了action与servlet API的解耦,而方法3和4中action与servlet API直接耦合
文章目录
1.通过ActionContext类完成
//获取ActionContext对象,每个Action实例都有一个ActionContext对象
ActionContext ctx = ActionContext.getContext();
//通过ActionContext对象获取请求、会话和上下文对象相关联的Map对象
Map request=(Map) ctx.get("request");
Map session=(Map) ctx.getSession();
Map application=(Map) ctx.getApplication();
application.put("xxx", xxx);
示例代码:
loginAction中的login方法:
public String login() {
ActionContext ctx = ActionContext.getContext();
//通过ActionContext对象获取请求、会话和上下文对象相关联的Map对象
Map request=(Map) ctx.get("request");
Map session=(Map) ctx.getSession();
Map application=(Map) ctx.getApplication();
//访问application范围的属性值
Integer counter = (Integer)application.get("counter");
if(counter == null)
counter = 1;
else
counter++;
//设置application范围的属性
application.put("counter", counter);
UserService userServ = new UserService();
if(userServ.login(loginUser)) {
//设置session范围的属性
session.put("user", loginUser.getAccount());
//设置request范围的属性
request.put("tip", "您已登录成功");
return "loginsuccess";
}
this.addActionError(this.getText("login.fail"));
return "loginfail";
}
loginSuccess.jsp:
<body>
本站访问次数为:<s:property value="#application.counter"/><br>
<s:property value="#session.user"/>
<s:property value="#request.tip"/>
</body>
2.实现***Aware接口(RequestAware、SessionAware和ApplicationAware)
注意在这里要声明私有属性,因此login方法也和前面有所不同,不需要再进行声明。
public class UserAction extends ActionSupport implements
RequestAware,SessionAware,ApplicationAware {
private Map request,session,application;
……
public void setRequest(Map<String, Object> request) {
this.request=request; }
public void setSession(Map<String, Object> session) {
this.session=session; }
public void setApplication(Map<String, Object> application) {
this.application=application; }
……
public String login(){
//访问application范围的属性值
Integer counter = (Integer)application.get("counter");
if(counter == null)
counter = 1;
else
counter++;
//设置application范围的属性
application.put("counter", counter);
UserService userServ = new UserService();
if(userServ.login(loginUser)) {
//设置session范围的属性
session.put("user", loginUser.getAccount());
//设置request范围的属性
request.put("tip", "您已登录成功");
return "loginsuccess";
}
this.addActionError(this.getText("login.fail"));
return "loginfail";
}
}
loginSuccess.jsp与第一种方法时相同
3.servletActionContext工具类
注意这里不再用.set()和.put()方法了,而是使用setAttribute()和getAttribute()
public class UserAction extends ActionSupport {
……
public String login(){
HttpServletRequest request = ServletActionContext.getRequest();
//HttpServletResponse response = ServletActionContext.getResponse();
ServletContext application = ServletActionContext.getServletContext();
HttpSession session = request.getSession();
//访问application范围的属性值
Integer counter = (Integer)application.getAttribute("counter");
if(counter == null)
counter = 1;
else
counter++;
//设置application范围的属性
application.setAttribute("counter", counter);
UserService userServ = new UserService();
if(userServ.login(loginUser)) {
//设置session范围的属性
session.setAttribute("user", loginUser.getAccount());
//设置request范围的属性
request.setAttribute("tip", "您已登录成功");
return "loginsuccess";
}
this.addActionError(this.getText("login.fail"));
return "loginfail";
}
}
4.通过实现接口:ServletContextAware、ServletRequestAware、ServletResponseAware
public class UserAction extends ActionSupport implements ServletRequestAware, ServletContextAware{
private ServletContext application;
private HttpServletRequest request;
private HttpSession session;
……
public String login() {
//访问application范围的属性值
Integer counter = (Integer)application.getAttribute("counter");
if(counter == null)
counter = 1;
else
counter++;
//设置application范围的属性
application.setAttribute("counter", counter);
UserService userServ = new UserService();
if(userServ.login(loginUser)) {
//一定要记得getSession
session = request.getSession();
//设置session范围的属性
session.setAttribute("user", loginUser.getAccount());
//设置request范围的属性
request.setAttribute("tip", "您已登录成功");
return "loginsuccess";
}
this.addActionError(this.getText("login.fail"));
return "loginfail";
}
@Override
public void setServletContext(ServletContext application) {
// TODO Auto-generated method stub
this.application = application;
}
@Override
public void setServletRequest(HttpServletRequest request) {
// TODO Auto-generated method stub
this.request = request;
}
}
但是要注意不使用servlet API的时候也是可以在跳转到的界面获取值的
因为result的type属性默认值是dispatcher,就相当于在servlet中的.forward,所以至少同一个request下的变量还是可以在跳转到的页面共享的
在Action中:
package cn.edu.zjut.action;
import java.util.List;
import cn.edu.zjut.service.ItemService;
public class ItemAction{
private List items;
ItemService itemServ;
public String getAllItems() {
itemServ = new ItemService();
if(itemServ.getAllItems() != null) {
items = itemServ.getAllItems();
return "success";
}
return "fail";
}
public List getItems() {
return items;
}
}
返回success后对应的.jsp页面:
<body>
<table border="1">
<tr>
<th>编号</th><th>书名</th><th>说明</th><th>单价</th>
</tr>
<s:iterator value="items">
<tr>
<!-- 这是主键为itemID时的写法
<td><s:property value="itemID"/></td>
<td><s:property value="name"/></td>
-->
<!-- 在这里主键是ipk,即itemID和name构成复合主键 -->
<td><s:property value="ipk.itemID"/></td>
<td><s:property value="ipk.name"/></td>
<td><s:property value="description"/></td>
<td><s:property value="cost"/></td>
</tr>
</s:iterator>
</table>
</body>
注意在这里,要让jsp获取到items,首先在Action中要有items这个私有属性,然后要提供这个属性的get方法,不然jsp页面是获取不到的。
当然action中也可以用上面四种servlet API的方法,比如说把它存到session里面,那么在jsp中只需要<s:iterator value="#session.items">