java自定義注解實現前后台參數校驗


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>接口

官方文檔是這樣描述的:

javax.validation

Interface ConstraintValidator<A extends Annotation,T>



  • public interface ConstraintValidator<A extends Annotation,T>
    Defines the logic to validate a given constraint  A for a given object type  T.

    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 a ConstraintValidator implementation to mark it as supporting cross-parameter constraints. Check out SupportedValidationTarget and Constraint 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM