Spring的XML解析中关于DTD的路径问题-

在Spring中最简单的一个xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" " http://www.springframework.org/dtd/spring-beans.dtd ">
<beans>
<bean id="hello" class="com.test.Hello" singleton="true"/>
</beans>
但是这里的DTD使用的是网络路径,如果电脑没有上网的话,那么Spring读取这个XML就一定会出问题,因为无法到达这个网络地址,解决方法就是使用本地的DTD,那么路径应该如何设置呢?一般我们的配置文件都是放在classes目录下的,也就是在Classpath下,那么是不是要把spring-beans.dtd放到classes里面呢?不行,来看一下Spring中org.springframework.beans.factory.xml.BeansDtdResolver这个类的源代码:
/*
* Copyright 2002-2004 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.xml;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/**
* EntityResolver implementation for the Spring beans DTD,
* to load the DTD from the Spring classpath resp. JAR file.
*
* <p>Fetches "spring-beans.dtd" from the classpath resource
* "/org/springframework/beans/factory/xml/spring-beans.dtd",
* no matter if specified as some local URL or as
* " http://www.springframework.org/dtd/spring-beans.dtd ".
*
* @author Juergen Hoeller
* @since 04.06.2003
*/
public class BeansDtdResolver implements EntityResolver {
private static final String DTD_NAME = "spring-beans";
private static final String SEARCH_PACKAGE = "/org/springframework/beans/factory/xml/";
protected final Log logger = LogFactory.getLog(getClass());
public InputSource resolveEntity(String publicId, String systemId) throws IOException {
logger.debug("Trying to resolve XML entity with public ID [" + publicId +
"] and system ID [" + systemId + "]");
if (systemId != null && systemId.indexOf(DTD_NAME) > systemId.lastIndexOf("/")) {
String dtdFile = systemId.substring(systemId.indexOf(DTD_NAME));
logger.debug("Trying to locate [" + dtdFile + "] under [" + SEARCH_PACKAGE + "]");
try {
Resource resource = new ClassPathResource(SEARCH_PACKAGE + dtdFile, getClass());
InputSource source = new InputSource(resource.getInputStream());
source.setPublicId(publicId);
source.setSystemId(systemId);
logger.debug("Found beans DTD [" + systemId + "] in classpath");
return source;
}
catch (IOException ex) {
logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);
}
}
// use the default behaviour -> download from website or wherever
return null;
}
}
很清楚Spring已经把/org/springframework/beans/factory/xml/这个路径写死到代码里了,所以我们也只能把spring-beans.dtd放到这个目录下,才可以保证被xml解析引擎解析到,当然这里也可以使用绝对路径,但是这样的话,就很难在移植了,所以还是使用相对路径比较好,而且Spring已经把这个spring-beans.dtd打包到spring.jar文件中了。
好,现在已经确定是使用相对路径了,那么相对路径应该怎么写呢?看之前要搞清楚Spring用的是什么解析引擎,由于Spring使用的是JAXP解析XML文件的,在不做特殊声明的情况下,JDK会使用Crimson解析引擎,具体见Robbin的分析: http://forum.javaeye.com/viewtopic.php?t=75
好了,现在就来看一下Crimson这个解析引擎,在解析DTD时候的代码:
private String resolveURI(String uri)
throws SAXException
{
int temp = uri.indexOf (':');
// resolve relative URIs ... must do it here since
// it's relative to the source file holding the URI!
// "new java.net.URL (URL, string)" conforms to RFC 1630,
// but we can't use that except when the URI is a URL.
// The entity resolver is allowed to handle URIs that are
// not URLs, so we pass URIs through with scheme intact
if (temp == -1 || uri.indexOf ('/') < temp) {
String baseURI;
baseURI = in.getSystemId ();
if (baseURI == null)
fatal ("P-055", new Object [] { uri });
if (uri.length () == 0)
uri = ".";
baseURI = baseURI.substring (0, baseURI.lastIndexOf ('/') + 1);
if (uri.charAt (0) != '/')
uri = baseURI + uri;
else {
// We have relative URI that begins with a '/'
// Extract scheme including colon from baseURI
String baseURIScheme;
int colonIndex = baseURI.indexOf(':');
if (colonIndex == -1) {
// Base URI does not have a scheme so default to
// "file:" scheme
baseURIScheme = "file:";
} else {
baseURIScheme = baseURI.substring(0, colonIndex + 1);
}
uri = baseURIScheme + uri;
}
// letting other code map any "/xxx/../" or "/./" to "/",
// since all URIs must handle it the same.
}
// check for fragment ID in URI
if (uri.indexOf ('#') != -1)
error ("P-056", new Object [] { uri });
return uri;
}
由此可知路径里面必须包含":" 和"/"而且":"还必须在"/"的前面,所以这个路径我们可以最简单的写成 ":/spring-beans.dtd" 就可以了。当然":"前面在加上其他的什么路径都不影响解析。
Spring的XML解析中关于DTD的路径问题-
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值