有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在构造函数中分配字符串值

任务

我正在尝试搜索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());
    }
}

其中,CSVProperty是一个仅包含yaml配置文件中属性的getter/setter的类。此类具有以下注释:

@Component
@ConfigurationProperties("csv")

它是有效的。将读取配置文件中的值。CSVPI可以在调试期间确认。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字符串的初始化

CSV = mockCSV;

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

classpath:/first.csv

我认为,问题是initialisation order,因为我在构造函数后面的方法中使用CSV的值及其null


共 (1) 个答案

  1. # 1 楼答案

    由于您似乎忽略了我创建MCVE的建议,因此我尝试使用您问题中的代码来创建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之后缺少一个:,其次是因为您似乎在spring下嵌套了csv,这不是您设置配置属性的方式—它需要位于上面的根级别。同样,我假设这些只是问题中的输入错误,因为您说应用程序启动(它不会使用缺少的:),并且您看到配置属性get set(它不会使用嵌套在spring下的csv

    最后,我用一个简单的控制器测试了所有这些。您还没有给出关于应用程序其余部分的任何详细信息,但这就是我所做的,希望能模仿您的代码:

    @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,我会在响应中得到字符串“production”,如果我重新启动应用程序,并且配置文件为“development”,我会得到响应“classpath:/first.csv”

    我理解这可能不是您希望的“只做这个”答案,但我建议您将其与代码进行比较,并尝试修改任何不同之处。如果您仍然无法让它工作,那么您的应用程序中肯定还有其他一些差异导致了这个问题。如果您需要更多帮助,请用我错过的细节编辑您的问题,但请尝试发布实际代码(复制并粘贴,而不是重新键入,以避免引入混淆的打字错误)