Spring allows us to externalize String literals in its context configuration files into external properties files in order to separate application-specific settings from the framework-specific configuration. You can use the property values in context configuration XML in style of ${variable_name} or in Java code in style of annotation.
Supposed that you have two property files:
redis.properties
|
redis.host=192.168.0.136 redis.port=6379 redis.pass=root redis2.host=127.0.0.1 redis2.port=6380 |
system_config.properties
|
server.apiUrl=api.novastartupclassic.com/nova-api/ |
Now you have a requirement that redis.properties can only be used in context configuration XML, and system_config.properties will be used in both XML and Java code. How to do this?
1. 1. Read properties in Controller etc.(high-level Spring components)
1-1. Solution
Add this configuration in your context XML file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<!-- read configuration properties for XML and Java--> <bean id="system_config" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="locations"> <list> <value>classpath:system_config.properties</value> </list> </property> </bean> <!-- read configuration properties--> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <!-- works for XML--> <property name="locations"> <list> <value>classpath:redis.properties</value> </list> </property> <!-- works for XML and Java--> <property name="properties" ref="system_config" /> </bean> |
1-2. Simple Test
In my redis context configuration XML, ${redis.host} and etc. are used as paramters.
|
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:use-pool="true"> <!--<constructor-arg ref="redisSentinelConfiguration" />--> <constructor-arg ref="jedisPoolConfig" /> </bean> |

In my other Java bean code, the variable was injected in the style of annotation.
|
@Value( "#{system_config['server.apiUrl']}" ) private String serverApiUrl; |

2. 2. Read properties in Filter(low-level Spring components)
I’m trying to inject a property value into a filter in the same way, but I got a null value. This is the code of filter:
|
@Component public class CorsOpenApiFilter implements Filter { @Value( "#{system_config['server.cors.AllowDomains']}" ) private String serverCorsAllowDomains; ...... |
And I have registered this filter into web.xml
|
<filter> <filter-name>corsOpenApiFilter</filter-name> <filter-class>net.mobabel.nova.api.filter.CorsOpenApiFilter</filter-class> </filter> <filter-mapping> <filter-name>corsOpenApiFilter</filter-name> <url-pattern>/v1/*</url-pattern> </filter-mapping> |
2-1. Solution
ADelegatingFilterProxy should be used to allow the filter to be managed by Spring. It is a special proxy that does all the low-level tasks of finding the root application context get the bean and relay all requests to it. Extract from the javadoc:
web.xml will usually contain a DelegatingFilterProxy definition, with the specified filter-name corresponding to a bean name in Spring’s root application context. All calls to the filter proxy will then be delegated to that bean in the Spring context, which is required to implement the standard Servlet Filter interface.
A bean of class CorsOpenApiFilter to which been given a name (such as corsOpenApiFilter as default ) should be implemented and the filter declaration in the web.xml file need to be changed.
|
<filter> <filter-name>corsOpenApiFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>corsOpenApiFilter</filter-name> <url-pattern>/v1/*</url-pattern> </filter-mapping> |
Now the property works fine.
Reference:
https://dzone.com/articles/spring-be-careful-when-using-propertyplaceholderconfigurer
https://stackoverflow.com/questions/37475167/how-to-inject-a-property-value-into-a-filter
http://forum.spring.io/forum/spring-projects/web/49837-adding-a-simple-servlet-filter-using-spring