当前位置: 首页 > 知识库问答 >
问题:

基于前缀在Spring中对YAML属性进行后处理,以从REST服务中检索属性

赵昊阳
2023-03-14

我有一个Spring启动配置YAML,类似于

spring:
  application:
    name: my-app
a: a literal
b: <<external due to special first and last chars>>

我想做的是添加某种解析器,它将检测b的值是否为的形式

我尝试使用< code > EnvironmentPostProcessor 但失败了,因为我无法获得实际的属性值,只能获得属性源,所以我无法对值进行后处理。

当前对我有效的是@配置bean,它保存字段a,和b,在setters中实现一些东西,以检测spring试图设置的值是否以开始

在Spring 5中实现这样的东西的正确方法是什么?我知道Spring属性支持使用语法${a}引用其他属性,因此必须有一些机制已经允许添加自定义占位符解析器


共有3个答案

冯永长
2023-03-14

这是我使用Spring Boot 2.1.5想出的一个黑客解决方案。使用自定义属性解析器可能更好

基本上是这样的:

  1. 抓住我关心的财产来源。对于这种情况,它是应用程序.属性。应用程序可以有 N 个源,因此,如果有其他地方

我的属性是:

a=hello from a
b=<<I need special attention>>

我被黑客入侵的应用程序Listener是:

import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

public class EnvironmentPrepareListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {

    private final RestTemplate restTemplate = new RestTemplate();

    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        // Only focused main application.properties (or yml) configuration
        // Loop through sources to figure out name
        final String propertySourceName = "applicationConfig: [classpath:/application.properties]";
        PropertySource<?> propertySource = event.getEnvironment().getPropertySources()
                .get(propertySourceName);

        Map<String, Object> source = ((OriginTrackedMapPropertySource) propertySource).getSource();
        Map<String, Object> myUpdatedProps = new HashMap<>();
        final String url = "https://jsonplaceholder.typicode.com/todos/1";

        for (Map.Entry<String, Object> entry : source.entrySet()) {
            if (isDynamic(entry.getValue())) {
                String updatedValue = restTemplate.getForEntity(url, String.class).getBody();
                myUpdatedProps.put(entry.getKey(), updatedValue);
            }
        }

        if (!myUpdatedProps.isEmpty()) {
            event.getEnvironment().getPropertySources()
                    .addBefore(
                            propertySourceName,
                            new MapPropertySource("myUpdatedProps", myUpdatedProps)
                    );
        }
    }

    private boolean isDynamic(Object value) {
        return StringUtils.startsWith(value.toString(), "<<")
                && StringUtils.endsWith(value.toString(), ">>");
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}

点击<code>/test</code>会得到:

{ "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false }

吴展
2023-03-14

不知道正确的方法,但从REST调用获取属性的一种方法是实现您自己的Property tySource,它获取(和缓存?)特定命名属性的值。

洪黎昕
2023-03-14

我最终稍微改变了一些东西来标记特殊属性。然后我创建了自己的PropertySource,有点像@Andreas建议的那样。这一切都受到org.springframework.boot.env.RandomValuePropertySource的启发。

技巧是更改特殊字符<code>

这是我的解决方案的简化版本

public class MyPropertySource extends PropertySource<RestTemplate> {
  private static final String PREFIX = "rest.";

  public MyPropertySource() {
    super(MyPropertySource.class.getSimpleName());
  }

  @Override
  public Object getProperty(@Nonnull String name) {
    String result = null;
    if (name.startsWith(PREFIX)) {
        result = getValueFromRest(name.substring(PREFIX.length()));
    }

    return result;
  }
}

最后,为了注册属性源,我使用了环境后处理器,如下所述。我找不到一种不需要维护新文件META-INF/spring.factories的简单方法

 类似资料:
  • 本文向大家介绍JavaScript 从对象检索属性,包括了JavaScript 从对象检索属性的使用技巧和注意事项,需要的朋友参考一下 示例 性能特点: 可以从对象检索的属性可能具有以下特征, 可数 不可数 拥有 在使用创建属性时,我们可以设置其特征(“ own”除外)。在对象的直接级别而非原型级别()可用的属性称为自己的属性。Object.defineProperty(ies)__proto__

  • 当我在应用程序属性中添加表前缀时,我遇到了一个问题,Spring Batch没有获取该属性并设置默认前缀Batch。 Spring版 org.springframework.jdbc.错误的SQL语法[SELECTJOB_INSTANCE_ID,JOB_NAMEBATCH_JOB_INSTANCEJOB_NAME=?和JOB_KEY = ?]; 嵌套异常java.sql.SQLSyntaError

  • 问题内容: 我刚开始使用Spring DI,但是我在依赖注入方面苦苦挣扎,更糟糕的是,我什至不确定为什么对我来说似乎还可以。希望你们能帮助我! 问题是注释为@Autowired的属性始终为null 我有一些具有Maven结构的项目: com.diegotutor.lessondeliver com.diegotutor.utility 我正在通过Tomcat 7运行示例 我在我的使用以下依赖项:

  • 我正在Spring 3.1上构建REST服务。我正在为此使用@EnableWebMVC注释。由于我的服务将只接受JSON请求,因此我还希望将传入请求转储到MongoDB集合中以进行日志记录(以及稍后的数据转换)。我想访问原始的JSON请求(我可以在非Spring实现上使用“@Content HttpServletRequest request”作为方法参数来执行此操作)。 我是Spring新手。因

  • 基于另一个子DTO的属性值从arraylist中搜索元素的最佳方法是什么。 场景:我有Employee对象,它有另一个ContactDetails对象。我需要从extNumber为1234的员工列表中查找员工(extNumber是ContactDetails中的属性。我需要在创建新员工和分配新ext时检查ext是否可用。 无法直接使用JDBC查询,因为我正在使用corba api。没有任何提供此类

  • 我想使用应用程序.yml 而不是应用程序属性 我跟着: https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-external-config.html 我正在使用: 春靴 2.6.2 爪哇 17 渐变 7.3.2 我的https://github.com/OldEngineer1911