Come impostare cacheControlMappings in WebContentInterceptor in Spring 5 Xml
Voglio aggiungere la direttiva di controllo della cache (impostare secondi sia public che max-age) per un paio di URL in Spring MVC e voglio apportare queste modifiche solo tramite applicationContext.xml.
Sto cercando di impostare la proprietà map cacheControlMappings
di org.springframework.web.servlet.mvc.WebContentInterceptor
, ma l'unico problema è il design della classe che non ha un metodo setter per la proprietà. Come soluzione alternativa, sto invocando il addCacheMapping
metodo utilizzando il org.springframework.beans.factory.config.MethodInvokingBean
.
La mia configurazione in spring-mvc-config.xml è la seguente: sto creando un CacheControl
bean come segue e ho verificato tramite il debug che questo bean venga creato correttamente con i valori appropriati popolati nel contesto dell'applicazione.
<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>
Quindi desidero invocare questo metodo, public void addCacheMapping(CacheControl cacheControl, String... paths)
di WebContentInterceptor
cui aggiungerò voci alla mappa cacheControlMappings
.
Ho verificato che chiamare questo metodo a livello di codice funziona alla grande, quindi dovrebbe funzionare bene se lo richiamo dall'XML, giusto? Ma sto provando a fare lo stesso, come mostrato di seguito, ma questo non funziona per me e ottengo zero voci aggiunte alla mappa finale.
<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>
Perché l'invocazione di cui sopra con MethodInvokingBean
non funziona? Sto impostando gli argomenti in modo sbagliato in qualche modo? I vararg necessitano di una gestione diversa? Non vedo alcun errore generato neanche durante l'avvio del server.
Inoltre, sono a conoscenza di questo thread SO ( How to set Cache-control: private with applicationContext.xml in Spring 4.2 o later ) dove la risposta accettata menziona che non c'è modo di farlo nello stesso XML. Volevo riconfermare se è corretto provando a implementare la soluzione sopra ma non funziona, ma non vedo perché.
Risposte
Come avevo sospettato, c'era un problema nel modo in cui gli argomenti venivano popolati. I vararg in una spring injection devono essere forniti come un elenco esplicito invece di un sovraccarico di argomenti (come si fa in Java).
Quindi il modo corretto per invocare un tale metodo -
public void addCacheMapping(CacheControl cacheControl, String... paths)
in primavera applicationContext.xml è il seguente:
<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>
Come puoi vedere ora l'ho usato MethodInvokingFactoryBean
. In qualche modo MethodInvokingBean
non ha funzionato per me.