从零开始学GeoServer源码(一)(搭建开发环境Win10+IDEA23.3.5+jdk11+geoserver2.24.x)
搭建开发环境
- 参考资料
- 0、基础环境准备
- 0.1、idea
- 0.2、jdk
- 0.3、源码
- 1、导入工程
- 2、配置启动环境
- 2.1、打开新增配置面板
- 2.2、配置工作目录
- 2.2.1、从常用配置中选择
- 2.2.2、直接粘贴
- 2.3最终效果
- 3、调整源码
- 3.1、添加maven引用
- 3.2、注释无效代码
- 3.3、删除测试代码
- 4、修改运行端口
- 4.1、直接修改启动类中的端口设置
- 4.2、修改jetty配置
- 5、启动
参考资料
- 主要参考了这个系列,因此文档开头特别感谢一下https://blog.csdn.net/xiangshangdemayi/article/details/122441730
- 添加依赖的参考文档https://blog.csdn.net/qq_15065903/article/details/128781051
- maven仓库https://mvnrepository.com/artifact/javax.xml.soap/javax.xml.soap-api
0、基础环境准备
0.1、idea
我使用的是2023.3.5

0.2、jdk
部门的工程主要使用的是jdk1.8,geoserver2.24.x源码使用的是jdk11以上。所以需要安装一下jdk11。我使用的是OpenLogic的OpenJDK,以前用Oracle的openjdk还得登录,所以没有用Oracle的。

ps:
各个openjdk版本资源列表:https://jdk.java.net/archive/
写这篇文档的时候才发现这个网页。囊括了几乎所有维护中的版本。比较友好。提供的文件是编译好的,下载后不用配置,放到固定位置即可(个人推荐c:/java/openjdk11)
0.3、源码
公司当前使用的是geoserver-cloud 2.24.2.因此选用了2.24.x这个分支

1、导入工程

代码下载好之后按提示打开工程,然后切换到2.24.x分支

idea自动检测maven工程。安装提示窗,load即可

识别完成后,确认每个模块的jdk版本。右键任意一个模块名称,如:src[geoserver] 。选择右键后弹出菜单中的 Open Module Settings。

确保每个module的jdk都是11以上

2、配置启动环境
2.1、打开新增配置面板

添加配置


2.2、配置工作目录
2.2.1、从常用配置中选择


把默认目录删除,保证working directory框里只有$MODEL_DIR $ 复制的时候记得把第二个$ 符号之前的空格删除(暂时不知道怎么在MarkDown中打出两个$$夹内容)

2.2.2、直接粘贴
直接向working directory框里输入$MODEL_DIR $
复制的时候记得把第二个$ 符号之前的空格删除(暂时不知道怎么在MarkDown中打出两个$$夹内容)
2.3最终效果
总共需要保证五处都改好了。

注:
如果Working directory没设置好,可能会报4.4错误

参考文档中的errorprone问题没有遇到,我直接安装了这个插件。就不补充了
3、调整源码
3.1、添加maven引用
源码中有个类缺少Node引用。编译的时候报错,点击报错的提示,定位到源码文件的工程。在pom.xml中添加maven依赖

文件目录:src/wcs1_1/pom.xml
<!-- https://mvnrepository.com/artifact/javax.xml.soap/javax.xml.soap-api -->
<dependency><groupId>javax.xml.soap</groupId><artifactId>javax.xml.soap-api</artifactId><version>1.4.0</version>
</dependency>

代码添加引用
源文件相对目录:src/wcs1_1/src/main/java/org/geoserver/wcs/kvp/rangesubset/AbstractContentNode.java
package org.geoserver.wcs.kvp.rangesubset;
import javax.xml.soap.Node;
public abstract class AbstractContentNode implements Node {protected String content;public String getContent() {return content;}public void setContent(String content) {this.content = content;}
}
3.2、注释无效代码
需要修改的源文件(相对目录)src/wcs1_1/src/main/java/org/geoserver/wcs/kvp/RangeSubsetKvpParser.java
文件注释后的结果
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved* (c) 2001 - 2013 OpenPlans* This code is licensed under the GPL 2.0 license, available at the root* application directory.*/
package org.geoserver.wcs.kvp;import static org.vfny.geoserver.wcs.WcsException.WcsExceptionCode.InvalidParameterValue;import java.io.StringReader;
import net.opengis.ows11.CodeType;
import net.opengis.ows11.Ows11Factory;
import net.opengis.wcs11.AxisSubsetType;
import net.opengis.wcs11.FieldSubsetType;
import net.opengis.wcs11.RangeSubsetType;
import net.opengis.wcs11.Wcs111Factory;
import org.geoserver.ows.KvpParser;
//import org.geoserver.wcs.kvp.rangesubset.ASTAxisId;
//import org.geoserver.wcs.kvp.rangesubset.ASTAxisSubset;
//import org.geoserver.wcs.kvp.rangesubset.ASTFieldId;
//import org.geoserver.wcs.kvp.rangesubset.ASTFieldSubset;
//import org.geoserver.wcs.kvp.rangesubset.ASTInterpolation;
//import org.geoserver.wcs.kvp.rangesubset.ASTKey;
//import org.geoserver.wcs.kvp.rangesubset.ASTRangeSubset;
//import org.geoserver.wcs.kvp.rangesubset.Node;
//import org.geoserver.wcs.kvp.rangesubset.RangeSubsetParser;
//import org.geoserver.wcs.kvp.rangesubset.RangeSubsetParserVisitor;
//import org.geoserver.wcs.kvp.rangesubset.SimpleNode;
import org.vfny.geoserver.wcs.WcsException;/*** Parses the RangeSubset parameter of a GetFeature KVP request** @author Andrea Aime*/
public class RangeSubsetKvpParser extends KvpParser {public RangeSubsetKvpParser() {super("RangeSubset", RangeSubsetType.class);}@Overridepublic Object parse(String value) throws Exception {return null;/* RangeSubsetParser parser = new RangeSubsetParser(new StringReader(value));SimpleNode root = parser.RangeSubset();RangeSubsetType result =(RangeSubsetType) root.jjtAccept(new RangeSubsetKvpParserVisitor(), null);for (Object o : result.getFieldSubset()) {FieldSubsetType type = (FieldSubsetType) o;String interpolationType = type.getInterpolationType();if (interpolationType != null) {try {InterpolationMethod.valueOf(interpolationType);} catch (IllegalArgumentException e) {throw new WcsException("Unknown interpolation method " + interpolationType,InvalidParameterValue,"RangeSubset");}}}return result;*/}/* private static class RangeSubsetKvpParserVisitor implements RangeSubsetParserVisitor {Wcs111Factory wcsf = Wcs111Factory.eINSTANCE;Ows11Factory owsf = Ows11Factory.eINSTANCE;@Overridepublic Object visit(SimpleNode node, Object data) {throw new UnsupportedOperationException("This method should never be reached");}@Override@SuppressWarnings("unchecked") // EMF model without genericspublic Object visit(ASTRangeSubset node, Object data) {RangeSubsetType rs = wcsf.createRangeSubsetType();for (int i = 0; i < node.jjtGetNumChildren(); i++) {ASTFieldSubset fs = (ASTFieldSubset) node.jjtGetChild(i);FieldSubsetType fst = (FieldSubsetType) fs.jjtAccept(this, data);rs.getFieldSubset().add(fst);}return rs;}@Override@SuppressWarnings("unchecked") // EMF model without genericspublic Object visit(ASTFieldSubset node, Object data) {FieldSubsetType fs = wcsf.createFieldSubsetType();for (int i = 0; i < node.jjtGetNumChildren(); i++) {Node child = node.jjtGetChild(i);if (child instanceof ASTFieldId) {CodeType id = owsf.createCodeType();id.setValue((String) child.jjtAccept(this, null));fs.setIdentifier(id);} else if (child instanceof ASTInterpolation) {fs.setInterpolationType((String) child.jjtAccept(this, null));} else if (child instanceof ASTAxisSubset) {fs.getAxisSubset().add(child.jjtAccept(this, null));}}return fs;}@Override@SuppressWarnings("unchecked") // EMF model without genericspublic Object visit(ASTAxisSubset node, Object data) {AxisSubsetType as = wcsf.createAxisSubsetType();as.setIdentifier(((SimpleNode) node.jjtGetChild(0)).getContent());for (int i = 1; i < node.jjtGetNumChildren(); i++) {as.getKey().add(node.jjtGetChild(i).jjtAccept(this, null));}return as;}@Overridepublic Object visit(ASTFieldId node, Object data) {return node.getContent();}@Overridepublic Object visit(ASTAxisId node, Object data) {return node.getContent();}@Overridepublic Object visit(ASTInterpolation node, Object data) {return node.getContent();}@Overridepublic Object visit(ASTKey node, Object data) {return node.getContent();}}*/
}
3.3、删除测试代码
做好以上处理后,我启动时测试代码报错,提示找不到文件。为了快速启动,直接把测试代码删掉了。猜测是我没有配置测试环境

4、修改运行端口
4.1、直接修改启动类中的端口设置
找了半天才找到启动类的位置,是个测试类,相对路径:src/web/app/src/test/java/org/geoserver/web/Start.java

直接修改启动类的端口就可以了,我改成了8010

能正常启动

4.2、修改jetty配置
我下载的这个pom文件里引用jetty组件异常,所以pom里面设置的端口号没起效果。我只用了上边那种方式,直接在启动类修改了端口


5、启动

相关文章:
从零开始学GeoServer源码(一)(搭建开发环境Win10+IDEA23.3.5+jdk11+geoserver2.24.x)
搭建开发环境 参考资料 0、基础环境准备0.1、idea0.2、jdk0.3、源码 1、导入工程2、配置启动环境2.1、打开新增配置面板2.2、配置工作目录2.2.1、从常用配置中选择2.2.2、直接粘贴 2.3最终效果 3、调整源码3.1、添加maven引用3.2、注释无效代码3.3、删除测试代码 4、修改运行端…...
分类模型:MATLAB判别分析
1. 判别分析简介 判别分析(Discriminant Analysis) 是一种统计方法,用于在已知分类的样本中构建分类器,并根据特征变量对未知类别的样本进行分类。常见的判别分析方法包括线性判别分析(Linear Discriminant Analysis, …...
生产 的mybatisplus 日志输入到日志文件
默认是输出到控制台.不输出到日志文件 输出到日志文件.需要修改配置 第一步. logging:config: classpath:logback-wshoto.xml第二步 mybatis-plus:configuration:cache-enabled: truedefault-executor-type: reuselog-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl第三步…...
八分钟生成一篇两万字的文章演示——《基于灰色预测的人口预测模型》
文章目录 工具使用 《基于灰色预测的人口预测模型》-全文由AI一次性生成文献综述研究方法模型开发灰色预测模型的数学构建参数估计模型验证 案例研究案例研究描述数据收集与预处理灰色预测模型的应用 文献综述研究方法模型开发灰色预测模型的数学构建参数估计模型验证 案例研究…...
golang 透明底图转白底
url : ""var s []byte// 请求线上图片s GetUrl(url)// 处理透明底图转白底img, _, err : image.Decode(bytes.NewReader(s))if err ! nil {fmt.Println("读取图片失败")}bounds : img.Bounds()dst : image.NewNRGBA(bounds)draw.Draw(dst, bounds, image.…...
【一】【网络使用小知识】使用aria2软件结合Windows PowerShell命令行快速下载文件
下载aria2软件 点击进入网址,aria2下载网址. 下载windows版本. 通过Windows PowerShell命令行使用aria2软件下载文件 通用下载文件命令行代码 aria2软件完整路径 -x 16 -s 32 -d 下载目录(文件夹) -o 文件名 下载链接路径示例,用aria2下载qq 找到aria2应用的直接地址,结合…...
报错:C1189#error: The <experimental/filesystem> header providing 解决方案
今天开发过程中,需要使用文件系统experimental/filesystem,报错C1189#error: The <experimental/filesystem> header providing ,通过以下解决方案,成功运行程序。 目录 一、打开项目下的属性 二、选择C/…...
Elixir学习笔记——速构(函数式编程基础)
在 Elixir 中,循环遍历 Enumerable 是很常见的,通常会过滤掉一些结果并将值映射到另一个列表中。 速构是此类构造的语法糖:它们将这些常见任务分组为 for 特殊形式。 例如,我们可以将一串整数映射到它们的平方值: 速构…...
开源项目大合集(热门)
人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…...
【JVM】JVisualVM的介绍、使用和GC过程
VisualVM介绍 VisualVM 是Netbeans的profile子项目,已在JDK6.0 update 7 中自带,能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈(如100个String对象分别由哪几…...
个人在家如何获取World Scientific文献的经验分享
今天有位同学求助一篇World Scientific文献,他的学校虽然有这个数据库,但订购的该数据库资源内容有限,这位同学所需的文献不在学校订购范围内所以下载不了。今天小编就分享一个在家就可获取各个数据库文献的方法。本文以这篇求助文献为例&…...
Java 收集常见面试题
set和list的区别?给定一系列字符串,从集合的set和list中查询,如何查询出相关的数据? 在Java中,Set和List都是用于存储对象的集合 Set: 不允许包含重复的元素。 没有顺序(即不保证元素的迭代顺序…...
JS 严格模式和正常模式的区别
严格模式使用"use strict"; 作用: 消除 Javascript 语法的一些不合理、不严谨之处,减少一些怪异行为;消除代码运行的一些不安全之处,保证代码运行的安全;提高编译器效率,增加运行速度;为未来新…...
9种编程语言的对比分析
在当今的软件开发领域,编程语言扮演着至关重要的角色。不同的编程语言各有其特点和适用场景,选择合适的编程语言能够提高开发效率和软件质量。本文将对十种常见的编程语言进行对比分析,帮助读者了解它们的优缺点和适用场景。 Java 特点&…...
模拟14位相机输出Verilog代码
1 代码 `timescale 1ns / 1psmodule simulate_camera_out (input clk,input rest_n,output camera_clk, //像素时钟output [13:0] camera_data, //像素值数据output [19:0] pixel_xy, //此时输出的像素值坐标output reg frame_valid //帧有效信号,1代表帧有效0代表帧无效…...
Linux远程访问及控制
SSH远程管理 SSH(Secure Shell)是一种安全通道协议,主要用来实现字符界面的远程登录、远程复制等功能。SSH 协议对通信双方的数据传输进行了加密处理,其中包括用户登录时输入的用户口令。与早期的 Telent(远程登录)、RSH(Remote Shell,远程执…...
归并排序个人见解
归并排序个人见解 思路实现代码实现题目 思路实现 归并排序属于分治算法,分治算法有三个步骤: 分:将问题划分为多个规模较小的子问题,这些子问题与原始问题相似。治:递归地解决这些子问题。如果子问题足够小…...
软考初级网络管理员__网络单选题
1.观察交换机状态指示灯初步判断交换机故障,交换机运行中指示灯显示红色表示()。 警告 正常 待机 繁忙 2.通常测试网络连通性采用的命令是()。 Netstat Ping Msconfig Cmd 3.一台16端口的交换机可以产生()个冲突域? 1 4 15 16…...
22.2 正则表达式-数据验证、数据变换
1. 数据验证 正则表达可用于验证文本是否满足某种给定的模式。 正则表达式也是一种语言,因此在使用之前必须先对其进行编译,并将编译结果保存在一个Regexp类型的变量里。以下两个函数即返回该变量的指针。 re, err : regexp.Compile("^[a-zA-Z0-…...
示例:WPF中应用DataGrid读取实体DisplayAttribute特性自动自动生成列名
一、目的:通过重写DataGrid的OnAutoGeneratingColumn方法实现根据定义特性自动生成列头信息功能 二、实现 <DataGrid ItemsSource"{local:GetStudents Count50}"/>实体定义如下 public class Student{[DataGridColumn("*")][Display(Na…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...
