Como definir cacheControlMappings em WebContentInterceptor no Spring 5 Xml

Aug 24 2020

Quero adicionar a diretiva de controle de cache (definir segundos públicos e de idade máxima) para alguns URLs no Spring MVC e quero fazer essas alterações apenas por meio de applicationContext.xml.

Estou tentando definir a propriedade map cacheControlMappingsde org.springframework.web.servlet.mvc.WebContentInterceptor, mas o único problema é o design da classe que não possui um método setter para a propriedade. Como solução alternativa, estou invocando o addCacheMappingmétodo usando o org.springframework.beans.factory.config.MethodInvokingBean.

Minha configuração em spring-mvc-config.xml é a seguinte - estou criando um CacheControlbean como segue e verifiquei pela depuração que esse bean foi criado com êxito com os valores apropriados preenchidos no contexto do aplicativo.

<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>

Então, desejo invocar esse método - public void addCacheMapping(CacheControl cacheControl, String... paths)do WebContentInterceptorqual adicionará entradas ao mapa cacheControlMappings.

Eu verifiquei que chamar esse método programaticamente funciona muito bem, então ele deve funcionar bem se eu invocá-lo do XML, certo? Mas estou tentando fazer o mesmo, conforme mostrado abaixo, mas isso não funciona para mim e não recebo nenhuma entrada adicionada ao mapa final.

<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>

Por que a invocação acima MethodInvokingBeannão funciona? Estou apresentando os argumentos errados de alguma forma? Os varargs precisam de um tratamento diferente? Não vejo nenhum erro gerado durante a inicialização do servidor.

Além disso, estou ciente desse segmento SO ( Como definir Cache-control: private com applicationContext.xml no Spring 4.2 ou posterior ), onde a resposta aceita menciona que não há como fazer isso no próprio XML. Queria reconfirmar se isso está correto tentando implementar a solução acima, mas não está funcionando, mas não vejo por quê.

Respostas

Anurag Aug 25 2020 at 04:52

Como eu suspeitava, havia um problema no modo como as discussões estavam sendo preenchidas. Os varargs em uma injeção de primavera precisam ser fornecidos como uma lista explícita em vez de uma sobrecarga de argumentos (como é feito em Java).

Portanto, a maneira correta de invocar tal método -

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

em spring applicationContext.xml é o seguinte -

<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>

Como você pode ver, agora usei MethodInvokingFactoryBean. De alguma forma MethodInvokingBeannão funcionou para mim.