Webgis项目java 一键入库GDB及发布GeoServer服务

819 阅读9分钟

1. springboot项目初始化

1.1 方式一:springboot官方的模板生成器

1.2 方式二:idea开发工具生成(推荐)

1.2.1 新建项目

1.2.2 选择spring initializr, 修改参数

1.2.3 添加依赖

1.2.4 项目初始化成功

1.2.5 idea连接本地数据库

  1. 打开database工具

  1. 添加postgresql

  1. 测试连接,添加

2. 引入mybatis-plus

根据官网文档(baomidou.com/)引入

2.1 创建用户表

create table "user"
(
    id            bigint not null
        primary key,
    user_name     varchar(50),
    age           integer,
    email         varchar(100),
    user_account  varchar(256),
    avatar_url    varchar(1024),
    gender        integer,
    user_password varchar(512),
    user_status   integer default 0,
    phone         varchar(128),
    create_time   timestamp,
    update_time   timestamp,
    is_delete     integer default 0
);

comment on table "user" is '用户表';

comment on column "user".user_name is '用户昵称';

comment on column "user".age is '年龄';

comment on column "user".email is '邮箱';

comment on column "user".user_account is '账号';

comment on column "user".avatar_url is '头像';

comment on column "user".gender is '性别';

comment on column "user".user_password is '密码';

comment on column "user".user_status is '状态 0-正常';

comment on column "user".phone is '电话';

comment on column "user".create_time is '创建时间';

comment on column "user".update_time is '更新时间';

comment on column "user".is_delete is '是否删除';

alter table "user"
    owner to postgres;

2.2 往测试表user插入数据

DELETE FROM user;

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

2.3 引入依赖

2.3.1 pom.xml文件添加依赖

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>

2.3.2 重新加载maven

2.4 修改配置文件

2.4.1 将application文件的后缀名为.yml 支持嵌套写法

2.4.2 修改内容

# DataSource Config
spring:
  application:
    name: webgis-demo
  datasource:
    driver-class-name: org.postgresql.Driver
    #    schema: classpath:db/schema-h2.sql
    #    data: classpath:db/data-h2.sql
    url: jdbc:postgresql://localhost:5432/postgis_21_sample
    username: postgres
    password: Giseryin
server:
  port: 8301
  servlet:
    #服务应用名
    context-path: /webgis-demo
    session:
      timeout: PT540M

2.5 创建实体类

2.5.1 创建module包存放java对象

2.5.2 创建 user 实体类,使用lombok简化代码

/**
 * 用户表
 * @TableName user
 */
@TableName(value ="public.user")
@Data
public class User implements Serializable {
    /**
     * 
     */
    @TableId
    private Long id;

    /**
     * 用户昵称
     */
    private String userName;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 邮箱
     */
    private String email;

    /**
     * 账号
     */
    private String userAccount;

    /**
     * 头像
     */
    private String avatarUrl;

    /**
     * 性别
     */
    private Integer gender;

    /**
     * 密码
     */
    private String userPassword;

    /**
     * 状态 0-正常
     */
    private Integer userStatus;

    /**
     * 电话
     */
    private String phone;

    /**
     * 创建时间
     */
    private Date createTime;

    /**
     * 更新时间
     */
    private Date updateTime;

    /**
     * 是否删除
     */
    private Integer isDelete;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;

    @Override
    public boolean equals(Object that) {
        if (this == that) {
            return true;
        }
        if (that == null) {
            return false;
        }
        if (getClass() != that.getClass()) {
            return false;
        }
        User other = (User) that;
        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
            && (this.getUserName() == null ? other.getUserName() == null : this.getUserName().equals(other.getUserName()))
            && (this.getAge() == null ? other.getAge() == null : this.getAge().equals(other.getAge()))
            && (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()))
            && (this.getUserAccount() == null ? other.getUserAccount() == null : this.getUserAccount().equals(other.getUserAccount()))
            && (this.getAvatarUrl() == null ? other.getAvatarUrl() == null : this.getAvatarUrl().equals(other.getAvatarUrl()))
            && (this.getGender() == null ? other.getGender() == null : this.getGender().equals(other.getGender()))
            && (this.getUserPassword() == null ? other.getUserPassword() == null : this.getUserPassword().equals(other.getUserPassword()))
            && (this.getUserStatus() == null ? other.getUserStatus() == null : this.getUserStatus().equals(other.getUserStatus()))
            && (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone()))
            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
            && (this.getIsDelete() == null ? other.getIsDelete() == null : this.getIsDelete().equals(other.getIsDelete()));
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
        result = prime * result + ((getUserName() == null) ? 0 : getUserName().hashCode());
        result = prime * result + ((getAge() == null) ? 0 : getAge().hashCode());
        result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
        result = prime * result + ((getUserAccount() == null) ? 0 : getUserAccount().hashCode());
        result = prime * result + ((getAvatarUrl() == null) ? 0 : getAvatarUrl().hashCode());
        result = prime * result + ((getGender() == null) ? 0 : getGender().hashCode());
        result = prime * result + ((getUserPassword() == null) ? 0 : getUserPassword().hashCode());
        result = prime * result + ((getUserStatus() == null) ? 0 : getUserStatus().hashCode());
        result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode());
        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
        result = prime * result + ((getIsDelete() == null) ? 0 : getIsDelete().hashCode());
        return result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", userName=").append(userName);
        sb.append(", age=").append(age);
        sb.append(", email=").append(email);
        sb.append(", userAccount=").append(userAccount);
        sb.append(", avatarUrl=").append(avatarUrl);
        sb.append(", gender=").append(gender);
        sb.append(", userPassword=").append(userPassword);
        sb.append(", userStatus=").append(userStatus);
        sb.append(", phone=").append(phone);
        sb.append(", createTime=").append(createTime);
        sb.append(", updateTime=").append(updateTime);
        sb.append(", isDelete=").append(isDelete);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}

2.6 添加mapper

2.6.1 添加mapper包

2.6.2 启动类添加注解,扫描mapper包

2.6.3 添加mapper类 UserMapper

/**
* @author Giseryin
* @description 针对表【user(用户表)】的数据库操作Mapper
* @createDate 2022-11-10 10:31:23
* @Entity generator.domain.User
*/
public interface UserMapper extends BaseMapper<User> {

}

2.7 测试

2.7.1 添加依赖引入 单元测试工具Junit

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

2.7.2 编写测试类,查看测试结果

@SpringBootTest
@RunWith(SpringRunner.class)
public class SampleTest {

    @Resource
    private UserMapper userMapper;

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userMapper.selectList(null);
        // Assert.assertEquals(5, userList.size());
        userList.forEach(System.out::println);
    }
}

打印成功

3.gdb数据入库

3.1 pom.xml 引入Geotools、GDAL依赖

添加仓库地址

<!-- 添加仓库地址 -->
<repositories>
  <repository>
    <id>osgeo</id>
    <name>OSGeo Release Repository</name>
    <url>https://repo.osgeo.org/repository/release/</url>
    <snapshots><enabled>false</enabled></snapshots>
    <releases><enabled>true</enabled></releases>
  </repository>
</repositories>

<!--设置Geotools 版本号 -->
 		<properties>
        <geotools.version>21.0</geotools.version>
    </properties>


  <!--geoTools-->
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-jdbc</artifactId>
            <version>${geotools.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>commons-collections</artifactId>
                    <groupId>commons-collections</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-cql</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <!--操作shape文件-->
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-shapefile</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <!--坐标系-->
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-epsg-hsql</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-geojson</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools.jdbc</groupId>
            <artifactId>gt-jdbc-postgis</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-jts-wrapper</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-epsg-hsql</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-opengis</artifactId>
            <version>${geotools.version}</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.osgeo/proj4j 用于投影坐标转化 -->
        <dependency>
            <groupId>org.osgeo</groupId>
            <artifactId>proj4j</artifactId>
            <version>0.1.0</version>
        </dependency>
				<!-- 引入gdal -->
        <dependency>
            <groupId>org.gdal</groupId>
            <artifactId>gdal</artifactId>
            <version>3.5.0</version>
        </dependency>

3.2 GDAL环境安装

  1. download.gisinternals.com/archive.php 下载gdal环境

  1. 把release-xxxx/bin/目录及其子目录下的dll文件全部复制到你要使用的JDK版本%JAVA_HOME%/jre/bin/目录下

  1. 添加环境变量

注: 看变量值那个路径中有没有 proj.db 这个文件,如果没有说明GDAL不完整,需要重新下载或编绎

  1. 设置好环境变量后重启电脑

3.3 创建数据库连接实体类

import lombok.Data;

import java.io.Serializable;

@Data
public class DBconn implements Serializable {

    /**
     * 数据库类型
     */
    private String dbtype;

    /**
     * ip
     */
    private String host;

    /**
     * 端口
     */
    private String port;

    /**
     * 模式
     */
    private String schema;

    /**
     * 数据库名
     */
    private String database;

    /**
     * 用户名
     */
    private String user;

    /**
     * 密码
     */
    private String passwd;

}

3.4 创建gis数据导入工具类 编写导入逻辑代码

  1. gdal注册及数据库配置
static {
        gdal.AllRegister();
        // 为了支持中文路径,请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文,请添加下面这句
        gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8");
    }

	//默认的geom字段
    private static String GEOM_NAME = "geom";
    //用于geotools创建数据库连接对象
	private static Map DBMAP = new HashMap<String, Object>();

    private static void setDBMAP(DBconn dBconn){
        DBMAP.put("dbtype", dBconn.getDbtype());
        DBMAP.put("host", dBconn.getHost());
        DBMAP.put("port", dBconn.getPort());
        DBMAP.put("schema", dBconn.getSchema());
        DBMAP.put("database", dBconn.getDatabase());
        DBMAP.put("user", dBconn.getUser());
        DBMAP.put("passwd", dBconn.getPasswd());
    }
    
  1. 获取gdal 的 gdb数据源对象,读取gdb数据
/**
     * 根据文件路径获取gdb数据源对象
     *
     * @param filePath
     * @return
     */
    public static DataSource GetDataSourceByGdbFilePath(String filePath) {
        Driver driver = ogr.GetDriverByName("OpenFileGDB");
        DataSource dataSource = driver.Open(filePath, 0);
        return dataSource;
    }

注:gdal支持读取的数据源类型,参考 gdal 官网,如下:

  1. 创建字段
 //创建字段
    public static SimpleFeatureType creatSimpleFeatureType(Feature feature, String wkt, String tableName) {
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setName(tableName);
        try {
            builder.setCRS(CRS.parseWKT(wkt));
        } catch (FactoryException e) {
            e.printStackTrace();
        }
        //添加矢量数据类型
        GeometryJSON geometryJSON = new GeometryJSON();
        try {
            Geometry read = geometryJSON.read(feature.GetGeometryRef().ExportToJson());
            Class geomClass = Class.forName("org.locationtech.jts.geom." + read.getGeometryType());
            builder.add(GEOM_NAME, geomClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //添加属性
        for (int p = 0; p < feature.GetFieldCount(); p++) {
            FieldDefn fieldDefn = feature.GetFieldDefnRef(p);
            String name = fieldDefn.GetName().toLowerCase();
            int fieldType = fieldDefn.GetFieldType();
            String typeName = fieldDefn.GetFieldTypeName(fieldDefn.GetFieldType());
            Class<?> clazz;
            //根据GDAL的 FieldDefn 的类型,创建对应的 java数据类型
            switch (typeName) {
                case "String":
                    clazz = String.class;
                    break;
                case "Real":
                    clazz = Double.class;
                    break;
                default:
                    clazz = String.class;
                    break;
            }
            builder.add(name, clazz);
        }

        //build the type
        final SimpleFeatureType LOCATION = builder.buildFeatureType();
        return LOCATION;
    }
  1. 创建表
//创建表
public static DataStore createTable(SimpleFeatureType simpleFeatureType) {
    DataStore dataStore = null;
    try {
        dataStore = DataStoreFinder.getDataStore(DBMAP);
        System.out.println(simpleFeatureType.getTypeName() + "test");
        String[] typeNames = dataStore.getTypeNames();
        List<String> collect = Arrays.stream(typeNames).filter(item -> item.equals(simpleFeatureType.getTypeName())).collect(Collectors.toList());
        if (collect.isEmpty()) {
            dataStore.createSchema(simpleFeatureType);//创建表
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
	return dataStore;
}
  1. 添加要素
/**
* 将GDBFeature 添加到 geotools 集合中
*
* @param features
* @param feature
* @param featureBuilder
*/
private static void addFeature(List<SimpleFeature> features, Feature feature, SimpleFeatureBuilder featureBuilder) {
    //添加矢量数据
    GeometryJSON geometryJSON = new GeometryJSON();
    try {
        featureBuilder.add(geometryJSON.read(feature.GetGeometryRef().ExportToJson()));
    } catch (IOException e) {
        throw new RuntimeException(e);
    }

    for (int p = 0; p < feature.GetFieldCount(); p++) {
        String data = feature.GetFieldAsString(feature.GetFieldDefnRef(p).GetName());
        featureBuilder.add(data);

    }
    SimpleFeature f = featureBuilder.buildFeature(null);
    features.add(f);
}
  1. 导入
 /**
     * 将GDB数据导入到数据库中
     * @param gdbFilePath gdb路径
     * @param dBconn    数据库连接参数
     */
    public static void importGdbToDatabase(String gdbFilePath, DBconn dBconn) {
        setDBMAP(dBconn);
        //获取gdb数据源
        DataSource dataSource = GetDataSourceByGdbFilePath(gdbFilePath);
        for (int i = 0; i < dataSource.GetLayerCount(); i++) {
            Layer layer = dataSource.GetLayer(i);
            String wkt = layer.GetSpatialRef().ExportToWkt();//坐标系信息
            String tableName = layer.GetName();//获取表名称
            SimpleFeatureType simpleFeatureType = null;
            List<SimpleFeature> features = new ArrayList<>();
            DataStore dataStore = null;
            do {//获取图层下的要素
                Feature feature = layer.GetNextFeature();
                if (null == feature) {
                    break;
                }
                //创建表数据类型
                if (simpleFeatureType == null) {
                    simpleFeatureType = creatSimpleFeatureType(feature, wkt, tableName);
                    dataStore = createTable(simpleFeatureType);
                }
                SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(simpleFeatureType);
                //将Feature对象添加到集合中去
                addFeature(features, feature, featureBuilder);
            } while (true);

            Transaction t = new DefaultTransaction("add");
            //将组装的数据插入数据库中
            try {
                SimpleFeatureCollection simpleFeatureCollection = DataUtilities.collection(new ListFeatureCollection(simpleFeatureType, features));
                SimpleFeatureSource featureSource = dataStore.getFeatureSource(tableName);
                if (featureSource instanceof SimpleFeatureStore) {
                    System.out.println("SimpleFeatureStore");
                    SimpleFeatureStore featureStore = (SimpleFeatureStore) dataStore.getFeatureSource(tableName);
                    featureStore.setTransaction(t);
                    featureStore.addFeatures(simpleFeatureCollection);
                    t.commit();
                } else {
                    System.out.println("not SimpleFeatureStore");
                }
            } catch (IOException e) {
                e.printStackTrace();
                try {
                    t.rollback();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            } finally {
                try {
                    if (t != null) {
                        t.close();
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                dataStore.dispose();

            }
        }
    }
  1. 完整代码
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.geotools.data.*;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.simple.SimpleFeatureCollection;

import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.FactoryException;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

public class GisUtils {

    static {
        gdal.AllRegister();
        // 为了支持中文路径,请添加下面这句代码
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // 为了使属性表字段支持中文,请添加下面这句
        gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8");
    }

    //默认的geom字段
    private static String GEOM_NAME = "geom";

    //数据库连接参数
    private static Map DBMAP = new HashMap<String, Object>() ;

    private static void setDBMAP(DBconn dBconn) {
        DBMAP.put("dbtype", dBconn.getDbtype());
        DBMAP.put("host", dBconn.getHost());
        DBMAP.put("port", dBconn.getPort());
        DBMAP.put("schema", dBconn.getSchema());
        DBMAP.put("database", dBconn.getDatabase());
        DBMAP.put("user", dBconn.getUser());
        DBMAP.put("passwd", dBconn.getPasswd());
    }

    

    /**
     * 根据文件路径获取gdb数据源对象
     * @param filePath
     * @return
     */
    public static DataSource GetDataSourceByGdbFilePath(String filePath) {
        Driver driver = ogr.GetDriverByName("OpenFileGDB");
        DataSource dataSource = driver.Open(filePath, 0);
        return dataSource;
    }

    /**
     * 根据文件路径获取 Shapefile数据源对象
     * @param filePath
     * @return
     */
    public static DataSource GetDataSourceByShpFilePath(String filePath) {
        Driver driver = ogr.GetDriverByName("ESRI Shapefile");
        DataSource dataSource = driver.Open(filePath, 0);
        return dataSource;
    }

    /**
     * 将GDB数据导入到数据库中,只会导入GDB中的矢量数据,保留现存的空间坐标系信息
     * @param gdbFilePath gdb路径
     * @param dBconn    数据库连接参数
     */
    public static void importGdbToDatabase(String gdbFilePath, DBconn dBconn) {
        setDBMAP(dBconn);
        DataSource dataSource = GetDataSourceByGdbFilePath(gdbFilePath);
        for (int i = 0; i < dataSource.GetLayerCount(); i++) {
            Layer layer = dataSource.GetLayer(i);
            String wkt = layer.GetSpatialRef().ExportToWkt();//坐标系信息
            String tableName = layer.GetName();//获取表名称
            SimpleFeatureType simpleFeatureType = null;
            List<SimpleFeature> features = new ArrayList<>();
            DataStore dataStore = null;
            do {//获取图层下的要素
                Feature feature = layer.GetNextFeature();
                if (null == feature) {
                    break;
                }
                //创建表数据类型
                if (simpleFeatureType == null) {
                    simpleFeatureType = creatSimpleFeatureType(feature, wkt, tableName);
                    dataStore = createTable(simpleFeatureType);
                }
                SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(simpleFeatureType);
                //将Feature对象添加到集合中去
                addFeature(features, feature, featureBuilder);
            } while (true);

            Transaction t = new DefaultTransaction("add");
            //将组装的数据插入数据库中
            try {
                SimpleFeatureCollection simpleFeatureCollection = DataUtilities.collection(new ListFeatureCollection(simpleFeatureType, features));
                SimpleFeatureSource featureSource = dataStore.getFeatureSource(tableName);
                if (featureSource instanceof SimpleFeatureStore) {
                    System.out.println("SimpleFeatureStore");
                    SimpleFeatureStore featureStore = (SimpleFeatureStore) dataStore.getFeatureSource(tableName);
                    featureStore.setTransaction(t);
                    featureStore.addFeatures(simpleFeatureCollection);
                    t.commit();
                } else {
                    System.out.println("not SimpleFeatureStore");
                }
            } catch (IOException e) {
                e.printStackTrace();
                try {
                    t.rollback();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            } finally {
                try {
                    if (t != null) {
                        t.close();
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                dataStore.dispose();

            }
        }
    }

    
    public static void importShpToDatabase(String shpFilePath, DBconn dBconn) {
        setDBMAP(dBconn);
        DataSource dataSource = GetDataSourceByShpFilePath(shpFilePath);
        for (int i = 0; i < dataSource.GetLayerCount(); i++) {
            Layer layer = dataSource.GetLayer(i);
            String wkt = layer.GetSpatialRef().ExportToWkt();//坐标系信息
            String tableName = layer.GetName();//获取表名称
            SimpleFeatureType simpleFeatureType = null;
            List<SimpleFeature> features = new ArrayList<>();
            DataStore dataStore = null;
            do {//获取图层下的要素
                Feature feature = layer.GetNextFeature();
                if (null == feature) {
                    break;
                }
                //创建表数据类型
                if (simpleFeatureType == null) {
                    simpleFeatureType = creatSimpleFeatureType(feature, wkt, tableName);
                    dataStore = createTable(simpleFeatureType);
                }
                SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(simpleFeatureType);
                //将Feature对象添加到集合中去
                addFeature(features, feature, featureBuilder);
            } while (true);
            Transaction t = new DefaultTransaction("add");
            ;
            //将组装的数据插入数据库中
            try {
                SimpleFeatureCollection simpleFeatureCollection = DataUtilities.collection(new ListFeatureCollection(simpleFeatureType, features));
                SimpleFeatureSource featureSource = dataStore.getFeatureSource(tableName);
                if (featureSource instanceof SimpleFeatureStore) {
                    System.out.println("SimpleFeatureStore");
                    SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;

                    featureStore.setTransaction(t);
                    featureStore.addFeatures(simpleFeatureCollection);
                    t.commit();
                } else {
                    System.out.println("not SimpleFeatureStore");
                }
            } catch (IOException e) {
                e.printStackTrace();
                try {
                    t.rollback();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            } finally {
                try {
                    if (t != null) t.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                dataStore.dispose();
            }
        }
    }

    /**
     * 将GDBFeature 添加到 geotools 集合中
     *
     * @param features
     * @param feature
     * @param featureBuilder
     */
    private static void addFeature(List<SimpleFeature> features, Feature feature, SimpleFeatureBuilder featureBuilder) {
        //添加矢量数据
        GeometryJSON geometryJSON = new GeometryJSON();
        try {
            featureBuilder.add(geometryJSON.read(feature.GetGeometryRef().ExportToJson()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        for (int p = 0; p < feature.GetFieldCount(); p++) {
            String data = feature.GetFieldAsString(feature.GetFieldDefnRef(p).GetName());
            featureBuilder.add(data);

        }
        SimpleFeature f = featureBuilder.buildFeature(null);
        features.add(f);
    }

    //创建字段
    public static SimpleFeatureType creatSimpleFeatureType(Feature feature, String wkt, String tableName) {
        SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
        builder.setName(tableName);
        try {
            builder.setCRS(CRS.parseWKT(wkt));
        } catch (FactoryException e) {
            e.printStackTrace();
        }
        //添加矢量数据类型
        GeometryJSON geometryJSON = new GeometryJSON();
        try {
            Geometry read = geometryJSON.read(feature.GetGeometryRef().ExportToJson());
            Class geomClass = Class.forName("org.locationtech.jts.geom." + read.getGeometryType());
            builder.add(GEOM_NAME, geomClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //添加属性
        for (int p = 0; p < feature.GetFieldCount(); p++) {
            FieldDefn fieldDefn = feature.GetFieldDefnRef(p);
            String name = fieldDefn.GetName().toLowerCase();
            int fieldType = fieldDefn.GetFieldType();
            String typeName = fieldDefn.GetFieldTypeName(fieldDefn.GetFieldType());
            Class<?> clazz;
            switch (typeName) {
                case "String":
                    clazz = String.class;
                    break;
                case "Real":
                    clazz = Double.class;
                    break;
                default:
                    clazz = String.class;
                    break;
            }
            builder.add(name, clazz);
        }

        //build the type
        final SimpleFeatureType LOCATION = builder.buildFeatureType();
        return LOCATION;
    }

    //创建表
    public static DataStore createTable(SimpleFeatureType simpleFeatureType) {
        DataStore dataStore = null;
        try {
            dataStore = DataStoreFinder.getDataStore(DBMAP);
            System.out.println(simpleFeatureType.getTypeName() + "test");
            String[] typeNames = dataStore.getTypeNames();
            List<String> collect = Arrays.stream(typeNames).filter(item -> item.equals(simpleFeatureType.getTypeName())).collect(Collectors.toList());
            if (collect.isEmpty()) {
                dataStore.createSchema(simpleFeatureType);//创建表
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dataStore;
    }

}

3.5 测试gdb数据入库

import org.junit.Test;

	@Test
    public void gdalTest() throws IOException {
        DBconn dBconn=new DBconn();
        dBconn.setDbtype("postgis");
        dBconn.setHost("localhost");
        dBconn.setPort("5432");
        dBconn.setSchema("sde");
        dBconn.setDatabase("postgis_21_sample");
        dBconn.setUser("postgres");
        dBconn.setPasswd("Giseryin");
        GisUtils.importGdbToDatabase("E:\hygt\5-data\1-图形\test.gdb",dBconn);
    }

4.发布样式

4.1 使用QGIS生成样式并导出

  1. 添加图层

  1. 打开图层属性

  1. 选择按名称对要素分类

4.添加文字标注

  1. 导出样式

4.2 geoserver发布样式

  1. 添加样式

  1. 导入样式

  1. 验证保存

5. 发布geoserver服务

5.1 引入所需依赖,调用geoserver接口

<!-- 添加仓库地址 -->
<repositories>
  <repository>
    <id>GeoSolutions</id>
    <url>https://maven.geo-solutions.it/</url>
  </repository>
</repositories>
<!--添加依赖  -->
<dependency>
  <groupId>it.geosolutions</groupId>
  <artifactId>geoserver-manager</artifactId>
  <version>1.7.0</version>
</dependency>

5.2 创建Geoserver 连接实体类

@Data
    public class GeoserverConn implements Serializable {
        private static final long serialVersionUID = 7143188313880619178L;

        private String url;

        private String username;

        private String password;
    }

5.3 发布postgis数据源的图层

/**
* 发布 postgis 表到 geoserver
* @param conn geoserver连接参数
* @param dBconn 数据库连接参数
* @param tableName 表名
* @param workspace 工作空间
* @param store 存储名
* @param srs 坐标系,eg: “EPSG:4490”
* @throws MalformedURLException
*/
public static void publishPostgisData(GeoserverConn conn, DBconn dBconn,String tableName,String workspace,String store,String srs) throws MalformedURLException {
    //判断工作空间是否存在,不存在则创建
    URL u=new URL(conn.getUrl());
    GeoServerRESTManager manager=new GeoServerRESTManager(u,conn.getUsername(),conn.getPassword());
    GeoServerRESTPublisher publisher=manager.getPublisher();
    List<String> workspaces=manager.getReader().getWorkspaceNames();
    if(!workspaces.contains(workspace)){
        boolean createws = publisher.createWorkspace(workspace);
        System.out.println("create ws:"+createws);
    } else {
        System.out.println("workspace 已经存在了,ws:"+workspace);
    }
    //判断数据存储(datastore)是否已经存在,不存在则创建
    RESTDataStore restStore=manager.getReader().getDatastore(workspace,store);
    if(restStore == null){
        GSPostGISDatastoreEncoder encoder = new GSPostGISDatastoreEncoder(store);
        encoder.setHost(dBconn.getHost());
        encoder.setPort(Integer.parseInt(dBconn.getPort()));
        encoder.setUser(dBconn.getUser());
        encoder.setPassword(dBconn.getPasswd());
        encoder.setDatabase(dBconn.getDatabase());
        encoder.setSchema(dBconn.getSchema());
        encoder.setConnectionTimeout(500);
        encoder.setMaxConnections(20);
        encoder.setMinConnections(1);
        encoder.setExposePrimaryKeys(true);
        boolean createStore=manager.getStoreManager().create(workspace,encoder);
        System.out.println("create store:"+createStore);
    }else {
        System.out.println("数据存储已经存在了,store:"+store);
    }
    //判断图层是否已经存在,不存在则创建发布
    RESTLayer layer=manager.getReader().getLayer(workspace,tableName);
    if(layer==null){
        GSFeatureTypeEncoder pds = new GSFeatureTypeEncoder();
        pds.setTitle(tableName);
        pds.setName(tableName);
        pds.setSRS(srs);
        GSLayerEncoder layerEncoder = new GSLayerEncoder();
        //查询是否有图层同名的样式,有则设为图层的默认样式
        boolean existsStyle = manager.getStyleManager().existsStyle(tableName);
        if (existsStyle) {
            layerEncoder.setDefaultStyle(tableName);
            layerEncoder.addStyle(tableName);
        }
        boolean publish=manager.getPublisher().publishDBLayer(workspace,store,pds,layerEncoder);
        System.out.println("publish:"+publish);
    }else {
        System.out.println("表已经发布过了,table:"+tableName);
    }
}

5.4 发布图层组

/**
* 发布 图层组 到 geoserver
* @param conn
* @param layerNames
* @param groupName
* @throws MalformedURLException
*/
public static void publishLayerGroups(GeoserverConn conn,List<String>layerNames,String groupName) throws MalformedURLException {
    URL u = new URL(conn.getUrl());
    GeoServerRESTManager manager = new GeoServerRESTManager(u, conn.getUsername(), conn.getPassword());
    GeoServerRESTPublisher publisher=manager.getPublisher();
    RESTLayerGroup layerGroup = manager.getReader().getLayerGroup(groupName);
    if(layerGroup ==null){
        GSLayerGroupEncoder gsLayerGroupEncoder=new GSLayerGroupEncoder();
        //添加图层
        for (int i = layerNames.size() - 1; i >= 0; i--) {
            gsLayerGroupEncoder.addLayer(layerNames.get(i));
        }
        //发布服务
        boolean create = publisher.createLayerGroup(groupName, gsLayerGroupEncoder);
    }else{
        System.out.println("图层组已存在:"+groupName);
    }
}

6. gdb入库及图层组发布

6.1 GIS服务接口

public interface GisService {
    ResponseResult publishLayergroup() throws IOException;
}

6.2 接口实现类

@Service
public class GisServiceImpl implements GisService {
        @Override
        public ResponseResult publishLayergroup() throws IOException {
            //数据库连接参数
            DBconn dBconn=new DBconn();
            dBconn.setDbtype("postgis");
            dBconn.setHost("localhost");
            dBconn.setPort("5432");
            dBconn.setSchema("sde");
            dBconn.setDatabase("postgis_21_sample");
            dBconn.setUser("postgres");
            dBconn.setPasswd("Giseryin");
            //geoserver连接参数
            GeoserverConn gsConn=new GeoserverConn();
            gsConn.setUrl("http://localhost:8787/geoserver");
            gsConn.setUsername("admin");
            gsConn.setPassword("geoserver");
            //gdb路径
            GisUtils.importGdbToDatabase("E:\hygt\5-data\1-图形\test.gdb",dBconn);
            DataSource dataSource = GisUtils.GetDataSourceByGdbFilePath("E:\hygt\5-data\1-图形\test.gdb");
            //导入数据库的表名列表
            List<String> tableNames=new ArrayList<>();
            //geoserver图层名
            List<String>layerNames=new ArrayList<>();
            //geoserver 要发布的工作空间名
            String workspace="publish-test";
            //geoserver 要发布的存储名称
            String store="pgstore1";
            //geoserver 要发布的图层组名称
            String groupName= "group1";
            for (int i = 0; i < dataSource.GetLayerCount(); i++) {
                Layer layer = dataSource.GetLayer(i);
                //获得图层的空间参考
                SpatialReference spatialReference = layer.GetSpatialRef();
                //获得图层的epsg 数字编码
                String epsgCode = spatialReference.GetAttrValue("AUTHORITY", 1);
                String tableName = layer.GetName();//获取gbb图层名称
                tableNames.add(tableName);
                String gsLayerNamme=workspace+":"+tableName;
                layerNames.add(gsLayerNamme);
                String epsg="EPSG:"+epsgCode;
                //发布图层
                GeoServerUtils.publishPostgisData(gsConn,dBconn,tableName,workspace,store,epsg);
            }
            //发布图层组
            GeoServerUtils.publishLayerGroups(gsConn,layerNames,groupName);
            return ResponseResult.success();
        }
}

7. mybatis-plus处理Geometry字段类型

  1. pom.xml 引入postgis-jdbc依赖
<!--编(解)码postgresql写入(或读取)的Geometry-->
<dependency>
  <groupId>net.postgis</groupId>
  <artifactId>postgis-jdbc</artifactId>
  <version>2.5.0</version>
</dependency>
  1. 定义 mybatis的TypeHandler,实现jts的Geometry Java类型 转成能够被postgis-jdbc的Geometry JDBC类型
public abstract class AbstractGeometryTypeHandler<T extends Geometry> extends BaseTypeHandler<T> {

    /**
     * WKTReader非线程安全
     */
    private static final ThreadLocal<WKTReader> READER_POOL = ThreadLocal.withInitial(WKTReader::new);

    /**
     * WKTWriter非线程安全
     */
    private static final ThreadLocal<WKTWriter> WRITER_POOL = ThreadLocal.withInitial(WKTWriter::new);

    /**
     * 与数据库中几何列的空间坐标系保持一致,要不然写入会报错
     */
    private static final int SRID_IN_DB = 4546;

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        PGgeometry pGgeometry = new PGgeometry(WRITER_POOL.get().write(parameter));
        org.postgis.Geometry geometry = pGgeometry.getGeometry();
        geometry.setSrid(SRID_IN_DB);
        ps.setObject(i, pGgeometry);
    }

    @SneakyThrows
    @Override
    public T getNullableResult(ResultSet rs, String columnName) {
        String string = rs.getString(columnName);
        return getResult(string);
    }

    @SneakyThrows
    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) {
        String string = rs.getString(columnIndex);
        return getResult(string);
    }

    @SneakyThrows
    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) {
        String string = cs.getString(columnIndex);
        return getResult(string);
    }

    private T getResult(String string) throws SQLException {
        if(string == null){
            return null;
        }
        PGgeometry pGgeometry = new PGgeometry(string);
        String s = pGgeometry.toString();
        String target = String.format("SRID=%s;", SRID_IN_DB);
        String wkt = s.replace(target, "");
        try {
            return (T) READER_POOL.get().read(wkt);
        } catch (Exception e) {
            throw new RuntimeException("解析wkt失败:" + wkt, e);
        }
    }
}
public class GeometryTypeHandler extends AbstractGeometryTypeHandler<Geometry>{
}
  1. 实体类的几何类型,添加TableField注解,定义Java类型和JDBC类型的转换器
	@TableField(value = "geom",typeHandler = GeometryTypeHandler.class)
    private Geometry geom;
  1. mybatis-plus 的xml配置文件定义字段的类型转换器

  1. service实现层读取接收到的geojson转为 jts 的geometry类型直接保存
	@Override
    public ResponseResult test(Map<String, Object> geojson) throws IOException {

        System.out.println(geojson);
        Cunju cunju=new Cunju();


        GeometryJSON gJson=new GeometryJSON();
        String jsonString = JSONObject.toJSONString(geojson);
        StringReader reader=new StringReader(jsonString);
        Geometry geometry = gJson.read(reader);
        cunju.setFid(new BigInteger("1001"));
        cunju.setGeom(geometry);
        cunju.setObjectid(1200D);
        cunju.setShapeLeng(1200D);
        cunju.setName("test3");
        cunju.setShapeLe1(1200D);
        cunju.setShapeArea(1200D);


        cunjuMapper.insert(cunju);
        return ResponseResult.success(geojson);
    }