在构造函数中指定字符串值

时间:2018-03-09 09:30:34

标签: java csv spring-boot

任务

我正在尝试搜索springboot应用程序的解决方案,我们希望在调试模式或开发模式下加载CSV文件。这些CSV文件包含测试值,表示格式正确的数据。

解决方案

根据spring boot documentation我选择yaml配置文件,我可以说,CSV文件将位于某个确切的位置(即:classpath:/)。财产看起来像这样:

spring
  profiles: development
  csv:
    first-csv: classpath:/first.csv

然后在我们阅读资源时有逻辑。该逻辑将决定我们是否将根据模式(开发或任何其他)调用生产数据或模拟数据(csv文件)。在开发模式中,我们将尝试读取csv文件,这些文件应放在应用程序的根文件夹中(如上面的yaml配置中所示。

问题

当我为类调用构造函数时,我需要知道.csv文件的位置,我不知道如何通过构造函数将这些字符串值设置为本地字符串值。我的电话看起来像这样:

@Configuration
class WhereWeDecideWhichWayToGo() {

  private final CSVProperties csvProperties;

  //Code for production solution - which works

  @Bean
  @Profile("development")
  public CreateMockData createMockData() {
    return new MockData(csvProperties.getMockCSV());
    }
}

其中CSVProperties是一个只有yaml配置文件属性的getter / setter的类。这个类有注释:

@Component
@ConfigurationProperties("csv")

它有效。读取配置文件中的值。在调试期间,我可以确认csvProperties.getMockCSV()=" classpath:/first.csv" ;,但它没有分配给MockData类中的正确变量,如下所示:

class MockData {

String CSV;

public MockData(
        String mockCSV) {
  // Following line is skipped in debug (and also in normal run)
    CSV = mockCSV;
  }
  // Do some stuff with CSV file
}

问题:

为什么MockData的构造函数中的行初始化为CSV String

CSV = mockCSV;

跳过 - 未分配且代码只是继续(跳过分配),即使mockCSV具有正确的值:

classpath:/first.csv

我认为问题是initialisation order,因为我在构造函数之后的方法中使用了CSV的值,并且它为null。

1 个答案:

答案 0 :(得分:2)

由于您似乎忽略了我创建MCVE的建议,我尝试使用您问题中的代码尝试这样做,这对我有用。

您发布的代码显然是根据您实际执行的内容进行大量编辑的,所以我不得不猜测一些事情,并且您的示例中也存在一些语法错误已发布,所以我试图推断出它们在您的代码中的真实含义。以下是我所做的工作,以及关于我猜到的地方的说明,希望它能指出你正确的方向。

所以,从一开始,这里就是@SpringBootApplication的类,大概你在代码库的某个地方有这样的东西:

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

这是配置属性类。请注意,您不需要它是@Component

@ConfigurationProperties("csv")
public class CSVProperties {
    private String firstCsv;

    public String getFirstCsv() {
        return firstCsv;
    }

    public void setFirstCsv(String firstCsv) {
        this.firstCsv = firstCsv;
    }
}

我调用了属性firstCsv以匹配application.yml文件first-csv中的值。有趣的是,在您的代码中,您似乎使用csvProperties.getMockCSV()来引用此属性。我猜你的问题只是一个错字,因为这样做永远不会有效 - 属性名称需要匹配application.yml文件中的密钥。

这是配置类。你没有在你的例子中的任何地方展示过这个,但可能你在某处有一个等价物。重要的部分是@EnableConfigurationProperties,它必须指定具有@ConfigurationProperties注释的类。

@Configuration
@EnableConfigurationProperties(CSVProperties.class)
public class CSVExampleConfiguration {
    private final CSVProperties csvProperties;

    @Autowired
    public CSVExampleConfiguration(CSVProperties csvProperties) {
        this.csvProperties = csvProperties;
    }

    @Bean
    @Profile("!development")
    public MockData createProductionMockData() {
        return new MockData("production");
    }

    @Bean
    @Profile("development")
    public MockData createMockData() {
        return new MockData(csvProperties.getFirstCsv());
    }
}

有趣的是,在您的问题中,您说您使用类似public CreateMockData createMockData() {的方法创建bean,但随后返回MockData。同样,我猜测这是你问题中的拼写错误,因为它不会像这样编译(除非MockData扩展CreateMockData,但这看起来很奇怪。)

我不确定您是如何设置制作配置文件的,但希望我上面所做的是合理的等效 - @Profile("!development")说"创建此bean如果'发展'个人资料未设置"

我的application.yml文件与您在问题中发布的内容略有不同:

spring:
  profiles: development

csv:
  first-csv: classpath:/first.csv

您的示例根本无法工作,首先是因为您在:之后错过了spring,其次是因为您似乎csv嵌套在spring之下{1}},这不是你如何设置配置属性 - 它需要在如上所述的根级别。同样,我认为这些只是问题中的拼写错误,因为你说应用程序启动(它不会丢失:)并且你看到配置属性得到设置(它不会# t csv嵌套在spring下。

最后,我用一个简单的控制器测试了所有这些。您还没有提供有关应用程序其余部分的任何详细信息,但这是我已经完成的工作,希望能够模仿您的代码:

@RestController
public class TestController {
    private final MockData mockData;

    @Autowired
    public TestController(MockData mockData) {
        this.mockData = mockData;
    }

    @RequestMapping(value = "/foo", method = RequestMethod.GET)
    public String getCsv() {
        return mockData.getCSV();
    }
}

那么,在应用程序运行且没有配置文件集的情况下,如果我在浏览器中访问http://localhost:8080/foo,我会得到String" production"在响应中,如果我重新启动应用程序,使用" development"的配置文件,我会收到" classpath的响应:/first.csv"。

我很欣赏这可能不是"只是这样做"您可能希望得到的答案,但我建议您将其与您的代码进行比较,并尝试修改任何不同的内容。如果仍然无法使其工作,那么应用程序中的其他地方必然存在导致问题的其他一些差异。如果您需要更多帮助,请使用我错过的详细信息编辑您的问题,但请尝试发布实际代码(复制和粘贴,而不是重新输入,以避免引入混乱的拼写错误)。