Action API
通过ActionContext 获取不同域对象 存放值
- Object get(Object key) 类似于调用HttpServletRequest 的 getAttribute(String name)方法
- Map getApplication() 返回一个Map对象 该对象模拟了应用ServletContext实例
- static ActionContext getContext() 静态方法 获取系统的ActionContext实例
- Map getParameters() 获取所有的请求参数。类似调用HttpServletRequest对象的getParameterMap()方法
- Map getSession() 返回一个Map对象 该Map对象模拟了HttpSession实例
- void setApplication(Map application) 直接传入一个Map实例,将该Map实例里的key-value对象转换成application的属性名、属性值
- void setSession(Map session) 直接传入一个Map实例,将该Map实例里的key-value对转换成session的属性名、属性值
结果跳转方式
Struts2中常用的结果跳转方式有4中:
转发
<package name="result" extends="struts-default">
<action name="Demo1Action" class="cn.probuing.struts2lesson.action.Demo1Action">
<result name="success" type="dispatcher">/hello.jsp</result>
</action>
</package>
查看源码分析
Struts2按照struts-default.xml配置文件可以找到 dispathcer对应的类 名为
rg.apache.struts2.dispatcher.ServletDispatcherResult
进入这个类中,我们可以看到如下的代码
/**
* Dispatches to the given location. Does its forward via a RequestDispatcher. If the
* dispatch fails a 404 error will be sent back in the http response.
*
* @param finalLocation the location to dispatch to.
* @param invocation the execution state of the action
* @throws Exception if an error occurs. If the dispatch fails the error will go back via the
* HTTP request.
*/
public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
if (LOG.isDebugEnabled()) {
LOG.debug("Forwarding to location " + finalLocation);
}
PageContext pageContext = ServletActionContext.getPageContext();
if (pageContext != null) {
pageContext.include(finalLocation);
} else {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
//add parameters passed on the location to #parameters
// see WW-2120
if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
Map<String, Object> parameters = getParameters(invocation);
Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true);
if (queryParams != null && !queryParams.isEmpty())
parameters.putAll(queryParams);
}
// if the view doesn't exist, let's do a 404
if (dispatcher == null) {
response.sendError(404, "result '" + finalLocation + "' not found");
return;
}
//if we are inside an action tag, we always need to do an include
Boolean insideActionTag = (Boolean) ObjectUtils.defaultIfNull(request.getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION), Boolean.FALSE);
// If we're included, then include the view
// Otherwise do forward
// This allow the page to, for example, set content type
if (!insideActionTag && !response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) {
request.setAttribute("struts.view_uri", finalLocation);
request.setAttribute("struts.request_uri", request.getRequestURI());
dispatcher.forward(request, response);
} else {
dispatcher.include(request, response);
}
}
}
由源码可以看到
- 先通过ServletActionContext.getRequest() 获取到了HttpServletRequest 这就是请求对象
- 通过ServletActionContext.getResponse()获取到了HttpServletResponse() 响应对象
- 通过请求和响应对象来进行结果的操作,其中
* 请求对象 request.getRequestDispatcher() 获得转发器,在最后dispathcer.forward(req,res)
可以看出 Struts2的转发 就是封装的Servlet的转发,加入了一些逻辑
重定向
<package name="result" extends="struts-default">
<action name="Demo2Action" class="cn.probuing.struts2lesson.action.Demo2Action">
<result name="success" type="redirect">/hello.jsp</result>
</action>
</package>
查看源码分析
HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);
sendRedirect(response, finalLocation);
同样 封装的Servlet重定向
转发到Action
<action name="Demo3Action" class="cn.probuing.struts2lesson.action.Demo3Action">
<result name="success" type="chain">
<!--结果集完成后会转发到namespace上的actionName-->
<param name="actionName">Demo1Action</param>
<param name="namespace">/</param>
</result>
</action>
重定向到Action
<action name="Demo4Action" class="cn.probuing.struts2lesson.action.Demo4Action">
<result name="success" type="redirectAction">
<param name="actionName">Demo1Action</param>
<param name="namespace">/</param>
</result>
</action>
获得Servlet API
Struts2的Action没有与任何Servlet API耦合,这是Struts2的一个改良之处
原理
原理通过ActionContext
Struts2提供了ActionContext来访问Servlet API ActionContext是Action执行的上下文对象。在ActionContext中保存了Action执行所需要的所有对象。包括parameters,request,session,application等
ActionContext context = ActionContext.getContext();
//获得request域 struts不推荐使用request域
Map<String, Object> requestScope = (Map<String, Object>) context.get("request");
//推荐 ActionContext
ActionContext.getContext().put("name", "requestTom");
//获得session域
Map<String, Object> session = context.getSession();
session.put("name", "sessionTom");
//获得application域
Map<String, Object> application = context.getApplication();
application.put("name", "applicationTom");
return SUCCESS;
获得session域
- Map<String, Object> session = context.getSession();
获得Application域
- Map<String, Object> application = context.getApplication();
通过ServletActionContext
为了直接访问Servlet API Struts2框架还提供了ServletActionContext类
public String execute(){
//原生request
HttpServletRequest request = ServletActionContext.getRequest();
//原生session
HttpSession session = request.getSession();
//原生response
HttpServletResponse response = ServletActionContext.getResponse();
//原生servletContext
ServletContext servletContext = ServletActionContext.getServletContext();
return SUCCESS;
}
通过实现接口方式
Struts2接口public class Demo7Action extends ActionSupport implements ServletRequestAware, ServletResponseAware, ServletContextAware {
private ServletContext context;
private HttpServletRequest request;
private HttpServletResponse resp;
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public void setServletResponse(HttpServletResponse response) {
this.resp = response;
}
@Override
public void setServletContext(ServletContext context) {
this.context = context;
}
public String execute() throws Exception {
System.out.println("原生request" + request);
return SUCCESS;
}
由拦截器完成
Action中获得参数
第一种:通过与参数键名称相同的属性
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute() throws Exception {
System.out.println(this.name);
return SUCCESS;
}
属性驱动获得参数
private String name;
private Integer age;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute() throws Exception {
System.out.println(this.name);
System.out.println(this.age);
System.out.println(this.birthday);
return SUCCESS;
}
<form action="${pageContext.request.contextPath}/Demo8Action" method="post">
用户名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
生日:<input type="text" name="birthday"/><br/>
<input type="submit" value="提交"/>
</form>
第二种 对象驱动
- 创建对象
public class User {
private String name;
private Integer age;
private Date birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
- 页面指定提交到对象的对应属性
<form action="${pageContext.request.contextPath}/Demo9Action" method="post">
用户名:<input type="text" name="user.name"/><br/>
年龄:<input type="text" name="user.age"/><br/>
生日:<input type="text" name="user.birthday"/><br/>
<input type="submit" value="提交"/>
</form>
- Action 中声名对象属性
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.printf(this.user.toString());
return SUCCESS;
}
其实某种意义上 对象驱动和属性驱动没有什么区别,只是将属性换成了对象
第三种 模型驱动
- Action实现ModelDriven<模型>接口
public class Demo10Action extends ActionSupport implements ModelDriven<User> {
private User user = new User();
@Override
public String execute() throws Exception {
System.out.printf(this.user.toString());
return SUCCESS;
}
/**
* @return 返回需要封装的对象
*/
@Override
public User getModel() {
return user;
}
}
- 页面正常提交
<form action="${pageContext.request.contextPath}/Demo10Action" method="post">
用户名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
生日:<input type="text" name="birthday"/><br/>
<input type="submit" value="提交"/>
</form>
缺点:封装的模型单一
原理(正在学习 日后补)
集合类型参数封装
封装list
- Action类
private List<String> list;
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
@Override
public String execute() throws Exception {
System.out.println("list" + list);
return SUCCESS;
}
- 页面page
list:<input type="text" name="list"/>
list:<input type="text" name="list[1]"/>
<input type="submit" value="提交"/>
前端表单指定name="list" Struts2直接将参数封装到list集合中
指定添加索引
list:<input type="text" name="list[1]"/>
封装Map
- Action类
public void setMap(Map<String, String> map) {
this.map = map;
}
public List<String> getList() {
return list;
}
@Override
public String execute() throws Exception {
System.out.println("list" + list);
System.out.println("map" + map);
return SUCCESS;
}
- 页面page
list:<input type="text" name="map['haha']"/>
扩展知识
StrutsMVC
StrutsMVCAction 生命周期
- 每次接收请求到来时,都会创建一个新的Action实例
- Action是线程安全的,可以使用成员变量接收参数
网友评论