1.结果页面配置
1.1 全局结果页面配置
result
标签中配置 action 方法的返回值到不同的路径中,如果 action
方法的返回值相同,并且到达的路径也相同,就可以使用全局结果页面配置,只需要在 package
标签中加上 global-results
标签,action
标签中就可以省略 result
标签了,这样达到代码的简化。
示例码代如下:
<global-results>
<result name="相同的返回值">相同的到达路径</result>
</global-results>
<action name="action1" class="cc.wenshixin.action.ActionDemo1">
</action>
<action name="action2" class="cc.wenshixin.action.ActionDemo2">
</action>
1.2 局部结果页面配置
如果在配置文件中,既设置了全局结果页面配置,又设置了局部结果页面配置,那么局部结果页面配置会覆盖全局结果页面配置。
1.3 result 标签的 type 属性
result
标签中除了 name
属性外,还有 type
属性,type
属性用来设置路径的跳转方式,是重定向还是转发操作,并且又分为页面的跳转和 action 的跳转。
- 针对页面的跳转
dispatcher:默认值,做转发操作。
redirect:重定向。
示例代码如下:
<package name="demo1" extends="struts-default" namespace="/">
<action name="action1" class="cc.wenshixin.action.ActionDemo1">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="action2" class="cc.wenshixin.action.ActionDemo2">
<result name="success" type="redirect">/success.jsp</result>
</action>
</package>
- 针对 action 的跳转
chain:转发到另一个 action,一般不使用这种方式,因为有浏览器缓冲的问题。
redirectAction:重定向到另一个 action,在result
标签中直接写另一个action
标签的name
属性值。
示例代码如下:
<package name="demo1" extends="struts-default" namespace="/">
<action name="action1" class="cc.wenshixin.action.ActionDemo1">
<result name="success" type="dispatcher">/success.jsp</result>
</action>
<action name="action2" class="cc.wenshixin.action.ActionDemo2">
<result name="success" type="redirectAction">action1</result>
</action>
</package>
2.struts2 访问 JSP 的 API
struts 中的 action 类就相当于是普通java web 项目中 servlet类,servlet 中要用到request和response等方法,而action 中也提供了可以访问这些方法的API,也可以访问到JSP的内置对象。
2.1 使用 ActionContext 类获取
方法 | 功能 |
---|---|
void put(String key,Object value) | 将键值对放到 ActionContext对象中,对应Servlet中的HttpServletRequest的setAttribute()方法 |
Object get(String key) | 通过参数key来获取ActionContext对象中的值 |
Map<String,Object> getApplication() | 返回一个Application中的Map对象 |
static ActionContext getContext() | 获取当前线程的ActionContext 对象,也即是创建对象,这里对象不是new出来的 |
Map<String,Object> getParameters() | 返回一个包含所有HttpServletRequest参数信息的Map对象 |
Map<String,Object> getSession() | 返回一个Map类型的HttpSession对象 |
void setApplication(Map<String,Object> application) | 设置Application的上下文 |
void setSesstion(Map<String,Object> session) | 设置一个Map类型的Session值 |
这种方式是 struts2 推荐的获取 jsp 页面对象的方式,耦合性(jsp页面和action的关系)很低,action中不需要知道jsp页面中表单具体的name属性值就能最终获取到输入的值。
示例代码:
jsp页面
<form action="${pageContext.request.contextPath}/action1.action" method="post">
姓名:<input type="text" name="name"><br>
班级:<input type="text" name="class"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交">
</form>
action类
package cc.wenshixin.action;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class ActionContextDemo extends ActionSupport{
@Override
public String execute() throws Exception {
//1.获取ActionContext对象
ActionContext context = ActionContext.getContext();
//2.调用方法得到表单的数据,key是表单输入项的name属性值,value是输入的值
Map<String, Object> map = context.getParameters();
Set<String> keys = map.keySet();
for (String key : keys) {
//value的值可能不止一个,因为输入项可能存在复选框
Object[] obj = (Object[])map.get(key);
System.out.println(Arrays.toString(obj));
}
return NONE;
}
}
struts配置
<package name="demo1" extends="struts-default" namespace="/">
<action name="action1" class="cc.wenshixin.action.ActionContextDemo">
<!-- 因为没有返回值,所以不需要result标签 -->
</action>
</package>
2.2 使用 ServletActionContext 类获取
这种方式是通过ServletActionContext类的静态方法获取web应用的HttpServletRequest对象,HttpServletResponse对象,ServletContext对象,PageContext对象实现的。这种方式就像是写servlet一样,经常使用这种方式。
方法 | 功能 |
---|---|
static HttpServletRequest getRequest() | 获取web应用的HttpServletRequest对象 |
static HttpServletResponse getResponse() | 获取web应用的HttpServletResponse对象 |
static ServletContext getServletContext() | 获取web应用的ServletContext对象 |
static PageContext getPageContext() | 获取web应用的PageContext对象 |
示例代码如下:
jsp页面同上面一样,注意把表单提交的路径换一下。
action 类
package cc.wenshixin.action;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class ServletActionContextDemo extends ActionSupport{
@Override
public String execute() throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
String name = request.getParameter("name");
String banji = request.getParameter("class");
String age = request.getParameter("age");
System.out.println("姓名:"+name+",班级:"+banji+",年龄:"+age);
return NONE;
}
}
struts配置
<action name="action2" class="cc.wenshixin.action.ServletActionContextDemo">
<!-- 因为没有返回值,所以不需要result标签 -->
</action>
2.3 使用接口注入方式获取
struts中提供了一系列的接口,只需让action实现接口,就可获取servle中的对象。
接口名 | 功能 |
---|---|
ServletRequestAware | 实现该接口的Action类可访问Web应用的HttpservletRequest对象 |
ServletResponseAware | 实现该接口的Action类可访问Web应用的HttpServletResponse对象 |
SessionAware | 实现该接口的Action类可访问Web应用的HttpSession对象 |
ServletContextAware | 实现该接口的Action类可访问Web应用的ServletContext对象 |
示例代码如下:
jsp页面同上面一样,注意把表单提交的路径换一下。
action 类
package cc.wenshixin.action;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionSupport;
public class ActionWithAware extends ActionSupport implements ServletRequestAware{
private HttpServletRequest request;
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public String execute() throws Exception {
String name = request.getParameter("name");
String banji = request.getParameter("class");
String age = request.getParameter("age");
System.out.println("姓名:"+name+",班级:"+banji+",年龄:"+age);
return NONE;
}
}
struts配置
<action name="action3" class="cc.wenshixin.action.ActionWithAware">
<!-- 因为没有返回值,所以不需要result标签 -->
</action>
3.封装表单数据
在servlet中,如果想把表单中的数据封装到一个对象里面,通常的做法是先获取页面表单的值,在new一个对象,设置这个对象的属性。相比这种原始的封装方式,struts2 提供了把表单数据封装到对象中更简单的方法。
3.1 属性封装
直接把表单提交的数据封装到 Action 类的属性中。
对 Action 类的要求:
- 在 Action 类定义和表单name属性值一样的数据成员
- 生成数据成员对应的 set 方法(建议把 set方法和get方法都写出来)
示例代码如下:
jsp页面
<form action="${pageContext.request.contextPath}/action1.action" method="post">
姓名:<input type="text" name="name"><br>
班级:<input type="text" name="banji"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交">
</form>
Action 类
package cc.wenshixin.action;
import com.opensymphony.xwork2.ActionSupport;
public class ActionDemo1 extends ActionSupport{
private String name; //表单中的姓名
private String banji; //表单中的班级
private int age; //表单中的年龄
public void setName(String name) {
this.name = name;
}
public void setBanji(String banji) {
this.banji = banji;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String execute() throws Exception {
System.out.println("姓名:"+name+",班级:"+banji+",年龄:"+age);
return NONE;
}
}
struts配置
<package name="demo1" extends="struts-default" namespace="/">
<action name="action1" class="cc.wenshixin.action.ActionDemo1">
<!-- 因为没有返回值,所以不需要result标签 -->
</action>
</package>
从上面的代码中,我们会发现,如果表单的数据项很多,那么在Action的属性也会很多,再加上set方法,Action类就会变得非常臃肿,下面的表达式封装方式就可以有效的解决这个问题。
3.2 模型驱动封装
使用模型驱动封装,也可以把表单数据封装到实体类对象中,这种实现方式是通过实现模型驱动接口 ModelDriven 来实现的。
实现步骤:
- 编写实体类的代码,并生成属性的 set 和 get 方法。
- 在 Action 类中使用实体类new一个实体类的对象,并实现接口 ModelDriven 的 getModel() 方法。
- 页面中表单的输入项的nam属性值要和实体类的属性一一对应。
示例代码如下:
jsp页面
<form action="${pageContext.request.contextPath}/action2.action" method="post">
姓名:<input type="text" name="name"><br>
班级:<input type="text" name="banji"><br>
年龄:<input type="text" name="age"><br>
<input type="submit" value="提交">
实体类
package cc.wenshixin.entity;
public class Student {
private String name; // 学生姓名
private String banji; // 学生所在班级
private int age; // 学生年龄
//这里get和set方法省略了
//为了方便打印实体类中的属性值,重写了该类的toString()方法
@Override
public String toString() {
return "Student [name=" + name + ", banji=" + banji + ", age=" + age + "]";
}
}
Action 类
package cc.wenshixin.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import cc.wenshixin.entity.Student;
public class ActionDemo2 extends ActionSupport implements ModelDriven<Student>{
private Student student = new Student();
@Override
public Student getModel() {
//返回创建的student对象
return student;
}
@Override
public String execute() throws Exception {
System.out.println(student);
return NONE;
}
}
struts配置
<action name="action2" class="cc.wenshixin.action.ActionDemo2">
<!-- 因为没有返回值,所以不需要result标签 -->
</action>
3.3 表达式封装
使用表达式封装可以把表单数据封装到实体类对象里面,表达式封装其实也是属性封装的一种方式,这里是单独列出了。
实现步骤:
- 编写实体类的代码,并生成属性的 set 和 get 方法。
- 在 Action 类中使用实体类声明实体类的变量。
- 在表单输入项的
name
属性值中写成实体类变量名.属性
的表达式形式。
- 在表单输入项的
示例代码如下:
jsp页面
<form action="${pageContext.request.contextPath}/action3.action" method="post">
姓名:<input type="text" name="student.name"><br>
班级:<input type="text" name="student.banji"><br>
年龄:<input type="text" name="student.age"><br>
<input type="submit" value="提交">
</form>
实体类同模型驱动封装方式的一样
Action 类
package cc.wenshixin.action;
import com.opensymphony.xwork2.ActionSupport;
import cc.wenshixin.entity.Student;
public class ActionDemo3 extends ActionSupport {
private Student student; // 表单中的学生信息
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
@Override
public String execute() throws Exception {
System.out.println(student);
return NONE;
}
}
struts配置
<action name="action3" class="cc.wenshixin.action.ActionDemo3">
<!-- 因为没有返回值,所以不需要result标签 -->
</action>
3.3 模型驱动封装和表达式封装的比较
相同点:
都可以把数据封装到实体类对象中
不同点:
使用模型驱动只能把数据封装到一个实体类对象中,也即是在一个 Action 类中不能使用模型驱动把数据封装到不同的实体类对象中,因为在 Action 类实现接口的泛型只能是一个实体类的,而使用表达式封装可以把表单中的数据封装到不同的实体类的对象中。
4.封装数据到集合
在开发中,有时候需要批量添加插入对象,这时就需要把这些数据封装到集合中,一般使用的集合是 List 集合和 Map 集合。
4.1 封装数据到 List 集合
实现步骤:
- 编写实体类,并生成属性的 set 和 get 方法。
- 在 Action 类中声明实体类的 List 集合,并生成 list 变量的 set 和 get 方法
- 在页面中,使用 List 集合表达式
示例代码如下:
jsp页面
<form action="${pageContext.request.contextPath}/action4.action" method="post">
姓名:<input type="text" name="list[0].name"><br>
班级:<input type="text" name="list[0].banji"><br>
年龄:<input type="text" name="list[0].age"><br>
<br>
姓名:<input type="text" name="list[1].name"><br>
班级:<input type="text" name="list[1].banji"><br>
年龄:<input type="text" name="list[1].age"><br>
<input type="submit" value="提交">
</form>
实体类和上面一样
Action 类
package cc.wenshixin.action;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import cc.wenshixin.entity.Student;
public class ActionDemo4 extends ActionSupport {
List<Student> list;
public List<Student> getList() {
return list;
}
public void setList(List<Student> list) {
this.list = list;
}
@Override
public String execute() throws Exception {
for (Student student : list) {
System.out.println(student);
}
return NONE;
}
}
struts配置
<action name="action4" class="cc.wenshixin.action.ActionDemo4">
<!-- 因为没有返回值,所以不需要result标签 -->
</action>
4.2 封装数据到 Map 集合
实现步骤:
- 编写实体类,并生成属性的 set 和 get 方法。
- 在 Action 类中声明实体类的 Map 集合,并生成 map 变量的 set 和 get 方法
- 在页面中,使用 map 集合表达式
示例代码如下:
jsp页面
<form action="${pageContext.request.contextPath}/action5.action" method="post">
姓名:<input type="text" name="map['one'].name"><br>
班级:<input type="text" name="map['one'].banji"><br>
年龄:<input type="text" name="map['one'].age"><br>
<br>
姓名:<input type="text" name="map['two'].name"><br>
班级:<input type="text" name="map['two'].banji"><br>
年龄:<input type="text" name="map['two'].age"><br>
<input type="submit" value="提交">
</form>
实体类同上面一样
Action 类
package cc.wenshixin.action;
import java.util.Map;
import com.opensymphony.xwork2.ActionSupport;
import cc.wenshixin.entity.Student;
public class ActionDemo5 extends ActionSupport {
Map<String, Student> map;
public Map<String, Student> getMap() {
return map;
}
public void setMap(Map<String, Student> map) {
this.map = map;
}
@Override
public String execute() throws Exception {
for(String key : map.keySet())
{
Student student = map.get(key);
System.out.println(student);
}
return NONE;
}
}
struts 配置
<action name="action5" class="cc.wenshixin.action.ActionDemo5">
<!-- 因为没有返回值,所以不需要result标签 -->
</action>