Spring boot получить свойства приложения для сопоставления запросов

Я пытаюсь получить для каждого запроса некоторые параметры из свойств моего приложения.

Мой класс ApplicationConfig:

@Configuration
@ConfigurationProperties("org.a.b")
public class ApplicationConfig implements Serializable {

    private String name;
    private String ip;
// GETTER AND SETTER

Мои application.properties:

org.a.b.name=huhu
org.a.b.ip=x.x.x.x

Я пробую разные варианты:

@RestController
public class HelloController

Первый:

@Autowired
private ApplicationConfig applicationConfig;

@ResponseBody
@GetMapping(value = "/", produces = "application/json")
public ApplicationConfig index() {
    return applicationConfig;
}

Исключение:

{"timestamp":"2018-08-24T12:28:50.623+0000","status":500,"error":"Internal Server Error","message":"Type definition error: [simple type, class org.springframework.context.expression.StandardBeanExpressionResolver]; nested exception is com.fasterxml.jackson.datab
ind.exc.InvalidDefinitionException: No serializer found for class org.springframework.context.expression.StandardBeanExpressionResolver and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (
through reference chain: hello.bootstrap.ApplicationConfig$$EnhancerBySpringCGLIB$$31a0e3d2[\"$$beanFactory\"]->org.springframework.beans.factory.support.DefaultListableBeanFactory[\"beanExpressionResolver\"])","path":"/"}

Второй:

@ResponseBody
@GetMapping(value = "/", produces = "application/json")
public ApplicationConfig index() {
    return new ApplicationConfig();
}
// return nothing {"name": null, "ip": null}

В третьих:

@ResponseBody
@GetMapping(value = "/", produces = "application/json")
public String index() {
    return applicationConfig.getIp();
}
// return x.x.x.x

Мой pom.xml:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>


    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>hello.ConfigServiceApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

Мне нужны свойства приложения как объект, например:

{"name": "dev", "ip": "x.x.x.x"}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
734
2

Ответы 2

Вы находитесь в правильном направлении с первой попытки, проблема, которую вы обнаруживаете, заключается в том, что когда Spring берет на себя управление такими объектами, как этот - для установки значений из вашего файла конфигурации - он не использует `` нормальный '' его экземпляр, но прокси-версия.

В Интернете много написано о деталях того, как работает прокси, я не буду пытаться объяснять это здесь (в основном потому, что, насколько я понимаю, это волшебство).

Однако самым простым вариантом для вашего случая, вероятно, было бы преобразование из класса, отмеченного аннотацией @Configuration, в простой POJO. В основном это может быть что-то вроде:

public class ApplicationConfigResponse {
    private final String name;
    private final String ip;

    public ApplicationConfigResponse(ApplicationConfig applicationConfig) {
        this.name = applicationConfig.getName();
        this.ip = applicationConfig.getIp();
    }

    public String getName() {
        return name;
    }

    public String getIp() {
        return ip;
    }
}

Затем вы можете вернуть этот POJO со своего контроллера, как в первом примере:

@Autowired
private ApplicationConfig applicationConfig;

@ResponseBody
@GetMapping(value = "/", produces = "application/json")
public ApplicationConfigResponse index() {
    return new ApplicationConfigResponse(applicationConfig);
}

Если вы ожидаете, что у вас будет гораздо больше свойств или это будет шаблон, который неоднократно используется в более крупном приложении, вы можете предпочесть взглянуть на встроенные функции Spring для преобразования между объектами - этот учебник является хорошей отправной точкой: https://www.baeldung.com/spring-type-conversions

он работает, но я пробую другое решение с ResponseEntity. @ResponseBody @GetMapping(value = "/", produces = "application/json") public ResponseEntity<ApplicationConfig> index() { return new ResponseEntity(applicationConfig, HttpStatus.OK); } У меня много приложений с разным профилем. Я не могу использовать pojo для каждого свойства.

emoleumassi 24.08.2018 15:13

Не рекомендуется аннотировать класс с помощью @Configuration и @ConfigurationProperties, поскольку spring обрабатывает все, что содержит @Configuration, особым образом.

Используйте первый подход и не аннотируйте ApplicationConfig с помощью @Configuration. Ваш первый подход должен сработать.

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