1、表单标签
表单标签将在HTML文档里被呈现为一个表单元素
使用表单标签的优点:
---表单回显
---对页面进行布局和排版
标签的属性可以被赋值为一个静态的值或一个OGNL表达式,如果在赋值时使用了一个OGNL表达式并把它用%{}括起来,这个表达式将会被求值(强制进行OGNL解析)。
表单标签:
1.使用和HTML的form标签的用法差不多
2.Struts2的form标签会生成一个table以进行自动的排版
3.可以对表单提交的值进行回显:从栈顶对象开始匹配属性,并把匹配的属性值赋到对应的标签的value中,
若栈顶对象没有对应的属性,则依次向下找相对于的属性
①textfield、password、hidden标签
---textfield标签将被呈现为一个输入文本字段,password标签将被呈现为一个口令字段,hidden标签将被呈现为一个不可见字段:
名字 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
maxlength | integer | 由这个标签呈现出来的HTML元素所能容纳的字符最大个数 | |
readonly | boolean | false | 用来表明该输出元素是不是只读的 |
size | integer | 尺寸属性 |
password标签扩展子textfield标签,多了一个showPassword属性,该属性是布尔型,默认值为false,它决定表单回显是是否显示输入密码。
②textarea标签:将呈现一个为HTML文本域元素
名字 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
cols | integer | HTMLcols属性 | |
readonly | boolean | false | 用来表明该textarea元素是不是只是可读的 |
rows | boolean | HTMLrows属性 | |
wrap | boolean | HTMLwrap属性 |
③checkbox标签
---checkbox标签将呈现为一个HMTL复选框元素,该复选框元素通常应用于提交一个布尔值
---当包含着一个复选框的表单被提交时,如果某个复选框被选中了,它的值将为true,这个复选框在HTTP请求里增加一个请求参数,但如果该复选框未被选中,在请求中就不会增加一个请求参数。
---checkbox标签解决了这个局限性,它采取的办法是为单个复选框元素创建一个配对的不可见字段
---checkbox标签有一个fieldValue属性,该属性指定地址将在用户提交表单时作为被选中的单选框的实际值发送到服务器,如果没有使用fieldValue属性,单选框的值将为true或者false
名字 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
fieldValue | String | true | 该单选框的实际值 |
list、listKey和listValue三个属性对radio、select、checkboxlist等标签非常重要
<input type="radio" name="city" value="1"/>Atlanta
<input type="radio" name="city" value="2"/>Chicago
<input type="radio" name="city" value="3"/>Detroit
1 - Atlanta
2 - Chicago ——>list
3 - Detroit 1、2、3——>listKey Atlanta、Chicago、Detroit——>listValue
可以把一个String,一个数组,一个Enumeration,Iterator,Map或者Collection赋给list属性
④radio标签
---radio标签将呈现为一组单选按钮,单选按钮的个数与程序员通过该标签的list属性提供的选项的个数相同。
---一般地,使用radio标签实现“多选一”,对于“真/假”则该使用checkbox标签
名字 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
list* | String | 用来充当选项来源的可遍历对象 | |
listKey | String | 用来提供选项值的对象属性 | |
listValue | String | 用来提供选项行标的对象属性 |
⑤select标签:将呈现一个select元素
名字 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
emptyOption | boolean | 指明是否要在标题下面插入一个空白选项 | |
headerKey | String | 选项列表中的第一个选项的键 | |
headerValue | String | 选项列表中的第一个选项的值 | |
list* | String | 用来充当选项来源的可遍历对象 | |
listKey | String | 用来提供选项值的对象属性 | |
listValue | String | 用来提供选项行标的对象属性 | |
mutiply | boolean | false | 指明是否允许多重选择(多选多)
|
size | integer | 同时显示在页面里的选项的个数 |
⑥optiongroup 标签:对 select 元素所提供的选项进行分组,每个选项有它自己的来源
名字 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
list* | String | 用来充当选项来源的可遍历对象 | |
listKe | String | 用来提供选项值的对象属性 | |
listValue | String | 用来提供选项行标的对象属性 |
⑦checkboxlist标签:将呈现一组多选框
名字 | 数据类型 | 默认值 | 说明 |
---|---|---|---|
list* | String | 用来充当选项来源的可遍历对象 | |
listKey | String | 用来提供选项值的对象属性 | |
listValue | String | 用来提供选项行标的对象属性 |
2、主题元素
默认情况下,form标签将呈现为一个HTML form元素和一个 table 元素
每一种输入标签都将呈现为一个带标号的输入元素,而这个输入元素将被包含在一个 tr 元素和 td 元素的内部
主题:为例让所有的UI标签能够产生同样的视觉效果而归集到一起的一组模板。即所有风格相近的模板被打包为一个主题
---simple:把UI标签翻译成最简单的HTML对应元素,而且会忽视行标属性
---xhtml:xhtml是默认的主题,这个主题的模板通过使用一个布局表格提供了一种自动化的排版机制。
---css_xhtml:这个主题里的模板与xhtml主题里的模板很相似,但他们将使用css来进行布局和排版。
---ajax:这个主题里的模板以xhtml主题里的模板为基础,但增加了一下Ajax功能。
修改主题:
---通过UI标签的theme属性
---在一个表单里,若没有给出某个UI标签的theme属性,它将使用这个表单的主题
---在page、request、session或application中添加一个theme属性
---修改struts.properties文件中的struts.ui.theme属性。
3、ModeDriven拦截器
①把Action和Model隔开(struts2-5——note.txt)
在使用Struts作为前端的企业级应用程序时把Action和Model清晰的隔离开是有必要的:有些Action类不代表任何Model对象,它们的功能仅限于提供显示服务。(如果Action类实现了ModelDriven接口,该拦截器将把ModelDriven接口的getModel()方法返回的对象置于栈顶)
---当用户触发add请求时,ModelDriven拦截器将调用EmployeeAction对象的getModel()方法,并把返回的模型(Employee实例)压入到ValueStack栈。
---接下来Parameters拦截器将把表单字段映射到ValueStack栈的栈顶对象的各个属性中,因为此时ValueStack栈的栈顶元素是刚被压入的模型(Employee)对象,所以该模型将被填充,如果某个字段在模型里没有匹配的属性,Param拦截器将尝试ValueStack栈中的下一个对象。
4、Preparable拦截器
Struts2.0中的modelDriven拦截器负责把Action类以外的一个对象压入到值栈栈顶,而prepare拦截器负责准备为getModel()方法准备model。
①PrepareInterceptor拦截器使用方法:
---若Action实现Preparable接口,则Action方法需实现prepare()方法。
---PrepareInterceptor拦截器将调用prepare()方法,prepareActionMethodName()方法或prepareDoActionMethodName()方法。
---PrepareInterceptor拦截器根据firstCallPrepareDo属性决定获取prepareActionMethodName、prepareDoActionMethodName的顺序。默认情况下先获取prepareActionMethodName(),如果没有改方法,就寻找prepareDoActionMethodName(),如果找到对应的方法就调用该方法。
---PrepareInterceptor拦截器会根据alwaysInvokePrepare属性决定是否执行prepare()方法。
②使用paramsPrepareParamsStack拦截器栈
---paramsPrepareParamsStack从字面理解上来说,这个stack的拦截器调用的顺序为:首先params,然后prepare,接下来modelDriven,最后再params。
---Struts2设计上要求modelDriven在params之前调用,而业务中prepare要负责准备model,准备model又需要参数,这就需要在prepare之前运行params拦截器设置相关参数这个也就是创建paramsPrepareParamsStack的原因。
---流程如下:
* params拦截器首先给action中的相关参数赋值,如id。
* prepare拦截器执行prepare方法,prepare方法中会根据参数,如id,去调用业务逻辑,设置mode对象。
* modelDriven拦截器将mode对象压入value stack,这里的mode对象就是在prepare中创建的。
* params拦截器在将参数赋值给mode对象。
* action的业务逻辑运行。
5、类型转换
①类型转换概述
---从一个HTML表单到一个Action对象,类型转换是从字符串到非字符串。
HTTP没有“类型”的概念,每一项表单输入只可能是一个字符串或一个字符串数组,在服务器端,必须把String转换为特定的数据类型。
---在Struts2中,把请求参数映射到action属性的工作由Parameters拦截器负责,它是默认的defaultStack拦截器中的一员,Parameters拦截器可以自动完成字符串和基本数据类型之间转换。
②类型转换出错时如何进行处理
类型转换失败:
---若Action类没有实现ValidactionAware接口:Struts在遇到类型转换错误时仍会继续调用其Action方法,就好像什么都没发生一员。
---若Action类实现了ValidactionAware接口:Struts在遇到类型转换错误时将不会调用其Action方法,Struts将检查相关action元素的声明是否包含着一个name=input的result,如果有,Struts将把控制权转交给你个result元素,若没有input结果,Struts将抛出一个异常。
③自定义类型转换器:自定义类型转换器必须实现ongl.TypeConverter接口或对这个接口的某种具体实现做扩展。
如何自定义类型转换器?
1).为什么需要自定义类型转换器?因为Struts2不能自动完成字符串到引用类型的转换。
2).如何定义类型转换器?
---开发类型转换器的类:扩展StrutsTypeConverter类
---配置类型转换器:
①基于字段的配置:
>在字段所在的Model(可能是Action,也可能是JavaBean)的包下,新建一个ModelClassName-converter.properties文件
>在该文件中输入键值对:fieldName=类型转换器的全类名。
②基于类型的配置:
>在src下新建xwork-conversion.properties
>键入:待转换的类型=类型转换器的全类名。
④类型转换与复杂对象配合使用
6、消息处理与国际化
①概述:在程序设计领域,把在无需改写源代码即可让开发出来的1应用程序能够支持多种语言和数据格式的技术叫国际化
与国际化对应的是本地化,指让一个具备国际化支持的应用程序支持某个特定的地区。
Struts2国际化是建立在Java的国际化基础上的:
---为不同国家/语言提供对应的消息资源文件
---Struts2框架会根据请求中包含的Locale加载对应的资源文件
---通过程序代码取得该资源文件中指定key对应的消息
②配置国际化资源文件
---Action范围资源文件:在Action类文件所在的路径建立名为ActionName_language_country.properties的文件。
---包范围资源文件:在包的根路径下建立文件名为package_langugae_country.properties的属性文件,一旦建立,处于该包下所有的Action都可以访问该资源文件。注意:包范围资源文件的baseName就是package,不是Action所在的包名。
---全局资源文件:
* 命名方式:basename_language_country.properties
* struts.xml:<constant name="struts.custom.i18n.resources" value="baseName" />
* struts.properties:struts.custom.i18n.resources=baseName
---临时指定资源文件:<s:i18n..../>标签的name属性指定临时的国际化资源文件
---国际化资源文件加载的顺序? 离当前Action较近的将被优先加载
③利用超链接实现动态加载国际化资源文件
---Struts1使用i18n拦截器处理国际化,并且将其注册在默认的拦截器中
---i18n拦截器在执行Action方法前,自动查找请求中一个名为request locale的参数。如果该参数存在,拦截器就将其作为参数,转换成locale对象,并将其设为用户默认的Locale(代表国家/语言环境)。并把其设置为session的WW_TRANS_I18N_LOCALE属性。
---若request没有名为request locale的参数,则i18n拦截器会从Session中获取WW_TRANS_I18N_LOCALE属性值,若该值不为空,则将该属性值设置为浏览器默认的Locale。
---若session中的WW_TRANS_I18N_LOCALE的属性值为空,则从ActionContext中获取Locale对象。
7、Struts2运行流程分析
①请求发送给StrutsPrepareAndExecuteFilter
②StrutsPrepareAndExecuteFilter询问ActionMapper:该请求是否是一个Struts2请求(即是否返回一个非空的ActionMapping对象)
③若ActionMappe认为请求是一个Struts2请求,则StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy
④ActionProxy通过Configuration Manager询问框架的配置文件,确定需要调用的Action类即Action方法
⑤ActionProxy创建一个ActionInvocation的实例,并进行初始化
⑥ActionInvocation实例在调用Action是的过程前后,涉及到相关拦截器(Intercepter)的调用
⑦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果,调用结果的execute方法,渲染结果。在渲染的过程中可以使用Struts2框架中的标签
⑧执行各个拦截器invocation.invoke()之后的代码
⑨把结果发送到客户端
8、输入验证
①概述
---一个完善的web应用程序必须确保用户输入是否合法、有效
---Struts2的输入验证
* 基于XWork Validation Framework的声明式验证:Struts2提供了一些基于XWork Validation Framework的内建验证程序。使用这些验证程序不需要编程,只要在一个XML文件里对验证程序应该如何工作作出说明就可以了
** 哪些字段需要进行验证
** 使用什么验证规则
** 在验证失效时应该把什么样的出错消息发送到浏览器端
---编程验证:通过编写代码来验证用户输入
* Struts2提供了一个Validateable接口,可以使Action类实现这个接口以提供编程验证功能。
* ActionSupport类已经实现Validateable接口。
②声明式验证(字段验证&&非字段验证)
字段验证VS非字段验证
---字段验证优先,可以为一个字段配置多个验证规则
---非字段验证规则优先
---大部分验证规则支持两种验证器,但个别的验证规则只能使用非字段验证,例如表达式验证。
非字段验证:不只针对某个字段,而是针对多个字段的输入值之间的逻辑关系进行校验。例如:对再次输入的密码进行判断。
字段验证:判断某个字段属性的输入是否有效
---先明确对哪一个Action的哪一个字段进行验证:age
---编写配置文件
*把struts2\struts-2.3.16.1\apps\struts2-blank.war\example下的Login-validation.xml
文件复制到当前Action所在的包
*把该配置文件改为:把Login改为当前Action的名字.(ActionClassName-validation.xml)
** 若一个Action类的多个action使用不同的验证规则:ActionClass-alias-validation.xml,例如UserAction-User_create- validation.xml
*编写验证规则:参见struts2\struts-2.3.16.1\docs\WW\docs\validation.html文档即可
---若验证失败则转向input的那个result,所以需要配置name=input的result
<result name="input">/validation.jsp</result>
---如何显示错误消息
*在配置文件中可以定义错误消息
<!-- 针对age属性进行验证,基于字段的验证 -->
<field name="age">
<field-validator type="int">
<param name="min">20</param>
<param name="max">50</param>
<message>Age needs to be between ${min} and ${max}</message>
</field-validator>
</field>
该错误消息可以国际化,可以在国际化资源文件中加入一个键值对
<message key="error.int"></message>
error.int=^^^Age needs to be between ${min} and ${max}
*如何显示错误消息?
** 若使用的是非simple,则自动显示错误消息
** 若使用的是simple主题,则需要s:fieldError标签或直接使用EL表达式(使用OGNL)
${fieldErrors.age[0] }
OR
<s:fielderror fieldName="age"></s:fielderror>
9、Struts2内建的验证程序
①required:确保某给定字段的值不是空值null
②requiredstring:确保某给定字段的值既不是空值null,也不是空白
---trim参数:默认为true,表示为struts在验证该字段值之前先剔除前后空白格
③stringlength:验证一个非空字段值是不是有足够长度
---minlength:相关字段的最小长度,若没有给出这个参数,该字段将没有最小长度限制。
---maxlength:相关字段的最大程度,若明天给出这个参数,该字段将没有最大长度限制。
---trim:在验证之前是否去除前后空格
④date:确保某给定日期字段的值落在一个给定的范围内
---max:相关字段的最大值,若没有给出这个参数,该字段将没有最大值限制。
---min:相关字段的最小值,若没有给出这个参数,该字段将没有最小值限制。
⑤email:检查给定String值是否有一个合法的email
⑥url:检查给定的String值是否是一个合法的url
⑦regex:检查某给定字段的值是否与一个给定的正则表达式模式相匹配
---expression*:用来匹配的正则表达式
---caseSensitive:是否区分字母大小写,默认为true
---trim:是否去除前后空格,默认为true
⑧int:检查给定整数字段值是否在某一个范围内
---min:相关字段的最小值,若没有给出这个参数,该字段将没有最小值限制。
---max:相关字段的最大值,若没有给出这个参数,该字段将没有最大值限制。
⑨conversion:检查对给定Action属性进行的类型转换是否会导致一个转换错误,该验证程序还可以默认的类型转换消息的基础上添加一条自定义的消息。
⑩expression和fieldexpression:用来验证给定字段是否满足个OGNL表达式
---前者是一个非字段验证程序,后者是一个字段验证程序。
---前者在验证失败时将生成一个action错误,而后者在验证失败时会生成一个字段错误。
---expression*:用来进行验证的OGNL表达式
10、自定义验证器
①自定义验证器必须实现Validator接口
②ValidatorSupport和FieldValidatorSupport实现了Validator接口
---若需要普通的验证程序,可以继承ValidatorSupport类
---若需要字段验证程序,可以继承FieldValidatorSupport类
---若验证程序需要接受一个输入参数,需要为祖国参数增加一个相应的属性
③注册验证程序:自定义验证器需要在类路径里的某个validators.xml文件里注册:验证框架首先在根目录下找validators.xml文件,没找到validators.xml文件,验证框架将调用默认的验证设置,即defalut.xml里面的配置信息。