2018.12.19 Struts2 框架总复习

总结Struts2 框架

struts2技术的优势

  • 项目开源,使用及拓展方便
  • 提供Exception处理机制
  • Result方式的页面导航,通过Result标签很方便的实现重定向和页面跳转
  • 通过简单、集中的配置来调度业务类,使得配置和修改都非常容易
  • 提供简单、统一的表达式语言来访问所有可访问的数据
  • 提供标准、强大的验证框架和国际化框架
  • 提供强大的、可以有效减少页面代码的标签
  • 提供良好的Ajax支持
  • 拥有简单的插件,只需放入相应的Jar包,任何人都可以扩展Struts2框架,比如自定义拦截器、自定义结果类型、自定义标签等,为struts2定制需要的功能,不需要什么特殊配置,摒弃可以发布给其他人使用
  • 拥有智能的默认设置,不需要另外进行繁琐的设置。使用默认设置就哭完成大多数项目程序开发所需要的功能

常见的Web层框架

  • Struts2
  • Struts1
  • WebWork
  • SpringMvc

    Web层框架都会有一个特点就是基于前端控制器模式实现的

什么是前端控制器模式呢?

在图中传统方式的开发,有一次请求就会对应一个Servlet。这样机会产生很多的Servlet,而struts2江苏哦哦于的请求都会先先经过一个前端控制器,在前端控制器中实现框架的部分功能,剩下具体擦坐要提交到具体的Action中。那么所有的请求都会经过前端控制器,那么用什么来实现前端控制器呢?过滤器就是最好的一个实现方式。因为需要所有的请求都可以被过滤器拦截,然后再过滤器中实现部分的功能。所以Struts2的前端控制器也是有过滤器来实现的。

1231979-20181128090158157-1218979659.png

1231979-20181128090301201-1763596584.png

Struts2框架的快速搭建

实现步骤:

  • 下载Struts2的开发包 https://struts.apache.org/
  • 选择对应的版本下载 然后解压出来一个文件夹
    1231979-20181128090625210-711961641.png
目录结构的总结

apps:该文件夹村用于存放官方提供的Struts2示例程序,这些程序可以作为学习的资料,可以为学习提供参照。各示例都是war文件,可以通过zip方式进行解压
docs:该文件夹用于存放官方提供的Sturt2文档,包括struts2快速入门、struts2的文档以及API文档等内容
lib:该文件夹用于存放struts2的核心类库,以及struts2的第三方插件类库
src:该文件用于存放该版本struts2框架对应的源代码
有了struts2的开发环境,就可以进行操作了

  • 创建Web项目引入相应的jar包(不需要全部都引入,参考apps下面的项目来)

    struts2-blank.war是一个空的工程,可以解压这个然后进去web-inf/lib 的文件下复制jar包
    1231979-20181128091550039-786244050.png

Struts2项目以来的额基础JAR包说明
1231979-20181128091724585-2007658261.png

到此为止,一个struts2项目就搭建好了。下面来复习做一个简单的测试吧

创建一个页面,在WebContent下创建一个页面 test.jsp,写一个超链接访问Action的
1231979-20181128094955712-382613621.png

接下来我们写一个Action,就是在类中创建一个 名为execute 的默认执行方法 返回值是String 方法无参数
1231979-20181128095544253-1470054760.png

String类型的值就是一个逻辑视图(逻辑视图:相当于对一个真实的页面,取一个别名) 通过这样的方式来实现页面的跳转

这个是一个普通的类如何编程一个Action类呢,接下来完成配置Action
1231979-20181128102438528-1872387927.png

接下来是最关键的也是最容易忘记的一步。配置我们的前端控制器,也叫核心过滤器StrutsPrepareAndExecuteFilter
1231979-20181128101225700-1382269410.png

标准的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>struts</display-name>
   <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

到此就能正常进入测试了是否能用

1231979-20181128101941804-1693582451.png

1231979-20181128102341360-1191307852.png

还是很成功的

下面来总结一写执行的流程
从客户端发送请求过来,先经过前端控制器(核心过滤器 StrutsPrepareAndExecuteFilter)过滤器中执行一组拦截器(一组拦截器完成部分功能),在其默认栈中的拦截器会得到执行,这个具体的可以看之前的博客。拦截器执行完成之后,就会执行目标Action,在Action中返回一个结果视图,根据Result的配置进行页面的跳转

Struts2的配置文件的加载顺序:

每次从客户端发送请求到服务器都要经过Struts2的核心过滤器StrutsPrepareAndExecuteFilter,这个过滤器有两个功能:预处理和执行。在预处理中主要就是用来加载配置文件的。对应的是过滤器中的init方法,而执行是用来执行一组拦截器完成部分功能的,对应的是过滤器的doFilter方法。

加载struts2的配置文件的方法

init_DefaultProperties();


init_TraditionalXmlConfigurations();

//加载struts.xml  struts-default.xml
init_LegacyStrutsProperties();


-->加载顺序是
    default.properties
    struts-default.xml
    struts-plugin.xml
    struts.xml     ----配置Action以及常量
    struts.properties  ---配置常量
    web.xml -----配置核心过滤器

注意:后加载配置文件中常量的值会将先加载的配置文件中常量的值给覆盖

struts.xml常见配置

Action的配置

Struts2的框架的核心配置文件是struts.xml文件,该文件主要用来配置Action和请求的对应关系。

package的配置
Struts2框架的核心组件是Action和拦截器,它使用包来管理Action和拦截器。每个包就是多个Action、多个拦截器、多个拦截器引用的集合。在struts.xml文件中,package元素用于定义包配置,每个package元素定义了一个包配置,每个package元素定义了一个包配置。package元素的常用属性

1231979-20181128110911915-1882733378.png

    表中就是package元素的常用属性,其中,在配置包时,必须指定name属性,就是包的标识。
    除此之外,还可以指定一个可选的extends属性,extends属性值必须是另一个包的name属性值,但该属性值通常都设置为struts-default,这样该包中的Action就具有了Struts2 框架默认的拦截器等功能了。除此之外,Struts2 还提供了一种所谓的抽象包,抽象包不能包含Action定义。为了显式指定一个包是抽象包,可以为该package元素增加abstract="true'属性。
    在package中还有namespace的配置,namespace 属性与action标签的name属性共同决定了访问路径


namespace三种配置:
    默认名称空间:跟名称空间就是namespace
    跟名称空间:就是namespace="/"
    带名称的名称空间:带名称的名称就是namespace="/demo1"

struts2常量的配置

Struts2常量配置共有3种方式,分別如下:
    在struts.xml文件中使用<constant>元素配置常量。
    在struts properties文件中配置常量。
    在web.xml文件中通辻< init-param>元素配置常量。
为了让大家更好地掌握这3种Struts2常量配置的方式,接下来分別对它们迸行讲解,具体如下:
    1、在struts.xml文件中通辻<constant>元素配置常量
        在struts.xml文件中通过<constant>元素来配置常量,是最常用的方式。在struts.xml文件中通过<constant .../> 元素来配置常量时,需要指定两个必填的属性name和value
        name:该属性制定了常量的常量名
        value:该属性制定了常量的常量值
        
struts.xml中配置常量

1231979-20181128115317472-619768446.png

struts.properties 的格式配置常量

1231979-20181128115116011-149308623.png

1231979-20181128115358444-35228446.png

web.xml 中配置常量

1231979-20181128115437572-1569546515.png

分模块配置

1231979-20181128115942594-1389581618.png


Action的编写的方式

Action的是一个POJO的类

在struts2中,Action可以不继承特殊的类或实现任何特殊的接口,仅仅是一个POJO。POJO全称Plain Ordinary Java Object(简单的Java对象),只要具有一部分getter/setter 方法的那种类,即使可以称为POJO。一般在这个类中,要有一个公共的无参构造方法和一个execute() 方法。

package com.legend.action;

public class TestAction {

    /**
     * 参数的返回值必须是String 类型
     * 方法不能带有参数
     * 可以抛出异常
     * 方法的权限修饰符是public
     */
    public String execute() throws Exception {
        System.out.println("Hello,Struts2被执行了......");
        return "success";
    }
    
}

Action类实现一个Action的接口(实际开发中很少使用)

package com.legend.d_api;

import com.opensymphony.xwork2.Action;
/**
 * Action类详解
 * 方式2:实现一个接口Action
 *      里面有execute方法,提供action方法的规范
 *      Action接口预置了一些字符串,可以在返回结果时使用。为了方便
 * @author qichunlin
 *
 */
public class Demo4Action implements Action{

    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }
    
    
}

在Action接口中提供了5个已经定义的五个常量如下:
1231979-20181128120912810-1774791608.png

Action类继承ActionSupport类(推荐)

package com.legend.d_api;

import com.opensymphony.xwork2.ActionSupport;

/**
 * Action类详解
 * 方式3:继承一个类ActionSupport
 *      帮我们实现了Validateable,ValidateAware,TextProvider,LocaleProvider
 *      如果我们需要用到这些接口的实现时就不需要自己来实现了
 * @author qichunlin
 *
 */
public class Demo5Action extends ActionSupport{

    
    public String method() throws Exception {
        // TODO Auto-generated method stub
        return LOGIN;
    }
    
}

Action访问

在Action标签中有一个属性method,通过method的配置来指定Action中的某个方法执行.

第一种:通过配置method属性完成

1231979-20181128132839829-1164482649.png

Action类
1231979-20181128133129215-519235637.png

struts.xml配置
1231979-20181128133430868-680487657.png

第二种:通过通配符的配置完成

1231979-20181128132819913-1112179152.png

1231979-20181128133129215-519235637.png

在<action>的name属性中使用的 * 表任意字符,method 中的{1}代表name 属性中的出现的第一个*所替代的字符

第三种:动态方法调用

动态发发在访问Struts2中默认是不开启的,如果使用需要开启一个常量

<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>     

动态方法访问主要控制的是在页面端,所以编写Action和配置Action都很简单,关键是访问路径的编写。在做测试的时候主要是直接访问没有页面

1231979-20181128134741529-2107405907.png


Day02 Struts2

1.Struts2访问Servlet的API

前面已经对Struts2的额流程已经执行完成了,但是如果表单中有参数如何进行接受又或者我们需要向页面保存一些数据,又要如何完成?这就下面我们学习ServletAPI的目的来实现这个功能。

1.1 通过ActionContext类访问

Struts2框架提供了Actioncontext类来访问Servlet API ,ActionContext是Action执行的上下文对象,在Actioncontext中保存了Action执行所需要的所有对象,包括parameters、request、session、application等。

ActionContext类访问ServletAPI

1231979-20181219152052728-1764953102.png
1231979-20181219153233098-1866860080.png

put方法使用
1231979-20181219152009492-1687843418.png

获取当前线程的ActionContext对象
1231979-20181219152648029-134850525.png

通过参数key来查找当前ActionContext中的值
1231979-20181219152942475-1733765376.png

返回一个包含所有HttpServletRequest参数信息的 Map对象
1231979-20181219153031085-943551958.png

1231979-20181219153205882-332292464.png

1231979-20181219154402443-452224763.png

项目测试

ServletAPI.jsp页面
1231979-20181219154516756-268124368.png

提交的Action配置
1231979-20181219154643157-998160581.png

ServletAPI2.jsp页面
1231979-20181219155604335-295096168.png

struts.xml
1231979-20181219155514214-907641551.png

web.xml配置
1231979-20181219154802370-1013381951.png

控制台打印前端页面接收的数据
1231979-20181219155252769-1766384526.png

从后台向前端输出的数据
1231979-20181219155418842-1555121629.png
****

1.2 通过特定的接口访问

1231979-20181219160410731-982907790.png

项目测试

1231979-20181219161406799-1545456076.png

1231979-20181219161553318-909463981.png

1231979-20181219161619348-469698530.png

2.结果页面配置

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

  • name属性:指定逻辑视图的名称,默认值是success
  • type属性:指定返回的视图资源的类型,不同的类型代表不同的结果输出,默认值是dispatcher。
在结果页面的配置中,Struts2有两种配置的方式,一种是全局结果页面,一种成为局部结果页面。全局结果是指在这个包下的所有返回相同的字符串的值,都可以向这个页面进行跳转。局部结果是指在某个Action中返回的字符串的值,会向这个页面跳转

2.1 全局结果页面

在package节点下面的节点位置顺序

Content Model : 
    (result-types?, interceptors?, default-interceptor-ref?, default-action-ref?, default-class-ref?, global-
 results?, global-exception-mappings?, action*)

1231979-20181219163611506-169389510.png

数据填充
1231979-20181219163752121-144803424.png

result-type 类型

1231979-20181219163905341-1827091462.png

红色标记的是比较常见的
如果用的时候可以查看文档。javadoc里面有对应的用法

提供具体的使用方法

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
<!-- 是否开启开发模式
    struts.enable.DynamicMethodInvocation = false
 -->
    <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
    
    <package name="result" namespace="/" extends="struts-default">
        <!-- 转发 -->
        <action name="Demo1Action" class="com.legend.action.Demo1Action" method="execute">
            <result name="success" type="dispatcher">/hello.jsp</result>
        </action>
        
        <!-- 重定向 -->
        <action name="Demo2Action" class="com.legend.action.Demo2Action" method="execute">
            <result name="success" type="redirect">/hello.jsp</result>
        </action>
        
        <!-- 转发到action -->
        <action name="Demo3Action" class="com.legend.action.Demo3Action" method="execute">
            <result type="chain">
                 <!-- action的名字 -->
                 <param name="actionName">Demo1Action</param>
                 <!-- action所在的命名空间 -->
                 <param name="namespace">/</param>
            </result>
        </action>
        
        <!-- 转发到action -->
        <action name="Demo4Action" class="com.legend.action.Demo4Action" method="execute">
            <result type="redirectAction">
                <!-- action的名字 -->
                <param name="actionName">Demo1Action</param>
                <!-- action所在的命名空间 -->
                <param name="namespace">/</param>
            </result>
        </action>
    </package>
    
    <!-- 引入xml文件 -->
    <include file="com/legend/b_api/struts.xml"></include>
    <include file="com/legend/c_param/struts.xml"></include>
</struts>   

3.Struts的数据封装------Action处理请求参数的方式

Struts2的数据封装分为两大类,一类是属性驱动,一类是模型驱动。

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

在Struts2中,可以直接在Action中定义各种Java基本数据类型的字段,使这些字段与表单字段数据相对应,并利用这些字段进行数据传递。

3.1.1 属性驱动方式一:提供属性的set方法的方式

Demo8Action的编写
1231979-20181219164953327-193285150.png
1231979-20181219164750220-202363565.png
1231979-20181219164922607-557086744.png

页面
1231979-20181219164831128-211759391.png

struts.xml
1231979-20181219165033557-619993546.png

控制台
1231979-20181219165248563-1996515344.png

总结:该方式如果属性很多回显得数据冗余,修改起来很麻烦

3.1.2 属性驱动方式二:页面提供表达式的方式

对象实体
1231979-20181219165529182-1075875772.png

Demo9Action
1231979-20181219165811292-971080312.png

页面
1231979-20181219165942025-2068541687.png

控制台
1231979-20181219170137097-563424490.png

相比之下,这种方式,比上面的方式更加符合日常编程,面向对象的需求。


3.2 模型驱动

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

编写Action类
1231979-20181219171201296-1779355090.png

页面
1231979-20181219171506280-313841061.png

控制台
1231979-20181219171424626-118381745.png

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

3.3 Struts2中封装集合类型数据

在实际开发中,有些时候我们需要批量插入用户或者批量插入其他的对象,在Action中需要接受多个Action中封装的对象,然后进行传递。表单的数据就要封装到集合中了,一般是List和Map

页面
1231979-20181219172536568-515931323.png

Action类(用的是属性驱动,定义集合,提供getset方法)
1231979-20181219172639947-704562201.png


Day03

1.OGNL

1.1 什么是OGNL

OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换。如果把表达式看作是一个带有语义的字符串,那么OGNL无疑成为了这个语义字符串与Java对象之间沟通的桥梁。

1.2 OGNL 的作用

Struts2默认的表达式语言就是OGNL,它具有一下的特点:

  • 支持对象方法调用。例如:objName.methodName();

  • 支持静态方法调用和值访问,表达式的格式为@[类全名(包括包路径)@[方法名 | 值名] 例如:@java.lang.String@format('foo%s','bar').

  • 支持赋值和表达式串联 例如:price=100,discount=0.8,calculatePrice(),在方法中进行惩罚计算会返回80

  • 访问OGNL上下文 (OGNLContext)和ActionContext

  • 操作集合对象

1.3 OGNL的要素

OGNL的操作实际上就是围绕OGNL结构的三要素而进行的,分别是表达式(Expression)、根对象(RootObject)、上下文环境(Context),

分析OGNL的结构

1.3.1 表达式
表达式是整个OGNL的核心,OGNL会根据表达式去对象中取值。所有OGNL操作都是针对表达式解析后进行的。它表明了此次OGNL操作要做什么。表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容。OGNL支持大龄的表达式语法
1.3.2 根对象(Root)
Root对象可以理解为OGNL的操作对象,表达式规定了做什么,而Root对象则规定了对谁操作。OGNL称为对象图导航语言,所谓对象图,即以一个任意一个对象为根,通过OGNL可以访问与这个对象关联的其他对象。
1.3.3 Context对象
    实际上OGNL的取值还需要一个上下文环境,设置了Root对象,OGNL可以对Root对象进行取值或者写值等操作,Root对象所在的环境就是OGNL的上下文环境(Context)上下文环境就是一个Map类型的对象,在表达式中访问Context中的对象,需要使用#好加上对象名称,即  #对象名称  的形式。

1.2 具体的应用

通用写法

1231979-20181219201144275-1290267054.png

访问对象的方法
String name = (String) Ognl.getValue("getName()", oc, oc.getRoot());//默认取得值是root元素的
        String name2 = (String) Ognl.getValue("#user1.getName()", oc, oc.getRoot());//指定调用user1中的额方法

//给User赋值/修改
String name3 = (String) Ognl.getValue("setName('小花'),getName()", oc, oc.getRoot());//默认取得值是root元素的
        String name4 = (String) Ognl.getValue("#user1.setName('小白'),#user1.getName()", oc, oc.getRoot());//指定调用user1中的额方法
                

1231979-20181219202630927-1648362095.png

访问对象的静态方法
String name = (String) Ognl.getValue("@com.legend.a_ognl.HahaUtils@echo('hello world')", oc, oc.getRoot());//默认取得值是root元素的
        Double PI = (Double) Ognl.getValue("@java.lang.Math@PI", oc, oc.getRoot());//默认取得值是root元素的
        Double PI2 = (Double) Ognl.getValue("@@PI", oc, oc.getRoot());//默认取得值是root元素的
        

1231979-20181219203835695-2022245932.png

获取root中的属性值
String name = (String) Ognl.getValue("name", oc, oc.getRoot());

1231979-20181219203510794-1118243134.png

获取Context中的属性值
String name = (String) Ognl.getValue("#user1.name", oc, oc.getRoot());

1231979-20181219203150521-828437282.png

为属性赋值
String name2 = (String) Ognl.getValue("#user1.name='123',#user1.name", oc, oc.getRoot());//赋值的同时还把值取出来
        Integer age = (Integer) Ognl.getValue("#user2.age", oc, oc.getRoot());//赋值
        

1231979-20181219203409294-1005446510.png


2. 值栈 (ValueStack)

2.1 什么是值栈

ValueStack是Struts的一个接口,字面意义是值栈,OgnlValueStack是ValueStack的实现类,客户端发起一个struts2架构会创建一个action实例创建一个Ognl值栈实例,OgnlValueStack贯穿整个Action的生命周期,struts2中使用OGNL将请求Action的参数封装为对象存储到值栈中,并通过OGNL表达式中读取栈中的对象属性值。

2.2 值栈的内部结构

在OgnlValueStack中包括两部分,值栈和map(即ognl上下文)

1231979-20181219210633445-928665820.png

1231979-20181219210231570-2124587025.png

1231979-20181219210309056-747083628.png

2.3 ActionContext和ValueStack的关系

1231979-20181219210744007-673238669.png

在创建ActionContext 的时候 创建ValueStack的对象,将ValueStack对象给ActionContext。
ActionContext中又一个ValueStack的引用,ValueStack中也有一个ActionContext的引用,
ActionContext获取ServletAPI 的时候,依赖值栈了。

2.4 操作值栈

对Action中的属性提供get方法的方式

因为Action本身在值栈中,Action中的属性也就默认在值栈中了,所以我们可以通过Action的属性提供get的方式来操作值栈。

2.5 EL的特殊字符的使用

'#' 号的使用

获取context的数据

<s:property value="#request.name" />

用于构建一个Map集合

<s:iterator value="#{'aaa':'111','bbb':'222','ccc':'333'}" var="entry">
    <s:property value="key" />-----<s:property value="value" />
    <s:property value="#entry.key" />-----<s:property value="#entry.value" /><br/>
</s:iterator>

<s:radio list="#{'1':'男','2':'女'}" name="sex"></s:radio>
'%' 号的使用

强制解析OGNL表达式

<s:textfiled name="name" value="%{#request.name}" />

强制不解析OGNL表达式

<s:textfiled name="name" value="%{'#request.name'}" />
'$' 号的使用

在配置文件中使用OGNL表达式

在struts的配置文件中使用   .XML文件或者属性文件



Day03 Struts2 学习

1.Struts2的拦截器

1.1 拦截器的概述

    拦截器,在AOP 中用于在某个方法或自负嗯被访问之前,进行拦截然后在之前或之后加入某些操作。拦截器是AOP的一种实现策略。
    在webwork的中文文档的解释为----拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义一个action执行的前后的执行代码,也可以在一个action执行前阻止其执行。同时也是提供了一个提取action可重用的部分的方式。
    拦截器链(Interceptor Chain) 在struts2中称为拦截器栈(Interceptor Stack) 。拦截器链就是将拦截器按一定的顺序连结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

1.2 拦截器的实现原理

大部分拦截器的方法都是通过代理的方式来调用。Struts2的拦截器实现简单。当请求到达struts2的ServletDispatcher时,Struts2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个调用列表中的拦截器。
    Struts2拦截器是可拔插。

1.3 Struts2的执行流程

1231979-20181220104951986-110787493.png

1.4 自定义拦截器(三种实现方式)

1.4.1 实现Interceptor接口

1231979-20181220114658466-1207366033.png

详细

该接口提供了三个方法,其具体介绍如下。
●
void init():该方法在拦截器被创建后会立即被调用,它在拦截器的生命周期内只被调用一
次.可以在该方法中对相关资源进行必要的初始化。
●
void destroy():该方法与init 方法相对应,在拦截器实例被销毁之前,将调用该方法来释放
和拦截器相关的资源。它在拦截器的生命周期内,也只被调用-次。
●
String intercept(ActionInvocation invocation) throws Exception:该方法是拦截器的核心方法,
用来添加真正执行拦截工作的代码,实现具体的拦截操作。它返回一个字符串作为逻辑视
图,系统根据返回的字符串跳转到对应的视图资源。每拦截--个动作请求,该方法就会被
调用一次。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该参
数的invoke()方法,将控制权转给下一个拦截器或者转给Action 的execute()方法。
如果需要自定义拦截器,只需要实现Interceptor接口的三个方法即可。然而在实际开发过程中,
除了实现Interceptor接口可以自定义拦截器外,更常用的一种方式是继承抽象拦截器类
AbstactIntercepter。该类实现了Interceptor 接口,并且提供了init()方 法和destroy()方 法的空实现。
使用时,可以直接继承该抽象类,而不用实现那些不必要的方法。拦截器类AbstractInterceptor中定义的方法如下所示: 

AbstractInterceptor底层源代码具体实现
1231979-20181220115304622-1878130899.png

1.4.2 继承 AbstractInterceptor接口

1231979-20181220122007221-1038080216.png

1.4.3 继承MethodFilterInterceptor 定制拦截方法

1231979-20181220122201162-1733044341.png

具体实现

编写Demo1Action类
1231979-20181220114008481-1209958401.png

配置文件struts.xml
1231979-20181220114510121-712431684.png
1231979-20181220114555798-1379969028.png

定义拦截器栈使用<interceptors>元素和<interceptor-stack>子元素,当配置多个拦截器时,需要使用<interceptor-ref >元素来指定多个拦截器.
    在 interceptorStackName 的值表示配置的拦截器栈的名称; interceptorName 值表示拦截器的名称。除此之外,在一个拦截器栈中还可以包含另一个拦截器栈,默认的拦截器是必须要引入的,
    <!-- 2.注册拦截器栈 -->
    <interceptor-stack name="myStack">
        <!-- 自定义拦截器(建议放在20个拦截器之前) -->
            <interceptor-ref name="MyInterceptor3">
                <!-- 指定那些方法是不拦截的 -->
                <!--  <param name="excludeMethods">find,add</param>-->
                    
                <!-- 指定那些方法需要拦截的 -->
                <param name="includeMethods">find,add</param>
            </interceptor-ref>
                
            <!-- 引用默认的拦截器栈(20个) -->
        <interceptor-ref name="defaultStack"></interceptor-ref>
    </interceptor-stack>

1231979-20181220113851983-495057692.png


2.Struts2 的标签库

对于一个MVC 框架而言,重点是实现两部分:业务逻辑控制器部分和视图页面部分。Struts2 作为优秀的MVC框架,控制器主要有Action来提供支持,而视图控制则是有大量的标签提供支持。

2.1 Struts2 标签库的概述

在JavaWeb中,Struts2标签库是一个比较完善,而且功能比较强大的标签库,他将所有的标签都统一到一个标签库中,从而简化了标签的使用,它还提供主题和模版的支持,极大地简化了视图页面代码的编写,同时还提供Ajax的支持,大大滴丰富了视图的表现形式

2.2 Struts2标签库的分类

早起的JSP页面需要嵌入大量的Java脚本来进行输出,这样使得一个简单的JSP页面加入了大量的
代码,不利于代码的可维护性和可读性。随着技术的发展,逐渐的采用标签库来进行了JSP页面的开发。

Struts2整个标签库分为两类 普通标签和UI标签
1231979-20181220125943855-1807773028.png

普通标签主要是在页面生成时,控制执行流程。UI标签则是以丰富而可服用的HTML文件来显示数据。
普通标签又分为控制标签和数据标签,控制标签用来完成条件逻辑、循环逻辑的控制,也可以用来做集合的操作。数据标签用来输出后台的数据和完成其他数据访问功能。
UI标签又分为表单标签、非表单标签、和Ajax标签。

2.3 Struts2 标签的使用

Struts2标签库被定义在struts-tags.tld 文件中,我们可以在struts-core-2.3.24.jar中的META-INF 目录下找到他。要使用struts2的标签库。一般只需在JSP文件中使用taglib 指令导入Struts2 标签库。
    <%@ taglib prefix="s" uri="/struts-tags" %> 
    

2.4 Struts2的控制标签

在程序开发中,经常要用流程控制实现分支、循环等操作,为此,Struts2标签可能中常用的逻辑控制标签主要包括: <s:if>  <s:elseif> <s:else>  <s:iterator>

2.5 <s:if 》 <s:elseif 》 <s:else》 标签

<s:if test="表达式1">  
    标签体
</s:if> 

<s:elseif test="表达式2">
    标签体
</s:elseif>

<s:else>
    标签体
</s:else>

具体应用

1231979-20181220163212938-485039819.png

1231979-20181220163102837-1728863108.png

2.6 <s:iterator》 标签

<s:iterator》标签主要用于对集合中的数据进行迭代,他可以根据条件遍历集合中的数据。 <s:iterator》 标签的属性看下图

1231979-20181220162854455-2107058553.png

1231979-20181220162953748-397566846.png

1231979-20181220163022920-600100660.png

2.7 <s:property》 标签

用于输出指定的值,通常输出的是value 属性指定的值,<s:property》 标签的属性以及说明
1231979-20181220163434467-651035805.png

1231979-20181220163518688-267472582.png

1231979-20181220164502194-2022588955.png

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- ======================控制标签====================== -->
    <!-- 遍历iterator标签 -->
    <!-- 方式二 -->
    <s:iterator value="#list">
        <!-- 默认取栈顶元素 -->
        <s:property/>
        <br/>
    </s:iterator>
    <!-- ------------------------------ --><hr/>

    <!-- 方式二 -->
    <s:iterator value="#list" var="name">
        <s:property value="#name"/><!-- 默认取栈顶元素 -->
    </s:iterator>
    <hr>
    
    <!-- 打印1~100数字的表达 -->
    <s:iterator begin="1" end="100" step="1" >
        <s:property />|
    </s:iterator>
    <!-- ------------------------------ --><hr />
    
    
    
    
    <!-- list标签的使用 -->
    <s:if test="#list.size()==4">
        list的长度是4
    </s:if>
    
     
    <s:elseif test="#list.size()==3">
        list的长度是3
    </s:elseif> 
    
    <s:else>
        list的长度不是3也不是4
    </s:else>
    
    <hr/>
    <!-- --------------------------------- --><hr/>
    
    
    <!-- 数据标签property -->
    <!-- 用来配合ognl表达式页面来取值
        #   代表从ActionContext中获取
     -->
    数组的长度是<s:property value="#list.size"/>
    
    
    <!-- struts2表单标签 -->
    <s:form action="Demo2Action" namespace="/"> 
        <s:textarea name="name" label="用户名" />
        <s:submit value="提交"></s:submit>
    </s:form>
    
    <s:debug></s:debug>
    <s:checkbox></s:checkbox>
    
    <s:a href="https://www.baidu.com">百度</s:a>
</body>
</html>

test.jsp

使用struts2的标签要注意,需要该有的标签属性都要写不然会报错  我就是没有写name属性就一直报错
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <s:form action="TestAction">
        <s:textfield label="用户名" name="username"></s:textfield>
        <s:password label="密码" name="password"></s:password>
        <s:password label="确认密码" name="password2"></s:password>
        <s:radio name="sex" label="性别" list="#{'0':'男','1':'女' }" value="0"/>
        
        <s:select label="所在城市" listValue="value" listKey="key" list="#{'beijing':'北京','shanghai':'上海' }" name="city"></s:select>
        <s:checkboxlist name="hobby" labelposition="left" label="爱好" list="{'篮球','足球'}"></s:checkboxlist>
        <s:reset value="重置"></s:reset>
        <s:submit value="提交"></s:submit>
    </s:form>
</body>
</html>

1231979-20181220175218032-489114507.png

转载于:https://www.cnblogs.com/qichunlin/p/10032395.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值