• 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用来查找呈现页面上的属性值)

    第七章  构建用户界面

  • 相关阅读:
    详解mysql int类型的长度值问题
    linux的作业控制(job control)
    Linux环境变量的设置和查看方法
    gearman入门初步
    VIM 乱码终极解决
    android系统通过图片绝对路径获取URI的三种方法
    Buck电路调试
    第二次画板
    1 第一次画PCB总结
    一起学习模拟电路之1
  • 原文地址:https://www.cnblogs.com/dayInAndOut/p/3857688.html
Copyright © 2020-2023  润新知