@Value в Springboot возвращает ноль

У меня есть application.properties, который находится в ресурсах

apllication.properties

hsm.provider=software
hsm.name=TestHsm
hsm.port=3001
hsm.ip=127.0.0.1
hsm.timeout=10000

и Контроллер

@RestController
@RequestMapping("/hsm")
public class Controller {

  @Value("${hsm.ip}")
  private String ip;

  @Value("${hsm.port}")
  private String port;

  @Value("${hsm.name}")
  private String name;

  @Value("${hsm.timeout}")
  private String timeout;

  @Value("${hsm.provider}")
  private String provider;}
}

однако, когда я запускаю приложение, все переменные остаются NULL. Что мне не хватает?

РЕДАКТИРОВАТЬ Это структура проекта из папки src

src
├───main
│   ├───java
│   │   └───com
│   │       └───xyz
│   │           └───hsmservice
│   │               └───hsm
│   │                   └───api
│   │                           Application.java
│   │                           Controller.java
│   │                           HSM.java
│   │
│   └───resources
│       │   application.properties
│       │
│       └───META-INF
│               plugin.xml
│
└───test
    ├───java
    │       LibraryTest.java
    │
    └───resources

РЕДАКТИРОВАТЬ 2 Вот класс приложения

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

Вероятно, ваш класс контроллера не обнаружен при сканировании вашего приложения. Не могли бы вы показать нам структуру вашего пакета?

Urosh T. 26.11.2018 15:02
apllication.properties вы уверены, что здесь нет опечатки? должен быть application.properties
pleft 26.11.2018 15:04

@pleft woops, это опечатка в вопросе, тот, который у меня на самом деле есть в проекте, правильный.

NicO 26.11.2018 15:14

@ УрошТ. я добавил это

NicO 26.11.2018 15:17

Ознакомьтесь со свойствами конфигурации SpringBoot для привязки внешних свойств к объекту, который может быть передан. Это чище, чем использование @Value где-либо, и должно решить вашу проблему через прокси. Контроллер может быть создан до того, как среда полностью обновит свойства.

Darren Forsythe 26.11.2018 16:56

1. Вы определенно используете правильную аннотацию @Value? stackoverflow.com/questions/51387952/spring-boot-value-is-nu‌ ll

Alan Hay 26.11.2018 17:00
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
12
6
28 973
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

У меня была такая же проблема раньше, и @Value не работал для контроллера, но работал для классов компонентов, поэтому я использовал решение ниже.

Вы можете @Autowire Environment environment, а затем environment.getProperty("hsm.provider").

Примечание. Это всего лишь временное решение.

Это тоже не работает, к сожалению, environment.getProperty("hsm.provider") выдает мне InvocationTargetException.

NicO 26.11.2018 15:35

Не могли бы вы добавить в свой pom: <build> <resources> <resource> <directory> src / main / resources </directory> <filtering> true </filtering> </resource> </resources> ...

TinyOS 26.11.2018 16:08

Судя по структуре вашего пакета, эти свойства обязательно должны быть загружены. Единственно возможный вариант заключается в том, что вы создали экземпляр своего класса Controller как new Controller() вместо того, чтобы позволить Spring внедрять класс (с использованием @Autowired или инъекции конструктора).

На самом деле я не уверен, как я его создал, единственный другой важный класс - это приложение, которое запускает все это. Я добавил класс в вопрос.

NicO 26.11.2018 15:27

Только убедитесь, что вы не используете Controller controller = new Controller();. См. Дополнительную информацию о том, как это сделать правильно: docs.spring.io/spring-boot/docs/current/reference/html/…

Urosh T. 26.11.2018 15:30

Я не сделал. Вы можете увидеть другой класс в новой редакции вопроса.

NicO 26.11.2018 15:37

Тогда где вы используете этот класс Controller? Как узнать, что эти значения равны нулю? Вы отладили это? В вашем контроллере тоже нет конечных точек ...

Urosh T. 26.11.2018 15:41

Да, я отлаживал это, я установил точку останова в небольшом конструкторе под переменными. К весне я сориентировался после туториала это.

NicO 26.11.2018 15:43

Когда дело доходит до создания экземпляров класса и application.properties, это может быть проблема курицы и яйца. Попробуйте поместить аннотации @Value в аргументы конструктора, а не в поля.

Urosh T. 26.11.2018 15:50

Controller.java

С Ломбоком

package com.example.demo;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hsm")
@Data
public class Controller {
    @Value("${hsm.ip}")
    private String ip;

    @Value("${hsm.port}")
    private String port;

    @Value("${hsm.name}")
    private String name;

    @Value("${hsm.timeout}")
    private String timeout;

    @Value("${hsm.provider}")
    private String provider;
}

Без Ломбока (создано Intelliji - Рефакторинг ДеЛомбока)

    package com.example.demo;

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;

    @RestController
    @RequestMapping("/hsm")
    public class Controller {
        @Value("${hsm.ip}")
        private String ip;

        @Value("${hsm.port}")
        private String port;

        @Value("${hsm.name}")
        private String name;

        @Value("${hsm.timeout}")
        private String timeout;

        @Value("${hsm.provider}")
        private String provider;

        public Controller() {
        }

        public String getIp() {
            return this.ip;
        }

        public String getPort() {
            return this.port;
        }

        public String getName() {
            return this.name;
        }

        public String getTimeout() {
            return this.timeout;
        }

        public String getProvider() {
            return this.provider;
        }

        public void setIp(String ip) {
            this.ip = ip;
        }

        public void setPort(String port) {
            this.port = port;
        }

        public void setName(String name) {
            this.name = name;
        }

        public void setTimeout(String timeout) {
            this.timeout = timeout;
        }

        public void setProvider(String provider) {
            this.provider = provider;
        }

        public boolean equals(final Object o) {
            if (o == this) return true;
            if (!(o instanceof Controller)) return false;
            final Controller other = (Controller) o;
            if (!other.canEqual((Object) this)) return false;
            final Object this$ip = this.getIp();
            final Object other$ip = other.getIp();
            if (this$ip == null ? other$ip != null : !this$ip.equals(other$ip)) return false;
            final Object this$port = this.getPort();
            final Object other$port = other.getPort();
            if (this$port == null ? other$port != null : !this$port.equals(other$port)) return false;
            final Object this$name = this.getName();
            final Object other$name = other.getName();
            if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
            final Object this$timeout = this.getTimeout();
            final Object other$timeout = other.getTimeout();
            if (this$timeout == null ? other$timeout != null : !this$timeout.equals(other$timeout)) return false;
            final Object this$provider = this.getProvider();
            final Object other$provider = other.getProvider();
            if (this$provider == null ? other$provider != null : !this$provider.equals(other$provider)) return false;
            return true;
        }

        protected boolean canEqual(final Object other) {
            return other instanceof Controller;
        }

        public int hashCode() {
            final int PRIME = 59;
            int result = 1;
            final Object $ip = this.getIp();
            result = result * PRIME + ($ip == null ? 43 : $ip.hashCode());
            final Object $port = this.getPort();
            result = result * PRIME + ($port == null ? 43 : $port.hashCode());
            final Object $name = this.getName();
            result = result * PRIME + ($name == null ? 43 : $name.hashCode());
            final Object $timeout = this.getTimeout();
            result = result * PRIME + ($timeout == null ? 43 : $timeout.hashCode());
            final Object $provider = this.getProvider();
            result = result * PRIME + ($provider == null ? 43 : $provider.hashCode());
            return result;
        }

        public String toString() {
            return "Controller(ip = " + this.getIp() + ", port = " + this.getPort() + ", name = " + this.getName() + ", timeout = " + this.getTimeout() + ", provider = " + this.getProvider() + ")";
        }
    }

DemoApplication.java

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class DemoApplication {
    @Autowired
    Controller controller;

    public static void main(String[] args) {
        try (ConfigurableApplicationContext ctx = SpringApplication.run(DemoApplication.class, args)) {
            DemoApplication app = ctx.getBean(DemoApplication.class);
            app.run(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run(String... args) throws Exception {
        System.out.println(controller);
    }
}

Вывод: Controller(ip=127.0.0.1, port=3001, name=TestHsm, timeout=1000, provider=software)

Похоже, это тоже не работает. Я получаю сообщение «Ошибка при создании bean-компонента с именем 'defaultValidator'». Я также не могу использовать lombok в этом проекте.

NicO 26.11.2018 16:10

добавлен код для Controller.java без Lombok, попробуйте

VietDD 26.11.2018 16:17

Я добавил ваш код в проект загрузки Spring, и он находится в рабочем состоянии.

Проверьте этот репозиторий 53482633 и следуйте инструкциям, чтобы запустить его.

Также сравните свой код с этим приложением, чтобы понять, что с вашей стороны пошло не так.

Если у вас все еще возникнут проблемы, опубликуйте их здесь.

Ответ принят как подходящий

Хорошо, я решил это с помощью верхнего ответа на вопрос это. Я помещаю переменные и @Values ​​в сигнатуру конструктора, а не как переменные класса.

Я уже говорил вам об этом несколько месяцев назад в комментариях :) Рад, что он у вас запущен.

Urosh T. 09.10.2019 09:57

У меня была такая же проблема с @Value в моем служебном файле. Я создавал новую службу в своем файле контроллера

НЕ РАБОТАЕТ:

UserController.java

UserService userService = new UserService();
String user = userService.getUser(); // NULL!!

UserService.java

public class UserService {

    @Value("${hello.world}")
    String hello;

    public String GetUser() {
        return hello;   // NULL!!
    }

}

и это переопределило мою инъекцию в моем файле UserService.

Поэтому вместо этого я сделал инъекцию @Value в свой файл контроллера и передал эту переменную в свой конструктор службы.

РАБОТАЮЩИЙ:

UserController.java

@Value("${hello.world}")
String hello;

UserService userService = new UserService(hello);

UserService.java

public class UserService {

    private String hello;

    // constructor
    public UserService(@Value("${hello.world}") String hello) {
    this.hello = hello;
    }

}

Причина, по которой @Value иногда возвращает null, заключается в том, что вы пытаетесь использовать содержимое application.properties для статических переменных, что запрещено весной. Следуйте этому: https://mkyong.com/spring/spring-inject-a-value-into-static-variables/ и он должен работать нормально.

Другие вопросы по теме