パラメータのキャリブレーションインターフェース実装カスタム注釈

1.はじめに

私たちは時々たいインターフェースの開発において、インターフェースのみが特定の人物(ソース)要求することができ、その後、我々は、サーバー上の検証パラメータを要求するために行う必要があります。

このケースでは使うことができinterceptor、パラメータのチェックを統一するのではなく、インタフェースの多くは、値の異なるセットがある場合、我々は多くのことを書くことができないinterceptorのパスに合わせてそれを追加し、その後、一つずつ?

このような状況の中で、私たちは私たちに伝えるために注釈してカスタム注釈を選択することができ、このインターフェースは、誰訪問することができます。

注:この例では、唯一の特定のフィールドにチェックを実現し、セキュリティが高くはないが、実際のプロジェクトでは、マルチフィールドの暗号化方式は、セキュリティを確保するために使用することができ、文化的な原理は同じです。

はじめに2.javaノート

アノテーションが導入さJDK5.0コメントメカニズムです。

注釈は、コンパイルすることができる特別なコードマーカである、クラスローディング、ランタイムが読み出され、対応する処理を行います。

注釈、プログラマー、オリジナルのロジックを変更せずに、ソースファイルに埋め込まれたいくつかの追加情報を使用することにより。

アノテーションは、JDK 1.8の後、パッケージ化するために使用することができるように改質剤、クラス、インタフェース、コンストラクタ、メソッド、メンバ変数(メンバ変数)、パラメータ、ローカル変数(ローカル変数)、注釈(ノート)として使用することができる、種類が表示され限り(クラス、インタフェース、注釈、列挙を含む)場所、コメントで使用することができます。

私たちはあなたにも注釈をカスタマイズすることができ、JDKおよび注釈他のフレームワークを使用することができます。

3.元のノート(メタアノテーション)

メタアノテーションそれは何ですか?私の理解では、公式のJavaのメタアノテーションは、他のいくつかの注釈の属性に関連する、提供されます。

オープンカスタムノートなので、すべてのノートが従うためのルールである必要があり、そのプロパティの一部を定義する必要があり、例えば:クラス上の任意の場所や方法やフィールドで使用されるノートこのコメントは、ライフサイクルである?? ?人が読み、またはクラスファイルを生成します好きなソースのために予約されてどのような、プログラムは、これらの実際の役割はそうそこに、事前に定義する必要が発生します?:

4メタアノテーション@ターゲット文書化@、Retation @、@、継承されています。

そして、1〜4元ずつ説明を指摘します

@ターゲット

注釈の使用を記載するために使用される(すなわち:注釈が記載されている任意の場所で使用することができます)

彼の列挙は、範囲JDKクラスを定義しElementType、次の彼の合計値を:

  1. CONSTRUCTOR:コンストラクタを記述するために使用されます
  2. FIELD:クラスのメンバ変数のドメインを記述するために使用されます
  3. LOCAL_VARIABLE:記述するために使用されるローカル変数
  4. METHOD:について記載された方法
  5. パッケージ:パッケージには、記述するために使用しました
  6. PARAMETER:記述するために使用されるパラメータ
  7. TYPE:クラス、(注釈のタイプを含む)インターフェース、または列挙宣言を記述するために使用

注:JDK1.8、新しく追加された二つのタイプでは、 8 TYPE_PARAMETER:それは型注釈の宣言の前に使用することができる示し、9 TYPE_USE注釈は、すべての種類の使用の代わりに使用することができることを示しています

@保持

どのレベルの注釈情報を保存する必要性を表明し、ノートのライフサイクルを説明するために使用された(すなわち:注釈がどの程度効果的に説明されています)

彼は、列挙クラスの範囲RetentionPolicy、値は以下の通りでした。

  1. SOURCE:ソースファイル内の有効な(すなわち、ソースファイル保存)
  2. CLASS:有効なクラスファイル(つまりクラスを保有)
  3. RUNTIME:効果的な(すなわち、予約実行時)、実行時に

@Documented

パブリックAPIプログラムのメンバーがマークされているようであるべき注釈の他のタイプを記述するために使用@Documented、そのようなJavadocドキュメントなどのツールとなります。マーカー注釈、ないメンバーがある文書化されました。

@継承されました

 @Inheritedメタ注釈がマーカー注釈で、@継承は、インデックス付きの特定のタイプが継承されて説明します。修飾@Inherited注釈型を用いたものをクラスに使用される場合、このアノテーションは、このクラスのサブクラスで使用されています。

4.共通アノテーション

人気のサードパーティ製のフレームワークは、以下のようなノート、多くの達成するために、などを。MybatisParamSpringComponentServicefastjsonJSONfield

具体的な方法は、ここで説明することはあまりありませんが、興味を持っている友人が見てとることができfastjson、プロジェクトに比べて、ソースコード、springおよび他のフレームワークを、より簡便なは理解します。

我々は1が何を達成するために手を所有することができるかどうか、このコメントまたは単純または複雑な機能を見て?

5.カスタム注釈

ノートの5.1定義

まず、我々は、アノテーションを定義します。

package com.huyan.demo.config;

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;

/**
 * created by huyanshi on 2019/1/20
 */
@Target(ElementType.METHOD) // 该注解使用在方法上
@Retention(RetentionPolicy.RUNTIME) //运行时注解
@Documented
public @interface CheckSource {
  //该注解的参数,是一个string数组
  String[] sources() default {"all"};

}
复制代码

私たちは、注釈パラメータなので、その使用範囲を確認するために必要な方法、ライフサイクル运行时保留。また、注釈の種類がありstring数组、現在のプロセスは、ソースリストを可能に表現するために使用されるパラメータのは。

5.2パーサ書かれたノート

私は理解できないので、実際に、私は、ここに長い時間のためのもつれ始めました一个注解应该在哪里以什么方式调用

私の考えによると、各注釈は、それが行くべきであることを示すために、フィールド(または類似したもの)を持っている必要があり哪里、この注釈の実際の使用を呼び出します。

その後、慎重に反射した後、私はこれは何の注釈アクションの法律がすべてではありませんので、あなたが望むすべての機能を実装することができ、戻り値はロジックが任意である任意の値とすることができる非現実的であることがわかりました。

そして、それはあなたがあなたのコメントに責任があることを意味し、または彼がどんな効果を持っていませんでした。つまり、あなた自身のノートを記述する必要が注解解析器定義しますか什么时候用到这个注解,用它干什么

@ビューの純粋に個人的なポイントは、慎重に見て
インターネットをサーフィンした後、私が発見した主な注釈パーサ形式3つの方法で:

1.interceptor

それはどのように波を操作する方法があれば、クラスやメソッドには、特定のコメントは、着信要求をチェックしないことがあり、あなたが直接、すべての要求を傍受することができ、より便利です。

しかし、比較的大きなの制限は、我々はノートを使用されるコントローラではないだけです。

2.AOP

このアプローチは、また、新しい場所、うまく新しいカットオフ点でアノテーションを使用する必要があり、より良いスケーラビリティより便利です。

いつでも呼び出す方法、など3.パッケージ

これは、(実際には、それが再びそれを書くために使用される最も愛され、すべての聖歌です)ほとんどの人々に愛されていますが、多くの場合、コードを再構築していない場合、あなたはあなたが特定のコメントに完全に利用コードを引き出すことがわかります、それは次のようになりますそれはあなたが呼び出す必要があるたびに、統一されたツールを入れて、パッケージを見てみてくださいする必要があり、クラッシュします。

@ビューの個人的なポイントを終了!

私たちは、もちろん最初の方法は、より信頼性があるので、不正な要求をインターセプトする必要があるためですので、我々はインターセプタを書きました:

package com.huyan.demo.config;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * created by huyanshi on 2019/1/20
 */
public class CheckSourceInterceptor extends HandlerInterceptorAdapter {

  private static Logger LOG = LoggerFactory.getLogger(CheckSourceInterceptor.class);


  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    if (!(handler instanceof HandlerMethod)) {
      LOG.warn("UnSupport handler");
      throw new IllegalArgumentException("Interceptor only supports HandlerMethod handler");
    }
    //拿到请求参数里面的source参数
    String source = request.getParameter("source");
    String errorMsg = null;
    //如果source为空,返回错误
    if (null == source || "".equals(source)) {
      errorMsg = "No source in params";
    }
    if (errorMsg != null) {
      response.setStatus(500);
      LOG.info(errorMsg);
      response.getWriter().write(errorMsg);
      return false;
    }
    //拿到该方法上的注解对象
    CheckSource checkSource = getCheckSource((HandlerMethod) handler);
    //如果拿到的对象为空,说明没有此注解,直接放行
    if (checkSource != null) {
      //拿到注解对象的属性,即允许通行的source列表
      String[] sources = checkSource.sources();
      if (sources.length == 0 || sources[0].equals("all")) {
        //列表为空或者为默认值,放行
        return true;
      }
      //遍历列表,如果传入的参数在其中,则放行
      for (String s : sources) {
        if (s.equals(source)) {
          return true;
        }
      }
      //如果传入的source参数不在允许的参数列表中,则拦截请求,并返回错误信息
      errorMsg = "source is not support";
      response.getWriter().write(errorMsg);
      return false;
    }
    return true;
  }

  /**
   * 拿到该方法上的checksource注解对象
   */
  private CheckSource getCheckSource(HandlerMethod handlerMethod) {
    if (handlerMethod.getBeanType().isAnnotationPresent(CheckSource.class)) {
      return handlerMethod.getBeanType().getAnnotation(CheckSource.class);
    } else if (handlerMethod.getMethod().isAnnotationPresent(CheckSource.class)) {
      return handlerMethod.getMethod().getAnnotation(CheckSource.class);
    }
    return null;
  }
}

复制代码

コードは単にアイデアについてはこちらを書き、より詳細なコメントを追加します。

インターセプターの機構を介して、取得する方法CheckSource空とすることができるオブジェクトは、それが空に時間を取得しないsources特性を、順次通過した後、それは許可の受信リストのソースか否かが判断されます。

このインターセプタでは、我々は定義します。

1.場合はこの注釈を使用するには?

我々は、いずれかの方法コントローラ層に構成されている場合、このインターセプターを使用しています。

2.どのようにこのアノテーションを使用するには?

入ってくるテイクsource属性パラメータと注釈sources試合を許可するための要求にマッチしたリスト1を、エラーメッセージの一致の値が返されません。

注釈の5.3。実際の使用

5.3.1。まず、インターセプタインターセプタを設定するstatusインターフェイスを

package com.huyan.demo.config;


import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * created by huyanshi on 2019/1/20
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

  CheckSourceInterceptor checkSourceInterceptor = new CheckSourceInterceptor();

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(checkSourceInterceptor).addPathPatterns("/status");
  }

}

复制代码

5.3.2.statusインタフェース

package com.huyan.demo.controller;

import com.huyan.demo.config.CheckSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * created by pfliu on 2018/9/2
 */
@RestController
public class StatusController {

  private Logger logger = LoggerFactory.getLogger(this.getClass());

  @CheckSource(sources = {"huyan", "huihui"})
  @GetMapping(value = "/status")
  public Object status(@RequestParam("source") String source) {
    return "哈哈哈";
  }
}
复制代码

まあ、すべてのコーディングが完了しました。

プロジェクトを開始し、その結果を見てください。

5.3.3。テスト結果

  • なしsourceパラメータ

  • 間違ったsourceパラメータ

  • 正しいsourceパラメータ

6.まとめ

Javaの注釈メカニズムを理解することはそれほど難しくありませんが、ポイントは、我々は一つの理由は、我々は彼らに慣れていないということです、毎日彼を適用することは困難であると思うし、第二に、私たちの业务、それほど一般的ではないロジック。

注釈メカニズムは、様々なフレームワークでの使用がたくさんあり、学び、自分の仕事に適用する私たちの努力の価値がある、彼は優れたメカニズムであることを証明するのに十分です。

7.参考リンク

josh-persistence.iteye.com/blog/222649... www.ibm.com/developerwo...

仕上がり。





変更履歴

完成2019年1月20日

上記のすべての個人の所得であり、間違ったが、コメント欄を歓迎している場合、私を修正し、と思います。

転載へようこそ、サインインし、元のリンクを保持してください。

連絡先Eメール:[email protected]

より多くの研究ノート、個々のブログを参照してください------> Huyan 10

おすすめ

転載: juejin.im/post/5cf8da13f265da1b7c61097b