国际化
介绍:
1、 国际化原理 ? 什么是国际化 ?
同一款软件 可以为不同用户,提供不同语言界面 ---- 国际化软件
需要一个语言资源包(很多properties文件,每个properties文件 针对一个国家或者语言 ,
通过java程序根据来访者国家语言,自动读取不同properties文件 )
2、 资源包编写
properties文件命名 : 基本名称_语言(小写)_国家(大写).properties
例如 :
messages_zh_CN.properties 中国中文
messages_en_US.properties 美国英文
3、 ResourceBundle 根据不同Locale(地域信息),读取不同国家 properties文件
ResourceBundle bundle = ResourceBundle.getBundle("messages", Locale.US);
----------------------------
集体实现:
1. 国际化的定义
1. 全局
在struts.xml 中声明 一个常量(struts.custom.i18n.resources=testmessages,testmessages2)
<constant name="struts.custom.i18n.resources" value="message"></constant>
value 的值:
src下:message
其他包下:com.uu.action.message
2. 局部
1. 针对与action
位置:与action类在同一个包下
名称:ActionClassName.properties
注意:这个配置文件只对当前action 有效
2. 针对package下所有action
位置:在指定的包下
名称:package.properties
3. jsp页面临时使用某个properties配置文件
1. 引入:
<%@taglib prefix="s" uri="/struts-tags" %>
2. 使用:
<s:i18n name="message">
<s:text name="username"/>
</s:i18n>
注意: 如果配置文件不是在 src 根目录下
需要写全路径
2. 国际化的使用
1. 在action类中的使用
前提: 当前action 继承ActionSupport
使用: this.getText("username"); 获取配置文件中的内容
2. 在validation
<field name="username">
<field-validator type="requiredstring">
<message key="nameerror"></message>
</field-validator>
</field>
3. 在jsp页面上使用
<s:text name="名称"> 如果没有使用
s:i18n name="">来指定,会从全局配置文件中获取。
3. 配置文件中使用动态文本
1. action 中怎样使用
配置文件: msg=hello world { 0}
action中: this.getText("username", new String[] { "你好啊,兄弟" }
2. jsp 页面上怎样使用
配置文件:同上
<s:i18n name="com.uu.action.package">
<s:text name="username">
<s:param> ,天不错,来 嘿嘿嘿</s:param>
</s:text>
</s:i18n>
拦截器
介绍:
struts2拦截器使用的是AOP思想。
AOP的底层实现就是动态代理。(Proxy)
拦截器 采用 责任链 模式
* 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。
* 责任链每一个节点,都可以继续调用下一个节点,也可以阻止流程继续执行
struts2中在struts-default.xml文件中声明了所有的拦截器。
而struts2框架默认使用的是defaultStack这个拦截器栈。
在这个拦截器栈中使用了18个拦截器。简单说,struts2框架
在默认情况下,加载了18个拦截器。
使用:
1. 创建一个Interceptor,自定义一个实现了Interceptor 的类
2. 声明:
在struts-defalult.xml文件中 (源码资源文件中的配置)
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletConfig"/>
..............18个
</interceptor-stack>
<default-interceptor-ref name="defaultStack"/>
<default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
3. 注意
只要显示声明了一个拦截器,name默认的拦截器就不起作用了
配置如下:
// 在interceptors中先配置拦截器,再整个拦截器栈,把默认的拦截器(那18个)
// 添加进栈中
<package>
<interceptors>
<interceptor name="bookInterceptor" class="com.uu.interceptor.BookInterceptor">
<param name="includeMethods">add,update,delete</param>
</interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="bookInterceptor" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
//配置global-results ,action
// 重点是:在要拦截的 action 中添加interceptor-ref 的属性
<global-results>
<result name="login">/login.jsp</result>
</global-results>
<action name="login" class="com.uu.action.LoginAction">
<result name="input">/login.jsp</result>
<result>/book.jsp</result>
</action>
<action name="book_*" class="com.uu.action.BookAction" method="{1}">
<interceptor-ref name="myStack" />
</action>
</package>
源码查看拦截器原理分析:
1.在StrutsPrepareAndExecuteFilter中查找
在doFilter方法内有一句话 execute.executeAction (request, response, mapping) 执行Action操作.
2.在executeAction执行过程中会访问Dispatcher类中的serviceAction,在这个方法中会创建一个
ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, method, extraContext, true, false);
这就是我们的Action的代理对象
3.查看ActionInvocation,查看其实现类 DefaultActionInvocation.
在其invoke方法中
if (interceptors.hasNext()) {//判断是否有下一个拦截器.
final InterceptorMapping interceptor = interceptors.next(); //得到一个拦截器
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
//调用得到的拦截器的拦截方法.将本类对象传递到了拦截器中。
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
}
通过源代码分析,发现在DefaultActionInvocation中就是通过递归完成所有的拦截调用操作.
关于interceptor与Filter区别
1. 拦截器是基于java 反射机制的,过滤器是基于函数回调的
2. 过滤器依赖于servlet容器,而拦截器不依赖与servlet容器
3. 拦截器只能对ACtion起作用,而过滤器则可以对几乎所有请求起作用
4. 拦截器可以访问Aciton上下文,值栈里的对象,而过滤器不能
5. 在Action的声明周期中,拦截器可以多次调用,而过滤器只能在容器初始化的时候调用