英文:
Not able to read values using @Value in application.yaml in Springboot
问题
我正在使用Spring Boot - 2.3.3.RELEASE。在application.yaml中有一些值,我正在尝试使用@Value注解将它们注入到类中。但出于某些原因,它们没有被加载。结果应该是在SendPhoneByPhoneNumbers.java中,我们应该能够从application.yaml中读取notificationServiceURL。
注意- 我正在使用工厂和策略模式。该项目将被其他项目用作库,以导入并使用服务层公开的方法。
这是文件夹结构:https://i.stack.imgur.com/jpbNj.jpg
我正在尝试通过以调试模式运行Demo.java来查看实际值的外观。
application.yaml
notificationService:
url: "https://someURL.com"
Demo.java
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@SpringBootApplication
public class Demo {
public static void main(String[] args) {
    SpringApplication.run(Demo.class, args);
    String title="Title";
    String message="message";
    List<String> phoneNumbers = new ArrayList<>();
    phoneNumbers.add("333-222-1111");
    PhoneService phoneService = new PhoneService();
    phoneService.sendNotificationByPhoneNumbers(title, message, phoneNumbers);
}
}
PhoneService.java
@Service
public class PhoneService {
PhoneServiceImpl notificationServiceImpl = new PhoneServiceImpl();
public void sendNotificationByPhoneNumbers(String title, String message, List<String> phoneNumbers) {
    notificationServiceImpl.sendNotificationByPhoneNumbers(title, message, phoneNumbers);
}
}
PhoneServiceImpl.java
@Slf4j
@Component
public class PhoneServiceImpl {
@Value("${notificationService.url}")
String url;
public void sendNotificationByPhoneNumbers(String title, String message, List<String> phoneNumbers) {
    PhoneContext phoneContext = new PhoneContext(new SendPhoneByPhoneNumbers(url));
    phoneContext.notify(title, message, phoneNumbers);
}
}
PhoneContext.java
public class PhoneContext {
private PhoneStrategy phoneStrategy;
public PhoneContext(PhoneStrategy phoneStrategy){
    this.phoneStrategy = phoneStrategy;
}
public void notify(String title, String message, List<String> employees){
    phoneStrategy.sendNotification(title, message, employees);
}
}
PhoneStrategy.java
public interface PhoneStrategy {
public void sendNotification(String title, String message, List
}
SendPhoneByPhoneNumbers.java
@Slf4j
public class SendPhoneByPhoneNumbers implements PhoneStrategy {
RestTemplate restTemplate;
String notificationServiceURL;
BuildHttpRequest buildHttpRequest;
public SendPhoneByPhoneNumbers(String notificationServiceURL) {
    this.notificationServiceURL = notificationServiceURL;
    this.restTemplate = new RestTemplate();
    this.buildHttpRequest = new BuildHttpRequest();
}
@Async
public void sendNotification(String title, String message, List<String> phoneNumbers) {
    SmsMessage smsMessage= new SmsMessage(title, message, phoneNumbers, Collections.emptyList(), Collections.emptyList());
    try {
        HttpHeaders headers = new HttpHeaders();
        headers.set("idToken", buildHttpRequest.getNewToken());
        HttpEntity<SmsMessage> newRequest = new HttpEntity<>(smsMessage, headers);
        restTemplate.postForObject(notificationServiceURL + "/someUrl", newRequest, String.class);
    } catch (Exception e) {
        log.error(e.getMessage());
    }
}
}
此外,如果您对修改代码/结构以使其更好的方式有任何建议,请务必提出。
提前致谢。
英文:
I'm using Spring boot - 2.3.3.RELEASE. There are some values in application.yaml which I'm trying to inject in the classes using @Value annotation. But for some reason, they are not loading up. The result should be that, in SendPhoneByPhoneNumbers.java, we should be able to read notificationServiceURL from application.yaml.
Note- I'm using Factory and Strategy pattern. This project is going to be used as a Library for other projects to import and use the methods exposed by Service layer.
Here is the folder structure: https://i.stack.imgur.com/jpbNj.jpg
I'm trying to test by running Demo.java in Debug mode to see how the actual values looks like.
application.yaml
notificationService:
  url: "https://someURL.com"
Demo.java
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@SpringBootApplication
public class Demo {
    public static void main(String[] args) {
        SpringApplication.run(Demo.class, args);
        String title="Title";
        String message="message";
        List<String> phoneNumbers = new ArrayList<>();
        phoneNumbers.add("333-222-1111");
        PhoneService phoneService = new PhoneService();
        phoneService.sendNotificationByPhoneNumbers(title, message, phoneNumbers);
    }
}
PhoneService.java
@Service
public class PhoneService {
    PhoneServiceImpl notificationServiceImpl = new PhoneServiceImpl();
    public void sendNotificationByPhoneNumbers(String title, String message, List<String> phoneNumbers) {
        notificationServiceImpl.sendNotificationByPhoneNumbers(title, message, phoneNumbers);
    }
}
PhoneServiceImpl.java
@Slf4j
@Component
public class PhoneServiceImpl {
    @Value("${notificationService.url}")
    String url;
    public void sendNotificationByPhoneNumbers(String title, String message, List<String> phoneNumbers) {
        PhoneContext phoneContext = new PhoneContext(new SendPhoneByPhoneNumbers(url));
        phoneContext.notify(title, message, phoneNumbers);
    }
}
PhoneContext.java
public class PhoneContext {
    private PhoneStrategy phoneStrategy;
    public PhoneContext(PhoneStrategy phoneStrategy){
        this.phoneStrategy = phoneStrategy;
    }
    public void notify(String title, String message, List<String> employees){
        phoneStrategy.sendNotification(title, message, employees);
    }
}
PhoneStrategy.java
public interface PhoneStrategy {
   public void sendNotification(String title, String message, List<String> listOfEmployeeIdGroupNamePhoneNumbers);
}
SendPhoneByPhoneNumbers.java
@Slf4j
public class SendPhoneByPhoneNumbers implements PhoneStrategy {
    RestTemplate restTemplate;
    String notificationServiceURL;
    BuildHttpRequest buildHttpRequest;
    public SendPhoneByPhoneNumbers(String notificationServiceURL) {
        this.notificationServiceURL = notificationServiceURL;
        this.restTemplate = new RestTemplate();
        this.buildHttpRequest = new BuildHttpRequest();
    }
    @Async
    public void sendNotification(String title, String message, List<String> phoneNumbers) {
        SmsMessage smsMessage= new SmsMessage(title, message, phoneNumbers, Collections.emptyList(), Collections.emptyList());
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.set("idToken", buildHttpRequest.getNewToken());
            HttpEntity<SmsMessage> newRequest = new HttpEntity<>(smsMessage, headers);
            restTemplate.postForObject(notificationServiceURL + "/someUrl", newRequest, String.class);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }
}
Also, if you guys have any suggestions on modifying the code/structure in an way to make it better, please do suggest.
Thanks in advance.
答案1
得分: 1
PhoneService phoneService = new PhoneService();
由于您使用的 PhoneService 不是 Spring 容器中的托管bean,所以值没有被注入。
代码改进和修复
String title = "Title";
String message = "message";
List<String> phoneNumbers = new ArrayList<>();
phoneNumbers.add("333-222-1111");
// PhoneService phoneService = new PhoneService();
phoneService.sendNotificationByPhoneNumbers(title, message, phoneNumbers);
将此代码移动到实现了 CommandLineRunner 或 ApplicationRunner 接口的类中,并覆盖相应的 run() 方法。在该类中,您可以使用 @Autowired 注入 PhoneService,而不是手动实例化它。另外请注意,您需要在这个类上标记 @Component 注解。
其他建议的小改动:
- 您可以将 
SendPhoneByPhoneNumbers类设置为单例。如果有多个实现,请使用@Qualifier。 RestTemplate和BuildHttpRequest都可以使用@Bean注解创建。- 由于您正在使用 lombok,考虑使用 
@RequiredArgsConstructor也是一个选择。 
英文:
PhoneService phoneService = new PhoneService();
Since PhoneService that you are using is not a managed bean by spring container, the values are not being injected.
Code Improvement and FIX
String title="Title";
        String message="message";
        List<String> phoneNumbers = new ArrayList<>();
        phoneNumbers.add("333-222-1111");
        // PhoneService phoneService = new PhoneService();
        phoneService.sendNotificationByPhoneNumbers(title, message, phoneNumbers);
Move this code to a class implementing CommanLineRunner or ApplicationRunner and override corresponding run(). In this class, you could @Autowire PhoneService rather than manually instantiating it. Also note that you have to mark this class with @Component
Other minor suggested changes:
- You can make 
SendPhoneByPhoneNumbersclass a singleton. If there are multiple implementions, use@Qualifier - Both 
RestTemplateandBuildHttpRequestcould be created using@Beanannotation. - Since you are using lombok, using 
@RequiredArgsConstructorcould also be considered. 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论