步驟
1、建立自訂註解類,並添加校正規則
2、解析自訂註解類並實現校正方法
3、建立測試類別並聲明自訂註解
4、編寫Junit測試類別測試結果 自訂註解類
package com.swk.common.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 自訂註解類 * @author fuyuwei * @Retention: 定義註解的保留原則 * @Retention(RetentionPolicy.SOURCE) 註解僅存在於源碼中,在class位元組碼檔案中不包含 @Retention(RetentionPolicy.CLASS) 預設的保留原則,註解會在class位元組碼檔案中存在,但運行時無法獲得, @Retention(RetentionPolicy.RUNTIME) 註解會在class位元組碼檔案中存在,在運行時可以通過反射擷取到 @Target 注釋型別宣告 CONSTRUCTOR 構造方法聲明 FIELD 欄位聲明(包括枚舉常量) LOCAL_VARIABLE 局部變數聲明 METHOD 方法聲明 PACKAGE 包聲明 PARAMETER 參數聲明 TYPE 類、介面(包括注釋類型)或枚舉聲明 */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE,ElementType.FIELD,ElementType.PARAMETER})public @interface CustomAnnotation { /** * 是否為空白 * @return */ boolean isNull() default false; /** * 最大長度 * @return */ int maxLength() default 8; /** * 欄位描述 * @return */ String description() default "";}
實現自訂註解類規則讀取與校正
package com.swk.common.annotation;import java.lang.reflect.Field;import java.util.concurrent.ConcurrentHashMap;import org.springframework.util.StringUtils;import com.swk.common.enums.CommonPostCode;import com.swk.common.exception.PostingException;/** * 解析自訂註解,並完成校正 * @author fuyuwei */public class AnnotationChecker { private final static ConcurrentHashMap<String,Field[]> fieldsMap = new ConcurrentHashMap<String, Field[]>(); public AnnotationChecker(){ super(); } public static void checkParam(Object object) throws PostingException{ Class<? extends Object> clazz = object.getClass(); Field[] fields = null; if(fieldsMap.containsKey(clazz.getName())){ fields = fieldsMap.get(clazz.getName()); } // getFields:獲得某個類的所有的公用(public)的欄位,包括父類;getDeclaredFields獲得某個類的所有申明的欄位,即包括public、private和proteced,但是不包括父類的申明欄位 else{ fields = clazz.getDeclaredFields(); fieldsMap.put(clazz.getName(), fields); } for(Field field:fields){ synchronized(field){ field.setAccessible(true); check(field, object); field.setAccessible(false); } } } private static void check(Field field,Object object) throws PostingException{ String description; Object value = null; CustomAnnotation ca = field.getAnnotation(CustomAnnotation.class); try { value = field.get(object); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } if (ca == null) return; // 如果沒有標註description預設展示欄位名稱 description = ca.description().equals("")?field.getName():ca.description(); if(!ca.isNull()){ if(value == null || StringUtils.isEmpty(value.toString().trim())){ throw new PostingException(CommonPostCode.PARAM_LENGTH.getErrorCode(),description+" "+CommonPostCode.PARAM_NULL.getErrorMesage()); } } if(value.toString().length() > ca.maxLength()){ throw new PostingException(CommonPostCode.PARAM_LENGTH.getErrorCode(),description+" "+CommonPostCode.PARAM_LENGTH.getErrorCode()); } }}
建立依賴的其他類
枚舉類
package com.swk.common.enums;public enum CommonPostCode { PARAM_NULL(-1,"param required"), PARAM_LENGTH(-2,"param too long"); private int errorCode; private String errorMesage; private CommonPostCode(int errorCode, String errorMesage) { this.errorCode = errorCode; this.errorMesage = errorMesage; } public int getErrorCode() { return errorCode; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } public String getErrorMesage() { return errorMesage; } public void setErrorMesage(String errorMesage) { this.errorMesage = errorMesage; }}
自訂異常類
package com.swk.common.exception;public class PostingException extends RuntimeException { private static final long serialVersionUID = 5969404579580331293L; private int errorCode; private String errorMessage; public PostingException(int errorCode, String errorMessage) { super(); this.errorCode = errorCode; this.errorMessage = errorMessage; } public int getErrorCode() { return errorCode; } public void setErrorCode(int errorCode) { this.errorCode = errorCode; } public String getErrorMessage() { return errorMessage; } public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }}
建立聲明自訂註解的測試類別
package com.swk.request;import com.swk.common.annotation.CustomAnnotation;public class UserInfoRequest { @CustomAnnotation(isNull=false,maxLength=4,description="姓名") private String name; @CustomAnnotation(isNull=false,maxLength=11,description="手機號") private String mobile; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; }}
編寫Junit測試類別
package com.swk.test.annotation;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.sun.istack.internal.logging.Logger;import com.swk.common.annotation.AnnotationChecker;import com.swk.common.exception.PostingException;import com.swk.request.UserInfoRequest;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:spring-mybatis.xml"})public class AnnotationTest { private Logger logger = Logger.getLogger(AnnotationTest.class); @Test public void testAnnotation(){ UserInfoRequest request = new UserInfoRequest(); try { AnnotationChecker.checkParam(request); } catch (PostingException e) { logger.info(e.getErrorCode()+":"+e.getErrorMessage()); } }}
運行結果
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:spring-mybatis.xml"})public class AnnotationTest { private Logger logger = Logger.getLogger(AnnotationTest.class); @Test public void testAnnotation(){ UserInfoRequest request = new UserInfoRequest(); request.setName("齊天大聖孫悟空"); try { AnnotationChecker.checkParam(request); } catch (PostingException e) { logger.info(e.getErrorCode()+":"+e.getErrorMessage()); } }}
運行結果