如何在Spring YAML配置中转义SpEL美元符号?

hrirmatl  于 12个月前  发布在  Spring
关注(0)|答案(8)|浏览(281)

在Spring YAML配置文件中,我需要有一个参数,如

csv:
  file:
    pattern: /some/path/${app-name}.csv

字符串
其中${app-name}在运行时被Java代码动态替换,我不希望Spring在启动时替换它。
为了实现这一点,我需要转义$字符,这样Spring就不会将其解释为SpEL。
以下答案在YAML中不适用

我试了所有的组合,

pattern: /some/path/\${app-name}.csv
pattern: "/some/path/\${app-name}.csv"
pattern: /some/path/#{'$'}{app-name}.csv
pattern: "/some/path/#{'$'}{app-name}.csv"


它们都不会产生包含所请求字符串的变量,带有美元符号,但没有转义字符。
请注意,它是YAML配置。在YAML文件中,#是行注解字符,从此字符开始的所有内容都被忽略。如果我使用\#,则\将传递给字符串。
添加:自25.06.2008以来一直开放Spring project open issue 9628
目前还没有办法注入一个不会被PropertyPlaceholderConfigurer拾取的${...}表达式。理想情况下,我们应该能够注入一个包含${...}的字符串,以便稍后在其目标bean中使用,而不需要PropertyPlaceholderConfigurer的参与。

bgibtngc

bgibtngc1#

我也有同样的问题,我只是找到了一个愚蠢的聪明的解决方案,定义一个名为dollarSign或ds的属性。

ds: "$"

字符串
然后像这样使用它,${ds}将在运行时被$替换。

csv:
  file:
    pattern: /some/path/${ds}{app-name}.csv


它起作用的时候还挺有趣的

9w11ddsr

9w11ddsr2#

我也遇到了同样的问题。所以你可以通过使用yaml文字样式符号“|“,或者像下面的例子一样使用literal_strip“|-“来解决这个问题。

application.yml

csv:
  file:
    pattern: |-
      /some/path/${app-name}.csv

字符串
实际上我的问题是在yml中配置一个公式,然后在java中动态解析表达式。在这里分享解决方案。
我选择spring el解决方案,使用spring版本5.0.9.RELEASE
我在yml中定义了一个公式,

score:
  formula: |-
    10 * #x + #y


然后在Spring组件Bean中,

@Value("${score.formula}")
String scoreFormula;


最后通过使用spring el,

ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

context.setVariable("x", 1);
context.setVariable("y", 1);
Integer score = parser.parseExpression(scoreFormula).getValue(context,Integer.class);

参考资料

yaml-multi-line

nfzehxib

nfzehxib3#

使用空键和美元符号$的组合作为默认值:

csv:
  file:
    pattern: /some/path/${:$}{app-name}.csv

字符串

r1zk6ea1

r1zk6ea14#

Spring目前没有为属性占位符提供转义机制,有一个open issue(25.06.2008开放)。在评论中,提到了这个解决方案(我不确定它是否适用于YAML):

csv:
  file:
    pattern: /some/path/#{'$'}{app-name}.csv

字符串
请注意,当在空格之后或行首使用时,YAML中的#将开始注解。

sg24os4d

sg24os4d5#

这个问题的答案取决于你是如何将值注入到代码中的。由于你还没有提供,我将只列出各种工作技术。
1.你可以使用@Value annotation来注入你的属性。因为,与@ConfigurationProperties不同,@Value执行SpEL计算,你必须转义你的值。
application.yml:

csv:
  file:
    pattern: /some/path/#{'$'}{app-name}.csv

字符串
TestController.java:

@RestController
public class TestController {
    @Value("${csv.file.pattern}") private String pattern;
    @GetMapping("pattern") public ResponseEntity<String> getPattern() {
        return ResponseEntity.ok(pattern);
    }
}


/pattern的GET操作将导致输出/some/path/#{app-name}.csv,正如您所需要的那样
1.您可以使用@ConfigurationProperties,这里它实际上取决于您如何构造配置对象。但是,通常情况下,@ConfigurationProperties不需要转义,因为它们默认不支持SpEL。下面的工作,但是,所以如果您的设置不同,请修改它:
application.yml:

csv:
  file:
    pattern: /some/path/#{app-name}.csv


Config.java:

@ConfigurationProperties(prefix = "csv.file")
public class Config {
    private String pattern;
    public String getPattern() { return pattern; }
    public void setPattern(String pattern) { this.pattern = pattern; }
}


TestController.java:

@RestController
public class TestController {
    @Autowired private Config config;
    @GetMapping("pattern") public ResponseEntity<String> getPattern() {
        return ResponseEntity.ok(config.getPattern());
    }
}


同样,对/pattern的GET将导致输出/some/path/#{app-name}.csv
你最有可能的是在你的Config.java中有一些不同的结构(可能是发布了相关的代码?),这可能会导致属性无法正确处理。

6fe3ivhb

6fe3ivhb6#

为什么不尝试使用${sys:$},这是丑陋的,但有效的。我认为没有人会使用$作为关键。

noj0wjuj

noj0wjuj7#

事实上,没有一个答案对我有用。然而,添加一个双美元符号对我来说很好:

csv:
  file:
    pattern: /some/path/$${app-name}.csv

字符串

ddhy6vgd

ddhy6vgd8#

你需要使用#{'$'},当你使用yaml时,你需要用双引号括住这个值:

csv:
  file:
    pattern: "/some/path/#{'$'}{app-name}.csv"

字符串

相关问题