2016.07.26
首先介紹些基本概念:
Annotations(also known as metadata)provide a formalized way to add information to your code so that you can easily use that data at some later point.
Annotations are partly motivated by a general trend toward combining metadata with source-code files,instead of keeping it in external documents. They are also a response to feature pressure from other languages like C#.
Annotations are one of the fundamental language changes introduced in Java SE5. They provide information that you need to fully describe your program, but that cannot be expressed in Java.Thus,annotations allow you to store extra information about your program in a format that is tested and verified by the compiler.Annotations can be used to generate descriptor files or even new class definitions and help ease the burden of writing "boilerplate" code.Using annotations,you can keep this metadata in the Java source code,and have the advantage of cleaner looking code,compile-time type checking and the annotation API to help build processing tools for your annotations.
---《Thinking in java》
1.java用@interface xx{}定義一個注解。
2.There are currently only three standard annotations(described earlier)(@Override @Deprecated @SuppressWarnings)and four meta-annotations defined in the Java language(@Target @Retention @Documented @Inherited):
@Retention(RetentionPolicy.SOURCE) // 注解僅存在於源碼中,在class字節碼文件中不包含
@Retention(RetentionPolicy.CLASS) // 默認的保留策略,注解會在class字節碼文件中存在,但運行時無法獲得
@Retention(RetentionPolicy.RUNTIME) // 注解會在class字節碼文件中存在,在運行時可以通過反射獲取到
(RUNTIME的值得注意下,因為意味着可以反射來獲取)
@Target(ElementType.TYPE) // 接口、類、枚舉、注解
@Target(ElementType.FIELD) // 字段、枚舉的常量
@Target(ElementType.METHOD) // 方法
@Target(ElementType.PARAMETER) // 方法參數
@Target(ElementType.CONSTRUCTOR) // 構造函數
@Target(ElementType.LOCAL_VARIABLE) // 局部變量
@Target(ElementType.ANNOTATION_TYPE) // 注解
@Target(ElementType.PACKAGE) // 包
有一種做法就是在定義注解時加上@Taget(xx)和@Retention(RetentionPolicy.RUNTIME) ,但沒有在注解中寫方法,只是在運行時通過反射機制來獲取注解,然后自己寫相應邏輯(所謂注解解析器)
大概是類似的寫法:
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented @Inherited @Target({ ElementType.FIELD, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface Validate { public int min() default 1; public int max() default 10; public boolean isNotNull() default true; }
之后運行時,用反射獲取注解,具體不談。
之前在網上查找這方面技術文章找到的都是這種,給當時的我帶來很大困惑。覺得不是我想要的。
關於Java 注解,在《java編程思想》一書里第十章有詳細的介紹(包括@Retention(RetentionPolicy.RUNTIME)的方式,的注解處理器的例子),具體不多談。
其實是可以通過@Constraint來限定自定義注解的方法。
@Constraint(validatedBy = xxxx.class)
下面是我做的 java自定義注解實現前后台參數校驗 的代碼示例:
package sonn.sonnannotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.Payload; import sonn.util.StringUtill; /** * @ClassName: IsValidString * @Description: 自定義注解實現前后台參數校驗,判斷是否包含非法字符 * @author 無名 * @date 2016-7-25 下午8:22:58 * @version 1.0 */ @Target({ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = IsValidString.ValidStringChecker.class) @Documented public @interface IsValidString { String message() default "The string is invalid."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default{}; class ValidStringChecker implements ConstraintValidator<IsValidString,String> { @Override public void initialize(IsValidString arg0) { } @Override public boolean isValid(String strValue, ConstraintValidatorContext context) { if(StringUtill.isStringEmpty(strValue)) { return true; } if(strValue.contains("<")) { return false; } return true; } } }
上述代碼,通過@Constraint(validatedBy = IsValidString.ValidStringChecker.class)限定了注解的方法邏輯---該注解類的名為ValidStringChecker的內部類。
而該內部類實現了ConstraintValidator<IsValidString,String>接口
官方文檔是這樣描述的:
Interface ConstraintValidator<A extends Annotation,T>
-
public interface ConstraintValidator<A extends Annotation,T>
Defines the logic to validate a given constraintA
for a given object typeT
.Implementations must comply to the following restriction:
T
must resolve to a non parameterized type- or generic parameters of
T
must be unbounded wildcard types
The annotation
SupportedValidationTarget
can be put on aConstraintValidator
implementation to mark it as supporting cross-parameter constraints. Check outSupportedValidationTarget
andConstraint
for more information.
實現的isValid方法便是,該接口的校驗方法。
試驗一下效果,在要校驗的實體類字段加上注解:
寫文章頁面,文章標題內加入'<'然后提交:
提交失敗,報500錯誤,說明注解生效:
但這樣還有問題,我的blog網站不能直接打印出報錯信息。還是要搞一個error頁面出來。
這個簡單,web.xml下加入error頁面路徑,然后做一個頁面即可:
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
參考文章:
http://www.cnblogs.com/liangweiping/p/3837332.html