Tiger出笼以后, Annotation成了一个小小的亮点,虽然有抄袭.net之嫌疑,毕竟让Java开发者方便了许多。EJB3.0和Hibernate Annotation版都是基于这个东西了。
下面是结合Spring的自动Log/鉴权/国际化应用:
public interface SessionService extends Service {
@Anonymous //允许未登录用户调用
@OperationLog //自动log
@Name(zh = "登录")
public String login(
@Name(en="user",zh = "用户")String user,
@OperationLog(false)String password); //不log密码
@OperationLog
@Name(zh="注销")
public void logout();
@Anonymous用于鉴权,允许匿名访问。通过ThreadLocal的变量保存当前用户的Session信息。
@OperationLog 用于标记是否自动Log, 可以作用于类、方法、参数
@Name用于i18n国际化支持。Java里面常见的国际化解决方法是.properties文件,个人认为这个方案不好,适合大型项目开发。小项目中这个标记一下足矣。如果要添加一种语言,只要在@Name中多一个参数,利用Eclipse的reference很容易知道有哪些地方要翻译。
同样@Name还可以加在Bean上,自动构造多语言的Table/List,方便之极。
下面是结合Spring的自动Log/鉴权/国际化应用:
public interface SessionService extends Service {
@Anonymous //允许未登录用户调用
@OperationLog //自动log
@Name(zh = "登录")
public String login(
@Name(en="user",zh = "用户")String user,
@OperationLog(false)String password); //不log密码
@OperationLog
@Name(zh="注销")
public void logout();
@Anonymous用于鉴权,允许匿名访问。通过ThreadLocal的变量保存当前用户的Session信息。
@OperationLog 用于标记是否自动Log, 可以作用于类、方法、参数
@Name用于i18n国际化支持。Java里面常见的国际化解决方法是.properties文件,个人认为这个方案不好,适合大型项目开发。小项目中这个标记一下足矣。如果要添加一种语言,只要在@Name中多一个参数,利用Eclipse的reference很容易知道有哪些地方要翻译。
同样@Name还可以加在Bean上,自动构造多语言的Table/List,方便之极。
@Name(zh="安全事件",en="Security Event")
public class SecurityEvent extends AbstractEmsEvent{
String cause;
@Name(zh="原因")
public String getCause() {
return cause;
}
}
public class SecurityEvent extends AbstractEmsEvent{
String cause;
@Name(zh="原因")
public String getCause() {
return cause;
}
}
附上我的I18nUtil工具类:
/**
* @author steeven
*/
public class I18nUtil {
public static String getName(Method method) {
return getI18n(method,Name.class);
}
public static String getTip(Method method) {
return getI18n(method,Tip.class);
}
public static String getI18n(Method method,Class<? extends Annotation> i18nClass) {
Annotation i18n = method.getAnnotation(i18nClass);
return getProperty(i18n,method.getName());
}
public static String getProperty(Annotation i18n, String defaultValue) {
if (i18n==null)
return defaultValue;
Class<? extends Annotation> clz = i18n.annotationType();
try {
Method method = clz.getMethod(getI18nMethodName());
assert method!=null;
String r = (String) method.invoke(i18n);
return r==null || r.length()==0?defaultValue:r;
} catch (Exception e) {
assert false;
return defaultValue;
}
}
private static String getI18nMethodName() {
return Locale.getDefault().getLanguage();
}
@SuppressWarnings("unchecked")
public static <T extends Annotation> T getAnnotation(Annotation[] argAnnotations, Class<T> clz) {
for(Annotation anno:argAnnotations)
if (clz.isInstance(anno))
return (T) anno;
return null;
}
}
* @author steeven
*/
public class I18nUtil {
public static String getName(Method method) {
return getI18n(method,Name.class);
}
public static String getTip(Method method) {
return getI18n(method,Tip.class);
}
public static String getI18n(Method method,Class<? extends Annotation> i18nClass) {
Annotation i18n = method.getAnnotation(i18nClass);
return getProperty(i18n,method.getName());
}
public static String getProperty(Annotation i18n, String defaultValue) {
if (i18n==null)
return defaultValue;
Class<? extends Annotation> clz = i18n.annotationType();
try {
Method method = clz.getMethod(getI18nMethodName());
assert method!=null;
String r = (String) method.invoke(i18n);
return r==null || r.length()==0?defaultValue:r;
} catch (Exception e) {
assert false;
return defaultValue;
}
}
private static String getI18nMethodName() {
return Locale.getDefault().getLanguage();
}
@SuppressWarnings("unchecked")
public static <T extends Annotation> T getAnnotation(Annotation[] argAnnotations, Class<T> clz) {
for(Annotation anno:argAnnotations)
if (clz.isInstance(anno))
return (T) anno;
return null;
}
}
元数据的结构似乎有些简单,有时候要加很多@Name,@Tip,@Help好像没办法一个Tag搞定。
另外,还可以通过Annotation加上验证、输入界面描述,等等。程序很容易自动化,再多的画面也用不了多少代码。
Jdk5.0提供了这么好用的原数据机制,你有什么好的用法呢?