在
js
中实现验证码资源的国际化
在
web
应用开发中,框架都提供了资源国际化的配置。但是,在
js
中实现资源国际化还是比较麻烦。比如:
alert('Hello!') ;
我需要将这个
hello
在中文环境中显示为‘你好’,而在英文环境中显示为英文‘
hello
’,就比较麻烦。
这里用到了
dwr
框架,它动态生成
javascript
代码
;
隐藏的
http
协议。关于
dwr
的资料网上面很多。
下面就是基本的资源关系图:
*.jsp 或 *.html
|
Message.js
|
Dwr Engineer
|
Messages.java
|
*_zh_CN.properties...
|
首先:在
jsp
或
html
中引入需要的
js
文件
然后:
js
就会通过
dwr
引擎调用
Messages.java
文件,而
Messages.java
文件提供了对属
性文件的操作。这样就可以实现在
js
中验证码资源的国际化。
下面就来进行具体的开发:
一:开发一个
sevlet
类,当应用系统启动时,就将资源文件读入缓存,就可以加快访问速度。
package test.message;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import org.xiaohongli.core.cache.Cache;
import org.xiaohongli.core.cache.LruCache;
/**
*
* @author xiaohongli
*
*/
public class MessagesServlet extends HttpServlet{
//
定义属性文件后缀
public static final String MESSAGE_SUFFIX = ".properties";
//
定义缺省属性文件前缀
public static final String DEFAULT_MESSAGE_PREFIX = "resourceMessages" ;
//
定义资源
cache
名为
message_cache
private static final String CACHE_NAME = "message_cache" ;
//
定义资源文件存放位置
private static final String PATH_PREFIX = "/WEB-INF/classes" ;
private Properties p = null ;
private static final long serialVersionUID = 3477255511805826715L;
//
获得本地化信息
protected final Locale defaultLocale = Locale.getDefault();
public void init() throws ServletException {
try{
initMessages();
}catch(Exception e){
System.out.println("Fatal:
读取属性文件出错!
");
}
}
protected void initMessages(){
//
获取资源文件名
String messagePrefix = getServletConfig().getInitParameter("messages") ;
//
获取资源文件存放路径
String messagePath = getServletConfig().getInitParameter("path") ;
if(null==messagePath){
messagePath = "" ;
}
InputStream input = null;
try {
String messageFileName = null ;
if(null==messagePrefix){
messageFileName = DEFAULT_MESSAGE_PREFIX + "_" +defaultLocale.toString()+MESSAGE_SUFFIX ;
}else{
messageFileName = messagePrefix+ "_" +defaultLocale.toString()+MESSAGE_SUFFIX ;
}
String mfile = PATH_PREFIX+messagePath+"/"+messageFileName ;
input = getServletContext().getResourceAsStream(mfile);
} catch (RuntimeException e) {
String messageFileName = null ;
if(null==messagePrefix){
messageFileName = DEFAULT_MESSAGE_PREFIX+MESSAGE_SUFFIX ;
}else{
messageFileName = messagePrefix+MESSAGE_SUFFIX ;
}
String mfile = PATH_PREFIX+messagePath+"/"+messageFileName ;
input = getServletContext().getResourceAsStream(mfile);
}
p = new Properties();
try {
p.load(input);
//
蒋资源写入
cache
Object object = this.getCache().get(CACHE_NAME) ;
if(null == object){
this.getCache().put(CACHE_NAME,p) ;
}
} catch (IOException e) {
e.printStackTrace();
}
}
//
获取
cache
实例
private LruCache getCache(){
return Cache.getCacheInstance() ;
}
}
二:在
web.xml
中配置
MessagesServlet
<
servlet
>
<
servlet-name
>
MessagesServlet
</
servlet-name
>
<
servlet-class
>
test.message.MessagesServlet
</
servlet-class
>
<
init-param
>
<
param-name
>
messages
</
param-name
>
<
param-value
>
jsMessages
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
path
</
param-name
>
<
param-value
>
/js
</
param-value
>
</
init-param
>
<
load-on-startup
>
2
</
load-on-startup
>
</
servlet
>
这里指定了属性文件名为
jsMessages.properties,jsMessages_zh_CN.properties….
文件存放路径为
WEB-INF/classes/js
下。
启动应用以后,资源文件就写入到
cache
中了,读取资源文件首先会查找本地资源文件,如中国就是
*_zh_CN.properties
,当这个文件不存在时就会读取
jsMessages.propeties
三:编写获取具体属性资源的
java
类
1.
MessageConstants
.java
package
test.message;
public
class
MessageConstants {
public
final
static
String
field_is_required
=
"field-is-required"
;
public
final
static
String
field_too_short
=
"field-too-short"
;
public
final
static
String
field_too_long
=
"field-too-long"
;
public
final
static
String
field_been_used
=
"field-been-used"
;
public
final
static
String
field_can_use
=
"field-can-use"
;
}
这里指定了几个常用的验证属性。
域必须
:
field-is-required
。。。。
2
.
BaseMessages.java
package
test.message.type;
import
java.util.HashMap;
import
java.util.Map;
import
java.util.Properties;
import
org.
xiaohongli
.core.cache.Cache;
import
org.xiaohongli.core.cache.LruCache;
public
abstract
class
BaseMessage {
private
static
final
String
CACHE_NAME
=
"message_cache"
;
private
static
Properties
prop
=
null
;
protected
LruCache getCache(){
return
Cache.getCacheInstance() ;
}
public
Map<String, String>
map
=
new
HashMap<String, String>();
protected
void
setString(String index,String value){
map
.put(index, value) ;
}
//
解析资源文件中的字符串如
You must enter a value for {0}.
protected
String parse(String str){
String ret =
""
;
String[] str1 = str.split(
"[{]"
) ;
for
(
int
i=0 ;i<str1.
length
;i++){
String temp = str1[i] ;
if
(
null
==str1[i]||
""
.equals(str1[i].trim())||i==0) {
ret = ret + temp ;
continue
;
}
String index = temp.substring(0,1) ;
String mstr = (String)
map
.get(index) ;
ret = ret + mstr + temp.substring(2) ;
}
return
ret ;
}
protected
String _getMessage(String key){
if
(
prop
==
null
)
prop
= (Properties)
this
.getCache().get(
CACHE_NAME
) ;
return
prop
.getProperty(key) ;
}
}
这个方法提供了获取属性的几个基本的方法,如
parse
解析资源文件中的字符串。
_getMessage
会得到资源文件的相关属性。
3
.
Messages.java
package
test.message;
import
test.message.type.BaseMessage;
public
class
Messages
extends
BaseMessage{
private
String
basekey
;
public
String getBasekey() {
return
basekey
;
}
public
void
setBasekey(String basekey) {
this
.
basekey
= basekey;
}
//
获取关键字对应的属性
public
String getMessage(String key){
String keyValue = _getMessage(key);
return
keyValue ;
}
//
检测是否唯一时,当已经被使用时
public
String getBeenUsedMessage(String key){
setBasekey(MessageConstants.
field_been_used
) ;
String keyValue = _getMessage(key);
setString(
"0"
, keyValue) ;
return
parse(_getMessage(
basekey
));
}
//
检测是否唯一时,没有被使用时
public
String getCanUseMessage(String key){
setBasekey(MessageConstants.
field_can_use
) ;
String keyValue = _getMessage(key);
setString(
"0"
, keyValue) ;
return
parse(_getMessage(
basekey
));
}
//
必须域
public
String getRequiredMessage(String key){
setBasekey(MessageConstants.
field_is_required
) ;
String keyValue = _getMessage(key);
setString(
"0"
, keyValue) ;
return
parse(
_getMessage
(
basekey
));
}
//
最小长度,
key:
关键字,
length
,长度
public
String getMinLengthMessage(String key,String length){
setBasekey(MessageConstants.
field_too_short
) ;
String keyValue = _getMessage(key);
setString(
"0"
, length) ;
setString(
"1"
, keyValue) ;
return
parse(_getMessage(
basekey
));
}
//
最大小长度,
key:
关键字,
length
,长度
public
String getMaxLengthMessage(String key,String length){
setBasekey(MessageConstants.
field_too_long
) ;
String keyValue = _getMessage(key);
setString(
"0"
, length) ;
setString(
"1"
, keyValue) ;
return
parse(_getMessage(
basekey
));
}
}
4
.这里列出具体的
*.properties
文件
jsMessages_zh_CN.properties
field-is-required=
/u8BF7/u8F93/u5165
{0}
/u7684/u5185/u5BB9/u3002
field-too-short=
{1}
/u7684/u5185/u5BB9/u4E0D/u80FD/u5C11/u4E8E
{0}
/u5B57/u7B26/u3002
field-too-long=
{1}
/u7684/u957F/u5EA6/u4E0D/u80FD/u8D85/u8FC7
{0}
/u4E2A/u5B57/u7B26/u3002
field-been-used
/u5BF9/u4E0D/u8D77/uFF0C/u8BE5
{0}
/u5DF2/u7ECF/u88AB/u4F7F/u7528/uFF01
field-can-use
/u60A8/u53EF/u4EE5/u4F7F/u7528/u8FD9/u4E2A
{0}
/uFF01
########
account=
/u8D26/u53F7
permission-name=
/u6743/u9650/u540D
resource-name=
/u8D44/u6E90/u540D
role-name=
/u89D2/u8272/u540D
jsMessages.properties
field-is-required=
You
must
enter
a
value
for
{0}
.
field-too-short=
You
must
enter
at
least
{0}
characters
for
{1}
.
field-too-long=
You
must
enter
no
more
than
{0}
characters
for
{1}
.
field-been-used
Sorry,
the
{0}
has
been
used/!
field-can-use=
You
can
use
the
{0}
/!
account=
account
permission-name=
permission
resource-name=
resource
role-name=
role
这个文件提供了几个最基本地验证属性,当然可以自己扩展。还有几个如
account..
是在我这个应用中要用到的。
四:
在项目中加入
dwr
- 到dwr官方网站上http://getahead.ltd.uk/dwr下载dwr.jar,放到lib目录下。
- 编写dwr.xml
<?
xml
version="1.0" encoding="UTF-8"?>
<!DOCTYPE
dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://www.getahead.ltd.uk/dwr/dwr20.dtd">
<
dwr
>
<
allow
>
<
create
creator="spring" javascript="UserManager">
<
param
name="beanName">userManager</param>
</
create
>
<
create
creator="spring" javascript="RoleManager">
<
param
name="beanName">roleManager</param>
</
create
>
<
create
creator="spring" javascript="PermissionManager">
<
param
name="beanName">permissionManager</param>
</
create
>
<
create
creator="spring" javascript="ResourceManager">
<
param
name="beanName">resourceManager</param>
</
create
>
<
create
creator="spring" javascript="Messages">
<
param
name="beanName">jsMessages</param>
</
create
>
</
allow
>
</
dwr
>
这里是调用
spring
中的
bean,
如果是通过其他方式获取
bean
的话,可参考
dwr
的官方文档。
3.
在
web.xml
中加入
<
servlet
>
<
servlet-name
>
dwr-invoker
</
servlet-name
>
<
display-name
>
DWR Servlet
</
display-name
>
<
description
>
Direct Web Remoter Servlet
</
description
>
<
servlet-class
>
uk.ltd.getahead.dwr.DWRServlet
</
servlet-class
>
<
init-param
>
<
param-name
>
debug
</
param-name
>
<
param-value
>
true
</
param-value
>
</
init-param
>
<
init-param
>
<
param-name
>
classes
</
param-name
>
<
param-value
>
java.lang.Object
</
param-value
>
</
init-param
>
<
load-on-startup
>
1
</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
dwr-invoker
</
servlet-name
>
<
url-pattern
>
/dwr/*
</
url-pattern
>
</
servlet-mapping
>
如果没有出错,就说明你
dwr
部署成功了。非常简单把。
五.具体应用。
<
script
type='text/javascript' src='../dwr/interface/UserManager.js'></script>
<
script
type='text/javascript' src='../dwr/interface/Messages.js'></script>
<
script
type='text/javascript' src='../dwr/engine.js'></script>
<
script
type='text/javascript' src='../dwr/util.js'></script>
<
script
type='text/javascript' src='js/message.js'></script>
<
script
>
function
check (){
var checkField = form.account.value ;
if(!requriedField(form.account,'account'))return false ;
if(!minLengthField(form.account,'4','account'))return false ;
UserManager.checkByField("Name",checkField,echoData) ;
}
function
echoData(data){
if(data){
beenUsedField('account') ;
}else{
canUseMessage('account') ;
}
}
</
script
>
可能还遗漏了什么地方。欢迎大家提出批评意见。