Cara mengatur cacheControlMappings di WebContentInterceptor di Spring 5 Xml

Aug 24 2020

Saya ingin menambahkan arahan kontrol-cache (menyetel detik publik dan usia maks) untuk beberapa URL di Spring MVC dan saya ingin melakukan perubahan itu hanya melalui applicationContext.xml.

Saya mencoba untuk mengatur properti peta cacheControlMappingsdari org.springframework.web.servlet.mvc.WebContentInterceptor, tetapi satu-satunya masalah adalah desain kelas yang tidak memiliki metode setter untuk properti. Sebagai solusinya, saya menjalankan addCacheMappingmetode menggunakan org.springframework.beans.factory.config.MethodInvokingBean.

Konfigurasi saya di spring-mvc-config.xml adalah sebagai berikut - Saya membuat CacheControlkacang sebagai berikut, dan saya memverifikasi dengan debugging bahwa kacang ini berhasil dibuat dengan nilai yang sesuai yang diisi dalam konteks aplikasi.

<bean id="cacheControlFactory" class="org.springframework.http.CacheControl" factory-method="maxAge">
    <constructor-arg index="0" value="3600"/>
    <constructor-arg index="1">
        <value type="java.util.concurrent.TimeUnit">SECONDS</value>
    </constructor-arg>
</bean>

<bean id="myCacheControl" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject">
        <ref bean="cacheControlFactory"/>
    </property>
    <property name="targetMethod">
        <value>cachePublic</value>
    </property>
</bean>

Lalu aku ingin memanggil metode ini - public void addCacheMapping(CacheControl cacheControl, String... paths)dari WebContentInterceptoryang akan menambahkan entri ke peta cacheControlMappings.

Saya memverifikasi bahwa memanggil metode ini secara terprogram berfungsi dengan baik, jadi seharusnya berfungsi dengan baik jika saya memanggilnya dari XML, bukan? Tetapi saya mencoba melakukan hal yang sama, seperti yang ditunjukkan di bawah ini, tetapi ini tidak berhasil untuk saya, dan saya tidak mendapatkan entri yang ditambahkan ke peta akhir.

<bean class="org.springframework.beans.factory.config.MethodInvokingBean">
    <property name="targetObject">
        <ref bean="webContentInterceptor"/>
    </property>
    <property name="targetMethod">
        <value>addCacheMapping</value>
    </property>
    <property name="arguments">
        <list>
            <ref bean="myCacheControl" />
            <value>/home</value>
            <value>/dp/**</value>
            <value>/**/b/*</value>
        </list>
    </property>
</bean>

Mengapa doa di atas dengan MethodInvokingBeantidak berfungsi? Apakah saya salah mengatur argumen? Apakah vararg membutuhkan penanganan yang berbeda? Saya juga tidak melihat kesalahan apa pun selama startup server.

Juga, saya mengetahui utas SO ini ( Cara menyetel Cache-control: private dengan applicationContext.xml di Spring 4.2 atau yang lebih baru ) di mana jawaban yang diterima menyebutkan tidak ada cara untuk melakukan ini di XML itu sendiri. Saya ingin mengonfirmasi ulang apakah itu benar dengan mencoba menerapkan solusi di atas tetapi tidak berhasil, tetapi saya tidak mengerti mengapa.

Jawaban

Anurag Aug 25 2020 at 04:52

Seperti yang telah saya duga, ada masalah dalam cara mengisi argumen. Variasi dalam injeksi pegas perlu diberikan sebagai daftar eksplisit, bukan argumen yang berlebihan (seperti yang dilakukan di Java).

Jadi cara yang benar untuk memanggil metode seperti itu -

public void addCacheMapping(CacheControl cacheControl, String... paths)

di spring applicationContext.xml adalah sebagai berikut -

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject">
        <ref bean="webContentInterceptor"/>
    </property>
    <property name="targetMethod">
        <value>addCacheMapping</value>
    </property>
    <property name="arguments">
        <list>
            <ref bean="myCacheControl" />
            <list>
                <value>/home</value>
                <value>/dp/**</value>
                <value>/**/b/*</value>
            </list>
        </list>
    </property>
</bean>

Seperti yang Anda lihat, saya sekarang telah menggunakan MethodInvokingFactoryBean. Entah bagaimana MethodInvokingBeantidak berhasil untuk saya.