从零开始学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…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
