
简介GeoServer 2.25.3 的 WAR 部署包面向 GIS 开发与运维人员用于将最新版 GeoServer 快速部署到 Tomcat 等 Servlet 容器中解决从源码构建到可用地图服务之间的环境配置问题。压缩包共 16 个文件整体约 105.18MB其中 geoserver.war 为可直接放入 webapps 的核心部署文件13 个 html 文件主要为各类开源许可证如 Apache/EPL/LGPL 等和官方说明页面2 个 txt 文件提供了版本信息与部署注意事项。已有 212 人学习下载适合需要快速搭建地理信息服务、评估新版本特性或进行二次开发的读者。下载后即可获得一个相对完整的 GeoServer 2.25.3 发布结构既能直接部署使用也能对照许可证文档检查合规性还可依据版本说明规避升级部署时的潜在问题。 聊个很多GIS初学者都会纠结的问题GeoServer官网下载页面里那个Web Archive包和Platform Independent Binary安装包到底有什么区别说实话我刚接触GeoServer那会儿也踩过这个坑——图省事装了安装包后来要换服务器、要定制登录页、要嵌到自己的Java工程里才发现被默认目录结构和自带的Jetty绑定得比较死。反而是简简单单的一个geoserver.war让我从2.19一路升到2.25.3几乎没有为“搬家”发过愁。这篇文章就把war包这条线的完整玩法写一遍从部署、配置、升级到反编译查问题、矢量切片生产配置全是我反复操作过的流程想用war包做GIS服务的人可以参考。1. 为什么我坚持用war包而不是安装包1.1 两种发布形态的本质区别GeoServer官方下载页面长期提供两个主要入口Platform Independent Binary平台无关二进制包和Web Archivewar包。前者本质上是把GeoServer和一个内嵌的Jetty容器打包在一起解压后执行bin/startup.sh就能跑起来后者只给一个符合Java Web规范的geoserver.war需要你自己准备一个外部Servlet容器最常见的就是Apache Tomcat。这两种形态最终跑的都是一套GeoServer代码区别在于“谁管理运行时环境”。二进制包自带Jetty对新手友好解压即用但代价是容器被焊死在安装目录里想统一纳入公司已有Tomcat集群比较麻烦。war包则把GeoServer看成普通Java Web应用容器的生命周期、端口、安全组、日志收集全部交给Tomcat统一管理。下面这张表能直观看出差异对比项二进制安装包war包解压即用是自带Jetty否需自行准备Tomcat多实例部署麻烦每个实例需独立目录和端口调整简单复制war并区分数据目录即可容器统一管理难Jetty被内置好可纳入已有Tomcat体系CI/CD流水线集成中目录结构复杂好一个war文件流转相对适合人群新手、单机快速验证生产环境、已有Java容器运维经验的团队从工程化角度讲war包的最大价值是“可复制”。你在一台机器上把一个war包部署调试好另一台机器只要环境变量一致、数据目录一致几乎不会出现“换个机器就起不来”的问题。1.2 真正让我转向war包的几个场景我第一次用war包是被生产环境逼的。当时项目方要求必须把GeoServer部署在已有的Tomcat集群里不能额外占用新端口也不能另起进程。二进制包自带的Jetty无论如何都做不到这一点只有war包能塞进Tomcat和其他业务系统共用8080端口。后来我越用越发现这些场景下war包的优势非常明显同容器部署和公司内部其他Java应用共享Tomcat运维只需要维护一套容器规范。多租户分实例复制war包分别指定GEOSERVER_DATA_DIR和端口一套代码多个服务互不干扰。灰度升级准备一个Tomcat目录先跑新版本war包验证完再切换流量回滚也只要换回旧war。资源可控二进制包自带的Jetty调优参数与公司规范不一致时war包完全复用Tomcat的JVM配置。当然war包也有学习门槛。你得懂Tomcat的目录结构、setenv.sh、webapps部署机制这对只习惯双击启动的用户来说是个坎。我的建议是个人学习、本地演示可以用二进制包但凡要进生产、要做自动化发布统一用war包。2. 2.25.3环境搭建JDK版本、Tomcat容器与数据目录2.1 版本兼容矩阵GeoServer 2.25.x这个版本系列对运行环境有明确要求我在搭建2.25.3时先确认了下面的兼容组合避免后期踩版本坑组件推荐版本说明JDK172.25.x支持Java 11和17生产环境建议17Tomcat9.0.x基于javax.servlet命名空间Tomcat 10不可用数据目录独立目录通过GEOSERVER_DATA_DIR指定不放在war解压目录内扩展插件严格匹配2.25.3扩展包版本必须和war主版本完全一致需要特别强调的是Tomcat版本。GeoServer 2.25.x仍然使用javax.servlet规范而Tomcat 10把命名空间整体迁移到了jakarta.servlet。直接把war包丢进Tomcat 10大概率会遇到ClassNotFoundError或者接口404的情况这个问题我在第5章会详细拆解。所以先装Tomcat 9不要拿Tomcat 10去试。2.2 部署步骤与关键配置整个部署流程可以归纳为“准备war包、指定数据目录、配置JVM编码、丢进webapps、启动验证”五步。下面是我在Linux服务器上的实际操作过程。先下载war包并解压得到geoserver.warwget https://build.geoserver.org/geoserver/2.25.x/geoserver-2.25.3-war.zip unzip geoserver-2.25.3-war.zip # 解压后目录里能看到 geoserver.war然后创建数据目录并设置环境变量。这一步非常关键很多新手忽略GEOSERVER_DATA_DIR结果GeoServer把数据写在Tomcat的temp目录里升级的时候数据全丢mkdir -p /opt/geoserver/data_dir export GEOSERVER_DATA_DIR/opt/geoserver/data_dir为了让环境变量持久化我把它写进Tomcat的setenv.sh。GeoServer的JVM参数也统一放在这里包括内存大小和编码# $CATALINA_HOME/bin/setenv.sh export GEOSERVER_DATA_DIR/opt/geoserver/data_dir export JAVA_OPTS-Xms2g -Xmx4g -Dfile.encodingUTF-8 -Duser.timezoneAsia/Shanghai这里解释一下为什么内存至少给2G。GeoServer在启动时会加载大量库、样式和数据源连接池内存太小的话发布大图层或做切片预览时很容易触发OutOfMemoryError。如果是8G内存的机器建议-Xms2g -Xmx6g如果机器内存小至少也要保证1G以上堆内存。2.3 web.xml中建议提前改掉的配置war包部署到Tomcat后会解压到webapps/geoserver目录配置文件就散落在WEB-INF下面。我每次都会在启动前先改两个地方先调整CORS跨域配置避免前端页面调用时被浏览器拦截。CORS过滤器在web.xml里的配置位置是在web-app标签内部默认GeoServer自带了一段被注释的配置模板把它取消注释并改成你需要的跨域策略即可。核心片段如下filter filter-namecross-origin/filter-name filter-classorg.apache.catalina.filters.CorsFilter/filter-class init-param param-namecors.allowed.origins/param-name param-valuehttp://localhost:3000,https://yourdomain.com/param-value /init-param /filter filter-mapping filter-namecross-origin/filter-name url-pattern/*/url-pattern /filter-mapping实际使用中如果前端是本地开发环境cors.allowed.origins建议直接填前端访问地址不要写星号。虽然星号也能通但一旦涉及带Cookie的鉴权请求浏览器会拒绝。另外WebSocket类型的推送请求和普通AJAX的跨域策略不一样GeoServer的WMS、WFS全是普通HTTP请求上面这段配置已经覆盖。改完web.xml后把geoserver.war复制到Tomcat的webapps目录下启动即可cp geoserver.war /opt/tomcat/webapps/ /opt/tomcat/bin/startup.sh2.4 启动验证与日志观察GeoServer启动过程通常需要20到50秒具体取决于机器性能。我启动后习惯先看日志再访问页面这样可以第一时间发现异常tail -f /opt/tomcat/logs/catalina.out tail -f /opt/geoserver/data_dir/logs/geoserver.log看到类似“Geoserver Startup Complete”或“Started ApplicationContext”的日志后再通过浏览器访问 http://localhost:8080/geoserver。页面能打开并且能看到默认工作区说明部署成功。第一次启动后系统会要求登录默认账号是admin密码是geoserver。登录后第一件事一定是改密码这个切勿跳过。我遇到过很多客户把默认密码带到生产环境然后被扫描工具爆破。3. 2.25.x相对老版本升级时的几件要紧事3.1 Java版本不再是“随便装个”以前用GeoServer 2.18、2.19的时候Java 8也能跑得很欢。但2.25.x把Java版本底线拉高了官方要求Java 11以上并且官方推荐Java 17。如果你的服务器还停留在Java 8环境直接换war包会出现UnsupportedClassVersionError。我在一次升级中踩过这个坑JDK没换直接把2.25.3的war丢进去Tomcat启动时抛了Class version错误日志指向某个Spring核心类。后来我把JDK从8切到17问题瞬间消失。所以升级到2.25.x之前先看java -version不要在这上面浪费时间。3.2 安全配置的默认策略更严格新版GeoServer对安全配置的要求明显提升最直观的变化是默认首页和接口暴露情况。界面上的“演示请求”等功能不再像老版本那样无脑开放配置不当会遇到403或404。我建议部署完成后按这个节奏做一轮安全加固立即修改admin密码避免使用默认口令。在“身份认证”页面关闭不必要的匿名访问纯内网调用最好只保留Basic Auth或Token认证。如果不需要对外暴露WFS-T写操作把WFS的写事务关闭。定期备份数据目录里的security文件夹这里的用户、角色、加密配置一旦丢失恢复成本很高。3.3 扩展模块版本必须严格匹配GeoServer的扩展模块是单独的zip包解压后把jar放进WEB-INF/lib目录即可。但有个铁律扩展包的版本号必须与war包完全一致。2.25.3的主程序配2.25.3的扩展包不能混用2.25.2或2.25.0的插件否则轻则插件不加载重则直接启动失败。常见的扩展模块包括矢量切片、CSS样式、监控、控制流等。我建议在安装扩展前先检查官方扩展下载页与war包大版本是否一致然后下载对应小版本的zip包再解压复制到lib目录。扩展包安装完必须重启Tomcat有些模块需要重新生成Spring上下文热加载会留隐患。4. war包反编译工具定位问题与定制行为的实用姿势4.1 什么情况下需要反编译war包正常使用war包不需要反编译但碰到一些特殊问题反编译是最高效的定位手段。我总结过三类场景第一类是报错信息指向某个类但文档没有详细说明。比如日志里出现异常异常类在某一个jar里我想知道这个类的逻辑从而判断是不是版本冲突或配置缺失。第二类是觉得某个默认行为不合理想确认代码里硬编码了哪些常量。比如有的扩展模块默认对输出数据做了某种限制我想看看这个限制写在哪里能否通过配置规避。第三类是发布内部定制版本需要改少量Java逻辑但不想fork整个Geoserver源码重新构建。这时候反编译出源码、修改后再重新打包是成本最低的路径。必须说明GeoServer本身是GPL 2.0协议的开源软件部署方修改自己使用的代码不违反授权协议。但如果你想把修改后的版本对外发布就要考虑GPL协议的衍生品条款务必咨询法律或法务人员。4.2 常用反编译工具与操作流程传统反编译工具如JD-GUI、Luyten对新版Java的支持参差不齐。GeoServer 2.25.3是基于Java 17构建的我实测下来命令行工具CFR兼容性最好处理新版class文件不容易报错。使用方式很简单。先解压war包里的jar或者直接对某个jar执行CFRmkdir -p /tmp/geoserver_cfr cd /tmp/geoserver_cfr # 如果只需要反编译某个jar里特定class先解压jar unzip /opt/tomcat/webapps/geoserver/WEB-INF/lib/gs-main-2.25.3.jar -d gs-main-classes # 用CFR反编译整个jar或指定class java -jar cfr.jar gs-main-classes/org/geoserver/catalog/impl/CatalogImpl.class --outputdir ./srcCFR反编译出来的代码可读性不错虽然变量名、注释不会还原但逻辑结构基本能看懂。如果是想改代码后重新打包可以用Cavaj或Recaf这类支持字节码编辑的工具但操作门槛更高。我只在极少数情况下用字节码方式修改大部分依赖CFR阅读源码然后重新编译完整工程。4.3 比反编译更干净的替代思路反编译适合“快速定位”但不适合“长期维护”。如果项目里需要大量改动GeoServer行为我更推荐直接从GitHub拉取GeoServer源码创建自己的分支修改后再用Maven构建。官方构建虽然慢但修改可追溯、可review后续合并上游更新也方便。对于只是想改登录页Logo、默认权限设置、中文字体这类资源层面的需求根本不需要反编译直接修改数据目录里对应文件或者WEB-INF里的配置文件就行。我自己在实际生产中反编译的主要用途还是排查jar包冲突和确认第三方扩展的实现逻辑。5. 部署后最容易翻车的三件事从现象到根因的完整排查链路5.1 Tomcat 10启动即失败javax与jakarta的割裂现象把war包部署到Tomcat 10后Tomcat能启动但访问geoserver页面一直报404或者直接抛NoClassDefFoundError日志中频繁出现javax.servlet字样。根因过程在新版本Tomcat里Servlet API的包名从javax.servlet迁移到了jakarta.servlet而GeoServer 2.25.3仍基于旧的javax命名空间。Tomcat 10不会自动做兼容转换导致GeoServer的类加载器找不到对应的Servlet类。排查链路很简单先确认Tomcat版本如果确认是10就不要继续折腾配置了直接换Tomcat 9。这类问题不是改几个配置能绕过去的两个包名体系不兼容。5.2 中文标注变成方块现象用SLD样式发布的服务图例和地图上的中文标注显示为方块或缺字图片上的字全部变成“豆腐块”。根因服务器缺少中文字体。GeoServer渲染文字时依赖操作系统字体库Linux服务器如果只装了英文环境字体列表里没有中文字形就会回退到空白块。解决思路分两步先装字体再调整编码# 安装字体工具和中文字体 apt-get install -y fontconfig fonts-noto-cjk fc-list :langzh命令执行后能列出Noto Sans CJK等中文字体说明字体库已就绪。再确保JVM参数里加了-Dfile.encodingUTF-8避免样式文件中的中文字符串读取时乱码。修改后重启Tomcat中文标注一般就能正常显示。5.3 前端跨域报错现象用OpenLayers或Leaflet在前端页面调用GeoServer的WMS服务浏览器控制台报CORS错误请求到达了GeoServer但响应被浏览器拦截。排查链路先确认请求是否真的到达服务器。可以在浏览器Network里看请求状态如果能看到HTTP响应但控制台报跨域限制说明服务端没有返回Access-Control-Allow-Origin头。GeoServer的CORS配置主要靠web.xml里的CorsFilter如果没有配置或配置未生效就会触发这个报错。解决办法就是第2章提到的web.xml配置。改完配置后重启Tomcat再用curl检查响应头是否包含Access-Control-Allow-Origincurl -i -H Origin: http://localhost:3000 http://localhost:8080/geoserver/wms?requestGetCapabilities看到响应头里有Access-Control-Allow-Origin字段基本就可以确认跨域问题解决。如果还是没有检查一下CorsFilter的jar包是否存在于WEB-INF/lib中Tomcat自带的Catalina过滤器类在极简安装时可能没被打包进去。6. 矢量切片生产实践war包模式下从扩展到客户端出图6.1 安装矢量切片扩展GeoServer原生不支持输出矢量切片需要安装矢量切片扩展模块。下载时注意两点一个是扩展包版本必须2.25.3另一个是确认下载对应的“vectortiles”插件而不是之前老的“geowebcache”插件。安装流程和普通jar包扩展一致wget https://build.geoserver.org/geoserver/2.25.x/extensions/geoserver-2.25.3-vectortiles-plugin.zip unzip geoserver-2.25.3-vectortiles-plugin.zip -d vectortiles-plugin cp vectortiles-plugin/*.jar /opt/tomcat/webapps/geoserver/WEB-INF/lib/ # 重启Tomcat使其生效 /opt/tomcat/bin/shutdown.sh /opt/tomcat/bin/startup.sh重启后进入Layer Preview选择一个图层在格式下拉列表里如果出现了“MapBox Vector Tiles”或“OpenLayers MVT”选项说明扩展安装成功。6.2 图层配置要点矢量切片的质量很大程度上取决于图层配置不是装上插件就能出理想效果。我建议优先把数据源切成Web墨卡托坐标系EPSG:3857因为矢量切片的瓦片方案通常基于Web墨卡托金字塔。如果原始数据是CGCS2000或WGS84经纬度坐标GeoServer会在切片时做动态投影增加出图耗时而且数据密集区域容易出现怪异变形。开启矢量切片还需要在GWC切片缓存中配置对应的瓦片矩阵集。操作路径是“Tile Layers”- 选择图层 - 找到“Tile Caching”相关选项默认会生成EPSG:4326和EPSG:3857两套矩阵集。生产环境我一般只保留EPSG:3857并且把GridSet的范围调整到和前端地图容器一致减少无效瓦片生成。SLD样式也需要专门为矢量切片调整。栅格瓦片的SLD可以很复杂但矢量切片中的每个要素在客户端要做样式重绘SLD里复杂的符号化规则会被客户端忽略或翻译不完整。我实践的结论是尽量使用简单填充和描边不要依赖SLD里的外部图标把复杂样式留到前端用Mapbox Style或OpenLayers表达式去写。6.3 前端衔接与性能调优矢量切片装好之后最方便的验证方式是Layer Preview里选择“MapBox Vector Tiles”。它会直接打开一个以MapLibre为核心的前端预览页面能看到图层样式是否生效。如果要在自己的前端项目里接OpenLayers的接入代码可以这样写import VectorTileLayer from ol/layer/VectorTile; import VectorTileSource from ol/source/VectorTile; const vtLayer new VectorTileLayer({ declutter: false, source: new VectorTileSource({ format: new MVT(), url: http://localhost:8080/geoserver/gwc/service/wmts?SERVICEWMTSREQUESTGetTileVERSION1.0.0LAYERyourworkspace:yourlayerSTYLEyourstyleTILEMATRIXEPSG:3857:{z}TILEMATRIXSETEPSG:3857FORMATapplication/x-protobuf;typemapbox-vector-tileTILECOL{x}TILEROW{y} }) });性能调优方面我建议重点看两个地方。一个是GWC的磁盘缓存目录生产环境下瓦片缓存应该放在独立磁盘分区不要和系统盘混在一起避免缓存膨胀导致磁盘满。另一个是GeoServer日志中的瓦片渲染耗时如果频繁出现超时优先核对数据源连接池大小和数据库索引而不是盲目调大JVM内存。数据量大时还可以给GWC设置配额清理策略比如按容量或时间自动清理旧瓦片。这一点对长期运行的服务尤其重要否则缓存目录会持续膨胀。最后分享一个我这两年用war部署养成的习惯每次升级前先把整个GEOSERVER_DATA_DIR做一次tar备份再停Tomcat删掉work/Catalina下的对应缓存把新war丢进webapps覆盖启动。这套动作看着简单却帮我绕过了至少三次因为旧class缓存和数据目录版本不一致导致的怪异问题。war包的好处就在这它把服务变成可复制的文件剩下的事情全靠你的运维习惯来兜底。本文还有配套的精品资源点击获取