SSH框架之Struts2进阶数据封装与结果页面的配置(二)

第一节:Struts2访问Servlet的API

考虑这么一种情况:如果表单中有参数,通过Action如何进行接收又或者需要向页面保存一些数据,又该如何操作呢?我们可以通过学习Struts2访问Servlet的API来实现这样的功能。
在Struts2中,Action并没有直接和Servlet API进行耦合,也就是说在Struts2的Action中不能直接访问Servlet API。虽然Struts2中的Action访问Servlet API麻烦一些,但是这却是Struts2中Action的重要改良之一,方便Action进行单元测试。
尽管Action和Servlet API解耦会带来很多好处,然而在Action中完全不访问Servlet API几乎是不可能的,在实现业务逻辑时,经常要访问Servlet中的对象,如 session、request和application等。在Struts2中,访问Servlet API有3种方法,具体如下:

1.1 通过ActionContext类访问

Struts2框架提供了ActionContext类来访问Servlet API,ActionContext是Action执行的上下文对象,在ActionContext中保存了Action执行所需要的所有对象,包括parameters、request、session、application等。下面列举ActionContext类访问Servlet API的几个常用方法:


image.png

具体使用,请参照如下案例:

  • 访问页面的代码
<%--
  Created by IntelliJ IDEA.
  User: F
  Date: 2019/4/5
  Time: 19:38
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    ActionContext访问Servlet API 实例



用户名:
密码:
  • Action的处理逻辑
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.dispatcher.Parameter;

public class RequestActionDemo extends ActionSupport {

    public String login() throws Exception{
        //接收表单的参数
        //使用actionContext来获取参数
        ActionContext context = ActionContext.getContext();
        //接收参数
        HttpParameters parameters = context.getParameters();
        Parameter name = parameters.get("name");
        String nameValue = name.getValue();
        Parameter password = parameters.get("password");
        String passwordValue = password.getValue();
        System.out.println(nameValue +"=====" + passwordValue);

        //设置参数
        context.put("requestName","张三");
        context.getSession().put("sessionName","李四");
        context.getApplication().put("applicationName","王五");

        return SUCCESS;
    }
  • struts2.xml中对Action的配置,使用通配符来实现方法的调用。
 
        
                /demo01.jsp
        
  • 通过jsp界面对Action传入参数的获取
<%--获取action中传递过来的参数--%>
${requestName}
${sessionName}
${applicationName}

1.2 通过特定接口访问:

Struts2框架提供了ActionContext类来访问Servlet API,虽然这种方法可以访问Servlet API,但是无法直接获得Servlet API实例。为了在Action中直接访问Servlet API,Struts2还提供了一系列接口,具体如下:

  • ServletRequestAware:实现该接口的Action可以直接访问Web应用的HttpServletRequest实例。
  • ServletResponseAware:实现该接口的Action可以直接访问Web应用的HttpServletResponse实例。
  • SessionAware:实现该接口的Action可以直接访问Web应用的HttpSession实例。
  • ServletContextAware:实现该接口的Action可以之间访问Web应用的ServletContext实例。
    下面以ServleRequestAware为例,讲解如何在Action中访问HttpServletRequest实例:
  • 定义Action继承ActionSupport实现ServleRequestAware接口:
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.interceptor.ServletRequestAware;

import javax.servlet.http.HttpServletRequest;

public class RequestActionDemo02 extends ActionSupport implements ServletRequestAware {

    HttpServletRequest httpServletRequest;

    @Override
    public void setServletRequest(HttpServletRequest httpServletRequest) {
        this.httpServletRequest = httpServletRequest;
    }

    public String login() throws Exception {
        String username = httpServletRequest.getParameter("name");
        String password = httpServletRequest.getParameter("password");
        System.out.println(username + "======" + password);
        httpServletRequest.setAttribute("message","通过ServletRequestAware接口来访问Servlet API");
        return SUCCESS;
    }
}

需要注意的是,上述类必须实现setServletRequest()方法和execute()方法,
通过setServletRequest()方法,可以得到HttpServletRequest的实例。这是在调用execute()方法或其他自定义的方法之前就调用了的。

  • 修改struts.xml配置文件,添加上述Action的访问配置。
  
        
                /demo01.jsp
        
  • 修改提交界面的url地址,并在成功返回界面获取Action中返回的数据
<%--获取HttpServletRequest返回的数据--%>
${requestScope.message}
  • 结果界面如下:


1.3 通过ServletActionContext访问

为了直接访问Servlet API,Struts2框架还提供了ServletActionContext类,该类包含了几个常用的静态方法,具体如下:

  • static HttpServletRequest getRequest():获取web应用的HttpServletRequest对象。
  • static HttpServletResponse getResponse():获取Web应用的HttpServletResponse对象。
  • static ServletContext getServletContext():获取Web应用的ServletContext对象。
  • static PageContext getPageContext():获取Web应用的PageContext对象。
    接下来,实现如何通过ServeltActionContext来访问Servlet API:
  • 实现Action测试类。具体代码如下:
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Map;

public class RequestActionDemo03 extends ActionSupport {
    
    
    public String login() throws Exception{
        
        //1.通过ServletActionContext对象获取request对象
        HttpServletRequest request = ServletActionContext.getRequest();
        //2.通过request对象来获取参数
        Map parameterMap = request.getParameterMap();
        for (String key:parameterMap.keySet()) {
            String[] value = parameterMap.get(key);
            System.out.println(Arrays.toString(value));
        }

        String name = request.getParameter("name");
        String password = request.getParameter("password");
        System.out.println(name + "=====" + password);

        //3.设置参数
        request.setAttribute("requestName","张三");//向request域中存值
        request.getSession().setAttribute("sessionName","李四");//向session域中存值
        ServletActionContext.getServletContext()
                .setAttribute("applicationName","王五");//向application域中存值
        
        return SUCCESS;
    }   
}
  • 配置struts.xml

        
                /demo01.jsp
        
  • 成功返回界面的代码及内容展示
<%--获取action中传递过来的参数(通过ServletActionContext传入)--%>
${requestName}
${sessionName}
${applicationName}

第二节:结果页面的配置

在struts.xml文件中,Result的配置非常简单,使用元素来配置Result逻辑视图与物理视图之间的映射,元素可以有name和type属性,但这两种属性都不是必选的。

  • name属性:指定逻辑视图的名称,默认值是success;
  • type属性:指定返回的视图资源的类型,不同的类型代表不同的结果输出,默认值是dispatcher;
    struts.xml文件中的元素配置代码如下所示:
  
                /demo01.jsp
        

注意:name属性的值可以是jsp页面,也可以是一个Action的name值。
在结果界面的配置中,Struts2有两种配置的方式,一种称为全局结果页面,一种称为局部结构页面。全局结果是指在这个包下的所有返回相同字符串的值,都可以向这个页面进行跳转。局部结果是指在某个Action中返回的字符串的值,会向这个页面跳转。

2.1 全局结果页面:

全局结果页面是指在同一个包下面配置的Action中返回相同的字符串的值,都可以跳转到该页面,需要通过进行配置:

 
        
            /demo01.jsp
        

2.2 局部结果页面:

局部结果页面是指在某个Action中根据该字符串的值进行页面的跳转。只对这个Action有效。

 
                /demo01.jsp
        

在Struts2中,当框架调用Action对请求进行处理后,就要向用户呈现一个结果视图。在Struts2中,预定义了多种ResultType,其实就是定义了多种展示结果的技术。
一个结果类型就是实现了com.opensymphony.xwork.Result接口的类,Struts2把内置的都放在struts-default包中,struts-default就是配置包的父包。每个元素都是一种视图技术或者跳转方向的封装,其中name属性指出在元素中如何引用这种视图技术或跳转方式,对应着元素的type属性。Struts2中预定义的ResultType如表所示:



其中红色的几个值比较常用,需要重点记忆。

第三节:Struts2中数据的封装

在很多实际开发的场景中:页面提交请求参数到Action,在Action中接收参数并且对请求参数进行数据封装。封装到一个JavaBean中,然后将JavaBean传递给业务层。在Struts2中将数据的封装分成两大类,一类被称为属性驱动,一类被称为模型驱动。

3.1 属性驱动(提供属性的set方法)

属性驱动又可以细分为两种,一种只需要提供属性的set方法即可。另一种可以通过表达式方法直接封装到对象中。

  • 定义jsp页面,建立表单提交数据与需要封装的数据对应
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    struts2中的数据封装



    
姓名:
年龄:
生日:
工资:
  • 定义Action实现需要封装数据的set方法
public class RequestActionDemo04 extends ActionSupport {

    private String name;
    private int age;
    private Date birthday;
    private Double salary;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    public String submit() throws Exception{

        System.out.println(name);
        System.out.println(age);
        System.out.println(birthday);
        System.out.println(salary);

        return NONE;
    }
  • 在struts.xml中对Action进行配置;
  
                
        

以上这种方式需要通过在Action中定义属性,并且提供属性的set方法来完成。这种方式只需要提供set方法即可。但若需要传入的数据很多的话,那么Action的属性也会变得很多。再加上属性有对应的getter/setter方法,Action类的代码会变的很膨大。在Action里编写业务代码时,会使得Acction非常臃肿。那么如何解决这个问题呢?具体如下:
把属性和相应的getter/setter方法从Action里提取出来,单独作为一个值对象,这个对象就是用来封装这些数据的,在相应的Action里直接使用这个对象,而且可以在多个Action里使用。采用这种方式,一般以JavaBean来实现,所封装的属性和表单的属性一一对应,JavaBean将成为数据传递的载体。

3.2 属性驱动(页面提供表达式方式):

  • 编写jsp,在表单中添加对应的表达式(OGNL)
 

通过页面表达式实现数据的封装

姓名:
年龄:
生日:
工资:
  • Action的代码实现:
public class RequestActionDemo05 extends ActionSupport {

    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String submit() throws Exception{

        System.out.println(user);

        return NONE;
    }

}
  • 实现User的JavaBean对象
package com.seapp.struts2.domain;

import java.util.Date;

public class User {

    private String name;
    private int age;
    private Date birthday;
    private Double salary;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Double getSalary() {
        return salary;
    }

    public void setSalary(Double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                ", salary=" + salary +
                '}';
    }
}

注意:以上这种方式在Action中需要提供User对象的get方法,如果没有get方法,在Struts2的底层就没有办法获得该对象,那么在User中只会有一个属性被封装进去,而其他的属性都是null;

3.3 模型驱动:

在Struts2中模型驱动(ModelDriven)通过实现ModelDriven接口来接收请求参数,并且要重新getModel()方法,这个方法返回的就是Action所使用的数据模型对象。
模型驱动方式通过JavaBean模型进行数据传递。只要是普通的JavaBean就可以充当模型部分。采用这种方式,JavaBean所封装的属性与表单的属性一一对应,JavaBean将成为数据传递的载体。

  • 编写jsp页面进行数据传递
 

通过驱动模型的方法实现数据的封装

姓名:
年龄:
生日:
工资:
  • 新建Action并实现ModelDriVen,通过数据模型来获取传递过来的数据
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.seapp.struts2.domain.User;

public class RequestActionDemo06 extends ActionSupport implements ModelDriven {

    private User user = new User();

    @Override
    public User getModel() {
        return user;
    }

    public String submit() throws Exception{
        System.out.println(user);
        return NONE;
    }
}

大部分我们会优先使用模型驱动的方式,因为Struts2内部有很多结果是围绕模型驱动设计的。但如果页面向多个对象中封装,那么就需要使用属性驱动的方式二了。

第四节:Struts2中封装集合类型的数据

4.1 Struts2中List集合数据的封装。

  • jsp中页面编写,提供list集合中的提交测试数据

实现List集合数据的封装

姓名:
年龄:
生日:
工资:
姓名:
年龄:
生日:
工资:
  • Action中对该list设置getter/setter方法,获取数据并打印
public class RequestActionDemo07 extends ActionSupport {

    private List list;

    public List getList() {
        return list;
    }

    public void setList(List list) {
        this.list = list;
    }

    public String submit() throws Exception{
        for(int i =0;i

4.2 Struts2中Map集合数据的封装:

  • 编写jsp ,提供封装Map所需要的测试数据
 

实现Map集合数据的封装

姓名:
年龄:
生日:
工资:
姓名:
年龄:
生日:
工资:
  • 新建Action,实现对Map集合数据的封装以及打印
public class RequestActionDemo08 extends ActionSupport {

    private Map map;

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }
    
    public String submit() throws Exception{

        for (String key:map.keySet()) {
            System.out.println(key + "======"+map.get(key));
        }
        
        return NONE;
    }
}

你可能感兴趣的:(SSH框架之Struts2进阶数据封装与结果页面的配置(二))