struct2 笔记

HTTP 特点: 无状态和基于文本

基于文本 于 强类型的技术匹配 引来大量的数据绑定工作—— 文本 跟 数据类型的矛盾  —— 核心:数据处理

servlet

将HTTP公开给java语言

提供了会话机制。

深入的需求研究 ——servlet不能解决的问题——由此引入的struct2的 功能

1. 数据验证(高级验证)

2. 访问 业务逻辑 及 数据层

struct2 遵循  MVC设计模式 —— 分离 重用

控制器 : 框架帮助完成所有控制器的任务,因此在本书,控制器的内容直接就被跳过了。

本书讲的是动作被控制器调用之后的内容。

模型: 即处理  对应struct的 动作action

有两个作用: 

封装 业务逻辑

数据传输

---------------------------------------------

第二章

(声明性)架构 组件

是一种特殊的配置方式,它以描述

而不是编码的方式

创建应用程序的架构。

声明性架构 入口点 structs.xml (主要是包含其他的 xml,模块化)

它在classes目录下: /WEB-INF/classes/structs.xml

structs.xml:

1. 设置 框架属性:

<structs>

<constant name="structs.devMode" value="true" />

...

<include file="包名/xxx.xml" />

</structs>

2.  在默认包内(即应用的根目录)定义全局动作

<package name="default" namespace="/" extends="structs-default">

<action name="xxx">

<result>/xxx.jsp</result>

</action>

</package>

3. include 模块的xml

模块的xml:

 除了action 和action里的result元素之外,仅有的 其他元素是 structs根元素和package元素。

structs元素 是所有Struct2 xml文件的 强制性的 文档根元素

package是 容器元素,它声明了一个url 映射到动作时,用到的命名空间:

应用名 + package元素里的namespace + 动作名.action

注释: 即使 一个简单的不需要 动作处理 的jsp页面, 也要用空的动作组件来转到该jsp页面,

这样可以保持架构一致, 且可以隐藏资源的真正结构,而只显示动作的逻辑命名空间

HelloWorld 动作 代码:

主要包括:

动作 的业务逻辑处理,并 返回 用来 选择结果 的 控制 字符串。

数据存储:

1. 领域数据 总是存储在 动作 中。——  动作 组件保存数据,动作组件的java代码就能方便地访问这些数据。

2. 动作对象 自身 被放在ValueStack中, 框架在 ValueStack上 提供了这些 动作的属性。——框架的其他区域也可以访问这些数据。

------------------------------------

struct2 核心组件

第三章, 动作 action

动作完成请求的核心处理

动作 包含业务逻辑,承载数据

struct2 是一个动作的框架,动作是这个框架的核心

动作 的作用:

封装 业务逻辑—— 需要做的实际工作

承载数据

选择结果页面

动作 携带数据——   由于数据保存在动作本地,因此在执行业务逻辑的过程中

可以很方便地访问,使得访问数据的代码变得简洁。

注释:Struct2 通过为每一个映射到这个动作的请求 创建一个新的动作实例,来存储数据。

返回控制字符串

返回的 字符串 指向  呈现视图的 结果组件的名字

包容器  像java包,—— 包 还提供了 一种继承 机制,能够 继承已经定义的组件

(继承)

组织包

<package name="xxxx" namesapce="xxx/xxx/xxx" extends="structs-default">

<action>

...

</action>

...

</package>

命名空间: 同c++命名空间

当一个url到达时,如 localhost/appName/aaa/test.action

框架会 到 aaa的命名空间里,去找叫test的动作。

注意:

如同c++ 一样, 可以为不同包 设置相同的命名空间(就像namespace std一样)

注意: 处于实用的原因我们把动作分在不同的包内,但是 没有理由 连命名空间也不同。

即: 把动作分在不同的包内,是因为功能和共享等原因

  但是 命名的空间 是没有什么理由 需要为每一个包 起一个不同的命名空间,这是没必要的。

除非是出于,单纯的为了让用户能够看到url的变化。 如进入安全访问的页面时,在命名空间上多一个

secure,这样用户知道,自己在进行安全的访问: localhost/appName/func/secure/xxx.action

如果不设置namespace,默认命名空间 ???

extends  structs-default 包

可以继承 和使用 这个包中定义的组件 ——  默认拦截器战

通常 必须  扩展 structs-default! 为了使用它提供的拦截器

核心内容:动作 —— 可选的Action接口(实现 execute()方法)

另外: Action接口提供了一些 返回控制字符串 的常量值

ActionSupport类 实现了Action接口 ,并且实现了一些另外的接口。—— 它 提供了 一些接口

来和 存在于默认拦截器栈中的 workflow拦截器 配合实现 基本验证工作。

workflow拦截器 就像所有拦截器一样致力于将横切任务从动作的执行逻辑中

分离转移出去

检验逻辑被 workflow 拦截器调用, 而这些拦截器都是在动作执行之前触发。——实现了分离

对象 数据

第四章 使用拦截器 追加 工作流

拦截器 完成 框架大部分的基础工作

动作 是框架的核心和灵魂

使框架达到高水平关注分离,拦截器起到至关重要的作用

拦截器消除了动作组件中的横切任务

如:日志记录、

横切任务 —— 它不是某一个动作所特有,它横向关注所有动作。 从而创建 清晰的 关注点的分离

预处理、和后加工 仍然属于 横切 ——  如 数据转移(通过params拦截器实现):

几乎所有动作都需要 将一些数据  从请求参数转移到属性上 —— 它必须在动作触发前完成。

可以视为仅是为动作的实际工作做准备工作。

拦截器机制—— 不是让控制器直接调用一个动作,而是有一个处在控制器和动作组件之间的组件。

框架创建了一个 ActionInvocation对象,该对象封装了动作和一系列在动作执行之前之后触发的拦截器。

拦截器的强大功能之一是改变 工作流

就像本章目录一样。

拦截器可能会 返回 控制字符串,动作不会被触发,甚至栈中的下一个拦截器也不会被调用。

分层 让软件整洁, 益处是可重用和可配置。

把 可重用的逻辑 分隔到 拦截器 后,可以把它  应用到  所有动作 上。

如:通过继承default-stack 获得 代码重用 的益处:我们 能够重用  Struct2 框架开发人员 编写的

数据转移代码、数据验证代码和国际化代码等。

拦截器分层的 另一个好处是,可以定制拦截器,可以追加删除拦截器等。

虽然拦截器很重要,但一般不会去编写很多拦截器。

在 开发动作 时,时刻注意  可以被转移到拦截器中的  任何 任务。

拦截器的工作原理:

框架 调用 --> ActionInvocation的 invoke()(每次invoke()方法被调用,ActionInvocation都会检测,调用接下来的拦截器,

如果所有拦截器都被调用后,invoke会执行动作):

Interceptor 接口 定义intercept方法(传参是ActionInvocation实例)是拦截器执行的入口点

拦截器 触发时做的工作

1.预处理

2.决定是否将控制权转移给剩余拦截器和动作: 调用 invoke()方法,将 控制 转移给后续拦截器,或者返回控制字符串中断执行

最终invoke返回,一个控制字符串,指示哪个结果被呈现。

3.后加工

1. 预处理阶段  拦截器可以操作数据

2. 如果拦截器决定请求处理不应该继续,它可以不调用invoke()方法。而是直接返回一个控制字符串。

通过这种方式,它可以停止后续执行,并且自行决定 哪个结果会被呈现。

3. invoke返回控制字符串之后,拦截器可以改变数据,进行后加工,但是,结果页面 已经被确定了,此时只能修改呈现的 数据 而已,页面已经确定。

研究 Struct2 内建的 拦截器

我们说过,好的框架能够自动化web应用中大部分的日常任务。 内建拦截器提供了这个自动化。

数据转移拦截器:

params拦截器:

把数据 转移到 ValueStack上第一个匹配的属性上。

static-params拦截器:

也将参数转移到ValueStack公开的属性上,不同的是参数的来源。 转移的参数定义在

声明性架构的动作元素中。

servlet-config 拦截器: (注意 来源自哪,转移到哪)

将来源于Servlet API的各种对象(比如HttpServletRequest, 会话等等),

它不是像前面那样转移到ValueStack

而是转移到 动作 实现的 接口 的方法。

如下一系列接口用来取得不同的Servlet API对象:

ServletContextAware 设置 ServletContext

ServletRequestAware设置HttpServletRequest

。。。

fileUpload拦截器:

将文件转换为常规请求参数,以便像普通参数一样转移到动作(实际通过params拦截器,转移到ValueStack)上。

面向 工作流 的拦截器:

workflow拦截器:(放在拦截器栈的最后,之前的拦截器都要通过它)

功能:与动作协作(动作需实现一些接口函数,可以通过继承ActionSupport),提供 数据验证以及验证错误发生时改变后续工作流的功能。(它只提供这些功能,可以查源码就明白)

只有动作实现了Validateable接口,才会进行数据验证。

如果动作实现了ValidationAware接口,拦截器通过调研hasErrors方法来确认 验证逻辑 是否生产错误信息,如果出现错误信息,

返回INPUT控制字符串。

为了避免不能通过验证(如预填充的表单),有了excludeMethods参数,来过滤。

还可以在 intercept-ref 中 使用 param来配置拦截器。

exception拦截器:

使用  exception-mapping 元素 —— 告诉exception拦截器 一个特定的异常呈现哪个页面:

<global-results>

<result name="error">/xxx/Errorxxx.jsp</result>

</global-results>

<exception-mapping exception="java.lang.Exception" result="error" />

综上:

拦截器的实现多种多样

像workflow拦截器需要 动作 实现某些接口来配合

像exception拦截器需要 xml文件 来建立

params拦截器,需要 属性 等等

因为: 拦截器做了框架的大部分工作,所有什么样的工作都有,也就没有一个统一的样子。

也无法统一。工作差别太大了。

第五章 数据转移 类型转换

数据转移和类型转换,这些工作都是准备工作而已

发生在请求处理周期的两端

第六章

OGNL 就像指针一样 指向ValueStack上的属性

实际上,OGNL可以指向一系列的对象,ValueStack只是默认的对象而已。 这一系列的对象叫做ActionContext。

它包含的对象主要有:ValueStack  Request Session等等。

property标签的 value属性 告诉标签呈现到页面上的 属性。

即:property通过 value属性的值 作为OGNL表达式 来查找 要呈现的属性。 没有使用#操作符指明ActionContext中的特

定对象,所有会默认在ValueStack查找。 如果不存在 空值会被转换为空字符串。

struct2标签的属性(这里说的是标签自己的属性像value、default等等) 分为两类:如 例子中的value 和 default属性

字符串属性(被标签当做String值使用)可以强制使用 ${expression}来当OGNL解析

和非字符串属性(标签当做OGNL表达式,OGNL用来查找呈现页面上的属性值)

第七章  构建用户界面

原文地址:https://www.cnblogs.com/dayInAndOut/p/3857688.html