Struts2

Struts2

 概念:是一个mvc框架

Servlet的缺点

1、 web.xml文件中需要配置很多行代码,维护起来很不方便,不利于团队合作

2、 一个servlet的入口只有一个doPost或者doGet方法,如果在一个servlet中写好几个方法,怎么办?

 

   这样会导致代码结构很乱

3、 servlet类与servlet容器高度耦合,每个方法中都有两个参数requestresponse。如果服务器不启动,这两个参数没有办法初始化。

4、 如果在servlet中的一个方法中,有很多功能,这个时候,会导致该方法比价复杂,以致于不利于维护

 

用户注册完成了4件事情,所以整个方法比较杂乱

5、 如果一个servlet类中有很多方法,浏览器对这些方法进行请求,url写起来很麻烦

 

 6、在servlet中如果要获取页面上表单中的数据,那么在方法中会写很多行

Servlet的重构

目的

1、 web.xml文件中只写一个过滤器

2、 action处理业务逻辑

3、 在过滤器中动态的调用action中的方法处理业务逻辑

类的设计

技术路线总图:

     

1、 监听器

    1、 准备一个map

    2、 把所有的actionkey,value放入到map

    3、  map放入到application域中

2、 过滤器

    1、 获取application域中的map

    2、 解析url

    3、 根据解析的urlmap中把value提取出来

    4、 根据java的反射机制动态调用action

    5、 根据action返回的方法跳转到相应的页面

3、执行action execute方法,该方法返回一个字符串

实现

1、 写监听器

 

 

2、 过滤器

 

 

3、 action

 

Struts2的历史

1、 servlet

2、 struts1

    1、 action

    2、 写了一个中控的servlet

    3、 actionForm 和页面上表单中的内容一致

3webwork

         1、使得actionservlet容器完全松耦合

         2、属性驱动和模型驱动获取页面上表单中的数据

         3、利用了拦截器的概念把servlet容器的第4个缺点克服掉了

         4struts1+webwork=struts2

Struts2的第一个例子

步骤

1、 创建一个web project

2、 导入jar

 

3、 编写web.xml文件

 

4、 写一个action

 

5、 编码struts.xml文件

 

6、 运行

解析

struts.xml文件的内容

 

上图为加载流程

注意:

1、 struts.xml文件必须放在classpath的根目录下

2、 名字必须为struts.xml文件

3、 因为整个加载过程写在了过滤器中的init方法中,所以tomcat启动的时候就把该文件加载了

Package

1、 用意:用来管理action

 

从上图可以看出在system模块下有三个action

2、 name属性

为包的名称,是唯一的

3、 namespace

为命名空间,是针对url

 

上述的命名空间针对的是:itheima09_struts2_helloworld/hello

当浏览器提交一个url:

 

上述的url直接从项目的根目录查找,所以找不到

 

该路径和上述的url是对应的

 

先找hello/a下的action,如果找不到,则查找上一层,再找不到再找上一层,直到找到,如果最上层找不到,则报错

如果我们的namespace设的是/a 那么:工程名/a/xx/xx/xx.action可以由右向左找到此目录,但是如果在工程名后面写不存在的目录则会报错:工程名xx/xx/a/xx/xx/xx.action这个样就报错了,可以理解为在url中工程名与namespace地址是紧密关联的,

 

上述的命名空间针对的是:itheima09_struts2_helloworld

只要命名空间加一层,最后跳转到相应的jsp以后,也会加上相应的路径

 

 

这样的体系不好。

4、 extends

1、 tomcat启动的时候,不仅加载了struts.xml文件,而且还加载了struts-default.xml文件,而这个文件在classpath下。针对该文件的路径在

 

在一个配置文件中:

  

说明helloworld拥有package的名称为struts-default包的所有的功能

案例:

Action

action元素代表一个类

    classaction的类的全名,可以写,也可以不写

    如果不写class属性,则默认执行ActionSupport中的execute方法

       该方法什么都没有做,仅仅返回了一个success字符串

如图:


Result

代表一种结果集

Type 为结果集的类型

Name 属性的值和action中某一个方法的返回值一致

type属性不写,则默认和struts-default中的结果集中的default="true"的结果集保持一致

    dispatcher,转发

result标签中的内容就是要转发到的页面

struts-default.xml文件中

 

Name属性也可以不写,如果不写,则默认值为”success”

Struts2基本用法的其他方法

Include

struts.xml文件中

就可以把struts-helloworld.xml文件包括进来了

Action的写法

简单的javabean

实现action接口

 

继承ActionSupport

Actin的模式

action的构造器中输出一句话,在浏览器中多次请求,可以看到构造器执行了好几次,所以action是多例的。

结果集

转发

重定向

重定向到action

通配符映射

第一种

 

将执行UrlPatternAction中的execute方法

第二种

 

 

缺点:action中有几个方法就得在配置文件中写几个action元素

第三种

第四种

 

第五种

该模型的好处:如果在action中增加了一个方法,配置文件是不需要改变的,在写url

urlPatternAction_后面的内容变成要请求的方法的名称就可以了

第六种

第七种(不推荐)

 

这么写不好,覆盖范围太大,很有可能出现和其他的action 的配置冲突的情况

第八种

强制让url中的_后面的内容和方法保持一致,跳转到的jsp页面的名称和方法的名称也保持一致。这么写带有一定的规范性

Struts2servlet容器的交互

 

这种方法可以交互,但是这种方法把ServletActionservlet容器耦合性变高了,不利于测试。

 

可以通过ServletActionContextservlet容器相关的类调出来

 

该写法使得actionservlet容器的耦合性不是很强。

总结

1、 sturts2的配置文件中用了package的机制,这样可以分模块

name是唯一的名称,extends采用了继承的机制

2、 写的actionservlet容器完全松耦合了

3、 通配符映射解决:很容器就把一个url映射到一个action的方法中了

4、 Include保证了可以写多个配置文件

5、 结果集的封装

 

值栈(重要)ognl表达式

1、 只要是一个mvc框架,必须解决数据的存和取的问题

2、 Struts2利用值栈来存数据,所以值栈是一个存储数据的内存结构

3、 把数据存在值栈中,在页面上利用ognl表达式显示出来

讨论的问题

1、 讨论值栈的生命周期

2、 值栈的内存结构

3、 通过什么样的方法把数据放入到值栈中

4、 显示出来

值栈的生命周期

一次请求

值栈的内存结构

获取值栈的路径

 

 

说明:

1、 值是一样的,说明只有一个对象

2、 因为有一种是从request域中获取的,所以是一次请求

内存结构

1、 大致图:

 

 

2、 上面图中的context的放大

 

   说明:

        _root(CompoundRoot)

        _values(HashMap)

             在这里存放了requestresponsesessionapplicationservlet容器的内容

3_root的放大

说明:

    ValueStack中的root是一致的

值栈的内存总图

说明:

     从上图中可以看出valueStack总共分为两个部分:

          对象栈:root

          Map栈:_values

 

对象栈的存放

1、 Push方法

 

 

2、 add方法

 

对象栈的提取

 

  从上图中可以看出,peek方法为获取对象栈的栈顶的元素

 

这行代码也可以获取对象栈的栈顶的元素

对象栈的元素的弹出

 

操作对象栈中的对象

 

说明:

     可以利用valueStack.setParameter方法改变对象栈中对象的属性的值

Map栈的存放

通过该方法可以把一个字符串放入到map栈中的request域中

 

通过该方法可以把一个字符串放入到map栈中的application域中

 

通过该方法可以把一个字符串放入到map栈中

Ognl表达式

Debug标签(重要)

在页面上引入标签库

标签库的位置:

 

可以通过网页的形式把valueStack中值提取出来

关于对象栈:

    

   从上图可以看出来,对象栈的属性来自于对象栈中的每一个对象的属性的get方法


把一个对象放入到对象栈中

s:debug

 

   如果在对象栈中有两个相同的属性:

 

上述的两个类中都同时有name属性,而且当前请求的action在对象栈中

 

利用该方法就把person对象放入到栈顶了

 

可以利用上述的方法改变对象栈中的name属性,但是从上往下找,只要找到一个,改变了值就完事了。

Property标签(重要)

  介绍

输出标签

       value  指定要输出的内容

            如果在对象栈中,直接指定属性

                                 也可以直接调用方法

            如果在map栈中,用#指定

          如果value属性不写,则默认输出栈顶的元素

 

  页面上:

把一个对象放入到对象栈中,可以利用s:prototype标签的value属性直接访问

该对象的属性。如果对象栈中出现两个相同的属性,则prototype标签的value属性会

从栈顶往下查找,直到找到为止。赋值的为第一个。

 

把一个对象放入到map中,再把map放入到对象栈中,在页面上可以利用

 

 

 

 


可以利用方法来访问

利用该标签访问map栈中的元素

 

Iterator标签(重要)

1、 用途:主要用于迭代,可以迭代List,Set,Map,Array

2、 案例

1、 把集合放入到对象栈中

 

 

  2、把list放入到map

 

3、 list放入到request域中

 

 

4、 map放入到map栈中

 

 

  5、把List<Map<String,Person>>放入到map栈中

 

总结:

1、 如果要迭代一个集合,当前迭代的元素在栈顶

2、 如果要迭代一个map,则当前迭代的元素是entry

3、 Iterator标签中有一个属性status

 

Ui标签

1、 struts2提供了一套标签机制,由struts2框架把struts2的标签解析成html标签。

2、 struts2的配置文件中,增加

 

 

struts2的配置文件中加入如下的内容:

 

struts2容器翻译过程来的html代码和struts2标签的代码就能保持一致。

 

Select标签

Checkbox:

 

回显

1、 如果把要回显的数据放入到map栈中,则必须根据value进行回显

Value=”%{ognl表达式}

    

2、 一般情况下,应该把回显的数据放入到对象栈中,因为页面上可以直接根据name进行回显

 

3、 因为当前请求的action在对象栈中,所以可以利用action中的属性进行回显,action中的属性必须有get方法。

4、 Checkbox的回显

 

上述图表示要回显的id

 

根据name属性进行回显

拦截器

需求

如果要访问某一个action类中的某一个方法的内容,如果是admin用户,则访问,如果不是admin用户,则不能访问。

实现

步骤

1、 编写interceptor

 

2、 写一个PvilegeSuperAction

 

3、 在配置文件中进行配置

 

详细解析

说明:

       通过该图可以看出:当提交一个url请求时,先执行所有的拦截器(按照声明的从上到下的顺序),再执行action

       声明一个拦截器

       声明一个拦截器栈

 

      既可以引用一个拦截器

       也可以引用一个拦截器栈

  真正的做法:

 

如果p包继承了privilege包就把所有的新的拦截器栈继承过来了,如果没有继承,则执行默认的拦截器栈

缺点

把权限判断的代码和业务逻辑的代码混合在一起了

利用拦截器改进

拦截器的优点

1、 把项目中一些经常用到的业务逻辑从action中分离出来,写到拦截器中

这样可以做到这些常用的逻辑和真正的逻辑的松耦合

2、 拦截器和action是真正的松耦合了

3、 Struts2把开发过程中的一些常用的业务已经封装到各个拦截器中了

案例2

在执行action的方法之前,

1、 开启日志

2、 权限的检查

 

声明两个拦截器

 

在执行的拦截器栈中,按照执行的先后顺序引入拦截器

拦截器的应用

属性驱动

注意事项:

1、 必须使用struts2默认的拦截器栈中的ParametersInterceptor

2、 Action中的属性和表单中的name属性的值保持一致

3、 利用valueStack.setValue方法可以赋值了

模型驱动

 


从上图可以看出,ModelDriverInterceptor有两个作用:

1、 当前请求的action必须实现ModelDriver接口

2、 model对象放入到了栈顶

Threadlocal

1、 本地线程类

2、 可以存放一个对象

3、 Threadlocal对象只能当前线程访问,其他的线程是不能访问的

4、 传递参数

案例:

参数的传递

 

    

说明:通过参数的传递,一个字符串很容易的从客户端传递到tl1中的tl1方法,再传递到tl2中的tl2方法

 

 

说明:

    TL1Super中用到一个字符串

    TL2Super中用到同样的字符串,但是这两个类是完全松耦合,这个时候要用

    Threadlocal传递数据,因为不管是否是送耦合的,但是可以肯定在同一个线程中。所以可以得到同一个线程threadlocal对象中的数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值