40

現在、Spring 3.1.0.M1に基づくWebアプリケーション、アノテーションに基づいて作業していますが、アプリケーションの特定の場所でプロパティプレースホルダーを解決する際に問題が発生します。

これが物語です。

1)私のWebアプリケーションコンテキスト(DispatcherServletによってロードされる)では、

mvc-config.xml:

<!-- Handles HTTP GET requests for /resources/version/**  -->
<resources mapping="/${app.resources.path}/**" location="/static/" cache-period="31556926"/> 

...

<!-- Web properties -->
<context:property-placeholder location="
    classpath:app.properties
    "/>

2)app.properties内には、特に2つのプロパティがあります。

app.properties:

# Properties provided (filtered) by Maven itself
app.version: 0.1-SNAPSHOT
...

# Static resources mapping
app.resources.path: resources/${app.version}

3)JSP2.1テンプレートにJSPカスタムタグがあります。このタグは、環境設定、アプリのバージョン、Springテーマの選択などに応じて、完全なリソースパスの構築を担当します。カスタムタグクラスはspring:url実装クラスを拡張するため、通常のurlタグと見なすことができますが、適切なパスに関する追加の知識があります。

私の問題は、JSPカスタムタグの実装で${app.resources.path}を正しく解決できないことです。JSPカスタムタグはSpringではなくサーブレットコンテナによって管理されるため、DIには参加しません。したがって、通常の@Value( "$ {app.resources.path}")を使用して、Springによって自動的に解決されるようにすることはできません。

私が持っているのはWebアプリケーションコンテキストインスタンスだけなので、プログラムでプロパティを解決する必要があります。

これまでに試しました:

ResourceTag.java:

// returns null
PropertyResolver resolver = getRequestContext().getWebApplicationContext().getBean(PropertyResolver.class);
resolver.getProperty("app.resources.path");


// returns null, its the same web context instance (as expected)
PropertyResolver resolver2 = WebApplicationContextUtils.getRequiredWebApplicationContext(pageContext.getServletContext()).getBean(PropertyResolver.class);
resolver2.getProperty("app.resources.path");


// throws NPE, resolver3 is null as StringValueResolver is not bound
StringValueResolver resolver3 = getRequestContext().getWebApplicationContext().getBean(StringValueResolver.class);
resolver3.resolveStringValue("app.resources.path");


// null, since context: property-placeholder does not register itself as PropertySource
Environment env = getRequestContext().getWebApplicationContext().getEnvironment();
env.getProperty("app.resources.path");

だから今、私はちょっとそれに固執しています。プレースホルダーを解決する機能はコンテキストのどこかにあることを知っていますが、それを行う正しい方法がわかりません。
チェックするヘルプやアイデアは大歓迎です。

4

6 に答える 6

51

appContext.getBeanFactory().resolveEmbeddedValue("${prop}")Spring 3.0.3以降、 callを使用する別の投稿で言及されているのと同じように機能するEmbeddedValueResolverAwareがあります。

この問題を解決するために:

  1. クラスを作成してEmbeddedValueResolverAwareインターフェースを実装すると、リゾルバーが注入されます

  2. 次に、コードスニペットに示されているようにプロパティを取得できる場所は次のとおりです。

    String propertyValue = resolver.resolveStringValue("${your.property.name}");
    

そうすれば、Beanは必要なプロパティを取得するためにApplicationContextに依存する必要はありません。

于 2013-04-19T14:15:11.960 に答える
25

バージョン3.0以降、Springは文字列リゾルバーのリストをbeanFactoryに保持します。次のように使用できます。

String value = appContext.getBeanFactory().resolveEmbeddedValue("${prop}");

javadocは、アノテーション属性などの埋め込み値を解決するためにこのメソッドを記述しているため、その使用法を回避している可能性がありますが、機能します。

于 2013-01-25T18:55:24.603 に答える
15

コンテキストプレースホルダーの内部動作に焦点を合わせるのではなく、次のように新しいutil:propertiesを定義するだけでよいと思います。

<util:properties id="appProperties" location="classpath:app.properties" />

コードでは、次のように使用します。

Properties props = appContext.getBean("appProperties", Properties.class);

または、DIを実行できる場所ならどこでもこのように:

@Value("#{appProperties['app.resources.path']}")
于 2011-03-03T01:15:42.270 に答える
5

1つのオプションは、PropertySource(ここMapPropertySourceではメモリ内の構成を例示する)をに追加し、ConfigurableEnvironmentプロパティを解決するように依頼することです。

public class Foo {

    @Autowired
    private ConfigurableEnvironment env;

    @PostConstruct
    public void setup() {
        env.getPropertySources()
           .addFirst(new MapPropertySource("my-propertysource", 
               ImmutableMap.<String, Object>of("your.property.name", "the value")));
        env.resolvePlaceholders("your.property.name");
    }
}

必要に応じて、を優先してプログラム構成のパワーを享受するために、Fooクラスに注釈を付けます。@ConfigurationXML

于 2015-01-21T15:31:57.240 に答える
1

もう1つの可能な解決策があります。AspectJを介してタグクラスを@Configurableにし、コンパイル時またはロード時のウィービングを有効にします。次に、カスタムタグで通常のSpring@Valueアノテーションを使用できます。しかし、実際には、いくつかのクラスがあるという理由だけで、ウィービングインフラストラクチャをセットアップしたくありません。ApplicationContextを介してプレースホルダーを解決する方法をまだ探しています。

于 2011-03-04T04:15:54.773 に答える
0

完全な答えを追加するために、これを追加します。

このようなカスタムクラスでそれを行うことができます。

import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.util.StringValueResolver;
import org.springframework.lang.Nullable;

public class MyValueResolver implements EmbeddedValueResolverAware {
    //this will be injected using the setter injection.
    //Spring already has an implementation org.springframework.beans.factory.config.EmbeddedValueResolver
    //Or you can implement your own and use @Primary
    @Nullable
    private StringValueResolver resolver;

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.resolver = resolver;
    }

    public String readMyProperty(String propertyString){
        return resolver.resolveStringValue(propertyString);
    }
}

これpropertyStringはとして渡す必要があります"${my.property}"

.propertiesファイルでは、次のように表示されます。

my.property=myPropertyValue
于 2020-01-20T08:15:20.930 に答える