1.2 知识点 1.2.1 Struts2的Servlet的API的访问 1.2.1.1 方式一 : 通过ActionContext实现 页面: <h1>Servlet的API的访问方式一:解耦合的方式</h1> <form action="${ pageContext.request.contextPath }/requestDemo1.action" method="post"> 姓名:<input type="text" name="name"/><br/> 年龄:<input type="text" name="age"><br/> <input type="submit" value="提交"> </form> 编写Action /** * Servlet的API的访问方式一:解耦合的方式 * * 只能用于接收参数 和 操作域中的数据 * @author jt */ public class RequestDemo1Action extends ActionSupport{ @Override public String execute() throws Exception { // 接收数据: /** * 在ActionContext中提供了一些方法:操作域对象的数据 * * Map<String,Object> getParameters(); * * Map<String,Object> getSession(); * * Map<String,Object> getApplication(); */ // 接收参数: ActionContext actionContext = ActionContext.getContext(); Map<String,Object> map = actionContext.getParameters(); for (String key : map.keySet()) { String[] arrs = (String[]) map.get(key); System.out.println(key+" "+Arrays.toString(arrs)); } // 向request域中存值: actionContext.put("reqName", "req如花"); // 向session域中存值: actionContext.getSession().put("sessName", "sess凤姐"); // 向application域中存值: actionContext.getApplication().put("appName","app石榴"); return SUCCESS; } } 1.2.1.2 方式二: 实现特定接口的方式实现: 在struts中提供了一些接口 : ServletRequestAware,ServletResponseAware,ServletContextAware; 页面: <h1>Servlet的API的访问方式二:实现特定接口的方式</h1> <form action="${ pageContext.request.contextPath }/requestDemo2.action" method="post"> 姓名:<input type="text" name="name"/><br/> 年龄:<input type="text" name="age"><br/> <input type="submit" value="提交"> </form> 编写Action: /** * Servlet的API的访问方式二: * @author jt * */ public class RequestDemo2Action extends ActionSupport implements ServletRequestAware,ServletContextAware{ private HttpServletRequest request; private ServletContext application; @Override public String execute() throws Exception { // 接收数据:使用request对象。 Map<String, String[]> parameterMap = request.getParameterMap(); for (String key : parameterMap.keySet()) { String[] arrs = parameterMap.get(key); System.out.println(key+" "+Arrays.toString(arrs)); } // 向域中保存数据; // 向request域中保存数据 request.setAttribute("reqName", "r郝三"); // 向session域中保存数据 request.getSession().setAttribute("sessName", "s李四"); // 向application域中保存数据 application.setAttribute("appName", "a王五"); return NONE; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } @Override public void setServletContext(ServletContext application) { this.application = application; } } 1.2.1.3方式 : 通过ServletActionContext对象的静态方法实现 : 页面: <h1>Servlet的API的访问方式三:通过ServletActionContext对象静态方法获取</h1> <form action="${ pageContext.request.contextPath }/requestDemo3.action" method="post"> 姓名:<input type="text" name="name"/><br/> 年龄:<input type="text" name="age"><br/> <input type="submit" value="提交"> </form> 编写Action: /** * Servlet的API访问方式三:通过ServletActionContext的静态方法访问 * @author jt * */ public class RequestDemo3Action extends ActionSupport { public String execute() throws Exception { //接收参数: /* ServletActionContext 在struts2的API中的 : HttpServletRequest getRequest(); HttpServletResponse getResponse(); ServletContext getServletContext(); */ HttpServletRequest request = ServletActionContext.getRequest(); Map<String,String[]> parameterMap = request.getParameterMap(); for(String key : parameterMap.get()) { String[] value = parameterMap.get(Key); System.out.println(key + " " + Arrays.toString(value)); } //向域中存值 : request.setAttribute("reqName" , "用request向域中存数据"); request.getSession.setAttribute("session","向session域中存数据"); ServletActionContext.getServletContext().setAttribute("ServletContext","向ServletContext域中存储数据"); return super.execute(); } } 1.2.2.1 :结果页面的分类 : 全局结果页面 : 针对一个包下所有的action都生效的一个页面. <!--全局结果页面--> <global-results> <result>/jsp/1.jsp</result> </global-results> 局部结果页面 : 针对某一个action生效的一个页面 : <action name="requestDemo1" class="com.baidu.struts2.demo1.ActionDemo1"> <result>/jsp/1.jsp</result> </action> 1.2.2.2 配置结果页面 : <result>标签配置: name : 逻辑视图的名称.默认值是success. type : dispatcher : 默认值,转发.(转发到jsp的页面) redirect : 重定向.(重定向到JSP的页面),被跳转的页面中丢失传递的信息. chain : 转发到另一个Action. redirectAction : 重定向到另一个Action.跳转的页面中丢失传递的信息 stream : 文件的下载 1.2.2.3 Struts2的多例性 : 原来的Servlet是单例存在,多次请求,请求都是同一个Servlet的实例.Struts2中Action是多实例的.有异常请求就会有一个Action的实例. 现在可以在Action中定义成员属性了. 大部分我们会优先使用模型驱动的方式,因为Struts2内部有很多结果是围绕模型驱动设计的。但如果页面向多个对象中封装,那么就需要使用属性驱动的方式二了。 这些都是像某个对象中封装数据, 1.2.3 Struts2的数据封装 : 1.2.3.1 Struts2中的数据封装-属性驱动 : 提供对应属性的set方法的方式 : 页面: <h3>数据封装的方式一:提供属性的set方法的方式</h3> <form action="${ pageContext.request.contextPath }/employee1Action.action" method="post"> 姓名:<input type="text" name="name"/><br/> 年龄:<input type="text" name="age"/><br/> 性别:<input type="text" name="sex"/><br/> 工资:<input type="text" name="salary"/><br/> <input type="submit" value="提交"/> </form> 编写Action: /** * 数据封装的方式一:提供set方法的方式 * @author jt * */ public class Employee1Action extends ActionSupport{ private String name; private Integer age; private String sex; private Double salary; public void setName(String name) { this.name = name; } public void setAge(Integer age) { this.age = age; } public void setSex(String sex) { this.sex = sex; } public void setSalary(Double salary) { this.salary = salary; } @Override public String execute() throws Exception { System.out.println("员工姓名:"+name); System.out.println("员工年龄:"+age); System.out.println("员工性别:"+sex); System.out.println("员工工资:"+salary); // 手动封装数据: Employee employee = new Employee(); employee.setName(name); employee.setAge(age); employee.setSex(sex); employee.setSalary(salary); return NONE; } } 这种方式不是特别常用,因为需要手动封装数据,而且如果属性很多,提供很多的set方法,导致Action类易读性变差 页面中提供表达式的方式: 页面: <h3>数据封装的方式二:页面提供OGNL表达式的写法</h3> <form action="${ pageContext.request.contextPath }/employee2Action.action" method="post"> 姓名:<input type="text" name="employee.name"/><br/> 年龄:<input type="text" name="employee.age"/><br/> 性别:<input type="text" name="employee.sex"/><br/> 工资:<input type="text" name="employee.salary"/><br/> <input type="submit" value="提交"/> </form> 编写Action: /** * 数据封装的方式二:页面提供表达式的方式 * @author jt * */ public class Employee2Action extends ActionSupport{ // 提供成员的属性employee,必须提供属性的get和set方法 private Employee employee; public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } @Override public String execute() throws Exception { System.out.println(employee); return NONE; } } 1.2.3.2 Struts2 中的数据封装-模型驱动 : 采用模型驱动完成数据封装(推荐) 页面: <h3>数据封装的方式三:采用模型驱动的方式</h3> <form action="${ pageContext.request.contextPath }/employee3Action.action" method="post"> 姓名:<input type="text" name="name"/><br/> 年龄:<input type="text" name="age"/><br/> 性别:<input type="text" name="sex"/><br/> 工资:<input type="text" name="salary"/><br/> <input type="submit" value="提交"/> </form> 编写Action: /** * 数据封装的方式三:采用模型驱动的方式 * @author jt * */ public class Employee3Action extends ActionSupport implements ModelDriven<Employee>{ // 模型驱动使用的对象:必须手动构建对象的实例。 private Employee employee = new Employee(); @Override public Employee getModel() { return employee; } @Override public String execute() throws Exception { System.out.println(employee); return NONE; } } ***** 模型驱动只能向一个实体中封装数据,如果需要向多个实体封装数据优先采用第二种方式。 1.2.4 Struts2 的复杂数据的封装 : 1.2.4.1 封装到List集合 : 页面: <form action="${ pageContext.request.contextPath }/product1Action.action" method="post"> 商品名称:<input type="text" name="list[0].name"/><br/> 商品价格:<input type="text" name="list[0].price"/><br/> 商品名称:<input type="text" name="list[1].name"/><br/> 商品价格:<input type="text" name="list[1].price"/><br/> 商品名称:<input type="text" name="list[2].name"/><br/> 商品价格:<input type="text" name="list[2].price"/><br/> <input type="submit" value="批量导入"/> </form> Action: /** * 封装复杂的数据到List集合中。 * @author jt * */ public class Product1Action extends ActionSupport{ private List<Product> list; public List<Product> getList() { return list; } public void setList(List<Product> list) { this.list = list; } @Override public String execute() throws Exception { for (Product product : list) { System.out.println(product); } return NONE; } } 1.2.4.2 封装到Map集合 页面: <h1>批量插入商品:封装到Map集合</h1> <form action="${ pageContext.request.contextPath }/product2Action.action" method="post"> 商品名称:<input type="text" name="map['one'].name"/><br/> 商品价格:<input type="text" name="map['one'].price"/><br/> 商品名称:<input type="text" name="map['two'].name"/><br/> 商品价格:<input type="text" name="map['two'].price"/><br/> 商品名称:<input type="text" name="map['three'].name"/><br/> 商品价格:<input type="text" name="map['three'].price"/><br/> <input type="submit" value="批量导入"/> </form> Action: /** * 复杂类型数据封装:封装到Map集合 * @author jt * */ public class Product2Action extends ActionSupport { private Map<String,Product> map; public Map<String, Product> getMap() { return map; } public void setMap(Map<String, Product> map) { this.map = map; } @Override public String execute() throws Exception { for (String key : map.keySet()) { Product product = map.get(key); System.out.println(key+" "+product); } return NONE; } } 随堂笔记 : 1 strtus2对servlet API的访问 1 使用ServletActionContext类的静态方法(重要) 2 使用ActionContext对象的方法(理解)往域中存储数据,到页面展示(ps:这个对象获取不到域对象,只能操作域中的数据) 静态方法getContext()获取ActionContext对象 特点: 只能接受页面的数据,以及对域中数据的进行操作 获取不response对象做不了响应,也获取不到域对象 使用ActionContext对象的方法(理解) // getContext() --获取ActionContext对象 // Map<String,Object> ----- getParameters() 获取页面的所有数据 // Map<String,Object> ------getSession() 获取session域中的数据 // Map<String,Object> -------getApplication() 获取servletContext域中的数据 3 实现特定的接口来获取的方法(了解) 证明Action是单实例还是多实例? servlet是单实例 成员属性有线程危机 Action是多实例 成员属性没有线程危机 2 结果页面的逻辑视图配置 分类: 全局配置 针对一个包下所有的action都生效的一个页面 局部配置 针对某一个action生效的一个页面 注意:如果全局配置和局部配置都配置了,局部配置的优先级大于全局配置 result标签: 对返回的逻辑视图进行匹配 name: 逻辑视图的名称。默认值是success。 type: dispatcher 默认 请求转发(用于转发到jsp页面) redirect 重定向(用于重定向到jsp页面) chain 请求转发(用于转发到action) redirectAction 重定向(用于重定向到action) stream 用于下载的(CRM3天案例) 3 struts2对页面数据的封装(模型驱动,属性驱动) 1 属性驱动---set属性方式(例如:分页玩法) (重点) 条件: 1 需要在action的成员位置提供属性,并且要有set()方法 2 属性驱动---页面表达式的方式 (理解) 条件: 1 需要在action的成员位置上申明javabean对象,且提供get/set方法 例如: private User user; get()/set() 2 在页面上的参数name属性需要: name=javabean对象.属性 例如: user.username; uiser.age; 3 模型驱动(单一的对象) (掌握) 条件: 1 让action实现一个接口: ModelDriven 2 需要在action的成员位置上申明javabean对象,并且这个对象得实例化 private User user=new User; 3 需要 ModelDriven 这个接口中的getModel()方法 4 需要在getModel()方法里面将我们的javabean对象以返回值的形式返回回去 主页:页面还是正常的写法 4 批量方式(针对的是多个对象数据的封装) 条件: 需要在action中提供集合,且提供get()/set()方法 list封装: 在action中集合名称: ll 在页面需要: ll[0].username ll[0].age ll[1].usrname ll[1].age map封装: 在action中集合名称: mm 在页面需要: mm[键名].属性 总结: 1 struts2怎么样获取到servlet的API(request,response,session,ServletContext,以及接受页面的数据) 1 通过ServletActionContext类的静态方法 2 通过ActionContext对象的方法(理解) getActionContext()--对象的获取 注意:只能接受操作页面参数,以及操作域中的数据 不能获取到域对象,也不能做响应(response对象也获取不到) 3 通过特定的接口来实现 ServletRequestAware,ServletResponseAware,ServletContextAware,SessionAware 2 结果逻辑视图的配置 全局配置 针对的是一个包下的所有action 局部配置 针对的是指定的action 2个都存在的情况下优先级:局部>全局 result标签: name: 逻辑视图的名称。默认值是success。 type: dispatcher :默认值,请求转发。(请求转发到JSP的页面) redirect :重定向。(重定向到JSP的页面) chain :转发到另一个Action。 redirectAction:重定向到另一个Action。 stream :文件的下载。 3 struts2对页面数据封装的方式: 4种 ps:action多实例的,每访问一次就创建一个action对象,所以它成员位置的属性不存在线程危机 1 属性驱动---set方式 条件: action提供相应的成员属性,必须得有set方法 2 属性驱动---页面表达式的方式 条件: 1 需要在action的成员位置上申明javabean对象,且提供get/set方法 2 在页面上的参数name属性需要: name=javabean对象.属性 例如: user.username; uiser.age; 3 模型驱动 条件: 1 让action实现一个接口: ModelDriven 2 需要在action的成员位置上申明javabean对象,并且这个对象得实例化 private User user=new User; 3 需要 ModelDriven 这个接口中的getModel()方法 4 需要在getModel()方法里面将我们的javabean对象以返回值的形式返回回去 主页:页面还是正常的写法 4 批量封装 条件: 提供集合且提供set/get方法 list: 在action中: ll 在页面: ll[索引].属性 map: 在action中: mm 在页面: mm['键名'].属性