2018.12.19 Struts2 框架总复习

总结Struts2 框架

struts2技术的优势

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

常见的Web层框架

  • Struts2
  • Struts1
  • WebWork
  • SpringMvc

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

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

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

Struts2框架的快速搭建

实现步骤:

  • 下载Struts2的开发包 https://struts.apache.org/
  • 选择对应的版本下载 然后解压出来一个文件夹

目录结构的总结

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包

Struts2项目以来的额基础JAR包说明

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

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

扫描二维码关注公众号,回复: 4571106 查看本文章

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

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

这个是一个普通的类如何编程一个Action类呢,接下来完成配置Action

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

标准的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>

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

还是很成功的

下面来总结一写执行的流程
从客户端发送请求过来,先经过前端控制器(核心过滤器 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元素的常用属性

    表中就是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中配置常量

struts.properties 的格式配置常量

web.xml 中配置常量

分模块配置


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个已经定义的五个常量如下:

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属性完成

Action类

struts.xml配置

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

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

第三种:动态方法调用

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

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

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


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


put方法使用

获取当前线程的ActionContext对象

通过参数key来查找当前ActionContext中的值

返回一个包含所有HttpServletRequest参数信息的 Map对象

项目测试

ServletAPI.jsp页面

提交的Action配置

ServletAPI2.jsp页面

struts.xml

web.xml配置

控制台打印前端页面接收的数据

从后台向前端输出的数据

****

1.2 通过特定的接口访问

项目测试

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*)

数据填充

result-type 类型

红色标记的是比较常见的
如果用的时候可以查看文档。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的编写


页面

struts.xml

控制台

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

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

对象实体

Demo9Action

页面

控制台

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


3.2 模型驱动

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

编写Action类

页面

控制台

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

3.3 Struts2中封装集合类型数据

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

页面

Action类(用的是属性驱动,定义集合,提供getset方法)


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 具体的应用

通用写法

访问对象的方法

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中的额方法
                

访问对象的静态方法

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元素的
        

获取root中的属性值

String name = (String) Ognl.getValue("name", oc, oc.getRoot());

获取Context中的属性值

String name = (String) Ognl.getValue("#user1.name", oc, oc.getRoot());

为属性赋值

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


2. 值栈 (ValueStack)

2.1 什么是值栈

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

2.2 值栈的内部结构

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

2.3 ActionContext和ValueStack的关系

在创建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文件或者属性文件

猜你喜欢

转载自www.cnblogs.com/qichunlin/p/10032395.html