美文网首页我爱编程
spring+mybatis无网启动时,java.net.Unk

spring+mybatis无网启动时,java.net.Unk

作者: 该用户已注销 | 来源:发表于2018-04-08 23:47 被阅读0次

    spring+mybatis无网启动报错

    提示加载不到xsd或dtd文件

        项目改造时,遇到了项目在无外网环境下无法启动的问题。启动时抛出java.net.UnknownHostException: mybatis.org 异常。

    原因是spring在加载mybatis-config.xml 文件时,无法找到
    mybatis-3-config.dtd 这个文件。一般遇到这种项目加载不到本地dtd或xsd文件时,只要检查引入的jar包版本是否与xml文件中声明的dtd或xsd文件是否相匹配即可。
    于是,我检查了一下引入的mybatis版本3.2.3,xml文件中声明的是mybatis-3-config.dtd,jar包中是存在的。这就有点困惑了,那就看一下spring是怎么加载dtd文件的吧。
    这个文件在


    mybatis配置文件.png
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"
    >
    <configuration>
        <!-- 全局参数 -->
        <settings>
           ······
        </settings>
        <typeAliases>
           ·······
        </typeAliases>
    </configuration>
    
    1. spring加载dtd文件
      spring 使用 org.springframework.beans.factory.xml.BeansDtdResolver这个类来加载dtd文件,这个文件的注释是这么写的:
    /**
     * EntityResolver implementation for the Spring beans DTD,
     * to load the DTD from the Spring class path (or JAR file).
     *
     * <p>Fetches "spring-beans-2.0.dtd" from the class path resource
     * "/org/springframework/beans/factory/xml/spring-beans-2.0.dtd",
     * no matter whether specified as some local URL that includes "spring-beans"
     * in the DTD name or as "http://www.springframework.org/dtd/spring-beans-2.0.dtd".
     *
     * @author Juergen Hoeller
     * @author Colin Sampaleanu
     * @since 04.06.2003
     * @see ResourceEntityResolver
     */
    public class BeansDtdResolver implements EntityResolver {
    
        private static final String DTD_EXTENSION = ".dtd";
    
        private static final String DTD_FILENAME = "spring-beans-2.0";
    
        private static final String DTD_NAME = "spring-beans";
    
        private static final Log logger = LogFactory.getLog(BeansDtdResolver.class);
    
    
        @Override
        public InputSource resolveEntity(String publicId, String systemId) throws IOException {
            if (logger.isTraceEnabled()) {
                logger.trace("Trying to resolve XML entity with public ID [" + publicId +
                        "] and system ID [" + systemId + "]");
            }
            if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
                int lastPathSeparator = systemId.lastIndexOf("/");
                //看这里,该类只加载以spring-beans开头的dtd文件
                int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator);
                if (dtdNameStart != -1) {
                    String dtdFile = DTD_FILENAME + DTD_EXTENSION;
                    if (logger.isTraceEnabled()) {
                        logger.trace("Trying to locate [" + dtdFile + "] in Spring jar on classpath");
                    }
                    try {
                        Resource resource = new ClassPathResource(dtdFile, getClass());
                        InputSource source = new InputSource(resource.getInputStream());
                        source.setPublicId(publicId);
                        source.setSystemId(systemId);
                        if (logger.isDebugEnabled()) {
                            logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
                        }
                        return source;
                    }
                    catch (IOException ex) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);
                        }
                    }
    
                }
            }
    
            // Use the default behavior -> download from website or wherever.
            return null;
        }
    
    
        @Override
        public String toString() {
            return "EntityResolver for spring-beans DTD";
        }
    
    }
    

    这个类很简单,只有一个resolveEntity方法。我们看注释和源码知道这个方法只加载spring-beans开头的dtd文件,所以mybatis-3-config.dtd文件当然不会从本地加载。

    看到这里,我们就知道了mybatis-config.xml这个文件不应该交给spring来解析,应该由mybatis自己解析。所以我们修改一下项目配置,在classpath下单独给mybatis-config.xml 建一个目录,配置spring 只解析config目录下的xml文件 配置修改.png

    给mybatis的SqlSessionFactoryBean配置新的mybatis-config.xml文件地址。

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="mapperLocations" value="classpath:/**/mapper/*Mapper.xml" />
            <property name="configLocation" value="classpath:/mybaits/mybatis-config.xml"></property>
        </bean>
    

    mybatis有自己的xml解析器


    mybatis-xml解析器.png

    这个类也非常简单,也是只实现了EntityResolver接口。有兴趣可以看一下。
    改完,断网启动,没有问题。齐活,溜。

    
    /*
     * Offline entity resolver for the iBATIS DTDs
     */
    public class XMLMapperEntityResolver implements EntityResolver {
    
      private static final Map<String, String> doctypeMap = new HashMap<String, String>();
    
      private static final String IBATIS_CONFIG_DOCTYPE = "-//ibatis.apache.org//DTD Config 3.0//EN".toUpperCase(Locale.ENGLISH);
      private static final String IBATIS_CONFIG_URL = "http://ibatis.apache.org/dtd/ibatis-3-config.dtd".toUpperCase(Locale.ENGLISH);
    
      private static final String IBATIS_MAPPER_DOCTYPE = "-//ibatis.apache.org//DTD Mapper 3.0//EN".toUpperCase(Locale.ENGLISH);
      private static final String IBATIS_MAPPER_URL = "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd".toUpperCase(Locale.ENGLISH);
    
      private static final String MYBATIS_CONFIG_DOCTYPE = "-//mybatis.org//DTD Config 3.0//EN".toUpperCase(Locale.ENGLISH);
      private static final String MYBATIS_CONFIG_URL = "http://mybatis.org/dtd/mybatis-3-config.dtd".toUpperCase(Locale.ENGLISH);
    
      private static final String MYBATIS_MAPPER_DOCTYPE = "-//mybatis.org//DTD Mapper 3.0//EN".toUpperCase(Locale.ENGLISH);
      private static final String MYBATIS_MAPPER_URL = "http://mybatis.org/dtd/mybatis-3-mapper.dtd".toUpperCase(Locale.ENGLISH);
    
      private static final String IBATIS_CONFIG_DTD = "org/apache/ibatis/builder/xml/mybatis-3-config.dtd";
      private static final String IBATIS_MAPPER_DTD = "org/apache/ibatis/builder/xml/mybatis-3-mapper.dtd";
    
      static {
        doctypeMap.put(IBATIS_CONFIG_URL, IBATIS_CONFIG_DTD);
        doctypeMap.put(IBATIS_CONFIG_DOCTYPE, IBATIS_CONFIG_DTD);
    
        doctypeMap.put(IBATIS_MAPPER_URL, IBATIS_MAPPER_DTD);
        doctypeMap.put(IBATIS_MAPPER_DOCTYPE, IBATIS_MAPPER_DTD);
    
        doctypeMap.put(MYBATIS_CONFIG_URL, IBATIS_CONFIG_DTD);
        doctypeMap.put(MYBATIS_CONFIG_DOCTYPE, IBATIS_CONFIG_DTD);
    
        doctypeMap.put(MYBATIS_MAPPER_URL, IBATIS_MAPPER_DTD);
        doctypeMap.put(MYBATIS_MAPPER_DOCTYPE, IBATIS_MAPPER_DTD);
      }
    
      /*
       * Converts a public DTD into a local one
       *
       * @param publicId Unused but required by EntityResolver interface
       * @param systemId The DTD that is being requested
       * @return The InputSource for the DTD
       * @throws org.xml.sax.SAXException If anything goes wrong
       */
      public InputSource resolveEntity(String publicId, String systemId)
          throws SAXException {
    
        if (publicId != null) publicId = publicId.toUpperCase(Locale.ENGLISH);
        if (systemId != null) systemId = systemId.toUpperCase(Locale.ENGLISH);
    
        InputSource source = null;
        try {
          String path = doctypeMap.get(publicId);
          source = getInputSource(path, source);
          if (source == null) {
            path = doctypeMap.get(systemId);
            source = getInputSource(path, source);
          }
        } catch (Exception e) {
          throw new SAXException(e.toString());
        }
        return source;
      }
    
      private InputSource getInputSource(String path, InputSource source) {
        if (path != null) {
          InputStream in;
          try {
            in = Resources.getResourceAsStream(path);
            source = new InputSource(in);
          } catch (IOException e) {
            // ignore, null is ok
          }
        }
        return source;
      }
    
    }
    

    相关文章

      网友评论

        本文标题:spring+mybatis无网启动时,java.net.Unk

        本文链接:https://www.haomeiwen.com/subject/rmlmhftx.html