在搭建系统时,我们经常需要定义很多错误类,包括错误码和错误信息。大多数情况下我们都用最传统的方式来做,比如先定义一组错误code,然后再定义一组错误信息,错误信息放在properties文件或者数据库中,系统启动时加载到内存,放在map中和错误code一一对应,使用时通过错误code获取错误信息返回给用户。 后来JAVA出现了自定义Annotation,这就给我们提供了一种更优雅的方法来管理错误信息类,下面写了一个小DEMO,大家有兴趣的话可以参考下。 JAVA自定义Annotation的用处非常广泛,尤其是在框架开发过程中,以后慢慢记录。

首先定义一个用于错误码定义类的Annotation

package errorAno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ErrorDefineClass {
    String value() default "error message description";
}

这个错误码定义类的Annotation的ElementType.TYPE代表其可以作用在类或者接口上,具体可以点进去看看,各种类型有不同的用途。

再定义一个用于错误码属性的Annotation

package errorAno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ErrorDefinition {
    String value();
}

这个错误码属性的Annotation的ElementType.FIELD代表其是作用在类属性上的注解。

再定义一个错误码类的加载和解析类,或者说构建错误码管理的全局上下文环境

package errorAno;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

public class ErrorContext {

    public final static int SUCCESS = 0;

    static private Map<Integer, String> errorMap;

    static {
        errorMap = new HashMap<Integer, String>();
        ErrorContext.errorMap.put(0, "Business successed!");
    }

    /*
     *return the preloaded error message without exception
     */
    public static String errnoExplain(int errno) {
        String explain = errorMap.get(errno);
        String backup = String.valueOf(errno);
        return explain != null ? explain : backup;
    }

    /*
     *return unloaded error message without exception
     */
    public static String errnoExplain(int errno, String explain) {
        if (errorMap.containsKey(errno)) {
            return errorMap.get(errno);
        } else {
            String backup = String.valueOf(errno);
            return explain != null ? explain : backup;
        }
    }

    /*
    * analyzed the error class and load them in to memory
    * */
    protected static void proxyExplain(Class<? extends ErrorContext> define) {
        //make sure the error def class extends ErrorContext
        if (define != null && define != ErrorContext.class) {
            final String dname = define.getName();
            //make sure the error class is Annotated by ErrorDefineClass
            if (define.isAnnotationPresent(ErrorDefineClass.class)) {
                Class<ErrorDefinition> defClazz = ErrorDefinition.class;
                //analyze the error fields
                for (Field field : define.getDeclaredFields()) {
                    //make sure the fields is Annotated by ErrorDefinition
                    if (field.isAnnotationPresent(defClazz)) {
                        //make sure the fields is modified by public
                        if (Modifier.isPublic(field.getModifiers())) {
                            try {
                                ErrorDefinition entry = null;
                                int errno = field.getInt(null);
                                entry = field.getAnnotation(defClazz);
                                ErrorContext.errorMap.put(errno, entry.value());
                                System.out.println("analyzed error message successed:" + entry.value());
                            } catch (Exception e) {
                                System.out.println("analyze error message exception");
                            }
                        }
                    }
                }
            }
        }
    }
}

具体详情可以看看代码里的注释,其主要作用就是在系统启动时加载所有的错误码定义类和属性,然后在使用时可以直接调用找到相应的错误码。

最后来看看如何融合到你的系统中去

package errorAno;

@ErrorDefineClass
public class BusinessError extends ErrorContext{

    /*
    * preload this error Class when system is startup
    * */
    static {
        ErrorContext.proxyExplain(BusinessError.class);
    }

    @ErrorDefinition("The action code is incorrect")
    final public static int ERR_ACTION_CODE = 1;

    @ErrorDefinition("The parameters is incorrect")
    final public static int ERR_PARAMETER = 2;


    public static void main(String[] args) {
        System.out.println(ErrorContext.SUCCESS);
        System.out.println(ErrorContext.errnoExplain(1));
        System.out.println(ErrorContext.errnoExplain(2));
    }
}

这就是一个你需要在系统中定义的错误码类,在系统启动时这个类会被自动加载,这种Annotation的用法就不需要以往那种循环加载map或者各种数据结构的操作了,只需要按照Annotation的标准来写,系统就会自动加载你需要的内容。来看看测试结果

错误码的管理可以是在数据库中,也可以是在properties中,没有好坏之分,只是根据不同的系统和使用场景做不同的选择,这里只是用错误码管理为例,简要介绍一下JAVA自定义Annotation的使用,供大家参考。


发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

Thanks for your support to bet365fans!