<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. vue-resource初体验

    这个插件是用于http请求的,类似于jquery的ajax函数,支持多种http方法和jsonp. 下面是resource支持的http方法. get: {method: 'GET'},save: { ...

  2. bzoj 3506 && bzoj 1552 splay

    查最小值,删除,翻转... 显然splay啊... #include<iostream> #include<cstdio> #include<algorithm> ...

  3. 【BZOJ-1656】The Grove 树木 BFS + 射线法

    1656: [Usaco2006 Jan] The Grove 树木 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 186  Solved: 118[Su ...

  4. SVG中 transform矩阵遇到的兼容性问题

    SVG  transform矩阵遇到的兼容性问题.在chrome.safari.火狐.360极速浏览器上都正常显示的图,在手机端就不行啊!!! 先上图. 图1     PC端浏览器 图2   iPho ...

  5. maven上传jar到nexus本地仓库

    一.nexus新增本地仓库 Hosted Repository:本地仓库,部署组织内部的版本内容 Proxy Repository:代理仓库,代理远程的公共仓库,如maven中央仓库 Virtual ...

  6. 通过实现System.IComparable接口的CompareTo方法对两个类进行比较

    假设现在有一个学生类 class Student { int age; public Student(int age) { this.age = age; } } 要使学生类之间能进行比较,实现Sys ...

  7. Nuget Command Console

    Get-Package -ListAvailable -Filter contracts 命令行 注意选择 程序包源

  8. fedora自带OpenJDK,所以如果安装官方的JDK的话要先删除OpenJDK

    1:rpm -qa|grep jdk 查看当前的jdk情况. 2:yum -y remove java java-1.7.0-openjdk* 卸载openjdk,这个过程中因为依赖原因可能会卸载一些 ...

  9. JVM内存垃圾回收方法

    1.概述 1.1.为什么要回收? 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断地分配内存空间而不进行回收.除非内存无限大,我们可以任性地分配而不回收,但是事实并非如此.所以,垃圾回收是必须 ...

  10. applicationContext.xml

    <bean id="dataSource" parent="parentDataSource"> <property name="u ...