Struts2

来源:互联网 发布:网页数据统计 编辑:程序博客网 时间:2024/05/18 01:17

struts2概述:

  1. struts2 应用于javaEE中三层框架的web层。
  2. struts2 是在struts1和webwork上面发展起来的全新框架。
  3. struts2 解决的问题:
    这里写图片描述

第一个案例:

  1. 导入jar包
  2. web.xml配置过滤器
  3. 创建Action,默认执行execute方法
  4. 创建配置文件,名称(struts.xml)和位置固定(src下)
  5. 配置访问路径。

执行过程:

  1. 浏览器器请求
  2. 经过过滤器
  3. 过滤器通过请求路径拿到actionname
  4. 再从src中的struts.xml中找到actionname和action标签中的name属性匹配的action,再通过提供的class和反射技术来调用相应的方法。
  5. 通过得到的返回值,根据result的name属性配置,跳转到相应的页面。

struts2核心配置:

  1. 具有package,action,result三种主要的标签。
  2. package标签:
    2.1 name属性:与功能本身并没有关系,目的只是为了区分不同的Action,可以随便写,但是同一个配置文件中name不能相同。
    2.2 extends:是固定值,struts-default 只有配置了这个,Action的配置才有效。
    2.3 namespace: 它的值与Action中的name构成访问路径,例如namespace=”/a” action中的name=”hello” 那访问路径是/a/hello,一般填写”/”,且默认值也为”/”。
  3. action标签:
    3.1 主要配置访问路径
    3.2 在一个package中可以有多个action标签,但是action的name属性值不能相同的。
    3.3 name属性:与namespace的值构成访问路径。
    3.4 class属性:action类的全路径名(包名+类名)
    3.5 method 属性:可以让action中的多个方法执行
  4. result标签:
    4.1 根据action的返回值进行相应的跳转。
    4.2 name属性:方法返回值
    4.3 <result>/xxx</result>其中的’/’是固定写法。
    4.4 type属性:配置跳转的方式,例如转发或者重定向,默认是转发。
  5. 常量配置(constant标签):
    5.1 一般封装了一种功能。
    5.2 name属性:常量的名字。
    5.3 value属性:常用的值。
    5.3 最常用的常量:struts.i18n.encoding=utf-8,解决post提交的编码问题,不需要自己处理。

    分模块开发:

  6. 有多个xml文件,直接在src中的struts.xml中引入这些文件即可,通过<include file=”renwen/com/hello.xml></include>”,记住最前面没有’/’,

action的编写方式:

  1. 创建普通类,不继承任何类,也不实现任何接口
  2. 创建一个类,实现接口Action
    2.1 实现execute()方法。
    2.2 Action接口中所定义的常量:
    2.2.1 ERROR = “error”;
    2.2.2 INPUT = “input”;
    2.2.3 LOGIN = “login”;
    2.2.4 NONE = “none”;
    2.2.5 SUCCESS =”success”;

  3. 创建一个类,继承ActionSupport(最常用)
    3.1 ActionSupport 已经实现了Action接口

访问action的方法

  1. 直接在action标签中的method属性中填写需要执行的方法这里写图片描述
  2. 使用通配符:在action的name属性中写上*来充当通配符,*代表任意字符这里写图片描述
  3. 动态访问实现(基本不用)
  4. 注意事项:
    4.1 action中的方法可以没有返回值,但是如果有,一定是string
    4.2 action中的返回值在result中如果没有找到,会404。
    4.3 没有返回值,可以通过方法写void,或者返回字符串NONE(none),则result中不需要配置。

结果页面的配置:

  1. result标签配置action方法的返回值进行相应的跳转。
  2. 全局结果页面配置:当多个action的返回值有重复的,且跳转的目的地也是相同的,就可以用全局结果页面配置,且只在同一个package中有效.
    这里写图片描述
    改为:
    这里写图片描述
  3. 局部结果界面配置:
    这里写图片描述
    当局部和全局进行了相同的结果配置,局部优先。
  4. result的type属性配置:确定以何种方式进行跳转。
    4.1 type的属性值:dispatcher(转发,默认值),redirect,chain(转发到action,一般不用),redirectAction(重定向到action),前面两种一般针对跳转到页面,而后面的针对跳转到action。
    这里写图片描述

获取表单数据的方式:

  1. 通过ActionContext
    这里写图片描述
    注意得到map集合后,通过get(key)得到的是一个Object[]数组。
  2. 通过ServletActionContext
    这里写图片描述
    大部分是静态方法,直接可以通过类名调用。
  3. 通过接口注入(一般不用)
    这里写图片描述

获取域对象:

  1. ruquest获取:ServletActionContext.getRequst();
  2. response获取: ServletActionContext.getResponse();
  3. session获取:通过request来获取。
  4. ServletContext获取: ServletActionContext.getServletContext();

数据封装:

  1. 原始数据封装:
    这里写图片描述
  2. 属性封装:

    public class BookAction extends ActionSupport{    private String sname;    private String spwd;    public String update(){        System.out.println(sname);        System.out.println(spwd);        return NONE;    }    public String getSname() {        return sname;    }    public void setSname(String sname) {        this.sname = sname;    }    public String getSpwd() {        return spwd;    }    public void setSpwd(String spwd) {        this.spwd = spwd;    }}

    注意属性的名字必须和表单项的name属性一样,且必须实现属性的setter和getter方法。

  3. 使用模型驱动封装(重点)

    public class BookAction extends ActionSupport implements      ModelDriven<Student>{    private Student stu=new Student();    public String update(){        System.out.println(stu);        return NONE;    }    @Override    public Student getModel() {        // TODO Auto-generated method stub        return stu;    }}

    必须实现ModeDriven接口,且实体类的属性必须和表单的name属性一致,实体类有getter和setter方法,且在action中创建实体类对象。

  4. 表达式封装:

    public class BookAction extends ActionSupport{    private Student stu;    public String update(){        System.out.println(stu);        return NONE;    }    public Student getStu() {        return stu;    }    public void setStu(Student stu) {        this.stu = stu;    }}

    必须声明该实体类对象,同时创建setter和getter方法,在表单应该使用表达式语言,以及注意表单name属性如何书写。

     <form action="update.action" method="post">        <input type="text" name="stu.sname"/>        <input type="text" name="stu.spwd"/>        <input type="submit"/> </form> 
  5. 注意:
    5.1 不能既用属性封装又用模型驱动封装,两个都用,只会执行模型驱动。
    5.2 表达式封装可以把数据封装到不同的实体类中,但是模型驱动封装只能把数据封装到同一个实体类中

将表单数据封装到集合中

  1. 封装数据到List中

    public class BookAction extends ActionSupport{    private List<Student>list;//声明list集合,提供setter和getter方法    public String update(){        for(Student stu:list){            System.out.println(stu);        }        return NONE;    }    public List<Student> getList() {        return list;    }    public void setList(List<Student> list) {        this.list = list;    }}
    <form action="update.action" method="post">        <input type="text" name="list[0].sname"/>        <input type="text" name="list[0].spwd"/>        <input type="submit"/></form>
  2. 封装数据到Map中

    public class BookAction extends ActionSupport{    private Map<String,Student>map;//声明map集合    public String update(){        System.out.println(map.get("one"));        return NONE;    }    public Map<String, Student> getMap() {        return map;    }    public void setMap(Map<String, Student> map) {        this.map = map;    }}

    <form action=”update.action” method=”post”> 
    <input type=”text” name=”map[‘one’].sname”/>
    <input type=”text” name=”map[‘one’].spwd”/>
    <input type=”submit”/>
    </form>

OGNL概述:

之前在javaweb阶段学过EL表达式,用于获取域对象里面的值,而OGNL也是类似于EL的一种表达式,只是功能更加的强大。
这里写图片描述
但是在struts2中主要的作用是操作值栈中的数据,和struts2中的标签联合使用(后面讲到),但是OGNL并不是struts2的一部分,只是他们经常一起使用,使用之前,得先导入OGNL的jar包。

小案例:

这里写图片描述
这里写图片描述
上面的例子会输出字符串的长度,但是在web.xml中过滤器<url-pattern>中必须中/*,现在暂时不知道为什么。

值栈

  1. 什么是值栈
    之前在javaweb阶段,数据是存储在域对象中,在页面中进行获取,现在提供了一种类似的机制—-值栈。
  2. servlet和action的区别
    2.1 默认在第一次访问的时候创建,只是创建一次,线程不安全。
    2.2 action也是访问的时候创建,每次访问创建一次,线程安全。
    2.3 每个action中存在一个值栈对象,仅有一个

获取值栈的方式:

  1. 通过ActionContext,常用
  2. 值栈的内部结构
    2.1 第一部分结构:root(List集合,常用)
    2.2 第二部分接口:context(Map集合),存储的一些对象的引用
    这里写图片描述

向值栈中放数据:

  1. 获取值栈对象,调用值栈中set的方法。
  2. 获取值栈对象,调用push方法。
  3. 在action定义一个成员变量,生成变量的get方法。
  4. 在值栈中的栈底保存了对于action的引用,同时如果采用第三种方法进行放入数据,则该数据是放在action中的。

从值栈中获取数据:

利用ognl和struts2的标签来进行数据的获取。

  1. 获取字符串

    public class BookAction extends ActionSupport{    private String name="123";    public String  update(){        return "ok";    }    public String getName() {        return name;    }}<s:property value="name"/>
  2. 从值栈中获取对象:

    public class BookAction extends ActionSupport{    private Student stu=new Student();    public String  update(){        stu.setSname("zhangsan");        stu.setSpwd("123");        return "ok";    }    public Student getStu() {        return stu;    }    public void setStu(Student stu) {        this.stu = stu;    }}<s:property value="stu.sname"/><s:property value="stu.spwd"/>
  3. 从值栈中获取List
    3.1: 第一种方式,不常用,写死了。

    public class BookAction extends ActionSupport{    private List<Student>list=new ArrayList<Student>();    public String  update(){        Student s1=new Student();        Student s2=new Student();        s1.setSname("123");        s1.setSpwd("455");        s2.setSname("789");        s2.setSpwd("897");        list.add(s1);        list.add(s2);        return "ok";    }    public List<Student> getList() {        return list;    }}<s:property value="list[0].sname"/><s:property value="list[0].spwd"/><s:property value="list[1].sname"/><s:property value="list[1].spwd"/>

    3.2 第二种
    java代码与第一种方法一样

    <s:iterator value="list" >    <s:property value="sname"/>    <s:property value="spwd"/></s:iterator>

    3.3 第三种
    java代码与第一种方法一样

    <s:iterator value="list" var="it">    <s:property value="#it.sname"/>    <s:property value="#it.spwd"/></s:iterator>

    为什么不是it.sname呢?因为it存储在context中,it.sname,默认it在root中获取,为了以示区分所以加了#。
    3.4 获取在action中调用ValueStack通过set方法设置的值

     <s:property value="setName"/>

    3.5 获取在action中调用ValueStack通过push方法设置的值,他会把数据放到数组中去,这个数组的名字是top.

为什么EL表达式也能获取值栈中的数据:

  1. 向域对象中设置属性,会使用setAttrubutem,向域对象中获取属性,会调用getAttribute方法。
  2. 首先从request域中进行获取
  3. 如果存在,则直接进行返回,否则从值栈中获取,然后放入request域中,然后在从request域中进行获取。
  4. 一般不用EL表达式来取值栈的值,因为性能较差。

‘#’的使用:

用来取context中的值,前面加个context

‘%’的使用:

这里写图片描述

拦截器:

  1. 拦截器的创建时间:在服务器启动的时候开始创建。
  2. struts2封装了很多的功能,这些功能都是封装在拦截器里面。
  3. 拦截器的执行时间:在action对象创建之后,在action方法执行之前。
  4. 在struts2中定义了许多的拦截器,但是并不是所有的拦截器都会执行,他有默认执行的拦截器。
    4.1 默认拦截器的位置:在struts的核心包里。
  5. 拦截器的相关原理:AOP,责任链设计模式
    5.1 AOP面向切面编程,浅显的说就是在添加功能的同时不需要改变源代码。
    这里写图片描述
    5.2 责任链设计模式:类似于过滤链,会有很多个拦截器执行。
  6. 过滤器与拦截器的区别:
    6.1 过滤器可以过滤任意内容,例如servlet,html,jsp都可以过滤,但是拦截器只可以拦截action.
  7. 自定义拦截器:
    7.1 struts2中已经定义好的拦截器可能没有我们需要的功能,所以我们需要自己去创建。
    7.2 拦截器的基本结构:
    继承AbstractInterceptor或者实现Interceptor接口
    接口中有三个方法:init(初始化方法),destory(销毁方法),intercept()拦截逻辑操作,但是在开发中一般使用继承MethodFilterInterceptor类实现,因为可以让我们对action某个方法不进行拦截,采用配置文件的方式让拦截器和action建立关系。
    7.3 创建拦截器:
    首先编写拦截器类:

    public class MyInterceptor extends MethodFilterInterceptor{    @Overrideprotected String doIntercept(ActionInvocation arg0) throws Exception {        // TODO Auto-generated method stub        HttpSession session=ServletActionContext.getRequest().getSession();            String username=(String) session.getAttribute("username");        if(username==null){            return "login";//返回,必须和result的值相匹配。        }else{            return arg0.invoke();//执行下面一个拦截器,或者action的方法。        }    }}

    再到action所在package中进行注册:
    这里写图片描述

0 0
原创粉丝点击