<context-param>
<param-name>pattern</param-name>
<param-value>yyyy-MM-dd hh:mm:ss</param-value>
</context-param>
//获取当前 WEB 应用的初始化参数 pattern
ServletContext servletContext = ServletActionContext.getServletContext();
System.out.println(servletContext);
String pattern = servletContext.getInitParameter("pattern");

获取web.xml中配置的参数

Struts2 中, HTML 表单将被直接映射到一个 POJO,通过params拦截器,类中定义对应属性,及对应set方法即可。

params拦截器会把请求参数的值赋给栈顶对象对应的各个属性,如果栈顶对象没有对应属性,则往下找下一个对象对应的属性。

如果已经有了一个javabean,表单传过来了bean的属性,就不需要再action中再写一遍bean的每个属性来赋值了,可以直接写一个bean的变量,通过ModelDriven拦截器,如果 Action 类实现了 ModelDriven 接口,该拦截器将把 ModelDriven 接口的 getModel() 方法返回的对象置于栈顶,然后params拦截器就会将表单属性赋给栈顶的空的bean对象了。继承接口后这样写(可以没有setEmployee方法)

  

 private Employee employee;
@Override
public Employee getModel() {
employee = new Employee();
return employee;
}

代码里不能直接return new Employee();因为和成员变量employee没关系,所以其他用到employee对象的时候,它是空。

每次求情,只要有ModelDriven的getModel()方法,一般栈顶对象都会是该方法返回的对象!

用class.hashcode()方法,可以看对象是不是同一个。

关于回显:

  从值栈站顶开始查找匹配的属性,若找到,就添加到value属性中,就会自动给赋上。

下图29。18

通常情况下,用ModelDriven拦截器要和Preparable拦截器一起用。

Struts 2.0 中的 modelDriven 拦截器负责把 Action 类以外的一个对象压入到值栈栈顶

而 prepare 拦截器负责准备为 getModel() 方法准备 model

 5). 存在的问题: 

 getModel 方法

 public Employee getModel() {
if(employeeId == null)
employee = new Employee();
else
employee = dao.get(employeeId); return employee;
} I. 在执行删除的时候, employeeId 不为 null, 但 getModel 方法却从数据库加载了一个对象. 不该加载!
II. 指向查询全部信息时, 也 new Employee() 对象. 浪费! 6). 解决方案: 使用 PrepareInterceptor 和 Preparable 接口. 7). 关于 PrepareInterceptor [分析后得到的结论] 若 Action 实现了 Preparable 接口, 则 Struts 将尝试执行 prepare+ActionMethodName 方法,
若 prepare+ActionMethodName 不存在, 则将尝试执行 prepareDo+ActionMethodName 方法.
若都不存在, 就都不执行. 若 PrepareInterceptor 的 alwaysInvokePrepare 属性为 false,
则 Struts2 将不会调用实现了 Preparable 接口的 Action 的 prepare() 方法 [能解决 5) 的问题的方案] 可以为每一个 ActionMethod 准备 prepare[ActionMethdName] 方法, 而抛弃掉原来的 prepare() 方法
将 PrepareInterceptor 的 alwaysInvokePrepare 属性置为 false, 以避免 Struts2 框架再调用 prepare() 方法. 如何在配置文件中为拦截器栈的属性赋值: 参看 /struts-2.3.15.3/docs/WW/docs/interceptors.html
一共有三种方法,有的可以为一个action修改值,有的可以为所有action修改至,下面是为所有action修改属性
<interceptors>
<interceptor-stack name="parentStack">
<interceptor-ref name="defaultStack">
<param name="params.excludeParams">token</param>
</interceptor-ref>
</interceptor-stack>
</interceptors> <default-interceptor-ref name="parentStack"/>

如图,私人订制,为需要的方法,添加上prepareMethod方法,来自自定义

修改拦截器中部分属性的配置如下:

paramsPrepareParmsStack拦截器栈,执行顺序:

params -> prepare -> modelDriven -> params

//***************************************类型转换*********

Parameters拦截器:把请求参数映射到action属性,能自动完成字符串和基本数据类型的转换。

如果类型转换失败:

若 Action 类没有实现 ValidationAware 接口: Struts 在遇到类型转换错误时仍会继续调用其 Action 方法, 就好像什么都没发生一样.

若 Action 类实现 ValidationAware 接口:Struts 在遇到类型转换错误时将不会继续调用其 Action 方法:  Struts 将检查相关 action 元素的声明是否包含着一个 name=input 的

result(一般情况下,继承ActionSupport类就好了,然后,都是将表单输入页面当做该result,好比,后台age需要int,你输入个string,输入的不合法的值,我还给你返回这个界面).  如果有, Struts 将把控制权转交给那个 result  元素; 若没有 input 结果, Struts 将抛出一个异常

此时返回到input的result页面后,输入框上面还有错误消息提示,输入不合法之类的(xhtml主题下)

覆盖默认的出错消息

在对应的 Action 类所在的包中新建  ActionClassName.properties 文件, ClassName 即为包含着输入字段的 Action 类的类名

在属性文件中添加如下键值对: invalid.fieldvalue.fieldName=xxx

这样就可以了,但是在simple主题下,没用。这个时候需要用标签来处理,值栈中有错误信息(${fieldErrors.arg[0]}、<s:fielderror fieldName="age"></s:fielderror>放在输入框后面即可)

 <body>

     <!--
问题1: 如何覆盖默认的错误消息?
1). 在对应的 Action 类所在的包中新建
ActionClassName.properties 文件, ActionClassName 即为包含着输入字段的 Action 类的类名
2). 在属性文件中添加如下键值对: invalid.fieldvalue.fieldName=xxx 问题2: 如果是 simple 主题, 还会自动显示错误消息吗? 如果不会显示, 怎么办 ?
1). 通过 debug 标签, 可知若转换出错, 则在值栈的 Action(实现了 ValidationAware 接口) 对象中有一个 fieldErrors 属性.
该属性的类型为 Map<String, List<String>> 键: 字段(属性名), 值: 错误消息组成的 List. 所以可以使用 LE 或 OGNL 的方式
来显示错误消息: ${fieldErrors.age[0]} 2). 还可以使用 s:fielderror 标签来显示. 可以通过 fieldName 属性显示指定字段的错误. 问题3. 若是 simple 主题, 且使用 <s:fielderror fieldName="age"></s:fielderror> 来显示错误消息, 则该消息在一个
ul, li, span 中. 如何去除 ul, li, span 呢 ?
在 template.simple 下面的 fielderror.ftl 定义了 simple 主题下, s:fielderror 标签显示错误消息的样式. 所以修改该
配置文件即可. 在 src 下新建 template.simple 包, 新建 fielderror.ftl 文件, 把原生的 fielderror.ftl 中的内容
复制到新建的 fielderror.ftl 中, 然后剔除 ul, li, span 部分即可. 问题4. 如何自定义类型转换器 ?
1). 为什么需要自定义的类型转换器 ? 因为 Struts 不能自动完成 字符串 到 引用类型 的 转换.
2). 如何定义类型转换器:
I. 开发类型转换器的类: 扩展 StrutsTypeConverter 类.
II. 配置类型转换器:
有两种方式
①. 基于字段的配置:
> 在字段所在的 Model(可能是 Action, 可能是一个 JavaBean) 的包下, 新建一个 ModelClassName-conversion.properties 文件
> 在该文件中输入键值对: fieldName=类型转换器的全类名.
> 第一次使用该转换器时创建实例.
> 类型转换器是单实例的! ②. 基于类型的配置:
> 在 src 下新建 xwork-conversion.properties
> 键入: 待转换的类型=类型转换器的全类名.
> 在当前 Struts2 应用被加载时创建实例. --> <s:debug></s:debug> <s:form action="testConversion" theme="simple">
Age: <s:textfield name="age" label="Age"></s:textfield>
${fieldErrors.age[0] }
^<s:fielderror fieldName="age"></s:fielderror>
<br><br> Birth: <s:textfield name="birth"></s:textfield>
<s:fielderror fieldName="birth"></s:fielderror>
<br><br> <s:submit></s:submit>
</s:form> </body>

类型转换的笔记

以上是字符串到基本数据类型的类型转换,下面是字符串到引用类型的类型转换(如日期,这个时候需要自定义类型转换器)

自定义类型转换器必须实现 ongl.TypeConverter 接口或对这个接口的某种具体实现做扩展

通常情况下,自定义类型转换器的类对StrutsTypeConverter进行扩展就好了

1. Department 是模型, 实际录入的 Department. deptName 可以直接写到

s:textfield 的 name 属性中. 那 mgr 属性如何处理呢 ?

struts2 表单标签的 name 值可以被赋为 属性的属性: name=mgr.name, name=mgr.birth

2. mgr 中有一个 Date 类型的 birth 属性, Struts2 可以完成自动的类型转换吗 ?

全局的类型转换器可以正常工作!

 public class DateConverter extends StrutsTypeConverter {

     private DateFormat dateFormat;

     public DateConverter() {
System.out.println("DateConverter's constructor...");
} public DateFormat getDateFormat(){
if(dateFormat == null){
//获取当前 WEB 应用的初始化参数 pattern
ServletContext servletContext = ServletActionContext.getServletContext();
System.out.println(servletContext);
String pattern = servletContext.getInitParameter("pattern");
dateFormat = new SimpleDateFormat(pattern);
} return dateFormat;
} @Override
public Object convertFromString(Map context, String[] values, Class toClass) { System.out.println("convertFromString..."); if(toClass == Date.class){
if(values != null && values.length > 0){
String value = values[0];
try {
return getDateFormat().parseObject(value);
} catch (ParseException e) {
e.printStackTrace();
}
}
} //若没有转换成功, 则返回 values
return values;
} @Override
public String convertToString(Map context, Object o) { System.out.println("convertToString..."); if(o instanceof Date){
Date date = (Date) o;
return getDateFormat().format(date);
} //若转换失败返回 null
return null;
} }

Date类型自定义转换器示例

//**************************************国际化**************************************

 1. 国际化的目标

 1). 如何配置国际化资源文件

 I.   Action 范围资源文件: 在Action类文件所在的路径建立名为 ActionName_language_country.properties 的文件
II. 包范围资源文件: 在包的根路径下建立文件名为 package_language_country.properties 的属性文件,
一旦建立,处于该包下的所有 Action 都可以访问该资源文件。注意:包范围资源文件的 baseName 就是package,不是Action所在的包名。
III. 全局资源文件
> 命名方式: basename_language_country.properties
> struts.xml <constant name="struts.custom.i18n.resources" value="baseName"/> IV. 国际化资源文件加载的顺序如何呢 ? 离当前 Action 较近的将被优先加载. 假设我们在某个 ChildAction 中调用了getText("username"): (1) 加载和 ChildAction 的类文件在同一个包下的系列资源文件 ChildAction.properties
(2) 加载 ChildAction 实现的接口 IChild,且和 IChildn 在同一个包下 IChild.properties 系列资源文件。
(3) 加载 ChildAction 父类 Parent,且和 Parent 在同一个包下的 baseName 为 Parent.properties 系列资源文件。
(4) 若 ChildAction 实现 ModelDriven 接口,则对于getModel()方法返回的model 对象,重新执行第(1)步操作。
(5) 查找当前包下 package.properties 系列资源文件。
(6) 沿着当前包上溯,直到最顶层包来查找 package.properties 的系列资源文件。
(7) 查找 struts.custom.i18n.resources 常量指定 baseName 的系列资源文件。
(8) 直接输出该key的字符串值。 2). 如何在页面上 和 Action 类中访问国际化资源文件的 value 值 I. 在 Action 类中. 若 Action 实现了 TextProvider 接口, 则可以调用其 getText() 方法获取 value 值
> 通过继承 ActionSupport 的方式。
1.在action中访问国际化资源文件的value值
String username = getText("username");
2.带占位符的
String time = getText("time",Arrays.asList(new Date()));
syso,就可以打印出来 II. 页面上可以使用 s:text 标签; 对于表单标签可以使用表单标签的 key 属性值
> 若有占位符, 则可以使用 s:text 标签的 s:param 子标签来填充占位符
> 可以利用标签和 OGNL 表达式直接访问值栈中的属性值(对象栈 和 Map 栈) time=Time:{0}(这个是在i18n.properties中写的) <s:text name="time">
<s:param value="date"></s:param>
</s:text> ------------------------------------ time2=Time:${date}(类似一个ongl表达式的情况,在i18n.properties中直接获取值) <s:text name="time2"></s:text> 3). 实现通过超链接切换语言. I. 关键之处在于知道 Struts2 框架是如何确定 Local 对象的 !
II. 可以通过阅读 I18N 拦截器知道.
III. 具体确定 Locale 对象的过程: > Struts2 使用 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 对象。 IV. 具体实现: 只需要在超连接的后面附着 request_locale 的请求参数, 值是 语言国家 代码.
<a href="testI18n.action?request_locale=en_US">English</a>
<a href="testI18n.action?request_locale=zh_CN">中文</a> > 注意: 超链接必须是一个 Struts2 的请求, 即使 i18n 拦截器工作!

在页面上使用国际化(xhtml主题):

在页面上使用国际化(simple主题):

国际化资源文件:

**************************************国际化**************************************//

//**************************************动态加载国际化**************************************

i18n拦截器

具体实现代码:

**************************************动态加载国际化**************************************//

struts2笔记(2)的更多相关文章

  1. struts2笔记(3)

    关于回显: 如果是int型,默认就会回显为0,如果不想让回显,则Integer就好 //**************************************声明式验证************* ...

  2. struts2笔记

    Struts2 中, HTML 表单将被直接映射到一个 POJO,通过params拦截器,类中定义对应属性,及对应set方法即可. Struts2 中,任何一个POJO都可以是一个action类. S ...

  3. struts2笔记4

    1.自定义struts拦截器 应用场景:如果用户登陆后可以访问action中的所有方法,如果用户没有登陆不允许访问action中的方法,并且提示“你没有操作权限” 1)两个页面,一个用户登陆user. ...

  4. struts2 笔记04 杂记

    流程: 1. StrutsPrepareAndExcuteFilter:StrutsPrepareAndExcuteFilter作为前端控制器,是整个Struts2的调度中心. 2. ActionMa ...

  5. struts2 笔记03 异常支持、防止页面刷新和后退、方法验证

    Struts2对异常支持(声明式异常.自动的异常处理), 异常处理(运行期异常事务自动回滚) 1. 自定义异常类,继承RuntimeException或Exception实现构造方法. 2. 配置异常 ...

  6. struts2 笔记02 文件上传、文件下载、类型转换器、国际化的支持

    Struts2的上传 1. Struts2默认采用了apache commons-fileupload  2. Struts2支持三种类型的上传组件 3. 需要引入commons-fileupload ...

  7. struts2 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用

    Struts2登录 1. 需要注意:Struts2需要运行在JRE1.5及以上版本 2. 在web.xml配置文件中,配置StrutsPrepareAndExecuteFilter或FilterDis ...

  8. Struts2笔记——利用token防止表单重复提交

    在一些项目中经常会让用户提交表单,当用户点击按钮提交后,如果再次浏览器刷新,这就会造成表单重复提交,若是提交的内容上传至服务器并请求数据库保存,重复提交的表单可能会导致错误,然后跳转到错误界面,这是一 ...

  9. Struts2笔记——struts常用标签

    使用struts标签前,首先要配置struts2架构,然后导入标签库,jsp插入如下语句: <%@taglib uri="/struts-tags" prefix=" ...

随机推荐

  1. web.xml加载顺序

    一 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Ser ...

  2. sql三维数据

    今天有个钢铁项目在导入数据时 存货规格各种缺 相吐血 原表结构是这样的 编码.规格.名称 三种存货 三种都有想同的规格 规格对分厚度和宽度 那么问题来了 简简单单的几个厚度宽度 三种商品 就到了 10 ...

  3. 使用XHR2或Jsonp实现跨域以及实现原理

    我们直接使用XMLHttpRequset请求外部接口 会发现 报这个错误 其实浏览器成功发送请求并拿回了数据  只是浏览器的同源策略 禁止了获取  在xhr2 服务器端支持跨域 需要在响应头增加 Ac ...

  4. Beta阶段项目终审报告

    先上图 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件主要是用来解决玩狼人杀这款桌游时无牌.无法官.游戏流程不熟悉等情况的.我觉得我们对典型 ...

  5. 关于ACM的总结

    看了不少大神的退役帖,今天终于要本弱装一波逼祭奠一下我关于ACM的回忆. 从大二上开始接触到大三下结束,接近两年的时间,对于大神们来说两年的确算不上时间,然而对于本弱来说就是大学的一半时光.大一的懵懂 ...

  6. UOJ59 WC2013 小Q运动季

    题意:给一个模线性方程组,构造解满足尽量多的方程. 直接枚举. 模数两两互质,先排除无解的,然后CRT,然而要高精,上python. 直接高消,有完美解. 2^20暴搜. 分解模数,对每个质数高消,C ...

  7. python模块(shelve,xml,configparser,hashlib,logging)

    1.1shelve模块 shelve 模块比pickle模块简单,只有一个open函数,返回类似字典对象,可读可写:key必须为字符串, 而值可以是python所支持的数据类型. shelve模块主要 ...

  8. MAC上安装 HLA(High Level Assembly)

    1.安装HLA 最新版的hla汇编器可在这里下载,支持MacOs,Linux,Windows平台 2.安装步骤 将下载好的hla程序包放在Mac根目录下 最重要的一步是设置好环境变量,打开Mac根目录 ...

  9. C++构造函数2

    一.构造函数分类 普通构造函数,复制(拷贝)构造函数,赋值构造函数, #include <iostream> using namespace std; class A { public: ...

  10. SQL2008 无日志附加MDF文件

    SQL数据在附加的时候..有时会因为日志文件过大..或者一些其他问题造成附加失败.. 笔者遇到的问题是数据库主文件(*.mdf)超过25G..日志文件超过200G..附加的耗时简直日了狗了..最后超时 ...