purpose

The auxiliary function of configuration automatic prompt can make configuration write faster and accuracy greatly improved.

The Springboot JAR contains metadata files that provide details of all supported configuration properties. The purpose of the file is to allow IDE developers to provide context assistance and code completion when users use application.properties or application.yml files.

Most metadata files are generated automatically at compile time by processing all items annotated with @ConfigurationProperties. You can also write some metadata manually.

version

Refer to the SpringBoot 2.2.0.release documentation

file

Meta-inf /spring-configuration-metadata.json (automatically generated) or meta-INF/Additional spring-configuration-metadata.json (manually added)

In actual combat

<! <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>Copy the code

@Configuration @ConfigurationProperties(prefix = "file.upload") public class FileUploadConfig { /** Maximum number of bytes per file */ private String maxSize = "1024M"; /** Disallowed file suffixes */ private String rejectSuffix; Getter /setter}; // Use getter/setter}; // Use getter/setter}Copy the code
@configuration@configurationProperties ("map.test") public class MapTestConfig {/** private map <String,  Object> data; Getter /setter}; // Use getter/setter}; // Use getter/setter}Copy the code

Chinese annotations will be garbled. Where Chinese annotations are deliberately used above, the corresponding description will be specified in the following file to see whether they will be overwritten.

additional-spring-configuration-metadata.json

{
  "properties": [
    {
      "name": "file.upload.reject-suffix",
      "type": "java.lang.String",
      "defaultValue": "exe,jar",
      "description": "The file suffix is not allowed.",
      "sourceType": "com.lw.metadata.config.FileUploadConfig"
    },
    {
      "name": "map.test.data",
      "type": "java.util.Map",
      "description": "Tips for testing Map type data.",
      "sourceType": "com.lw.metadata.config.MapTestConfig"
    }
  ],
  "hints": [
    {
      "name": "map.test.data.keys",
      "values": [
        {
          "value": "name",
          "description": "The name of the person."
        },
        {
          "value": "sex",
          "description": "The sex of the person."
        }
      ]
    }
  ]
}Copy the code

Json = spring-configuration-metadata.json = spring-configuration-metadata.json = spring-configuration-metadata.json = spring-configuration-metadata.json = spring-configuration-metadata.json

{
  "groups": [
    {
      "name": "file.upload",
      "type": "com.lw.metadata.config.FileUploadConfig",
      "sourceType": "com.lw.metadata.config.FileUploadConfig"
    },
    {
      "name": "map.test",
      "type": "com.lw.metadata.config.MapTestConfig",
      "sourceType": "com.lw.metadata.config.MapTestConfig"
    }
  ],
  "properties": [
    {
      "name": "file.upload.max-size",
      "type": "java.lang.String",
      "description": "Maximum number of bytes per file",
      "sourceType": "com.lw.metadata.config.FileUploadConfig",
      "defaultValue": "1024M"
    },
    {
      "name": "file.upload.reject-suffix",
      "type": "java.lang.String",
      "description": "The file suffix is not allowed.",
      "sourceType": "com.lw.metadata.config.FileUploadConfig",
      "defaultValue": "exe,jar"
    },
    {
      "name": "map.test.data",
      "type": "java.util.Map<java.lang.String,java.lang.Object>",
      "description": "Tips for testing Map type data.",
      "sourceType": "com.lw.metadata.config.MapTestConfig"
    }
  ],
  "hints": [
    {
      "name": "map.test.data.keys",
      "values": [
        {
          "value": "name",
          "description": "The name of the person."
        },
        {
          "value": "sex",
          "description": "The sex of the person."
        }
      ]
    }
  ]
}Copy the code

The effect

The following phenomena can be seen:

  • Default values in the code are automatically generated in the prompt file, such as FileUploadConfig#maxSize
  • Comments in the code are automatically generated in a prompt file, such as FileUploadConfig#maxSize
  • The information in the additional-spring-configuration-metadata.json file overwrites the automatically generated property. If the automatically generated property does not contain this property, it is automatically added.

Write the prompt file manually

The sample

{
    "groups": [
        {
            "name": "server",
            "type": "org.springframework.boot.autoconfigure.web.ServerProperties",
            "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
        },
        {
            "name": "spring.jpa.hibernate",
            "type": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate",
            "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties",
            "sourceMethod": "getHibernate()"
        }
    ],
    "properties": [
        {
            "name": "server.port",
            "type": "java.lang.Integer",
            "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
        },
        {
            "name": "server.address",
            "type": "java.net.InetAddress",
            "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties"
        },
        {
              "name": "spring.jpa.hibernate.ddl-auto",
              "type": "java.lang.String",
              "description": "DDL mode. This is actually a shortcut for the \"hibernate.hbm2ddl.auto\" property.",
              "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate"
        }
    ],
    "hints": [
        {
            "name": "spring.jpa.hibernate.ddl-auto",
            "values": [
                {
                    "value": "none",
                    "description": "Disable DDL handling."
                },
                {
                    "value": "validate",
                    "description": "Validate the schema, make no changes to the database."
                },
                {
                    "value": "update",
                    "description": "Update the schema if necessary."
                },
                {
                    "value": "create",
                    "description": "Create the schema and destroy previous data."
                },
                {
                    "value": "create-drop",
                    "description": "Create and then destroy the schema at the end of the session."
                }
            ]
        }
    ]
}Copy the code

groups

Grouping, grouping configuration classes. You can group by file, that is, put all attributes of the same profile in the same group

attribute

type

Whether must use

name

String Y

The full name of the group

type

String N

Class names of grouped data types (e.g., full class names with @ConfigurationProperties annotations, method return types with @bean annotations)
description

String N

Grouping ofbriefDescription.

sourceType

String N

Provide the name of the class from which the grouping is derived.

sourceMethod String N

Provides methods for grouping, including parentheses and parameter types.

properties

Prompt subject, must

attribute

type

Whether must use

name

String

Y

The full name of the property. The namesLowercase period separatorFormat, such as:server.address
type

String

N

The full signature of the property data type (e.g.java.lang.String) or a full generic type (e.g.java.util.Map). This property prompts the user for a value type. Native types use their wrapper types here (e.g.booleanusejava.lang.Boolean).
description

String

N

Grouping ofbriefDescription.

sourceType

String

N

Provide the name of the class from which the grouping is derived.

defaultValue Object

N

The default value. Used when the property is specified.

deprecation

Deprecation N

Specifies whether the attribute is deprecated.

The deprecation attribute is as follows:

attribute

type

Whether must use

level

String N

Deprecation level, which can bewarning(Default value) orerror.warning: Attributes should still be available;errorThe: attribute is not guaranteed to be used
reason

String N

Short reasons for attribute deprecation.

replacement String N

Replaces the new property full name for this deprecated property.Can be null

Note: Prior to Spring Boot version 1.3, deprecated was deprecated using Boolean.

The following example from official documentation shows how to handle this scenario:

`java

@ConfigurationProperties(“app.acme”)

public class AcmeProperties {

private String name;

public String getName() { … }

public void setName(String name) { … }

@DeprecatedConfigurationProperty(replacement = “app.acme.name”)

@Deprecated

public String getTarget() {

return getName();

}

@Deprecated

public void setTarget(String target) {

setName(target);

}

}

`

Once the getTarget and setTarget methods are removed from the public API, the automatic deprecation prompts in the metadata also disappear. If you want to keep hints, adding manual metadata with the error deprecation level ensures that users are still aware of the property. This is particularly useful when providing alternatives.

hints

Auxiliary hints, not required

attribute

type

Whether must use

name

String

Y

Indicates the full name of the associated property. The name isLowercase period separatorFormat (e.g.spring.mvc.servlet.path), if the attribute is associated with a map type (e.g.system.contexts), indicating that the map can be associated with the key (system.contexts.keys) or value (system.contexts.values).
values

ValueHint[]

N

Set of valid values. (Detailed in the table below)

providers ValueProvider[] N

Collection of providers. (Detailed in the table below)

Values attributes are as follows:

attribute

type

Whether must use

value

Object Y

Prompt for valid values for reference elements. If the property is an array, value and description can also be arrays.
description String N

Value Indicates the short description of the value

ValueHint

Map types are supported as follows:

@ConfigurationProperties("sample")
public class SampleProperties {

    private Map<String,Integer> contexts;
    // getters and setters
}Copy the code

{"hints": [
    {
        "name": "sample.contexts.keys",
        "values": [
            {
                "value": "sample1"
            },
            {
                "value": "sample2"
            }
        ]
    }
]}Copy the code

The prompt is for each pair of key-values in the Map.

The. Keys and. Values prefixes must be associated with keys and values of the Map, respectively.

Providers attributes are as follows:

attribute

type

Whether must use

name

String

N

The name of the provider used to provide additional content assistance for the element referenced by the prompt.

parameters JSON object N

Any other parameters supported by the provider (see the documentation for the provider for more information).

ValueProvider

* It is recommended to skip *

The following table summarizes the supported providers list:

attribute

describe

any

Any added value is allowed.

class-reference

Automatically complete the classes available in the project. Base class constraints, usually specified by the target parameter.

handle-as

Handle the property as if it were defined by a type defined by the required target parameter.
logger-name

Automatically complete valid logger names and logger groups. Typically, the package and class names available in the current project can be completed automatically or groups can be defined.
spring-bean-reference Automatically complete the bean names available in the current project. The base class constraint, usually specified by the target parameter.
spring-profile-name

The name of the Spring configuration file available in the autocomplete project.

any

All values that match the attribute type.

{"hints": [
    {
        "name": "system.state",
        "values": [
            {
                "value": "on"
            },
            {
                "value": "off"
            }
        ],
        "providers": [
            {
                "name": "any"
            }
        ]
    }
]}Copy the code

class-reference

Provide the following parameters:

parameter

type

The default value describe

target

String (Class) There is no

The fully qualified class name of the class assigned to the value. Usually used to filter non-candidate classes.
concrete boolean

true

Specifies whether only concrete classes are considered valid candidates.

{"hints": [
    {
        "name": "server.servlet.jsp.class-name",
        "providers": [
            {
                "name": "class-reference",
                "parameters": {
                    "target": "javax.servlet.http.HttpServlet"
                }
            }
        ]
    }
]}Copy the code

handle-as

Allows you to replace the type of a property with a more advanced type.

This usually happens when the property has type java.lang.String, because you don’t want the configuration class to depend on classes that aren’t on the classpath.

parameter

type

The default value
describe

target String (Class) There is no

Y

The fully qualified name of the type considered for the property.

The available values are as follows:

  • anyjava.lang.Enum: lists the possible values for the attribute.
  • java.nio.charset.Charset: Supports automatic completion of character set/encoding values (e.gutf-8)
  • java.util.Locale: Automatically completes locale Settings (e.g.en_US)
  • org.springframework.util.MimeType: Supports auto-complete content-type values (e.g. text/plain )
  • org.springframework.core.io.Resource: Supports automatic spring resource abstraction to reference files on file systems or classpath (e.g.classpath:/sample.properties)

Note: If you want to supply multiple values, use Collection or array types

{"hints": [
    {
        "name": "spring.liquibase.change-log",
        "providers": [
            {
                "name": "handle-as",
                "parameters": {
                    "target": "org.springframework.core.io.Resource"
                }
            }
        ]
    }
]}Copy the code

logger-name

Logger-name The provider automatically completes the valid logger name and logger group. Typically, the package and class names available in the current project can be done automatically. If a group is enabled (the default) and a custom logger group is identified in the configuration, auto-completion for that group should be provided.

The following parameters are supported:

parameter

type

The default value describe

group boolean true

Specifies whether known groups should be considered.

Because logger names can be arbitrary, this provider should allow any value, but it can highlight valid package and class names that are not available in the project’s classpath.

Here is the logging.level property. Keys is logger name, values is associated with standard log levels or custom levels,

{"hints": [
    {
        "name": "logging.level.keys",
        "values": [
            {
                "value": "root",
                "description": "Root logger used to assign the default logging level."
            },
            {
                "value": "sql",
                "description": "SQL logging group including Hibernate SQL logger."
            },
            {
                "value": "web",
                "description": "Web logging group including codecs."
            }
        ],
        "providers": [
            {
                "name": "logger-name"
            }
        ]
    },
    {
        "name": "logging.level.values",
        "values": [
            {
                "value": "trace"
            },
            {
                "value": "debug"
            },
            {
                "value": "info"
            },
            {
                "value": "warn"
            },
            {
                "value": "error"
            },
            {
                "value": "fatal"
            },
            {
                "value": "off"
            }

        ],
        "providers": [
            {
                "name": "any"
            }
        ]
    }
]}Copy the code

spring-bean-reference

This provider automatically completes the beans defined in the configuration of the current project. The following parameters are supported:

{"hints": [
    {
        "name": "spring.jmx.server",
        "providers": [
            {
                "name": "spring-bean-reference",
                "parameters": {
                    "target": "javax.management.MBeanServer"
                }
            }
        ]
    }
]}Copy the code

spring-profile-name

This provider automatically completes the Spring configuration file defined in the configuration of the current project.

The following example represents the name of the profile that can be enabled by the spring.profiles.active property.

{"hints": [
    {
        "name": "spring.profiles.active",
        "providers": [
            {
                "name": "spring-profile-name"
            }
        ]
    }
]}Copy the code

Repeatable metadata items

Objects with the same “property” and “group” names can appear more than once in a metadata file. For example, two separate classes can be bound to the same prefix, each with potentially overlapping attribute names. While the same name that appears multiple times in metadata should not be common, consumers of metadata should take care to ensure that they support it.

Automatically generate prompt files

Using the Spring-boot-configuration-Processor JAR, you can easily generate your own configuration metadata files from classes annotated with @ConfigurationProperties. The JAR contains a Java annotation handler that is called when the project is compiled. To use this processor, you need to introduce the spring-boot-configuration-processor dependency.

`xml

org.springframework.boot

spring-boot-configuration-processor

true

`

The handler gets classes and methods annotated with @ConfigurationProperties. The Javadoc that configures the field values in the class is used to populate the Description attribute.

Note: Only simple text should be used with the @ConfigurationProperties field Javadoc, because they are not processed before they are added to JSON.

If the class has a “at least one argument” constructor, create a property for each constructor argument. Otherwise, properties are discovered through standard getters and setters that perform special treatment on collection types (even if only the getter exists).

The annotation processor also supports Lombok annotations using @data, @getter, and @setter.

The annotation processor cannot automatically detect the default values for Enum and Collections. Manual metadata should be provided in cases where a collection or enumeration property has a non-empty default value.

@ConfigurationProperties(prefix="acme.messaging")
public class MessagingProperties {

    private List<String> addresses = new ArrayList<>(Arrays.asList("a", "b")) ;

    private ContainerType = ContainerType.SIMPLE;

    // ... getter and setters

    public enum ContainerType {
        SIMPLE,
        DIRECT
    }
}Copy the code

To indicate the default values for the above attributes, the following metadata should be manually added:

{"properties": [
    {
        "name": "acme.messaging.addresses",
        "defaultValue": ["a", "b"]
    },
    {
        "name": "acme.messaging.container-type",
        "defaultValue": "simple"
    }
]}Copy the code

Note: If you are using AspectJ in your project, you need to ensure that the annotation processor runs only once. When using Maven, you can explicitly configure the Maven-apt-plugin plug-in and add dependencies to the annotation processor only there. You can also have the AspectJ plug-in run on all processing and disable annotation processing in the Configuration of the Maven-Compiler-plugin, as follows:

`java

org.apache.maven.plugins

maven-compiler-plugin

none

`

Binding properties

Annotation handlers automatically treat inner classes as nested properties.

@ConfigurationProperties(prefix="server")
public class ServerProperties {
    private String name;
    private Host host;
    // ... getter and setters
    public static class Host {
        private String ip;
        private int port;
        // ... getter and setters
    }
}Copy the code

The above example generates metadata information for the server.name, server.host. IP, and server.host.port properties. Can be used on field @ NestedconfigurationProperty annotations to indicate that the conventional (internal) class should be regarded as nested classes.

Note: This has no effect on collections and maps because these types are automatically identified and a metadata attribute is generated for each type.

Add additional metadata

Spring Boot’s configuration file handling is very flexible, and in general there may be properties that are not bound to the @ConfigurationProperties bean. You may also need to adjust some properties of your existing key, and to support this and allow you to provide custom “hints,” The annotation processor automatically merges the prompts in meta-INF/Additional -spring-configuration-metadata.json into the main metadata file (spring-configuration-metadata.json).

If a reference is made to an automatically detected property, the description, default value, and deprecation information (if specified) are overridden. If the declaration in the manual property is not identified in the current module, it is added as a new property.

The format of the additional-spring-configuration-metadata.json file is the same as that of the spring-configuration-metadata.json file. The attached properties file is optional. If you don’t have any other properties, don’t add the file.

The resources

Yi Fei Xi (focus on in-depth learning of Java domain knowledge, from source code to principle, systematic and orderly learning)