前面说道实现Action一般选择继承ActionSupport的方式,因为它提供了一些额外的功能,比如基本的数据验证和访问本地信息。
基本数据验证
由于ActionSupport类实现了Validateable接口,那么在该动作被触发的时候会在执行动作方法之前先执行validate方法,如果验证没有通过,那么就会返回信息输入结果页面。因此我们只需要在Action中重写validate方法就可以实现数据的验证了。
input.jsp
<body>
<s:if
test="hasFieldErrors()">
<s:iterator
value="fieldErrors">
<font
color="#FF0000"><s:property
value="value[0]"/></font><br>
</s:iterator>
</s:if>
<form
action="login.action"
method="post">
username : <input
type="text"
name="userName"/><br/>
password :<input
type="password"
name="password"><br/>
<input
type="submit"
value="submit"/>
</form>
</body>
执行:
结果:
这里有几点需要注意:
(1) 每次执行动作方法之前,都会执行validate方法,如果我们的Action中有多个动作方法的话,那么每个动作方法执行之前都会执行validate方法,因此validate方法中一般执行一些通用的检查。
(2) 如果validate中没有通过,即产生了错误消息,那么不会执行动作方法,会直接返回”input”。
下面大致了解一下validate方法执行的原理。首先我们需要知道,这个方法是被拦截器调用的,拦截器放在动作执行之前,拦截每个访问该Action的请求。这个拦截器叫做Workflow拦截器,查看文档可以知道,该拦截器的实现类为com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor。文档中说这个拦截器要做的事情:
(1)如果Action中有validate{MethodName}()方法,那么执行它
(2)如果(1)不成立,但是Action中有validateDo{MethodName}()方法,那么执行它
(3)不管(1)或(2)是否执行,只要这个拦截器的alwaysInvokeValidate属性为true,那么总是会执行validate方法。
查看DefaultWorkflowInterceptor的源码:
发现在这个拦截器中根本就没有调用validate方法,而只是对是否产生的错误信息进行了检测。并且看以看到,如果存在错误信息,默认返回的Result是Action.input(”input”)。
那么既然workflow拦截器没有执行validate方法,由于我们的Action使用的默认的拦截器栈,那么就去看看在workflow拦截器前面的拦截器validation拦截器。
查看文档可以知道这个拦截器的实现类为:org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor。这个类继承了com.opensymphony.xwork2.validator.ValidationInterceptor这个类查看这个类的源码,里面有一个doBeforInvocation方法:
可以看到,正是在这个方法中对Action中的validate方法进行了调用。为了验证到底validate方法是在validation拦截器中被调用的还是在workflow拦截器中被调用的,我们写个小实例,不使用defaultStack,我们手动为Action配置拦截器栈(这个拦截器栈基本和defaultStack相同):
我们仅仅是将validation拦截器移出了Action的先前默认的defaultStack拦截器栈中,我们再来执行前面执行过的测试:
结果:
success结果被显示了,说明validate方法没有被调用了。那么就说明了validate方法是在validattion拦截器中被调用的。
workflow拦截器和validation拦截器可以传递一些参数:
当执行到与excludeMethods参数中指定的方法同名的方法时,拦截器不会做出反映。还可以通过这种形式来为拦截器指定其他属性,比如为workflow指定默认返回的Result等。
访问本地信息
在上面的例子程序中,我们将错误信息硬编码在代码中,这样有一些弊端:
(1) 一是不容易修改,如果我们想改变消息的内容,还得重新修改代码和重新编译类
(2) 而是不利于国际化,如果要将其中的中文换成英文,那么还得到代码中来修改和重新编译类
通过访问本地信息,我们将一些消息按照键值对的形式保存在类文件外部的文件,通过key来获取文件中对应的消息,那么一旦我们需要修改消息内容,那么就只需要修改这个外部文件而不需要重新编译类了。基本步骤:
(1) 首先建立消息文件,在Action类的类路径下建立一个与Action同名的properties文件,例如HelloWorld.properties,然后在文件里按照 key= value的形式添加错误消息。
nameIsNull =\u672A\u83B7\u53D6\u5230\u53C2\u6570
nameIsTooLong=\u7528\u6237\u540D\u592A\u957F
需要注意的是Value的值必须是unicode编码,这样在程序充才能正确获取,在eclipse中可以使用可视化工具编辑properties文件,这样生成的代码会将中文转换为unicode编码。JDK中也提供了native2ascii命令来实现这种转换,具体方法google一下就知道了。
(2)修改原来在Actin中硬编码的错误消息,改成从配置文件中读取信息。
public
void validate() {
if(userName ==null){
addFieldError("userName",getText("nameIsNull"));
}else
if(userName.length()>5){
addFieldError("userName",getText("nameIsTooLong"));
}
}
重新运行程序,结果和前面一样。至于实现的原理,最终还是借助JDK提供的ResourceBoundle来实现的。ActionSupport类实现了TextProvider接口和LocalProvider接口。当我们调用ActionSupport的getText方法时,其内部实际上是调用了TextProvider一个实现类(TextProviderSupport)的对象上的getText方法。
public String getText(String aTextName) {
return getTextProvider().getText(aTextName);
}
private TextProvider getTextProvider() {
if (textProvider ==null) {
TextProviderFactory tpf = new TextProviderFactory();
if (container !=null) {
container.inject(tpf);
}
textProvider = tpf.createInstance(getClass(), this);
}
return textProvider;
}
由于实现了LocalProvider,因此ActionSupport也是LocalProvider类型,其getLocal从ActionContext中获取Local对象。使用系统默认的Local对象时,ResourceBoundle会在Class所在路径下寻找与当前类同名的properties文件,如果使用指定的Local对象,那么我们的资源文件还需要在名字中添加相应的国家代码,例如:HelloWorld_zh_CN.properties
分享到:
相关推荐
struts2学习笔记,拦截器,action,所需jar包,从零开始
三、 Namespace Namespace决定了action的访问路径,默认为“”,可以接收所有路径的action,如果没有找到相应的namespace时,则使用namespace为空的action ...struts2中的package与java的package是相同的作用的。
01 Struts2-Action 5 一、 Struts作用: 5 二、 搭建Struts2的运行环境: 5 三、 Namespace 6 四、 标签 6 五、 Action 6 六、 路径问题的说明 8 七、 Action的动态调用方法 8 八、 Action通配符(wildcard)的配置 9 ...
Struts2_Action学习笔记、通配符{1},{2}......
struts2学习笔记!因为还没有全部学完,所以分部分分享!主要内容:struts.xml配置,web.xml配置 Action要点!全局类型转换,部分类型转换,类型转换文件 类型装换错误的处理问题局部使用,把中文汉字转换为编码 struts2对...
struts2学习笔记,总结了很多学习的经验,标签的使用,action的使用。struts2.0 和 struts2.1 的区别
Struts2 是一个非常优秀的MVC框架,基于Model2 设计模型 由传统Struts1和WebWork两个经典框架发展而来 Struts2框架=Struts2+XWork Strust2 核心功能 允许POJO(Plain Old Java Objects,简单javabean对象,没有继承,...
struts2学习笔记 很基础 容易懂第一个struts2的web用户登录工程:创建一个web工程->创建login.jsp(创建advanced的JSP)->登录的form表单(注意:action=“login.action”)->编写完成后配置
struts2.2学习笔记总结,action,拦截器,过滤器,国际化,struts.xml解析等的总结。
struts1.2学习笔记了解struts工作流程: 首先struts基于MVC模式, 用户发送的请求讲被ActionServlet处理,转发,但是它是怎样实现的了??
建立一个Java Web项目,提取最少运行Struts2应用的包集合,目标:实现一个简单的用户登录 包括内容: 一、先实现登录页面 二、实现处理页面的Action 三、配置Web.xml 四、配置Action处理结果和资源资源之间的映射关系 ...
NULL 博文链接:https://coderdream.iteye.com/blog/812871
当前struts2的filter过滤到一个.action结尾的请求的时候,会把这个请求交给struts2内部的拦截器(interceptor) 2)拦截器起到什么作用 可以帮我们丰富action的功能,比自动类型转换(页面传一个String类型的id,接收的...
Struts 1.3 备忘笔记 【资源特点】 1、以项目形式组织,包含所有的源代码 2、内含详细的注释说明 3、知识点较全面 【内容目录】 01 Struts_01HandworkApply : 手工配置Struct应用程序,演示用户提交数据后服务器的...
向页面传值可以使用struts2中特有的两个类的对象 com.opensymphony.xwork2.ActionContext和com.opensymphony.xwork2.util.ValueStack 1)ValueStack和ActionContext的作用: 当客户端向action发送请求并且最后跳转...
Struts2_04ActionResultType : Struts2关于Action跳转类型的应用 对各种不同的跳转类型使用的实例 Struts2_05Interceptor : Struts2拦截器的使用 Struts2_06FileUpload : Struts2上传文件的使用
struts2中action路径的搜索顺序 博文链接:https://wuzhaohuixy-qq-com.iteye.com/blog/710102
整合Spring,换句话说,也就是让spring的IOC功能为我们的struts action注入逻辑组件....
action 的一些基础操作 的学习过程
比上面的完整 博文链接:https://shangdiyefankun.iteye.com/blog/122443