在SpringMVC项目中使用@Value从配置文件中取值时,发现service层中可以正常取值,但controller层却无法取到期望值。
最终发现是Spring父容器无法使用子容器的配置引起的。对配置文件的扫描配置到了spring配置文件中,在springMVC配置文件中没有。而对Controller层的扫描只配置到了springMVC配置文件中,因此无法用@Value从配置文件中取值,特此记录。
jdbc.properties配置文件如下:
jdbc.dialog = oracle
controller层从jdbc.properties读值并打印,代码如下:
@Controller
@RequestMapping("/test")
public class testController extends BaseController {
@Autowired
private TestService testService;
@Value("${jdbc.dialog}")
String jdbcDialog;
@RequestMapping(value = "/test", method = RequestMethod.POST)
@ResponseBody
public JsonResult test() {
System.out.println("Controller层从配置文件读值: " + jdbcDialog);
testService.test();
return renderSuccess();
}
}
service层从jdbc.properties读值并打印,代码如下:
@Service
public class TestSericeImpl implements TestService {
@Value("${jdbc.dialog}")
String jdbcDialog;
@Override
public void test() {
System.out.println("service层从配置文件读值: " + jdbcDialog);
}
}
运行结果如下:
可以看到,在Controller层中直接输出了${name}字符串,在Service层能直接取到properties文件中定义的变量值。
再检查相应的配置,spring配置文件是spring.xml,springMVC配置文件是spring-mvc.xml,在web.xml中相关配置如下:
<!-- spring配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring.xml</param-value>
</context-param>在这里插入代码片
<!-- Spring MVC配置 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<description>SpringMVC</description>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
spring.xml中扫描了service目录,并配置了属性文件解析,相关配置如下:
<!-- Service包(自动注入) -->
<context:component-scan base-package="com.shawn.*.service,com.shawn.*.listener" ></context:component-scan>
<!-- 引入属性文件 -->
<bean id="propertyConfigurer" class="shawn.core.config.DecryptPropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config/jdbc.properties</value>
<value>classpath:config/redis.properties</value>
<value>classpath:config/config.properties</value>
<value>classpath:config/mongoDb.properties</value>
</list>
</property>
<property name="fileEncoding">
<value>UTF-8</value>
</property>
</bean>
spring-mvc.xml中只扫描了controller目录,也没有扫描属性文件,相关配置如下:
<!-- Controller包(自动注入) -->
<context:component-scan base-package="com.shawn.*.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
可以看到,*.properties的解析在Spring父容器里,而对controller目录的扫描在SpringMVC子容器里。父容器访问不到子容器的东西。配置文件在父容器里,而@Value是由父容器去操作的,他访问不了子容器,所以无法完成注入动作。因此出现了上述现象。
解决办法也很简单,只要将属性文件解析部分的配置拷到spring-mvc.xml配置文件中即可。