如何在Spring YAML配置中逃避SpEL美元符号?

时间:2017-12-21 16:45:51

标签: java spring escaping yaml spring-el

在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文件中,#是行注释字符,忽略此字符的所有内容。如果我使用\#,则会将\传递给字符串。

7 个答案:

答案 0 :(得分:1)

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

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

请注意,在空白之后或行的开头使用时,YAML中的#会开始发表评论。

答案 1 :(得分:1)

实际上,没有答案对我有用。但是,加一个双美元符号对我来说很好:

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

答案 2 :(得分:0)

答案实际上取决于您在代码中注入值的确切方式。由于您还没有提供,我只列出各种工作技术。

  1. 您可以使用UINavigationBar.appearance().largeTitleTextAttributes = [NSAttributedStringKey.foregroundColor:UIColor.blue, NSAttributedStringKey.font:UIFont.boldSystemFont(ofSize: 22)] 注释来注入您的财产。因为,unlike @ConfigurationProperties, @Value does SpEL evaluation,你必须逃避你的价值。
  2. application.yml:

    @Value

    TestController.java:

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

    GET到@RestController public class TestController { @Value("${csv.file.pattern}") private String pattern; @GetMapping("pattern") public ResponseEntity<String> getPattern() { return ResponseEntity.ok(pattern); } } 会产生输出/pattern,就像您需要的那样

    1. 您可以使用/some/path/#{app-name}.csv,这实际上取决于您如何构建配置对象。但一般情况下,@ConfigurationProperties应该不需要转义,因为默认情况下它们不支持SpEL。但是,以下是有效的,因此如果您的设置不同,请对其进行修改:
    2. application.yml:

      @ConfigurationProperties

      Config.java:

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

      TestController.java:

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

      同样,GET到@RestController public class TestController { @Autowired private Config config; @GetMapping("pattern") public ResponseEntity<String> getPattern() { return ResponseEntity.ok(config.getPattern()); } } 会产生输出/pattern

      您最有可能的是Config.java中的一些不同结构(可能会发布相关代码?),这可能导致该属性无法正常处理。

答案 3 :(得分:0)

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

ds: "$"

然后像这样使用它,${ds}将在运行时替换为$

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

工作时有点有趣。

答案 4 :(得分:0)

为什么不尝试使用${sys:$}却很丑但很有效。我认为没有人会使用$作为密钥。

答案 5 :(得分:0)

我遇到了同样的问题。因此,您可以通过使用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

答案 6 :(得分:0)

您需要使用#{'$'},并且在使用yaml时,需要用双引号将值引起来:

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