由于我们使用Struts2代替了表现层的Servlet,同样我们也需要学习如果通过Struts2获取页面传来的数据,或者如何向页面传数据,同时还要学习如何转发或者重定向到一个逻辑页面(jsp或者action类)。
在Servlet时,我们是通过域对象向页面传数据,这些域对象都是Servlet为我们提供好的,在Struts2中也有这些域对象,但是需我们自己去创建或者访问,Struts2有三种方式可以去访问Serlvet的API。
访问Servlet的API的三种方式 实现接口的方式 package com.wzm.action; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.util.ServletContextAware; import com.opensymphony.xwork2.ActionSupport; /* * 使用ServletAPI的第一种方法,可以通过实现Struts提供的接口 * ServletRequestAware,ServletResponseAware,ServletContextAware * 通过实现接口,会为我们提供ServletContext,HttpServletResponse,HttpServletRequest * 我们需要定义全局变量来接这些对象,这样我们就可以在其他方法种使用这些对象 */ public class ActionDemo1 extends ActionSupport implements ServletRequestAware,ServletResponseAware,ServletContextAware{ //定义全局变量 private ServletContext servletContext; private HttpServletResponse response; private HttpServletRequest request; //ececute方法,在里边使用域对象 @Override public String execute() throws Exception { //获取页面传来的值 Map<String, String[]> map = request.getParameterMap(); //遍历输出 for (String key : map.keySet()) { System.out.println(key+":"+map.get(key)); } //往域对象中存值,操作方式与servlet时一样 servletContext.setAttribute("msg1", "实现接口方法,servletContext"); request.getSession().setAttribute("msg2", "实现接口方法,session"); return "success"; } //Struts2提供的ServletContext,赋值给全局变量 public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } //Struts2提供的HttpServletResponse,赋值给全局变量 public void setServletResponse(HttpServletResponse response) { this.response = response; } //Struts2提供的HttpServletRequest,赋值给全局变量 public void setServletRequest(HttpServletRequest request) { this.request = request; } } 使用ActionContext的方式 package com.wzm.action; import java.util.Arrays; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.util.ServletContextAware; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; /* * 通过使用ActionContext来访问ServletAPI, * 但是只能控制底层的Map对象,不能使用域对象的一些方法 */ public class ActionDemo2 extends ActionSupport { @Override public String execute() throws Exception { //获取actionCotext对象,该对象有点类似于request ActionContext actionContext = ActionContext.getContext(); //通过actionContext获取servletContext Map<String, Object> servletContext = actionContext.getApplication(); //通过actionContext获取session Map<String, Object> session = actionContext.getSession(); //获取页面传来的值 Map<String, Object> map = actionContext.getParameters(); //遍历输出 for (String key : map.keySet()) { System.out.println(key+":"+Arrays.toString((String[])map.get(key))); } //往域中存值,注意是直接操作map servletContext.put("msg1", "ActionContext方法,servletContext"); session.put("msg2", "ActionContext方法,session"); return "success"; } } 使用ServletActionContext的方式(常用) package com.wzm.action; import java.util.Arrays; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import org.apache.struts2.interceptor.ServletRequestAware; import org.apache.struts2.interceptor.ServletResponseAware; import org.apache.struts2.util.ServletContextAware; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; /* * 通过使用ServletActionContext来访问ServletAPI, * 可以使用域对象的方法API * 这种方法比较建议使用 */ public class ActionDemo3 extends ActionSupport { @Override public String execute() throws Exception { //通过ServletActionContext获取request HttpServletRequest request = ServletActionContext.getRequest(); //通过ServletActionContext获取servletContext ServletContext servletContext = ServletActionContext.getServletContext(); //通过request获取session HttpSession session = request.getSession(); //获取页面传来的值 Map<String, String[]> map = request.getParameterMap(); //遍历输出 for (String key : map.keySet()) { System.out.println(key+":"+Arrays.toString(map.get(key))); } //往域中存值,操作与servlet的类似 servletContext.setAttribute("msg1", "ServletActionContext方法,servletContext"); session.setAttribute("msg2", "ServletActionContext方法,session"); return "success"; } }在web开发中,当服务端接受到一个请求,会根据业务的不同来处理这请求,有时是转发请求,有时就是重定向,在Struts2中,这些操作是通过result标签的type属性来实现的。
type的常见使用 <!-- result标签中的type属性介绍 --> <package name="test4" extends="struts-default" namespace="/"> <action name="demo" class="com.wzm.action.ActionDemo"> <!-- dispatcher:这表示转发到jsp页面,默认不写就是这个类型 --> <result name="add" type="dispatcher">/result.jsp</result> <!-- chain:这表示转发到一个action,注意这里不需要有斜杆 --> <result name="delete" type="chain">demo1</result> <!-- redirect:表示重定向到jsp页面 --> <result name="update" type="redirect">/result.jsp</result> <!-- redirectAction:表示重定向到一个action中,注意不用斜杆 --> <result name="find" type="redirectAction">demo1</result> </action> </package>在Servlet时,我们需要自己手动的去一个个封装页面传来的数据,有时候数据多了就会变得比较繁琐,在Struts2中为我们提供了两种不同的封装方式:属性封装和模型封装。
属性驱动的封装 import java.util.List; import com.opensymphony.xwork2.ActionSupport; import com.wzm.entity.User; public class ActionDemo4 extends ActionSupport { /* * 在servlet时期,如果我们要封装页面传来的属性的话,我们需要通过request获取参数,然后使用beanutils封装 * 在Struts2,封装数据不再需要我们自己封装,struts2会帮我们封装,有两种方式封装,一种为属性封装,一种为模型封装 * 属性封装又分为三种,封装基本类型和String类型,封装对象类型,封装复杂类型list.map等 */ //第一种方式就是通过定义属性和属性的getter和setter方式来封装 //struts2会通过对比表单的name和属性名来进行封装 //定义属性,注意属性名要与页面表单中的name相对应 private String username; private Integer age; //定义setter方法,对于基本类型、包装类和String类型的封装,只需要有setter方法 public void setUsername(String username) { this.username = username; } public void setAge(Integer age) { this.age = age; } public String attr() throws Exception { System.out.println(username+":"+age); return null; } //第二种直接将参数封装到一个对象中,首先要有要封装的对象的类 //定义一个对象成员变量,注意名字要与表单的一致,对象内的属性名也要与表单的一致 private User user; //定义user的getter和setter方式,封装对象的话,getter也要定义出来 public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String obj() throws Exception { System.out.println(user.getUsername()+":"+user.getAge()); return null; } //第三种直接将参数封装到一个复杂对象中 //定义一个对象成员变量,注意名字要与表单的一致,对象内的属性名也要与表单的一致 private List<User> list; //定义list的getter和setter方式,封装复杂对象的话,getter也要定义出来 public List<User> getList() { return list; } public void setList(List<User> list) { this.list = list; } public String complex() throws Exception { System.out.println(list.get(0).getUsername()+":"+list.get(0).getAge()); return null; } } 模型驱动的封装 package com.wzm.action; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; import com.wzm.entity.User; /* * 在servlet时期,如果我们要封装页面传来的属性的话,我们需要通过request获取参数,然后使用beanutils封装 * 在Struts2,封装数据不再需要我们自己封装,struts2会帮我们封装,有两种方式封装,一种为属性封装,一种为模型封装 * 模型封装需要实现一个模型驱动接口ModelDriven<T>,泛型要写自己想要封装进去的对象 */ public class ActionDemo5 extends ActionSupport implements ModelDriven<User>{ //实现接口会让我们实现一个getModel()方法,返回值就我们要封装的对象 //如果要使用模型驱动封装,我们就要自己实例化出要的封装的对象 User user = new User(); public User getModel() { //这里的方法要返回自己定义的对象 return user; } @Override public String execute() throws Exception { System.out.println(user.getUsername()+":"+user.getAge()); return null; } } form表单和Struts.xml的编写示例 form表单: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> 使用属性封装基本类型和String类型<br> <form action="${pageContext.request.contextPath }/demo4_attr"> 姓名:<input type="text" name="username"><br> 年龄:<input type="text" name="age"><br> <input type="submit" value="提交"><br> </form> <!-- 如果封装的是一个对象,那么这里name就需要为 对象属性名.对象中的成员变量名 对象属性名与action类中定义的对象属性名相同 --> 使用属性封装对象类型<br> <form action="${pageContext.request.contextPath }/demo4_obj"> 姓名:<input type="text" name="user.username"><br> 年龄:<input type="text" name="user.age"><br> <input type="submit" value="提交"><br> </form> <!-- 如果封装的是一个复杂类型,那么这里name就需要为 list[下标].list中的对象内的属性名,如list存储User对象, list[0]代表第一个user对象,list[0].username代表user的username属性 复杂对象的属性名与action类中定义的对象属性名相同 --> 使用属性封装复杂对象类型<br> <form action="${pageContext.request.contextPath }/demo4_complex"> 姓名:<input type="text" name="list[0].username"><br> 年龄:<input type="text" name="list[0].age"><br> <input type="submit" value="提交"><br> </form> <!-- 使用模型封装的话,这里的name的写法就普通写法 --> 使用模型封装参数<br> <form action="${pageContext.request.contextPath }/demo5"> 姓名:<input type="text" name="username"><br> 年龄:<input type="text" name="age"><br> <input type="submit" value="提交"><br> </form> </body> </html>struts.xml:
<!-- 封装页面传来的参数的方法: 第一种是属性引擎,也就是属性封装 第二种是模型引擎,也就是模型封装 --> <package name="test5" extends="struts-default" namespace="/"> <!-- 属性引擎,也就是属性封装 --> <action name="demo4_*" class="com.wzm.action.ActionDemo4" method="{1}"> <!-- 没有逻辑页面,返回值null --> </action> <!-- 模型引擎,也就是模型封装 --> <action name="demo5" class="com.wzm.action.ActionDemo5"> <!-- 没有逻辑页面,返回值null --> </action> </package>