简介: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 Archive(war包)。前者本质上是把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时先确认了下面的兼容组合,避免后期踩版本坑:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| JDK | 17 | 2.25.x支持Java 11和17,生产环境建议17 |
| Tomcat | 9.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.war:
wget 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.encoding=UTF-8 -Duser.timezone=Asia/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-name>cross-origin</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> <init-param> <param-name>cors.allowed.origins</param-name> <param-value>http://localhost:3000,https://yourdomain.com</param-value> </init-param> </filter> <filter-mapping> <filter-name>cross-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执行CFR:
mkdir -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 :lang=zh命令执行后能列出Noto Sans CJK等中文字体,说明字体库已就绪。再确保JVM参数里加了-Dfile.encoding=UTF-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-Origin:
curl -i -H "Origin: http://localhost:3000" http://localhost:8080/geoserver/wms?request=GetCapabilities看到响应头里有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?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=yourworkspace:yourlayer&STYLE=yourstyle&TILEMATRIX=EPSG:3857:{z}&TILEMATRIXSET=EPSG:3857&FORMAT=application/x-protobuf;type=mapbox-vector-tile&TILECOL={x}&TILEROW={y}' }) });性能调优方面,我建议重点看两个地方。一个是GWC的磁盘缓存目录,生产环境下瓦片缓存应该放在独立磁盘分区,不要和系统盘混在一起,避免缓存膨胀导致磁盘满。另一个是GeoServer日志中的瓦片渲染耗时,如果频繁出现超时,优先核对数据源连接池大小和数据库索引,而不是盲目调大JVM内存。
数据量大时还可以给GWC设置配额清理策略,比如按容量或时间自动清理旧瓦片。这一点对长期运行的服务尤其重要,否则缓存目录会持续膨胀。
最后分享一个我这两年用war部署养成的习惯:每次升级前,先把整个GEOSERVER_DATA_DIR做一次tar备份,再停Tomcat删掉work/Catalina下的对应缓存,把新war丢进webapps覆盖启动。这套动作看着简单,却帮我绕过了至少三次因为旧class缓存和数据目录版本不一致导致的怪异问题。war包的好处就在这:它把服务变成可复制的文件,剩下的事情全靠你的运维习惯来兜底。
本文还有配套的精品资源,点击获取