Springboot(六)自定义配置文件属性值注入两种方法

前言:

    在配置文件中自己定义的值,怎么注入到程序中,比如:mq队列的名称,缓存的key,文件的路径等。

 

代码:

首先建一个springboot工程

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xhx.springboot</groupId>
    <artifactId>springboot2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot2</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

自己定义一个配置文件test.properties

my.name=xuhaixing
my.age=25
my.sex=man

启动类:

package com.xhx.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Springboot2Application {

    public static void main(String[] args) {
        SpringApplication.run(Springboot2Application.class, args);
    }
}

 

 

 

 

第一种方式@Value注入:

其中@PropertySource指明要加载的配置文件

@Value("${}"),注入配置文件中的值

package com.xhx.springboot.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * made by xuhaixing
 * 18-4-8 下午9:01
 */


@Configuration  //证明这是一个配置类
@PropertySource(value = {"classpath:test.properties"}, ignoreResourceNotFound = true)//可以放多个,{}里面用,分开
public class User {

    //可以不用set方法,直接就能注入,属于注入
    @Value("${my.name}")
    private String name;

    @Value("${my.age}")
    private int age;

    @Value("${my.sex}")
    private String sex;


    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getSex() {
        return sex;
    }

}

 

可以在controller中把user类注入,然后测试一下:

 

package com.xhx.springboot.controller;

import com.xhx.springboot.config.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * made by xuhaixing
 * 18-4-8 下午9:48
 */
@RestController
public class HelloController {

    @Autowired
    private User user;

    @RequestMapping(value = "/getUser")
    public String getUser() {
        return user.getName() + " " + user.getSex() + " " + user.getAge();
    }
}

 

 

 

第二种方式 prefix:

package com.xhx.springboot.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * made by xuhaixing
 * 18-4-8 下午9:58
 */
@Configuration
@PropertySource(value = "classpath:test.properties")
@ConfigurationProperties(prefix = "my")  //需要有set方法
public class UserPrefix {
    private String name;
    private int age;
    private String sex;


    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getSex() {
        return sex;
    }
}

 

然后注入到controller中,测试

 

package com.xhx.springboot.controller;

import com.xhx.springboot.config.UserPrefix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * made by xuhaixing
 * 18-4-8 下午10:01
 */
@RestController
@EnableConfigurationProperties({UserPrefix.class})  //激活配置,测试了一下,也可以没有
public class HelloPrefixController {

    @Autowired
    private UserPrefix userPrefix;

    @RequestMapping(value = "/getUserPrefix")
    public String getUserPrefix() {
        return userPrefix.getName() + " " + userPrefix.getSex() + " " + userPrefix.getAge();
    }

}

 

我的github地址

更多内容请关注微信公众号:程序员星星

<think>我们面对的问题:如何在Spring Boot中从配置文件获取枚举类的属性值。 根据引用[4]和引用[5],我们可以知道: - 使用`@ConfigurationProperties`可以绑定配置文件中的属性到Java Bean。 - 枚举类在Spring Boot中用于定义一组常量,具有类型安全等优点。 但是,直接使用`@ConfigurationProperties`绑定到枚举类的属性值,需要做一些处理。 思路: 1. 在配置文件中,我们可以使用字符串来表示枚举值。 2. 在Java配置类中,我们可以定义一个枚举类型的字段,然后通过Spring的自动转换机制将字符串转换为枚举值。 然而,用户的问题不是获取枚举值本身,而是获取枚举类的“属性值”。这里有两种理解: a)配置文件中的值绑定到枚举类型的字段(即获取枚举实例) b)配置文件中的值绑定到一个普通类的字段,而这个字段的类型是某个枚举类(即获取枚举实例) c) 或者,我们有一个枚举类,这个枚举类的每个实例都有一些属性(比如除了枚举常量名外,还有附加属性),我们想从配置文件中读取这些属性的值。 根据引用[5]中提到的,枚举类可以定义属性方法。因此,这里可能是指:我们有一个带有属性的枚举类,然后希望从配置文件中读取值,并设置到枚举实例的属性上。但是,枚举实例是固定的(在编译时定义),我们通常不会在运行时通过配置文件来改变枚举实例的属性值。所以,更常见的需求是:从配置文件中读取一个字符串,然后映射到枚举类的一个实例(常量)。 因此,我们先按照常见的需求(读取字符串并映射为枚举实例)来解答,然后再考虑如果枚举类有属性,我们如何通过配置来设置这些属性(这通常需要自定义转换或使用工厂模式)。 常见做法(从配置文件中读取字符串并转化为枚举实例): 1. 定义一个枚举类。 2. 在配置类中,使用`@Value`或`@ConfigurationProperties`注入字符串,然后手动转换为枚举(或者Spring会自动转换)。 例如: 枚举定义: ```java public enum Status { OPEN, CLOSED } ``` 然后在配置类中: ```java @Component @ConfigurationProperties(prefix = "my") public class MyProperties { private Status status; // 配置文件中使用 my.status=OPEN // getter and setter } ``` Spring Boot会自动将字符串"OPEN"转换为Status.OPEN。 但是,如果枚举类有属性,比如: ```java public enum Status { OPEN("open", 1), CLOSED("closed", 2); private final String code; private final int value; Status(String code, int value) { this.code = code; this.value = value; } // getters } ``` 那么,我们可能希望从配置文件中读取一个字符串,然后匹配枚举的某个属性(比如code)来得到对应的枚举实例。这需要自定义转换器。 步骤: 1. 创建一个实现`Converter<String, Status>`的转换器。 2. 注册这个转换器。 例如: ```java import org.springframework.core.convert.converter.Converter; public class StringToStatusConverter implements Converter<String, Status> { @Override public Status convert(String source) { for (Status status : Status.values()) { if (status.getCode().equals(source)) { return status; } } return null; } } ``` 然后,我们需要将这个转换器注册到Spring中。可以通过在配置类中添加`@Configuration`并提供一个`ConversionService` bean: ```java @Configuration public class EnumConfig { @Bean public ConversionService conversionService() { DefaultConversionService service = new DefaultConversionService(); service.addConverter(new StringToStatusConverter()); return service; } } ``` 这样,在配置文件中使用`my.status=open`,Spring就会自动调用这个转换器将字符串"open"转换为Status.OPEN枚举实例。 但是,用户的问题描述是“获取枚举类属性值”,可能是指:我们有一个枚举类,它有一些属性(比如上面例子中的code和value),我们想从配置文件中读取这些属性的值,然后设置到枚举实例上?注意,枚举实例是单例且不可变的,通常我们不会在运行时改变它们的属性值。所以,更合理的需求是:我们有一个配置类,其中包含一个枚举类型的字段,我们想从配置文件中读取一个字符串,然后将其转换为枚举实例(通过枚举的某个属性来匹配)。 因此,我们按照自定义转换器的方式来解决。 另外,还有一种情况:我们可能希望将一组配置直接映射到枚举类的多个实例上?这不太常见,因为枚举实例是固定的。所以,我们主要解决将配置字符串转换为枚举实例的问题。 总结步骤: 1. 定义枚举类,包含所需的属性(如果需要通过属性来匹配,则定义属性)。 2. 如果需要通过属性(而不是枚举常量名)来匹配,则创建自定义转换器。 3. 注册自定义转换器。 4. 在配置类中使用`@ConfigurationProperties`或`@Value`注入枚举类型的字段。 示例: 步骤1:定义枚举类 ```java public enum Status { OPEN("open", 1), CLOSED("closed", 2); private String code; private int value; Status(String code, int value) { this.code = code; this.value = value; } public String getCode() { return code; } public int getValue() { return value; } } ``` 步骤2:自定义转换器 ```java import org.springframework.core.convert.converter.Converter; public class StringToStatusConverter implements Converter<String, Status> { @Override public Status convert(String source) { for (Status status : Status.values()) { if (status.getCode().equals(source)) { return status; } } throw new IllegalArgumentException("Invalid status code: " + source); } } ``` 步骤3:注册转换器(使用Spring Boot的配置方式) ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.support.DefaultConversionService; @Configuration public class EnumConfig { @Bean public DefaultConversionService conversionService() { DefaultConversionService conversionService = new DefaultConversionService(); conversionService.addConverter(new StringToStatusConverter()); return conversionService; } } ``` 步骤4:创建配置属性类 ```java import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix = "my") public class MyProperties { private Status status; public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } } ``` 在application.yml中配置: ```yaml my: status: open # 这里会通过自定义转换器转换为Status.OPEN ``` 这样,在MyProperties中,status字段就会被赋值为Status.OPEN。 但是,请注意:如果枚举类中的属性不是用来匹配的,而是我们想直接配置这些属性,那就不一样了。例如,我们想为每个枚举实例配置不同的属性值,但这些属性值是在配置文件中指定的?这通常不可行,因为枚举实例是在代码中定义的,是固定的。我们只能在定义枚举实例时指定属性值,而不能在运行时通过配置文件改变。 因此,我们只能通过配置文件来指定使用哪个枚举实例(通过匹配枚举实例的某个属性),而不能改变枚举实例本身的属性值。 所以,回答用户的问题:在Spring Boot中,通过配置文件获取枚举类的属性值,通常是指将配置的字符串值转换为对应的枚举实例(可能通过枚举的某个属性来匹配)。这需要自定义转换器。 另外,如果只是通过枚举常量名来匹配,则无需自定义转换器,Spring Boot会自动转换。 引用[4]中提到了使用`@ConfigurationProperties`绑定属性,我们可以利用它来绑定枚举类型的字段。 引用[5]中提到了枚举类的作用,包括可以定义属性方法,这为我们自定义转换器提供了基础。 因此,我们按照上述步骤来实现。 注意:在Spring Boot 2.x中,我们也可以使用`org.springframework.core.convert.converter.GenericConverter`,但这里使用简单的Converter即可。 另外,如果不想自定义转换器,也可以使用`@Value`注入字符串,然后在代码中手动转换,但这样不够优雅。 所以,推荐使用自定义转换器。 相关问题: 1. 如何在Spring Boot中自定义类型转换器? 2. Spring Boot中如何将配置属性绑定到枚举类型? 3. 枚举类在Spring Boot中如何与配置文件配合使用?</think>在 Spring Boot 中,可以通过以下两种主要方式从配置文件获取枚举类的属性值: ### 方法一:使用 `@ConfigurationProperties` 直接绑定枚举值 适用于将配置文件的字符串值直接映射为枚举常量 1. **定义枚举类**: ```java public enum AppMode { DEVELOP("开发模式", 100), PRODUCTION("生产模式", 200), TEST("测试模式", 300); private final String description; private final int code; AppMode(String description, int code) { this.description = description; this.code = code; } // Getters public String getDescription() { return description; } public int getCode() { return code; } } ``` 2. **创建配置类绑定枚举**: ```java @Component @ConfigurationProperties(prefix = "application") @Getter @Setter public class AppConfig { // 自动将配置文件中的字符串转为枚举实例 private AppMode mode; } ``` 3. **配置文件 (`application.yml`)**: ```yaml application: mode: PRODUCTION # 值必须匹配枚举常量名 ``` 4. **使用枚举值**: ```java @Autowired private AppConfig appConfig; public void printMode() { AppMode mode = appConfig.getMode(); System.out.println("当前模式: " + mode.getDescription()); System.out.println("状态码: " + mode.getCode()); } ``` ### 方法二:自定义转换器实现属性匹配 适用于需要通过枚举属性值(如 code/description)匹配的场景 1. **实现转换器**: ```java import org.springframework.core.convert.converter.Converter; public class StringToAppModeConverter implements Converter<String, AppMode> { @Override public AppMode convert(String source) { // 通过code匹配 for (AppMode mode : AppMode.values()) { if (mode.getCode() == Integer.parseInt(source)) { return mode; } } throw new IllegalArgumentException("无效的模式值: " + source); } } ``` 2. **注册转换器**: ```java @Configuration public class EnumConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new StringToAppModeConverter()); } } ``` 3. **配置文件 (`application.yml`)**: ```yaml application: mode: 200 # 通过枚举的code值匹配 ``` 4. **使用方式同方法一** ### 关键说明: 1. **自动转换原理**: Spring Boot 默认支持字符串到枚举的转换(通过 `name()` 方法匹配),无需额外配置[^4]。 2. **复杂匹配场景**: 当需要通过枚举属性(非常量名)匹配时,需自定义转换器并注册到 Spring 上下文[^5]。 3. **类型安全**: 枚举绑定提供编译时类型检查,避免无效值注入[^5]。 4. **配置提示**: 建议在 `application.yml` 中通过注释说明可选枚举值: ```yaml application: mode: # 可选值: # DEVELOP -> 开发模式 (100) # PRODUCTION -> 生产模式 (200) # TEST -> 测试模式 (300) PRODUCTION ``` ### 应用场景示例 ```java // 在业务逻辑中使用配置的枚举值 public void process() { switch (appConfig.getMode()) { case DEVELOP: // 开发环境逻辑 break; case PRODUCTION: // 生产环境逻辑 break; } } ``` > **最佳实践**:对于简单匹配直接使用默认枚举转换;需要按自定义属性匹配时实现转换器。枚举与配置结合可显著提升配置可读性和类型安全性[^5]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值