註解定義
Java註解又稱Java標註,是Java語言5.0版本開始支持加入源代碼的特殊語法元數據。爲我們在代碼中添加信息提供了一種形式化的方法,使我們可以在稍後某個時刻非常方便的使用這些數據。
Java語言中的類、方法、變量、參數和包等都可以被標註。和Javadoc不同,Java標註可以通過反射獲取註解內容。在編譯器生成類文件時,註解可以被嵌入到字節碼中。Java虛擬機可以保留註解內容,在運行時可以獲取到註解內容。
元註解
@Target
- 標記註解註釋哪種 Java 成員。@Retention
- 標記註解存儲方式@Documented
- 標記註解是否包含在Javadoc用戶文檔中。@Inherited
- 標記註解可以被繼承
1.@Target
限制註解的註釋類型,類型在 ElementType 中
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/** Type parameter declaration*/
TYPE_PARAMETER,
/** Use of a type*/
TYPE_USE
}
2.@Retention
規定註解的存儲方式,要保留多久,參數在 RetentionPolicy 中
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
* 保留在源代碼中,編譯時忽略
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
* 保留在字節碼中,VM 運行時忽略
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
* 運行 VM 時保留,因此可以通過反射進行讀取
*/
RUNTIME
}
模擬場景
校驗請求參數,參數爲手機號,校驗其格式的正確與否
1.自定義註解體
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定義手機號碼校驗註解
*
* @author YoonaLt
* @date 2019-10-14
*/
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyInterfaceRealize.class) // 約束類
public @interface MyAnnotation {
String message() default "數據格式有誤";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
註解內的 Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; 不要忘記,且名稱固定,否則使用時報錯
javax.validation.ConstraintDefinitionException: HV000074: com.yoona.MyAnnotation contains Constraint annotation, but does not contain a payload(或者爲groups) parameter.
2.編寫註解驗證器
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
/**
* 註解驗證器
*
* @author YoonaLt
* @date 2019-10-14
*/
public class MyInterfaceRealize implements ConstraintValidator<MyAnnotation, String> {
// ConstraintValidator<MyAnnotation, String> String爲要註釋的數據的類型
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
// 號碼長度
int len = 11;
if (value == null || "".equals(value) || value.length() != len) {
return false;
}
// 校驗規則(測試,一般情況可行)
String regex = "^1[3|4|5|7|8][0-9]\\d{4,8}$";
return value.matches(regex);
}
}
3.測試
import com.yoona.custom.MyAnnotation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author YoonaLt
* @date 2019-10-14
*/
@Validated // 這裏使用這個註解使我們自定義的註解生效
@RestController
@RequestMapping(value = "test")
public class TestAnnotation {
@GetMapping(value = "test")
public void myTest(@MyAnnotation String number) {
}
}
當參數 number 不符合驗證器內的規定時,我們可以看到報錯信息
javax.validation.ConstraintViolationException: myTest.number: 數據格式有誤
at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke(MethodValidationInterceptor.java:116)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
...........................................