Spring 项目中把属性或 SQL 语句写在 .xml 文件中
Spring 项目中把大量的 SQL 分散在 Java 代码中,无 Here Doc 的情况下用加号来连接写着实在是不爽,于是之前思考这个 Spring 项目中把 SQL 语句写在 .sql 文件中 -- 把它们写在 *.sql 文件中,但是这个 *.sql 需要特定的格式来标识属性 Key
也就是说其实我们是可以用 XML 文件来定义属性的。
继续深挖到
定义属性的 XML 该如何写已经一目了然了,关键是 http://java.sun.com/dtd/properties.dtd 给我们的定义,也可以直接抓下它的定义来
如果 entry 中有 XML 的特殊字符就用
现在要引用定义在 XML 中的属性值就简单了,没有什么特别的,不需要额外的文件解析类,只是文件扩展名的不同而已。比如在你的 Spring 代码中使用如下注解
如此,定义在
从此再也不用那个 SqlPropertySourceFactory 了。
IDE 打开 queries.sql.xml 只会以 XML 文件格式来进行语法高亮,如果想要 IDE 对其中的 SQL 语法进行高亮显示,可以修改 IDE 的配置,让 SQL 文件类型也包含
2019-06-12
Spring 对 xml 写属性文件的支持其实是由 JDK 的 Properties 类自 JDK 1.5 开始提供的,见 Properties 的 JavaDoc。Properties 中新增了
输出
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
--!select.user而且还需要一个额外的类 SqlPropertySourceFactory 来解析上面的 *.sql 文件, 识别出 select.user 是 Key, 紧接着后面的块是相应的属性值,用注解引用它时还有点额外的 factory 属性来配置,如
select id, firstname, lastname, address --!update.user
update ........
@PropertySource(value = "classpath:sql/queries.sql", factory = SqlPropertySourceFactory.class)所以一直在思考是否能够再简单些,是否能用一个自定义的注解,如
@SqlPropertySource("classpath:sql/queries.sql")捉摸了很久,似乎有点难度,不过再不断发掘的过程中找到了这个类
org.springframework.core.io.support.PropertiesLoaderUtils, 有下面的代码片断 1public static Properties loadProperties(EncodedResource resource) throws IOException {
2 Properties props = new Properties();
3 fillProperties(props, resource);
4 return props;
5}
6......
7static void fillProperties(Properties props, EncodedResource resource, PropertiesPersister persister)
8 throws IOException {
9
10 InputStream stream = null;
11 Reader reader = null;
12 try {
13 String filename = resource.getResource().getFilename();
14 if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
15 stream = resource.getInputStream();
16 persister.loadFromXml(props, stream);
17 }
18 else if (resource.requiresReader()) {
19......也就是说其实我们是可以用 XML 文件来定义属性的。
继续深挖到
run.util.spi.XmlPropertiesProvider, 这居然是来自于 rt.jar, 原来用 XML 定义属性由来已久。Spring 所用的一个实现同样是 rt.jar 中的 sun.util.xml.PlatformXmlPropertiesProvider, 看到这个类的前几行我瞬间就豁然开朗了1private static final String PROPS_DTD_URI = "http://java.sun.com/dtd/properties.dtd";
2private static final String PROPS_DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!-- DTD for properties --><!ELEMENT properties ( comment?, entry* ) ><!ATTLIST properties version CDATA #FIXED \"1.0\"><!ELEMENT comment (#PCDATA) ><!ELEMENT entry (#PCDATA) ><!ATTLIST entry key CDATA #REQUIRED>";
3private static final String EXTERNAL_XML_VERSION = "1.0";定义属性的 XML 该如何写已经一目了然了,关键是 http://java.sun.com/dtd/properties.dtd 给我们的定义,也可以直接抓下它的定义来
➜ / curl -L http://java.sun.com/dtd/properties.dtd根节点是
<!--
Copyright 2006 Sun Microsystems, Inc. All rights reserved.
--> <!-- DTD for properties --> <!ELEMENT properties ( comment?, entry* ) > <!ATTLIST properties version CDATA #FIXED "1.0"> <!ELEMENT comment (#PCDATA) > <!ELEMENT entry (#PCDATA) > <!ATTLIST entry key CDATA #REQUIRED>
properties, 其下是多个 entry 定义,entry 的 key 属性即属性的 Key, entry 中是 CDATA 文本内容就是属性值。下面是一个实际的属性 XML 文件 1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE properties PUBLIC "xml property dtd" "http://java.sun.com/dtd/properties.dtd">
3
4<properties>
5 <entry key="select.user">
6select id, firstname, lastname, address
7 from user
8 where id = ?
9 </entry>
10 <entry key="update.user">
11<![CDATA[
12update user set address='<where>'
13 where id = ?
14]]>
15 </entry>
16</properties>如果 entry 中有 XML 的特殊字符就用
<![CDATA[...]> 框起来,无 XML Entities 就无所谓了。现在要引用定义在 XML 中的属性值就简单了,没有什么特别的,不需要额外的文件解析类,只是文件扩展名的不同而已。比如在你的 Spring 代码中使用如下注解
1@PropertySource("sql/queries.sql.xml") //由于默认是 classpath 所以无需写成 @PropertySource("classpath:sql/queries.sql.xml")
2public class JavaConfig {
3......
4}如此,定义在
sql/queries.sql.xml 便进到属性环境中去了,在任何一个 Spring Bean 中可以用 @Value("${select.uer}") 引用到了1@Named
2public class UserRepository {
3
4 @Value("${select.user}")
5 private String selectUserSql;
6
7 ........从此再也不用那个 SqlPropertySourceFactory 了。
IDE 打开 queries.sql.xml 只会以 XML 文件格式来进行语法高亮,如果想要 IDE 对其中的 SQL 语法进行高亮显示,可以修改 IDE 的配置,让 SQL 文件类型也包含
*.sql.xml 这个模式的文件名,那么每次在 IDE 中打开后缀为 *.sql.xml 都会认成是 SQL 文件,更增添了可读性。2019-06-12
Spring 对 xml 写属性文件的支持其实是由 JDK 的 Properties 类自 JDK 1.5 开始提供的,见 Properties 的 JavaDoc。Properties 中新增了
loadFromXML(Inputstream) 和 storeToXML(OutputStream, String, String), 来见识一下用 Properties 如何加载前方那个 sql/queries.sql.xml 配置的属性文件1Properties properties = new Properties();
2properties.loadFromXML(Thread.currentThread().getContextClassLoader().getResourceAsStream("sql/queries.sql.xml"));
3System.out.println(properties.getProperty(""));输出
select id, firstname, lastname, address永久链接 https://yanbin.blog/spring-properties-sql-in-xml-file/, 来自 隔叶黄莺 Yanbin's Blog
from user
where id = ?
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。