## Struts2访问Servlet
1 概述:在Struts2中,Action并没有直接和Servlet API耦合,Action不能直接访问Servlet API。
尽管Action和Servlet的API的解耦会带来很多好处,但在实现业务逻辑时,还是要经常访问到Servlet中的对象。
2 ActionContext类:
(1)概述:Struts2提供ActionContext类来访问Servlet API。ActionContext类是Action执行的上下文对象,保存了
Action执行所需的所有对象,如parameters,request,session,application。
(2)ActionContext的生命周期和获取方式
<1>生命周期
每次接收请求到Action就会创建一个相应的ActionContext对象,请求处理完自动销毁ActionContext
<2>获取方式
ActionContext创建好后会和当前线程绑定,若要获取ActionContext对象只需从ThreadLocal中获取即可。
(3)ActionContext访问Servlet API的常用方法:
<1>void put(String key,Object value)
功能描述:将key-value放进ActionContext中,模拟Servlet API中的HttpServletRequest中的setAttribute()方法。
<2>Oject get(String key) 功能描述:通过参数key获取ActionContext中的value值
示例(获取request域):
Map<String,Object> requestScope = (Map<String, Object>) ActionContext.getContext().get("request");
<3>Map<String ,Object> getApplication() 功能描述: 返回一个Application级的Map对象
示例:
Map<String, Object> applicationScope = ActionContext.getContext().getApplication();
applicationScope.put("name","applicationTom");
<4>static ActionContext getContext() 功能描述:获取当前线程的ActionContext对象
示例:
ActionContext.getContext().put("name","requestTom");
<5>Map<String,Object> getParameters() 功能描述:返回一个包含所有HttpServletRequest信息的Map对象
<6>Map<String,Object> getSession() 功能描述:返回一个HttpSession级的Map对象
示例:
Map<String, Object> sessionScope = ActionContext.getContext().getSession();
sessionScope.put("name","sessionTom");
<7>void setApplication(Map<String,Object>) 功能描述:设置Application上下文
<8>void setSession(Map<String,Object>) 功能描述:设置Session
3 获取原生ServletAPI问题
获取原生的Servlet API方式一:
可使用stuts2提供的ServletActionContext类
代码示例:
//获取原生的request域
HttpServletRequest request = ServletActionContext.getRequest();
//获取原生的session
HttpSession session = request.getSession();
//获取原生的response域
HttpServletResponse response = ServletActionContext.getResponse();
//获取原生的ServletContext
ServletContext servletContext = ServletActionContext.getServletContext();
//获取原生的PageContext
PageContext pageContext=ServletActionContext.getPageContext();
获取原生的Servlet API方式二:
通过实现接口来获取 原生的 ServletAPI
代码示例:
public class Demo6Action extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware{
private HttpServletRequest request;
private HttpServletResponse response;
private ServletContext context;
public String execute()throws Exception{
System.out.println(request);
return SUCCESS;
}
//获取原生 request
@Override
public void setServletRequest(HttpServletRequest request) {
this.request=request;
}
//获取原生的 response
@Override
public void setServletResponse(HttpServletResponse response) {
this.response=response;
}
//获取原生的 ServletContext
@Override
public void setServletContext(ServletContext context) {
this.context=context;
}
}
5 获取原生的request域问题。
HttpServletRequest request = ServletActionContext.getRequest();
分析:
struts2不推荐使用原生的request域,若想达到原生的request域的效果,可直接把数据存到ActionContext容器中,
因为ActionContext的生命周期和原生的request一模一样。
值得一提的是:把值放到ActionContext中,但取的方法却是和原生的Request域一样,
使用 request.getParameter("name"),原因是在struts2的核心过滤器中StrutsPrepareAndExecuteFilter
已经把request域对象进行包装处理过了: request = prepare.wrapRequest(request);
## 结果页面配置
1 概述:在struts.xml使用<result>标签配置Result逻辑视图和物理视图之间的映射,<result>元素存在name,type常见属性,
但这两种属性都不是必选的。
name属性:指定逻辑视图名称,默认值为success.
type属性:指定返回视图资源的类型,默认值为dispatcher(请求转发),还包括的为redirect(重定向) ,
chain(转发到另一个Action,少用),redirectAction(重定向到另一个Action,常用)
2 结果页面配置
概述:在struts2的结果配置中,有两种方式,全局结果页面配置和局部结果页面配置。
(1)全局结果页面配置
全局结果页面是指在同一个包下配置Action中返回相同的字符串的值,都可以跳转到该页面。
示例:
<global-results>
<result name="success">/success.jsp</result>
</global-results>
(2)局部结果页面配置
局部结果页面是只针对某个Action,根据该字符串的值进行页面跳转。
示例:
<action name="Demo1Action"
class="cn.iesult.Demo1Action" method="execute">
<result name="success" type="dispatcher">/hello.jsp</result>
</action>
(3)结果页面配置扩展了解
一个结果类型resultType接口com.opensymphony.xwork2.Result的实现。
struts2把内置的<result-type>都放在 struts2-core-2.3.24.jar/struts-default.xml文件中
## Struts2的数据封装
1 概述:在实际开发中,Action会接收 页面提交的请求参数,并将数据封装到一个javaBean中,传递到业务层。
struts2封装数据的方式有两种:属性驱动(属性set方法) 和 模型驱动(表达式方式)。
2 属性驱动
(1)概述:直接在Action中定义各种Java基本数据类型的字段,使这些字段与表单数据相对应,并利用这些字段进行数据传递。
以前我们使用Serlvet只能在方法内获取参数的原因是:
一个web应用只能有一个Servlet,意味着该Servlet的成员变量都是唯一的。
但是因为Servelet是线程不安全的,当它的成员变量同时被几个请求访问时,就会出现被覆盖的情况。
所以我们使用Servlet接收参数只能在方法内用局部变量接收,不能像Action这样使用成员变量接收。
所以我们这里可以使用成员变量接收参数--也表明我们的Action是线程安全的
每次请求Action时都会创建新的Action实例对象。
(2)方式一:在Action内定义属性,通过提供属性set方法来完成。
示例:
<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 Demo8Action extends ActionSupport{
//接收姓名参数
private String name;
public void setName(String name) {this.name = name;}
//接收年龄参数--自动类型转,只能转换8大基本数据类型以及对应的包装类
private Integer age;
public void setBirthday(Date birthday) {this.birthday = birthday;}
//接收日期参数--struts2支持特定类型字符串(yy-MM-dd)转换为Date
private Date birthday;
public void setAge(Integer age) {this.age = age;}
public String execute()throws Exception{
System.out.println("参数name为:"+name+",参数age为:"+age+",birthday:"+birthday);
return SUCCESS;
}
public Demo8Action() {
super();
System.out.println("创建了一个新的Action对象");
}
}
缺点:数据过于多时,会使Action非常臃肿。
(3)方式二:把属性数据和对应的getter/setter方法抽取到一个javaBean类,Action直接使用javaBean即可。
此方式除了提供属性的set方法还要有get方法,get方法用于获取javaBean类中的属性。
同理,Action类中的javaBean对象也需要提供get/set方法。
示例:(注意此处jsp页面的name属性值与第一种方式的不同)
<form action="${pageContext.request.contextPath }/Demo10Action" method="POST">
用户名:<input type="text" name="user.username"/><br>
年龄:<input type="text" name="user.age"/><br>
生日:<input type="text" name="user.birthday"/><br>
<input type="submit" value="提交" />
</form>
public class User {
private String Username;
private Long age;
private Date birthday;
public String getUsername() {return Username; }
//提供getter/setter方法
public void setUsername(String username) {Username = username;}
public Long getAge() {return age;}
public void setAge(Long age) {this.age = age;}
public Date getBirthday() {return birthday;}
public void setBirthday(Date birthday) {this.birthday = birthday;}
@Override
public String toString() {
return "User [Username=" + Username + ", age=" + age + ", birthday=" + birthday + "]";
}
}
public class Demo9Action extends ActionSupport{
private User user;
//提供javaBean类的getter/setter方法
public User getUser() {return user;}
public void setUser(User user) {this.user = user;}
public String execute()throws Exception{
System.out.println(user);
return SUCCESS;
}
public Demo9Action() {
super();
System.out.println("创建了一个新的Action对象");
}
对比方式一的不同之处:
(1)方式二jsp页面的name属性格式为:user.name,user.age,user.birthday。
方式一的没有user前缀
(2)方式二的封装对象极其属性必须要提供getter/setter方法
方法一:只需提供属性的setter方法
3 模型驱动
(1)概述:
· 通过实现ModelDriven<>接口,复写getModel()方法直接获取Action数据模型对象(javaBean类型),
与属性驱动方式二都使用到javaBean对象,与之不同的是,
& 它不需提供javaBean对象的getter/setter方法。
& 它的jsp页面name属性没有user对象前缀。
开发我们优先使用模型驱动,若有多个数据模型对象则是用属性驱动的方式二获取数据。
(2)示例:
<form action="${pageContext.request.contextPath }/Demo10Action" method="POST">
用户名:<input type="text" name="username"/><br>
年龄:<input type="text" name="age"/><br>
生日:<input type="text" name="birthday"/><br>
<input type="submit" value="提交" />
</form>
public class Demo10Action extends ActionSupport implements ModelDriven<User>{
//复写接口ModelDriven<User>的方法
@Override
public User getModel() {
return user;
}
private User user=new User();
public String execute()throws Exception{
System.out.println(user+"10----");
return SUCCESS;
}
public Demo10Action() {
super();
System.out.println("创建了一个新的Action对象");
}
}
4 struts2对集合对象的数据模型封装
(1)概述:在开发中,我们需要批量插入用户或其他对象。Action中可能会接受多个其他的Action封装的对象,
这时候我们需将表单数据封装到集合中。我们一般使用的集合为List或Map
(2)表单数据封装到List集合中示例:
<form action="${pageContext.request.contextPath }/Demo11Action" method="POST">
list:<input type="text" name="list"/><br>
list:<input type="text" name="list[1]"/><br>
list:<input type="text" name="list[3]"/><br>
<input type="submit" value="提交" />
</form>
public class Demo11Action extends ActionSupport{
private List<String>list;
public List<String> getList() {return list;}
public void setList(List<String> list) {this.list = list;}
public String execute()throws Exception{
System.out.println("list:"+list);
return SUCCESS;
}
}
(3)表单数据封装到Map集合中示例:
<form action="${pageContext.request.contextPath }/Demo11Action" method="POST">
map:<input type="text" name="map['key1']"/><br/>
map:<input type="text" name="map['key2']"/>
<input type="submit" value="提交" />
</form>
public class Demo11Action extends ActionSupport{
private Map<String,String>map;
public Map<String, String> getMap() {return map;}
public void setMap(Map<String, String> map) {this.map = map;}
public String execute()throws Exception{
System.out.println(map);
return SUCCESS;
}
}
转载于:https://blog.51cto.com/14008076/2310434