Tomcat9 Axis环境下SOAP服务无法写入XML文件问题咨询
写入失败的核心原因
ClassLoader.getResource()本质是读取类路径下的只读资源,返回的URL对应Tomcat部署的war包内部路径,不管war包是否解压,该路径默认仅支持读操作,不支持写入。你读取逻辑走的是只读的openStream(),所以正常,写入时调用URLConnection的getOutputStream()会被JVM拒绝,你捕获的InvocationTargetException是Axis反射调用服务方法的外层包装异常,查看e.getCause()即可看到底层的IO不支持写入错误。- 即便部分测试环境下Tomcat解压了war包,WEB-INF目录对Tomcat运行用户一般也仅开放读权限,没有写入权限,也会触发写入失败。
- 如果是写入新的XML文件,
getResource()会直接返回null,后续调用openConnection()会触发空指针异常,也是常见报错原因。 - 额外注意:WEB-INF属于应用部署目录,每次重新部署war包都会清空覆盖该目录下的所有内容,即便临时写入成功,重启或者重新部署应用后写入的文件也会全部丢失,不适合存储业务数据。
正确实现方案
不要通过ClassLoader操作可写入的业务文件,选择服务器上独立于Tomcat部署目录的专属路径存储XML文件,比如/data/app_business/xml/(Windows环境可以配置D:/app_business/xml/),将该路径配置为应用的可配置常量,直接用标准文件IO进行读写即可。
示例代码如下:
写入方法
// 配置项,可从properties配置文件/web.xml上下文参数中读取 private static final String XML_STORAGE_PATH = "/data/app_business/xml/"; public boolean serialize(Station s) { File xmlFile = new File(XML_STORAGE_PATH, s.getName() + ".xml"); // 自动创建不存在的父目录 if (!xmlFile.getParentFile().exists()) { xmlFile.getParentFile().mkdirs(); } try (OutputStream out = new FileOutputStream(xmlFile); XMLEncoder encoder = new XMLEncoder(out)) { encoder.writeObject(s); return true; } catch (Exception e) { Main.LOGGER.info("Station serialization was not successful!", e); return false; } }
对应读取方法(也同步修改为从独立目录读取,保持路径一致)
public Station deserialization(String name) { File xmlFile = new File(XML_STORAGE_PATH, name + ".xml"); if (!xmlFile.exists()) { Main.LOGGER.info("Station XML file not found: " + name); return null; } try (InputStream is = new FileInputStream(xmlFile); XMLDecoder decoder = new XMLDecoder(is)) { return (Station) decoder.readObject(); } catch (Exception e) { Main.LOGGER.info("Station deserializaton was not successful!", e); return null; } }
如果确实有临时写入WEB-INF目录的需求(非常不推荐),可以通过ServletContext的getRealPath()方法获取磁盘真实路径后再做文件操作,注意该方法在Tomcat配置unpackWARs="false"时会返回null,且部署时文件会丢失:
// Axis环境可从MessageContext获取ServletContext实例 String realXmlPath = servletContext.getRealPath("/WEB-INF/resources/" + s.getName() + ".xml"); File xmlFile = new File(realXmlPath); // 后续IO逻辑和上面示例一致
内容的提问来源于stack exchange,提问作者Aleksandar Cvisic
相关产品推荐
相关产品推荐

