Spring环境读取Properties文件与编码问题

    目前Spring体系下基础技术栈有SpringMVC、SpringBoot(以及SpringCloud)两种,在读取配置文件的方式上有些差异,但是整体保持一致。最近遇到在读取配置文件时发生乱码的问题,其实解决方式也比较简单。

    1)对于properties文件,无论何种配置方式,Spring底层均使用Resource方式进行加载,最终基于JAVA本身的“classLoader.getResourceAsStream()”读取信息,编码默认为“ISO-8859-1”,编码方式可以通过配置指定。

    参见ConfigurationClassParser.java、ClassPathResource.java等。

    2)对于yml、xml文件,即配置文件的后缀以“yml”、“yaml”、“xml”(包括“properties”)结尾的配置文件,这种类型的配置目前只能在springboot技术栈中支持,编码方式为“UTF-8”,参见PropertiesPropertySourceLoader.java、YamlPropertySourceLoader.java。

    所以,对于编码问题,我们对于properties文件要特别注意,需要强制指定编码为“UTF-8”,否则可能出现本地环境运行正常、但是发布环境总是乱码的奇怪问题。

一、基于XML方式

    SpringMVC环境下,通常可以使用Bean-XML和注释两种方式来获取Properties属性,我们假定在resources目录下已存在“test.properties”文件:

test.name=Hi,你好,世界!

    Bean XML方式(一)

    1、Spring-Context.xml

<context:annotation-config />
<context:property-placeholder location="classpath:test.properties" ignore-unresolvable="true" file-encoding="UTF-8"/>

    2、TestService.java

@Service
public class TestService {

    @Value("${test.name}")
    private String testName;
    ...
}

    Bean XML方式(二)

    1、Spring-Context.xml

<bean id="globalProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="fileEncoding" value="UTF-8"/>
    <property name="locations">
        <array>
            <value>classpath:test2.properties</value>
        </array>
    </property>
</bean>

    2、TestService.java

@Service
public class TestService {

    @Value("#{globalProperties['test.name']}")
    private String testName;
    ...
}

    我们需要特别注意,如果在SpringMVC的Web项目中@Controllor层需要使用@Value注入属性时,我们需要将上述配置放在Servlet相关的Spring文件中,这个文件名通常与下属配置一致:

<servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-web.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

    以此例,那么@Controller需要使用Properties属性时,它们的配置信息应该放置在spring-web.xml中,你放置在Spring-context.xml等类似于的文件是不可行的,因为SpringMVC中“Servlet容器”和“Spring组件容器”来自不同的BeanFactory,所以@Controllor和@Service、@Component、@Resource等需要区别对待。

    为了避免乱码,我们需要在所有声明properties加载的地方,都强制指定encoding,此外建议大家将spring基线版本升级到4.3.X+。

二、基于注释

    Spring 3.1+提供了一个比较便捷的注解,@PropertySource,可以帮助我们在springMVC、springBoot环境下直接使用。

@PropertySource(value = "classpath:test3.properties",encoding = "UTF-8")
@Controller
public class IndexController {

    @Value("${test.name}")
    private String testName;
    ....
}

    @PropertySource注意可以在任意Spring Bean组件中使用;但是还是那句话,@Controller和@Service、@Component等可能需要各自配置;此外建议创建@Configuration的配置管理类,将这些Properties只加载一次、以Bean的方式export以供所有组件共享使用。不要忘记“encoding”属性。

猜你喜欢

转载自shift-alt-ctrl.iteye.com/blog/2419638