Spring 配置最好不要配置 xsd 版本号!

简介: 为什么dubbo启动没有问题?这篇blog源于一个疑问:我们公司使了阿里的dubbo,挂掉有好几个月了,为什么我们的应用启动没有问题?我们的应用的Spring配置文件里有类似的配置:


image.png

为什么dubbo启动没有问题?

这篇blog源于一个疑问:

我们公司使了阿里的dubbo,挂掉有好几个月了,为什么我们的应用启动没有问题?我们的应用的Spring配置文件里有类似的配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://code.alibabatech.com/schema/dubbo
    http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

我们都知道Spring在启动时是要检验XML文件的。或者为什么在Eclipse里xml没有错误提示?

比如这样的一个Spring配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

我们也可以在后面加上版本号:

xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

XML的一些概念

首先来看下xml的一些概念:

xml的schema里有namespace,可以给它起个别名。比如常见的spring的namespace:

xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"

通常情况下,namespace对应的URI是一个存放XSD的地址,尽管规范没有这么要求。

如果没有提供schemaLocation,那么Spring的xml解析器会从namespace的URI里加载XSD文件。我们可以把配置文件改成这个样子,也是可以正常工作的:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans/spring-beans.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

schemaLocation提供了一个xml namespace到对应的XSD文件的一个映射,所以我们可以看到,在xsi:schemaLocation后面配置的字符串都是成对的,前面的是namespace的URI,后面是xsd文件的URI。比如:

xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd"

*Spring是如何校验XML的? *


Spring默认在启动时是要加载XSD文件来验证xml文件的,所以如果有的时候断网了,或者一些开源软件切换域名,那么就很容易碰到应用启动不了。我记得当时Oracle收购Sun公司时,遇到过这个情况。


为了防止这种情况,Spring提供了一种机制,默认从本地加载XSD文件。打开spring-context-3.2.0.RELEASE.jar,可以看到里面有两个特别的文件:


spring.handlers

http://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

spring.schemas

http://www.springframework.org/schema/context/spring-context-2.5.xsd=org/springframework/context/config/spring-context-2.5.xsd
http://www.springframework.org/schema/context/spring-context-3.0.xsd=org/springframework/context/config/spring-context-3.0.xsd
http://www.springframework.org/schema/context/spring-context-3.1.xsd=org/springframework/context/config/spring-context-3.1.xsd
http://www.springframework.org/schema/context/spring-context-3.2.xsd=org/springframework/context/config/spring-context-3.2.xsd
http://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-3.2.xsd
...

再打开jar包里的org/springframework/context/config/ 目录,可以看到下面有

spring-context-2.5.xsd
spring-context-3.0.xsd
spring-context-3.1.xsd
spring-context-3.2.xsd

很明显,可以想到Spring是把XSD文件放到本地了,再在spring.schemas里做了一个映射,优先从本地里加载XSD文件。


并且Spring很贴心,把旧版本的XSD文件也全放了。这样可以防止升级了Spring版本,而配置文件里用的还是旧版本的XSD文件,然后断网了,应用启动不了。


我们还可以看到,在没有配置版本号时,用的就是当前版本的XSD文件:

http://www.springframework.org/schema/context/spring-context.xsd=org/springframework/context/config/spring-context-3.2.xsd

同样,我们打开dubbo的jar包,可以在它的spring.schemas文件里看到有这样的配置:

http://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

所以,Spring在加载dubbo时,会从dubbo的jar里加载dubbo.xsd。

如何跳过Spring的XML校验?

可以用这样的方式来跳过校验:

GenericXmlApplicationContext context = new GenericXmlApplicationContext();context.setValidating(false);

如何写一个自己的spring xml namespace扩展?

可以参考Spring的文档,实际上是相当简单的。只要实现自己的NamespaceHandler,再配置一下spring.handlers和spring.schemas就可以了。


http://docs.spring.io/spring/docs/current/spring-framework-reference/html/extensible-xml.html


其它的一些东东

防止XSD加载不成功的一个思路


http://hellojava.info/?p=135


齐全的Spring的namespace的列表


http://stackoverflow.com/questions/11174286/spring-xml-namespaces-how-do-i-find-what-are-the-implementing-classes-behind-t


aop - AopNamespaceHandler


c - SimpleConstructorNamespaceHandler


cache - CacheNamespaceHandler


context - ContextNamespaceHandler


jdbc - JdbcNamespaceHandler


jee - JeeNamespaceHandler


jms - JmsNamespaceHandler


lang - LangNamespaceHandler


mvc - MvcNamespaceHandler


oxm - OxmNamespaceHandler


p - SimplePropertyNamespaceHandler


task - TaskNamespaceHandler


tx - TxNamespaceHandler


util - UtilNamespaceHandler


security - SecurityNamespaceHandler


oauth - OAuthSecurityNamespaceHandler


int - IntegrationNamespaceHandler


amqp - AmqpNamespaceHandler


event - EventNamespaceHandler


feed - FeedNamespaceHandler


file - FileNamespaceHandler


ftp - FtpNamespaceHandler


gemfire - GemfireIntegrationNamespaceHandler


groovy - GroovyNamespaceHandler


http - HttpNamespaceHandler


ip - IpNamespaceHandler


jdbc - JdbcNamespaceHandler


jms - JmsNamespaceHandler


jmx - JmxNamespaceHandler


mail - MailNamespaceHandler


redis - RedisNamespaceHandler


rmi - RmiNamespaceHandler


script - ScriptNamespaceHandler


security - IntegrationSecurityNamespaceHandler


sftp - SftpNamespaceHandler


stream - StreamNamespaceHandler


twitter - TwitterNamespaceHandler


ws - WsNamespaceHandler


xml - IntegrationXmlNamespaceHandler


xmpp - XmppNamespaceHandler


###


总结:

为什么不要在Spring的配置里,配置上XSD的版本号?


因为如果没有配置版本号,取的就是当前jar里的XSD文件,减少了各种风险。 而且这样约定大于配置的方式很优雅。


相关文章
|
3月前
|
XML Java Nacos
Spring Boot 整合Nacos 版本兼容适配 史上最详细文档
本文介绍SpringBoot整合Nacos的完整流程,涵盖Nacos下载安装、配置中心与服务发现集成、版本兼容性问题及实战配置。重点解决SpringBoot 3.3.0与Nacos版本适配难题,推荐使用Spring Cloud Alibaba方案,并提供项目开源地址供参考学习。
|
3月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
3月前
|
Java 关系型数据库 MySQL
Spring Boot自动配置:魔法背后的秘密
Spring Boot 自动配置揭秘:只需简单配置即可启动项目,背后依赖“约定大于配置”与条件化装配。核心在于 `@EnableAutoConfiguration` 注解与 `@Conditional` 系列条件判断,通过 `spring.factories` 或 `AutoConfiguration.imports` 加载配置类,实现按需自动装配 Bean。
|
3月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
1407 0
|
2月前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
3月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
631 5
|
3月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
205 0
探索Spring Boot的@Conditional注解的上下文配置
|
4月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
1057 10
|
4月前
|
Cloud Native Java API
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
910 0

热门文章

最新文章