Parameter calibration interface implemented custom annotations

1 Introduction

In the development of the interface, we sometimes want an interface can only be a certain person (source) request , then we need to do to request verification parameters on the server.

In this case we can use interceptorto unify parameter check, but if a lot of interfaces, there is a different set of values, we can not write a lot interceptor, and then one by one to add it in accordance with the path?

Faced with this situation, we can choose a custom annotations by annotation to tell us, this interface allows visitors who.

Note: In our example, only realized the check to a certain field, security is not high, the actual project, multi-field encryption methods can be used to ensure the security, cultural principle is the same.

2.java notes Introduction

Java Annotation is a comment mechanism JDK5.0 introduced.

Annotation is the special code markers that can be compiled, class loading, the runtime is read, and performs a corresponding process.

By using the Annotation, programmers, some additional information embedded in the source file without changing the original logic.

Annotation may be used as modifiers like, can be used to package, class, interface, constructor, method, member variable (member variables), parameter, local variable (local variable), annotation (notes), after jdk 1.8, as long as the type appears place (including classes, interfaces, annotations, enumeration) can be used by the comment.

We can use the JDK and Annotation other framework, you can also customize Annotation.

3. yuan notes (meta-annotation)

Meta-annotation what is it? In my understanding, the official java meta-annotation is provided, pertaining to several other annotation attributes.

Because open custom notes, all notes must be rules to follow, some of their properties have to be defined, such as: the notes used in any place or method on the class or on the field this comment is the life cycle?? ? What is reserved for the source where people like to read, or will generate class files, the program generates the actual role of these need to be defined well in advance, so there?:

The four meta-annotation @ Target, @ Retation, @ Inherited, @ Documented.

Then one by one to four yuan notes Description

@Target

Used to describe the use of annotations (i.e.: annotations are described may be used in any place)

His enumeration defines the range JDK class ElementType, his total value of the following:

  1. CONSTRUCTOR: constructor is used to describe
  2. FIELD: that is used to describe the class member variable domain
  3. LOCAL_VARIABLE: local variables used to describe the
  4. METHOD: The method described for
  5. PACKAGE: package used to describe
  6. PARAMETER: parameters used to describe the
  7. TYPE: used to describe a class, an interface (including type of annotation), or an enum declaration

NOTE: In JDK1.8, the newly added two types, 8. The TYPE_PARAMETER: indicates that may be used in front of Type Annotation declarative, 9. TYPE_USE Annotation indicates that all can be used in place of the use of Type

@Retention

Expressed the need to save the annotation information on what level, it is used to describe the life cycle of notes (ie: annotations are described effectively to what extent)

He ranges from the enumerated classes RetentionPolicy, the values were the following:

  1. SOURCE: Effective in the source file (i.e., the source file retention)
  2. CLASS: valid class file (ie class reserved)
  3. RUNTIME: effective (ie reserved runtime) at runtime

@Documented

@Documented used to describe other types of annotation should be as a member of the public API program is marked, it can be such a tool such as javadoc documentation. Documented is a marker annotation, no members.

@Inherited

 @Inherited meta-annotation is a marker annotation, @ Inherited describes a certain type of indexed is inherited. If using a modified @Inherited annotation type is used for a class, then this annotation is used in a subclass of this class.

4. Common Annotations

Popular third-party framework to achieve a lot of notes, such as Mybatisthe Param, Springthe Component, Service, fastjsona JSONfield, and so on.

The specific method is not much to explain here, friends who are interested can take a look at fastjsonthe source code, compared to the project springand other frameworks, simpler and easier to understand.

After seeing this comment or simple or complex functions, whether we can own hands to achieve one do?

5. custom annotation

5.1 Definition of notes

First, we define the annotation:

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"};

}
复制代码

We need to check for annotation parameters, so its use range 方法, life cycle 运行时保留. In addition, there is a type of annotation string数组of parameters used to represent the current process allows the source list.

5.2 parser written notes

In fact, I started here tangled for a long time, because I can not understand 一个注解应该在哪里以什么方式调用.

According to my ideas, each annotation should have a field (or something similar), to indicate that it should go 哪里call the real use of this annotation.

Later, after careful reflection, I found that this is unrealistic because there is no annotation action law at all, you can implement any function you want, return value can be any value, which the logic is arbitrary.

Then it means that you are responsible for your comments, or he did not have any effect. In other words, you need to write your own notes 注解解析器to define 什么时候用到这个注解,用它干什么?

@ Purely personal point of view, carefully look
after surfing the Internet, I found that the main annotation parser 形式in three ways:

1.interceptor

It's more convenient, you can intercept all requests directly, there is no specific comments on the class and method to check the incoming request, if there is how how to operate a wave.

But the limitations of relatively large, we are not only in the controller which will be used notes.

2.AOP

This approach is also more convenient, better scalability when you need to use the annotation in a new place, a new cut-off point just fine.

3. Package as a method, called at any time

This is loved by most people (in fact, it is the most loved every chant used to write it again), but if you do not often reconstruct the code, you will find that you derive full use code to a particular comment, it would be it crashes, you need to try to look at the package, put a unified tools, every time when you need to call.

@ End personal point of view!

This is because we need to intercept illegal request, so of course the first way is more reliable, so we wrote an interceptor:

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;
  }
}

复制代码

Code adds more detailed comments, just write here about the idea:

Through the mechanism of the interceptor, the method to get the CheckSourceobject, which may be empty, it does not get time to empty sourcesproperties, after traversing successively, it is determined whether the source of the incoming list of allowed.

In this interceptor, we define:

1. When to use this annotation?

In using this interceptor when we configured into any one method when the controller layer.

2. how to use this annotation?

Take incoming sourceattribute parameters and the annotation sourceslist one matched with the request to allow the match, no match value of the error message is returned.

5.3. The actual use of annotations

5.3.1. First configure the interceptor, the interceptor statusinterfaces

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 Interface

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 "哈哈哈";
  }
}
复制代码

Well, all the coding completed.

Start the project, look at the results.

5.3.3. Test results

  • Without sourceparameters

  • Wrong sourceparameters

  • The correct sourceparameters

6. Summary

java annotation mechanism is not too difficult to understand, but the point is, we think it is difficult to apply in daily him, one reason is that we are not familiar with them, and secondly, our 业务, not so common logic.

Annotation mechanism is a lot of use in various frameworks, it is sufficient to prove that he is an excellent mechanism, it is worth our effort to learn and apply in their own work.

7. Reference Links

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

Finish.





ChangeLog

2019-01-20 completed

Above are all personal income and think, correct me if wrong welcomed the comments section.

Welcome to reprint, please sign, and retain the original link.

Contact E-mail: [email protected]

More study notes, see the individual blog ------> Huyan ten

Guess you like

Origin juejin.im/post/5cf8da13f265da1b7c61097b