Struts2笔记

来源:互联网 发布:淘宝上买刀具犯法吗 编辑:程序博客网 时间:2024/06/06 09:07

Struts2

概述

  • web层框架

  • 对servlet的封装

struts2做了什么

  • 将任意请求与action类中的方法建立请求
  核心过滤器:将请求分配到不同的类  映射文件(structs.xml):为核心过滤器提供类与请求的映射  映射文件的优化:                  用method属性将类中的方法与请求建立关系                  用通配符将任意请求与类中的方法建立关系
  • 将action与servlet解耦,为拦截器的动态代理提供先决条件
  • 在页面和Web层封装和解析JavaBean

核心功能

  • POJO对象作为action,处理请求
  • execute方法与servlet解耦
  • 支持JSP,FreeMarker,Velocity
  • 基于SpringAOP思想的拦截器机制
  • 校验功能
  • ajax支持

常见web层框架

  • structs1
  • structs2
  • springMVC
  • WEBWork

漏洞

  • 远程执行服务器脚本
  • 重定向漏洞

配置

  • 配置文件按先后顺序覆盖同名配置

default.properties(内置)

  • 位于struts-core.jar包的org.apache.struts2包下
  • 作用
    • 定义了一些常量(键值对)
    • 功能开关

struts-default.xml(内置)

  • struts-core.jar包下
  • 默认包structs-default,包类型abstract
  • 作用:
    • 定义了Bean元素、结果集类型、拦截器

struts-plugin.xml(内置)

  • 插件配置文件,用于扩展插件

struts.xml(自定义)

  • 配置约束文件
  • package标签
    • name:任意不可重复(一般用模块名称)
    • namespace:”/”,用于区分请求同名路径,默认名称空间”“,structs后台解析默认加/
    • extends
    • struts-default,继承默认配置中的拦截器等设置
    • 自定义
    • action的访问路径:namespace+action的name属性
  • action标签
    • name对应请求路径
    • class对应action类
  • result标签
    • name: 结果集(逻辑视图)
    • 内置视图:NONE,SUCCESS,ERROR,INPUT,LOGIN
    • 标签内容:响应路径
    • param标签:给结果集传递参数

struts.properties(自定义)

  • 用于覆盖内置常量

  • 常用常量配置

    • struts.devMode激活xml文件自动重新加载
    <!-- 开发者模式:好处自动加载核心配置文件,提供友好的错误页面。副作用:异步请求的错误无法处理会抛弃 -->    <!-- <constant name="struts.devMode" value="true" /> -->    <!-- 只自动加载核心配置文件 -->    <constant name="struts.configuration.xml.reload" value="true"/>    <!-- 简单样式 -->    <constant name="struts.ui.theme" value="simple"/>

    • struts.i18n.encoding=UTF-8 解决post乱码

    • struts.configuration.xml.reload=true 自动重新加载structs.xml

    • struts.i18n.reload = true自动重新加载国际化文件

    • struts.action.extension=action,, 配置action请求的默认扩展名

    • struts.ui.theme=xhtml 设置页面标签显示样式

    • struts.objectFactory=struts负责创建Action对象类

    • struts.enable.DynamicMethodInvocation=true支持动态调用

    • struts.multipart.maxSize=2097152 上次文件大小

  • 配置文件分离

  <struts>      <include file="struts-part1.xml"/>      <include file="struts-part2.xml"/>  </struts>

web.xml

  • 配置前段控制器(核心过滤器)
  • url-pattern:/*

默认配置

若不指定名称空间namespace,默认为“/”(有争议)若没有class属性,执行默认处理类ActionSupport,该默认处理类在struts-default.xml 文件中有定义。默认会执行Action类中的execute方法,而ActionSupport的execute会默认返回 success逻辑视图。若不指定结果集result的名字默认为“success”。

jar包

asm-*.jar:字节码操作类库 (.class文件)commons-fileupload-1.2.2.jar:文件上传组件,2.1.6版本后需要加入此文件。commons-io-2.0.1.jar:传文件依赖的jar包。commons-lang-2.5.jar:对java.lang包的增强,主要是提供字符串等操作的公用方法。commons-logging-1.1.x.jar:ASF出品的日志包,Struts 2框架使用这个日志包来支持Log4J和JDK 1.4+的日志记录。(JCL,java通用日志接口)freemarker-2.3.*.jar:模版引擎,struts2标签库,依赖freemarker ,Struts 2的UI标签的模板使用FreeMarker编写。javassist*.jar 生成代理的类库。log4j*.jar:一个日志实现。ognl-3.0.x.jar:OGNL对象图导航语言(Object Graph Navigation Language), struts2框架通过其读写对象的属性。(类似于EL但更强大)struts2-core-2.3.x.jar:Struts 2框架的核心类库。xwork-core-2.3.x.jar:Command命令模式框架, Struts2和WebWork都基于和依赖xwork。

Config Brower插件

  • 复制到lib下
  • http://ip地址:端口/上下文名字/config-browser/index.action查看配置情况

核心过滤器

  • StrutsPrepareAndExecuteFilter
  • 控制器模式

拦截器

  • 封装复用代码
  • 按照配置文件中上下顺序执行

拦截器原理

  • 创建代理对象
  • 注入方法执行者
  • 初始化方法执行者
  • 执行拦截器方法
    • 执行完毕,invoke放行
    • return,阻断action

与过滤器对比

过滤器(filter) javaweb学习,拦截服务器端所有资源的访问 (静态、 动态)。在web.xml拦截器(Interceptor) struts2 学习,在struts2框架内部,只对Action访问进行拦截 (默认拦截器 ,无法拦截静态web资源, 如果要拦截静态资源,比如html、jsp,可以将静态web资源放入WEB-INF\xxx, 通过Action间接访问)

拦截器实现

  • 实现Interceptor 接口
  • 继承AbstractInterceptorn,覆盖intercept方法
  • 继承MethodFilterInterceptor类,覆盖doIntercept方法

拦截器栈(Interceptor Stack):

  • 将拦截器按照一定的顺序连接成一条链后的一个称呼。
  • 在访问被拦截的方法时,拦截器链的拦截器按照定义的顺序被依次调用

拦截器配置

  • 在包下注册拦截器和拦截器栈

      在包下注册拦截器和拦截器栈  <Interceptors>    <Interceptor name="myInterceptor" class=""/>        <!--自定义拦截器栈-->        <Interceptor-stack>            <!--添加拦截器-->        <Interceptor-ref name="myInterceptor"/>        <!--添加拦截器栈-->        <Interceptor-ref name="defaultStack"/>    </Interceptor-stack>             </Interceptors>
  • 全局拦截器

    在包下配置<default-Interceptor-ref name="myStack">
  • 局部拦截器

    • 覆盖同名全局拦截器
    在action中书写<Interceptor-ref name="myStack">
  • 排除与包含

    • 必须继承methodFilterInterceptor,abstractInterceptor不支持方法排除
    在拦截器栈中配置<param name="excludeMethods">method1,method2</param>

Action

  • 用于代理servlet处理业务逻辑
  • 三种书写方式

    • 实现action接口
    • 命令模式:设计模式,将“行为请求者”与“行为实现者”解耦
    • 继承ActionSupport类(重写execute方法)
    • POJO类
    • 反射机制
    • public String execute();
  • 路径查找机制

    • 如果访问的路径,没有定义action,会自动向上层路径寻找。
  • 配置默认action

     配置默认的action:访问的name:如果访问时action找不到,默认会调用errorPage这action      <default-action-ref name="errorPage">      </default-action-ref>      <!-- 配置一个action,给默认action用目的:只是跳转到一个页面-->      <action name="errorPage">       <result>/errorPage.jsp</result>      </action>
  • 配置默认页面

    struts2默认寻找路径下index页面,需要在web.xml中配置index页面<default-action-ref name="user" />包下配置主入口,需要删除index页面

方法与请求的映射关系

  • 一一对应

    <action name="" class="" method="">
  • 通配符

    <action name="user_*" class="bean.User" method="{1}"><action name="*_*" class="{1}" method="{2}">会引起安全问题
  • 动态方法调用

    书写访问路径href="product!add.action"有安全隐患需要在structs.xml中配置常量0配置(注解项目)中使用

访问servlet的API

  • 获取与域对象对应 的Map
  • 操作Map简介操作域对象

ActionContext访问

  • 这是一个门面对象

接口注入

  • 根据需要实现接口
    • ServletRequestAware
    • ServletResponseAware
    • SessionAware
    • ServletContextAware
  • 在action初始化的时候,将接口实现类中持有的域对象注入Action中

ServletActionContext访问

  • 静态get方法获取域对象
    • get方法从ThreadLocal中获取一个ActionContext,其中持有一个域对象的map

结果页面的配置

全局结果页面

  • 对包下所有Action有效

局部结果页面

  • 局部覆盖全局

结果集类型

  • chain
    • 跳转(转发)到Action
  • dispatcher
    • 转发到页面
  • redirect
    • 重定向到页面
  • redirectAction
    • 重定向到Action
    • 同一个包下一般省略路径
  • json
    • 用于回写json数据
    • 需要导入Struts2-json-plugin-2.3.32包
    • 需要action所在的包继承json-default
    • 内部解决了死循环内存溢出问题

数据封装

参数的接收机制

  • ParametersInterceptor 的doIntercept方法封装参数
  • invoke执行action的业务逻辑

属性驱动

set方法

  • 需要在action中定义字段和set方法

表达式方法

  • 页面中以bean.age形式书写,属性与bean类属性一一对应
  • 在Action中持有Bean实例,并提供Bean的get和set方法
    • 封装数据时,struts会调用get方法获取Action中 的Bean,在拦截器的循环中逐个封装属性
    • 如果没有get方法,每次的Bean都是new出来的,并覆盖之前的引用,因此只能封装一条 属性

模型驱动

  • 实现ModelDriven接口
  • Action中持有Bean引用且实例化
    • ModelDriven的实现类中封装方法对Bean进行非空判断,为空则直接返回
  • Action中重写getModel方法
  • Action中同时有模型驱动与属性驱动时,模型驱动有限封装数据,剩下的数据由属性驱动处理
  • 模型中有复杂类型时,在页面用ongl表达式书写
  • model在值栈中存放的名字是”model”,取值用model.xxx

复杂类型封装

内置转换器

  • boolean 和 Boolean
  • char和 Character
  • int 和 Integer
  • long 和 Long
  • float 和 Float
  • double 和 Double
  • Date 可以接收 yyyy-MM-dd格式字符串
  • 数组 可以将多个同名参数,转换到数组中

list集合

  • 属性驱动的表达式方法
  • list[0].age形式书写,list[0]对应一个bean实例
  • Action中或者model中持有list实例,并提供set和get方法

Set集合

  • 属性驱动的表达式方法
  • list.makeNew[0].age形式书写,list[0]对应一个bean实例
  • Action中或者model中持有set实例,并提供set和get方法

map集合

  • 属性驱动的表达式方法
  • map[“key”].age形式书写map[“key”]对应一个”key”与 bean实例的键值对
  • Action中或者model中持有map实例,并提供set和get方法

自定义转换器

  • 实现 TypeConverter
    • 直接实现 TypeConverter 接口
    • 继承 DefaultTypeConverter 类
    • 继承 StrutsTypeConverter 类
  • 提供页面到Bean的数据转换和Bean到页面的数据显示
  • 注册转换器

类型转换错误处理机制

  • ConversionErrorInterceptor收集并封装错误
    • 将错误封装进actionErrors,actionMessages,fieldErrors集合中
    • 集合被ValidationAwareSupport持有,ValidationAwareSupport被ActionSupport持有
    • 集合为Map

值栈

概述

  • 挂载在request上的一个对象
    • request.getAttribute(“struts.valueStack”)
  • 实现类OnglValueStack
  • 生命周期与request相同

内部结构

root对象

  • CompoundRoot root;
    • extends CopyOnWriteArrayList,是一个ArrayList集合
    • ONGLValueStack中持有引用
    • ONGLValueStack的构造方法中调用setRoot方法时创建这个对象
    • 持有Action的引用

Context对象

  • OgnlContext context;
    • 是Map的一个实现类
    • ONGLValueStack中持有引用
    • ONGLValueStack的构造方法中调用setRoot方法时创建这个对象
    • 持有一个HashMap用于存取值
    • 持有root对象的引用

ValueStack与ActionContext的关系

  • ActionContext内置了一个map,ValueStack存放在这个map中
  • ActionContext是一个门面,持有Action类所有相关数据的引用
  • ActionContext的put/get,其实是对其中持有的Map

存放数据机制

  • 直接调用值栈的set方法存值
    • 创建了一个map
    • 这个map调用了push方法被压入root栈
  • root栈存放数据遵循先进后出原则
  • map栈按键值对存取数据
  • Action提供成员变量,并提供get方法
    • Action就在root栈中,Action属性可以被搜索

创建过程分析

  • StrutsPrepareAndExecuteFilter的dofilter方法

  • prepare.createActionContext方法创建了ActionContext

    • 创建了ActionContext的线程绑定的实例
    • 创建了值栈 ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
    • 将servlet相关对象放入了map栈中stack.getContext().putAll(dispatcher.createContextMap(request, response, null));
    • 此时root栈为空
  • prepare.wrapRequest

    • 加强了request
    • 装饰类的引用放入ActionContext
  • execute.executeAction

    • getContainer().getInstance(ActionProxyFactory.class).createActionProxy创建了Action的动态代理

    • 注入了方法执行者的引用

      ActionInvocation inv = createActionInvocation(extraContext, true);container.inject(inv);持有所有的拦截器,invoke方法中迭代拦截器,拦截器执行拦截方法并回调
    • 注入代理并加载参数

      container.inject(proxy);      proxy.prepare();      invocation.init(this);      初始化了方法执行者
    • 初始化方法执行者

      createAction(contextMap);生成了Action(定义的Action实例)stack.push(action);将action压入root栈顶contextMap.put("action", action);将action放入map栈createInterceptors(proxy);List<InterceptorMapping> interceptorList = new          ArrayList<InterceptorMapping(proxy.getConfig().getInterceptors());根据proxy之前加载的参数获取所有拦截器并注入方法执行者(现在可以执行拦截器方法并回调了)好处:将拦截的控制权交给拦截器责任链模式
    • 执行拦截器方法

      如果实现了modelDriven接口,拦截器将model压入root栈栈顶param拦截器执行intercept方法时,将参数放入root栈,如果 栈中有model,就会先放入model中,剩下的作为字段存入root栈

  • prepare.cleanupRequest

ONGL

  • Object-Graph Navigation Language

作用

  • 对象方法调用
    • ’itcast’.toUpperCase()
  • 类静态方法调用和值访问
    • 格式:@java.lang.Math@max(10,20)
    • @cn.itcast.MyConstant@APP_NAME
    • struts.ognl.allowStaticMethodAccess=true开启功能
  • 赋值操作和表达式串联
  • 访问ONGL上文
  • 操作集合对象
    • 构造
    • {“green”, “red”, “blue”}构造一个List,#{“key1” : “value1”, “key2” : “value2”, “key3” : “value3”}构造一个Map
    • 投影操作
    • collection.{XXX} ,将每个元素的xxx属性组成新集合

表达式

  • 格式
  • 访问root栈
    • set放入的值,通过名字(引用)访问
    • 压入值栈的值,[0].top
  • Map栈内容 (如request、response、session、servletContext、attr、parameters)
    • 需要#key来引用访问,例如 #request.name 相当于 request.getAttribute(“name” )
  • 搜索机制
    • 不加#,直接写名字(引用)
    • 执行值栈的findValue方法
    • (在Context中)搜索root栈,之后搜索Map栈
  • 强制解析/强制不解析
    • %{‘key’}强制不解析
    • %{key}强制解析
    • 标签默认不解析,此时从值栈中取值需要强制解析
  • 配置文件访问值栈
    • ${}

EL表达式对ONGL的解析

  • 加强了request的getAttribute方法
    • 装饰模式,持有request实例
    • getAttribute方法先执行request的默认方法,如果搜索不到值,获取值栈的引用,并调用值栈的findValue方法
  • 使用#获取值会报错
    • 调用了findValue方法,而findValue方法把#作为字符串的一部分解析

标签库

控制标签

<s:if> <s:elseif> <s:else>标签test属性可以接受ONGL表达式<s:a>标签    <!-- action是action的名字 -->    <s:a action="product_find" namespace="/">        <!-- name:是参数名,value:参数值        原因:value:是个ognl表达式         -->        <s:param name="name" value="'苹果'"/>        我是新的超链接    </s:a>

数据标签

<s:property/>  value属性,接收OGNL表达式  default 属性, 如果OGNL表达式,取不到值,default设置显示默认值  escapeHtml 属性, 是否对HTML标签转义输出 (默认是转义,可以关闭)<s:iterator>    value:迭代的集合,支持OGNL表达式,如果没有设置该属性,则默认使用值栈栈顶的集合来迭代    var:引用变量的名称,该变量是集合迭代时的子元素        会被压入root栈,且在map栈建立副本    status:引用迭代时的状态对象IteraterStatus实例,        int getCount(),返回当前迭代了几个元素;        int getIndex(),返回当前迭代元素的索引;        Boolean isEvent(),        boolean isOdd(),        boolean isFirst(),        boolean isLast(),<s:fielderror/><s:actionmessage/><s:i18n><s:param>

模板和主题

  • Struts2 模板文件,支持两种Freemarker生成 (.ftl模板文件) , Velocity生成 (.vm 模板文件) — struts2默认采用 Freemarker

  • 提供四种主题 :

    • Simple 没有任何修饰效果,最简单主题
    • Xhtml 通过 布局表格 自动排版 (默认主题 )
    • css_xhtml 通过CSS进行排版布局
    • ajax 以Xhtml模板为基础,增加ajax功能
  • 配置默认布局

    <constant name="struts.ui.theme" value="simple"/>

表单标签

action属性,对应 struts.xml <action>元素name属性;namespace属性,对象 struts.xml <package>元素 namespace属性<s:textfield>, <s:password>, <s:hidden>, <s:textarea><s:textfield> 文本域 ,生成 <input type=”text” ><s:password> 密码域 ,生成<input type=”password” ><s:hidden> 隐藏域 , 生成 <input type=”hidden” ><s:radio><s:checkboxlist><s:select><s:radio> 接收list或者map 生成一组单选按钮     <s:select> 接收list或者map ,生成一组下拉列表     <s:checkboxlist> 接收list或者map ,生成一组复选框    list="{'nan','nv'}"    list="#{'nan':'男','nv':'女'}"

数据回显的区别

  • 表单标签:name支持ognl表达式,value不支持,直接显示值
  • 其他所有通用标签,value支持ognl表达式的

文件上传