SSH框架之旅-struts2(2)

struts.jpg

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 类的要求:

    1. 在 Action 类定义和表单name属性值一样的数据成员
    1. 生成数据成员对应的 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 来实现的。

实现步骤:

    1. 编写实体类的代码,并生成属性的 set 和 get 方法。
    1. 在 Action 类中使用实体类new一个实体类的对象,并实现接口 ModelDriven 的 getModel() 方法。
    1. 页面中表单的输入项的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 表达式封装

使用表达式封装可以把表单数据封装到实体类对象里面,表达式封装其实也是属性封装的一种方式,这里是单独列出了。

实现步骤:

    1. 编写实体类的代码,并生成属性的 set 和 get 方法。
    1. 在 Action 类中使用实体类声明实体类的变量。
    1. 在表单输入项的 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 集合

实现步骤:

    1. 编写实体类,并生成属性的 set 和 get 方法。
    1. 在 Action 类中声明实体类的 List 集合,并生成 list 变量的 set 和 get 方法
    1. 在页面中,使用 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 集合

实现步骤:

    1. 编写实体类,并生成属性的 set 和 get 方法。
    1. 在 Action 类中声明实体类的 Map 集合,并生成 map 变量的 set 和 get 方法
    1. 在页面中,使用 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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容