Подтвердить что ты не робот

Spring аннотация @Value в классе @Controller, не оценивающая значение внутри файла свойств

Я новичок в Spring и пытаюсь ввести строку со значением, используя аннотацию @Value("${loginpage.message}") внутри контроллера, аннотированную аннотацией @Controller, и значение моей строки оценивается как строка "${loginpage.message}", а не то, что находится внутри моего файла свойств.

Ниже мой контроллер с строкой 'message', которую я хочу ввести.

@Controller
public class LoginController extends BaseController {
    @Value("${loginpage.message}")
    private String message;

    @RequestMapping("/")
    public String goToLoginPage(Model model) {
        model.addAttribute("message", message);

        return "/login";
    }
}

Мой контекст приложения выглядит следующим образом:

<context:property-placeholder location="classpath:properties/application.properties" />

<context:annotation-config />

<context:component-scan base-package="com.me.application" />

В моем файле свойств есть строка:

loginpage.message=this is a test message

Spring должен подбирать значение в какой-то момент, потому что всякий раз, когда я изменяю @Value("${loginpage.message}") на значение, не содержащееся в файле свойств, например @Value("${notInPropertiesFile}"), я получаю исключение.

4b9b3361

Ответ 1

Кажется, что вопрос уже задан Spring 3.0.5 не оценивает аннотацию @Value от свойств

Разница между контекстами приложений root и сервлетов является одним из главных источников путаницы в Spring, см. Разница между applicationContext.xml и spring -servlet.xml в Spring Framework

От @Value javadoc:

Обратите внимание, что фактическая обработка аннотации @Value выполняется с помощью BeanPostProcessor

Из Spring документация:

Интерфейсы BeanPostProcessor привязаны к контейнеру. Это актуально только в том случае, если вы используете иерархии контейнеров. Если вы определяете BeanPostProcessor в одном контейнере, он будет выполнять свою работу только с beans в этом контейнере. beans, которые определены в одном контейнере, не обрабатываются BeanPostProcessor в другом контейнере, даже если оба контейнера являются частью одной и той же иерархии.

Ответ 2

У меня такая же проблема с Spring 3. Она не работает внутри контроллеров. Чтобы исправить проблему, я создал другой bean с @Service и ввел его в контроллер. Это работало для меня. Надеюсь, это будет полезно для кого-то, поскольку я провел весь день, чтобы понять это.

Ответ 4

Вам нужно использовать PropertySourcePlaceHolder, если вы используете аннотацию @Value, потому что она может извлечь значение из файла свойств. Если вы используете базу java config, вам нужно создать bean, как этот

@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
    return new PropertySourcesPlaceholderConfigurer();
}

Или, если вы используете xml, тогда объявите bean соответственно.

Ответ 5

У меня была аналогичная проблема в моем проекте spring, но в частности spring BATCH one. Сначала я построил свою конфигурацию ниже

@Configuration
public class BatchConfig   
{
  @Bean
  public Job job(@Autowired Step stepMulti, @Autowired Step stepMultiDiff,  @Autowired Step stepMultiPolling
        ){

    Job job = jobBuilders.get("job")
                .start(init0())
                    .on("POLLING").to(stepMultiPolling)
                .from(init0()).on("*").to(stepMulti).next(stepMultiDiff).end()
                .build();
    return job;
  }

  @Bean
  public Step init0(){
    return stepBuilders.get("init0")
            .tasklet(new MyDecider())
            .build();
  }

  ...
}

с MyDecider в ближайшее время, как показано ниже

public class MyDecider implements StepExecutionListener , Tasklet{ 

  @Autowired ThreadPoolTaskScheduler taskScheduler;
  @Value("${read.chunk.size}") private Integer pagesize;

@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
    return RepeatStatus.FINISHED;
}

@Override
public ExitStatus afterStep(StepExecution exe) {
    String type = exe.getJobParameters().getString("mode");

    log.info("SPRING BATCH props:");
    log.info("    READ chunk size:  {}", pagesize);


    if (StringUtils.equals(type, "send")) {
        log.info("MODE batch SENDING...");

        if (taskScheduler !=null) taskScheduler.shutdown();
        else log.info("      Not able to stop scheduler (is null)");

        return new ExitStatus("SEND");
    } else  {
        log.info("MODE batch POLLING...");
        return new ExitStatus("POLLING");
    } 

}

Но таким образом не был подключен ни один TaskScheduler, ни встраивание не было выполнено; оба null. Благодаря ответу Бориса, после некоторых попыток я сменил BatchConfig как ниже отлично работающий

...

@Bean
public Step init0(){
    return stepBuilders.get("init0")
            .tasklet(decider())
            .build();
}

@Bean
public Tasklet decider() {
    return new MyDecider();
}

...

Причина: построение MyDecider ближе к аннотации Bean в BatchConfig (один из decider()), make spring понять, что MyDecider должен быть введен правильно, со значениями, найденными в значениях application.property и проводных с использованием TaskScheduler (потому что я попробовал также активировать SpringScheduler, но я хотел отбросить его, если опция запуска jar была "send" ).

ПРИМЕЧАНИЕ: с опционным режимом = "отправить" spring пакетное задание переходит к stepMulti, а не stepMultiPolling, поскольку статус выхода MyDecider был SEND, а не POLLING; но это только объяснение из этой темы, поэтому я пропущу дальнейшие подробности.

Надеюсь, что этот пакет spring может быть полезен для кого-то!