Функция, вызванная из другого пакета, не может получить доступ к параметрам

#java #spring #rest

#java #весна #rest

Вопрос:

Вот моя проблема :

У меня есть два класса: класс A содержит некоторые @Value("${param.username}") и @Value("${param.password}") , у меня есть функция, использующая эти 2 параметра, и я использую @GetMapping(path = "/functionA") для запуска функции (эта функция представляет собой Post-запрос на сервер для аутентификации)

Имя пользователя и пароль включены application-contextual-values.properties

Когда я запускаю браузер localhost:8080/app/functionA => это работает!

У меня есть другой класс B, в другом пакете B я хочу вызвать первый класс A и использовать функцию для аутентификации. => У меня ошибка : Username must not be null

Это означает, что я не могу получить username и password которые хранятся в application-contextual-values файле.

Вот мой код класса A :

 public class A {

    @Value("${param.username}")
    private String username;

    @Value("${param.password}")
    private String password;

    @GetMapping(path = "functionA")
    public AuthentificationModel getClient() {
        HttpHeaders headers = new HttpHeaders();
        headers.setBasicAuth(this.username, this.password);
        String jwt = getJWT(); <======  this function is also in this class A
        
        ...
     
        I'm doing a construction of params, to send on POST 

        return token;
     }
  

Это AuthentificationModel только то, что отправляется обратно после запроса POST (access_token, client_id, token_type)

Мой класс B :

 import fr.ag2rlamondiale.ytb.rest.A; <==== class A

public class B {

   private static Map<String, String> getRequestHeader() {

       Map<String, String> requestHeaders = new HashMap<>();
       try{
         final A objA = new A(); <===== instance of my class A here
           String token = objA.getClient().getAccessToken(); <==== getClient() is the funct that returns token on class A

           requestHeaders.put("Authorization", "Bearer ",   token); 
             
           ... many other put for header
         } catch (CommonException e) {
        e.printStackTrace();
    }
    return requestHeaders;
}
  

Мое приложение-contextual-values.properties :

 param.username="kljkjsdf555sdf"
param.password="xxx222xxx"
  

Это потому, что мне нужно будет добавить конструктор в класс A с именем пользователя и паролем params? каков правильный способ заставить его работать в моем контексте?

Редактировать :

В классе A я добавил: @Controller

В классе B: я добавил @Authowired A objA и нет new A();

Но теперь, имея новую ошибку : Cannot make a static reference to the non-static field objA

Это означает, что элементы класса A не являются статическими, и я использую objA как статический объект?

Ответ №1:

Используйте внедрение зависимостей и @Autowired вашего A экземпляра B и не создавайте новый экземпляр A в своем B классе.

Комментарии:

1. Я внес некоторые изменения в свой вопрос. Теперь после @ Autowired моего A в B появляется ошибка, предлагающая мне сделать @ Autowired статическим A

2. Почему getRequestHeader она должна быть статической?

3. Класс B может быть другим Component с нестатическим методом getRequestHeader .

4. Поместите @Component аннотацию над B классом @Authowired в любом другом месте, где вы хотите ее использовать.

5. Работает! getRequestHeader не должен быть статическим да!

Ответ №2:

Spring может обрабатывать только объекты, которыми он управляет (создает чтение), включая разрешение / ввод данных, аннотированных, @Value конечно.

Когда вы создаете экземпляр класса A самостоятельно из класса B:

 final A objA = new A();
  

Spring понятия не имеет, что этот класс должен быть обработан, фактически он даже не знает, что этот класс существует, следовательно, «значение» в не введено / установлено.

В общем, чтобы решить эту проблему, вам необходимо провести рефакторинг вашего кода. Непонятно, зачем вы создаете класс Controller (я предполагаю, что A это контроллер, потому что его метод getClient аннотируется @GetMapping , что имеет смысл только в контроллерах).

Однако вам не нужно создавать экземпляр A, а скорее вводить его и убедиться, что оба A и B управляются Spring

Ответ №3:

Поскольку вы создаете экземпляр A, используя A objA = new A() в классе B, spring не вводит никакого значения в класс A, поскольку это новый объект. Чтобы использовать внедрение свойств в классе A, вам необходимо использовать внедрение зависимостей и использовать компонент, уже созданный с использованием контекста приложения spring.

Я предполагаю, что класс A помечен @Controller .

 @Controller
public class A {
  

и используйте автозапуск в классе B, как показано ниже, чтобы внедрить экземпляр A

 public class B {

   @Autowired
   A objA;

   private static Map<String, String> getRequestHeader() {

       Map<String, String> requestHeaders = new HashMap<>();
       try{
         //final A objA = new A(); <===== instance of my class A here
           String token = objA.getClient().getAccessToken(); <==== getClient() is the funct that returns token on class A
  

Комментарии:

1. Спасибо, Такер, да, я забыл @Controller в классе A, но теперь, при автоматической настройке в классе B, у меня возникает ошибка: «Невозможно создать статическую ссылку на нестатическое поле objA», когда я делаю: @ Autowired static A objA; затем после компиляции у меня появляется ошибка 403, когда ядоступ к локальному хосту: 8080/app/functionA

2. @hek_ это связано с тем, что метод getRequestHeader является статическим методом, в то время как объект Autowired нестатичен.