私はSpringを初めて使用し、@Controller
注釈で注釈されたコントローラ内で@Value("${loginpage.message}")
注釈を使用して値を文字列に挿入しようとしていますが、私の文字列の値は文字列"${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
@Value("${loginpage.message}")
のようなプロパティファイルにない値に@Value("${notInPropertiesFile}")
を変更するたびに例外が発生するため、Springはある時点で値を取得する必要があります。
質問はすでに尋ねられているようです Spring 3.0.5はプロパティから@Valueアノテーションを評価しません
Webアプリのルートコンテキストとサーブレットアプリケーションコンテキストの違いは、Springの混乱の主な原因の1つです。 Spring FrameworkのapplicationContext.xmlとspring-servlet.xmlの違い
@Value
javadocから:
@Valueアノテーションの実際の処理はBeanPostProcessorによって実行されることに注意してください
春のドキュメント: から
BeanPostProcessorインターフェースは、コンテナーごとにスコープされます。これは、コンテナ階層を使用している場合にのみ関係します。 1つのコンテナでBeanPostProcessorを定義すると、そのコンテナ内のBeanに対してのみ処理が行われます。 1つのコンテナで定義されたBeanは、両方のコンテナが同じ階層の一部であっても、別のコンテナのBeanPostProcessorによって後処理されません。
はい、Spring 3でも同じ問題があります。Controllers内では動作しないようです。この問題を解決するために、@ Serviceで別のBeanを作成し、それをコントローラーに挿入しました。うまくいきました。私がそれを理解するために一日中過ごしたので、これが誰かに役立つことを願っています。
_@Autowire Environment
_を実行してからenvironment.getProperty("name")
を実行できます。 https://stackoverflow.com/a/15562319/63229 を参照してください
プロパティファイルから値を抽出できるため、@ Valueアノテーションを使用している場合は、PropertySourcePlaceHolderを使用する必要があります。 Java config baseを使用している場合、このようなBeanを作成する必要があります
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
または、xmlベースを使用している場合は、それに応じてBeanを宣言します。
私は私の春のプロジェクトで同様の問題を抱えていましたが、具体的には春のバッチの問題でした。私は最初に次のように設定を構築しました
@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は配線されず、ページサイズも挿入されません。両方ともヌル。 Borisの回答のおかげで、いくつかの試行の後、BatchConfigを以下のように完全に動作させました
...
@Bean
public Step init0(){
return stepBuilders.get("init0")
.tasklet(decider())
.build();
}
@Bean
public Tasklet decider() {
return new MyDecider();
}
...
理由:BatchConfigのBeanアノテーション(decider()の1つ)にMyDecider構造を近づけて、application.property値で見つかった値を使用してMyDeciderを適切に挿入する必要があることをspringに理解させ、ワイヤードTaskSchedulerを使用します(SpringSchedulerのアクティブ化も試みましたが、jar開始オプションが「送信」の場合はオフにしたかったため)。
注:オプションmode = "send"を使用すると、Spring BatchジョブはstepMultiPollingではなくstepMultiに移行します。これは、MyDeciderの終了ステータスがSENDであり、ポーリングではないためです。しかし、これはこのトピックの単なる説明なので、詳細は省略します。
この春のバッチケースが誰かに役立つことを願っています!