使用JAVA校验XML Schema
近期由于工作上的需求,需要对请求的xml
进行xsd
校验
于是想到了如下的方法:
所有的的.xsd
校验文件都放在resources/xsd
目录下
遇到的问题
国际化
首先是需要返回的提示信息要国际化
该类国际化资源的信息存放在jdk
的jre/lib/resources.jar
文件中的com/sun/org/apache/xerces/internal/impl/msg
路径下
需要设置为何种语言只需获取到javax.xml.validation.Validator
后,通过如下代码设置语言环境即可
1
| validator.setProperty("http://apache.org/xml/properties/locale", Locale.SIMPLIFIED_CHINESE);
|
部署到jboss上xsd文件路径获取不正确
由于项目要部署到jboss
上,jboss
上的文件系统是vfs
的,所以当执行以下代码时,会产生错误:
1 2
| xsdFile = ResourceUtils.getFile("classpath:" + xsdPath);
|
为了能获取到正确的路径,得借助jboss-vfs
的org.jboss.vfs.VirtualFile
1 2 3 4 5 6
| if (null== xsdFile){ final VirtualFile content = (VirtualFile) XmlValidateUtil.class.getClassLoader().getResource(xsdPath).getContent(); log.debug("校验规则 {} 真实路径为 :{}",xsdPath,content.getPhysicalFile().getPath()); xsdFile = content.getPhysicalFile(); }
|
jboss上设置国际化失败
这个文件主要是因为jboss
启动时,自己的类加载器加载了apache
的xerces
,jdk
中使用的是com/sun/org/apache/xerces
这样就导致我们获取到的Validator
是以apache
中的相关部分来实现的,不能直接使用jdk
中默认的
为了能使用jdk
自带的部分,只需获取到该类加载器的父类加载器去加载即可(绕过jboss的类加载器)
并且在生成javax.xml.validation.SchemaFactory
时,使用AppClassLoader
去加载相关的部分即可
1 2 3 4 5 6 7
| ClassLoader classLoader = XmlValidateUtil.class.getClassLoader(); if (!(classLoader instanceof URLClassLoader)){ classLoader = classLoader.getParent(); } SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema","com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory",classLoader);
|
完整工具类文件
XmlValidateUtil.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| @Slf4j public final class XmlValidateUtil {
public static final String XSD1 = "xsd/XSD1.xsd"; public static final String XSD2 = "xsd/XSD2.xsd";
static Map<String, Validator> validatorMap = new HashMap<>();
static { for (String key :of(XSD1, XSD2)) { try { validatorMap.put(key, getValidator(key)); } catch (Exception e) { log.error("init xsd map fail."); } } }
private XmlValidateUtil() { }
public static void validateXmlByXsd(String xml, String xsdPath) throws Exception { try { Source xmlFile = new StreamSource(new StringReader(xml)); Validator validator = validatorMap.get(xsdPath); validator.validate(xmlFile); log.info("xsd valid success."); } catch (SAXException var8) { log.error("xsd valid error."); log.error("Reason: {}", var8.getLocalizedMessage()); throw new Exception(var8.getLocalizedMessage()); } catch (Exception e){ log.error("获取校验规则 【{}】 路径失败 : {}",xsdPath,e); } }
static Validator getValidator(String xsdPath) throws Exception { File xsdFile = null; try { xsdFile = ResourceUtils.getFile("classpath:" + xsdPath); } catch (Exception e){ log.debug("----" + (new ClassPathResource(xsdPath)).getURI() + ""); }
try { if (null== xsdFile){ final VirtualFile content = (VirtualFile) XmlValidateUtil.class.getClassLoader().getResource(xsdPath).getContent(); log.debug("校验规则 {} 真实路径为 :{}",xsdPath,content.getPhysicalFile().getPath()); xsdFile = content.getPhysicalFile(); }
ClassLoader classLoader = XmlValidateUtil.class.getClassLoader(); if (!(classLoader instanceof URLClassLoader)){ classLoader = classLoader.getParent(); } SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema","com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory",classLoader); Schema schema = schemaFactory.newSchema(xsdFile); Validator validator = schema.newValidator(); validator.setProperty("http://apache.org/xml/properties/locale", Locale.SIMPLIFIED_CHINESE); return validator; } catch (Exception e){ log.error("获取校验规则 【{}】 路径失败 : {}",xsdPath,e); throw new Exception("获取校验规则失败"); } }
static <T> T[] of(T... values){ return values; } }
|