无法使用 @Value 在 Springboot 的 application.yaml 中读取值。

huangapple go评论67阅读模式
英文:

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 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());
    }
}

}


此外,如果您对修改代码/结构以使其更好的方式有任何建议,请务必提出。

提前致谢。
英文:

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: &quot;https://someURL.com&quot;

Demo.java

@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@SpringBootApplication
public class Demo {

    public static void main(String[] args) {

        SpringApplication.run(Demo.class, args);

        String title=&quot;Title&quot;;
        String message=&quot;message&quot;;
        List&lt;String&gt; phoneNumbers = new ArrayList&lt;&gt;();
        phoneNumbers.add(&quot;333-222-1111&quot;);
        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&lt;String&gt; phoneNumbers) {
        notificationServiceImpl.sendNotificationByPhoneNumbers(title, message, phoneNumbers);
    }
}

PhoneServiceImpl.java

@Slf4j
@Component
public class PhoneServiceImpl {

    @Value(&quot;${notificationService.url}&quot;)
    String url;

    public void sendNotificationByPhoneNumbers(String title, String message, List&lt;String&gt; 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&lt;String&gt; employees){
        phoneStrategy.sendNotification(title, message, employees);
    }
}

PhoneStrategy.java

public interface PhoneStrategy {

   public void sendNotification(String title, String message, List&lt;String&gt; 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&lt;String&gt; phoneNumbers) {
        SmsMessage smsMessage= new SmsMessage(title, message, phoneNumbers, Collections.emptyList(), Collections.emptyList());

        try {
            HttpHeaders headers = new HttpHeaders();
            headers.set(&quot;idToken&quot;, buildHttpRequest.getNewToken());

            HttpEntity&lt;SmsMessage&gt; newRequest = new HttpEntity&lt;&gt;(smsMessage, headers);
            restTemplate.postForObject(notificationServiceURL + &quot;/someUrl&quot;, 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);

将此代码移动到实现了 CommandLineRunnerApplicationRunner 接口的类中,并覆盖相应的 run() 方法。在该类中,您可以使用 @Autowired 注入 PhoneService,而不是手动实例化它。另外请注意,您需要在这个类上标记 @Component 注解。

其他建议的小改动:

  1. 您可以将 SendPhoneByPhoneNumbers 类设置为单例。如果有多个实现,请使用 @Qualifier
  2. RestTemplateBuildHttpRequest 都可以使用 @Bean 注解创建。
  3. 由于您正在使用 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=&quot;Title&quot;;
        String message=&quot;message&quot;;
        List&lt;String&gt; phoneNumbers = new ArrayList&lt;&gt;();
        phoneNumbers.add(&quot;333-222-1111&quot;);
        // 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:

  1. You can make SendPhoneByPhoneNumbers class a singleton. If there are multiple implementions, use @Qualifier
  2. Both RestTemplate and BuildHttpRequest could be created using @Bean annotation.
  3. Since you are using lombok, using @RequiredArgsConstructor could also be considered.

huangapple
  • 本文由 发表于 2020年10月14日 02:36:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/64341203.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定