SpringBoot结合PostGIS在省级旅游口号管理中的应用实践

SpringBoot结合PostGIS在省级旅游口号管理中的应用实践

目录

前言

一、数据库存储设计

1、一些需要考虑的点

2、物理表设计及表结构

二、SpringBoot后端设计

1、模型层实现

2、业务层实现

3、控制层实现

三、前端界面及成果展示

1、前端界面实现

2、旅游口号列表界面

3、旅游口号新增、编辑

四、总结


前言

        随着信息技术的飞速发展,旅游业作为全球经济增长的重要引擎之一,正经历着前所未有的数字化转型。旅游口号作为吸引游客、传播地方文化的重要手段,其管理和检索的效率直接关系到旅游营销的成功与否。在大数据时代背景下,如何高效地存储、管理和检索海量的省级旅游口号数据,成为旅游信息化建设的关键问题之一。这是上篇博文介绍了省级旅游口号相似性评估的下一篇。

        本实践旨在探索SpringBoot与PostGIS在省级旅游口号管理中的应用,通过构建一个基于SpringBoot和PostGIS的省级旅游口号存储及检索系统,实现对旅游口号的高效存储、精准检索和便捷管理。在系统设计过程中,我们充分考虑了系统的可扩展性、数据的安全性和查询的高效性。通过SpringBoot的依赖注入和自动配置功能,简化了开发流程,提高了开发效率。同时,利用PostGIS的地理空间数据类型和查询功能,实现了对旅游口号地理位置信息的精确存储和快速检索。此外,系统还采用了RESTful API架构,方便与其他系统进行集成和数据交互。

        通过本实践,我们期望为旅游行业的信息化建设提供一个可借鉴的案例,同时也为SpringBoot和PostGIS在地理信息系统领域的应用提供一个参考。在后续章节中,我们将详细介绍系统的架构设计、关键技术实现以及测试结果分析,旨在为读者提供一个全面、实用的实践指南。在当今数字化时代,旅游行业的信息化建设正面临着前所未有的机遇和挑战。通过SpringBoot与PostGIS的结合,我们希望能够为省级旅游口号的管理提供一个高效、可靠的技术解决方案,助力旅游业的数字化转型和可持续发展。

一、数据库存储设计

        在进行省级宣传口号的信息管理时,需要有以下两个点的信息考虑。需要支持时间的连续性,比如在2025年,某省份提出了新的宣传口号,而在2025年之前使用的是旧的口号。在设计时需要考虑这种情况。本节将从以下两个方面来进行讲解,第一个方面时候梳理一下在实现过程中需要考虑的点。第二是给出一个实际的数据库表接口的设计和给出表结构设计的SQL脚本。

1、一些需要考虑的点

        在实际情况下,时间连续性是一个比较常见的需求。比如一些口号经过多次的变更,在实现上我们会分割成多个部分,比如2023年以前是一个口号,2024到2025年又是一个口号,而2025年又启用了一个新的口号。这都是需要考虑的点。在进行数据赋值时,我们可以假定-1表示没有明确的起始年份,而在未来的年份上,使用9999来进行设置。除此之外,我们还需要设置当前口号的使用状态,比如使用0表示无效,而1表示有效。这都是需要考虑进来的。同时为了方便查询,我们将省份code和省份名称都设计到数据库表中。

2、物理表设计及表结构

        省级旅游口号的表结构如下图:

        对应的这里给出示例的数据库脚本:

CREATE TABLE "public"."biz_tourism_slogans_info" ( "pk_id" int8 NOT NULL, "province_code" varchar(10) COLLATE "pg_catalog"."default" NOT NULL, "province_name" varchar(20) COLLATE "pg_catalog"."default" NOT NULL, "start_year" int2, "end_year" int2, "slogan" varchar(50) COLLATE "pg_catalog"."default", "activity_flag" int2, "create_by" varchar(64) COLLATE "pg_catalog"."default", "create_time" timestamp(6), "update_by" varchar(64) COLLATE "pg_catalog"."default", "update_time" timestamp(6), CONSTRAINT "pk_biz_tourism_slogans_info" PRIMARY KEY ("pk_id") ); COMMENT ON COLUMN "biz_tourism_slogans_info"."pk_id" IS '主键'; COMMENT ON COLUMN "biz_tourism_slogans_info"."province_code" IS '省份code'; COMMENT ON COLUMN "biz_tourism_slogans_info"."province_name" IS '省份名称'; COMMENT ON COLUMN "biz_tourism_slogans_info"."start_year" IS '开始年份,-1没有具体年份'; COMMENT ON COLUMN "biz_tourism_slogans_info"."end_year" IS '结束年份,9999表示'; COMMENT ON COLUMN "biz_tourism_slogans_info"."slogan" IS '口号'; COMMENT ON COLUMN "biz_tourism_slogans_info"."activity_flag" IS '生效标记,0 无效,1有效'; COMMENT ON COLUMN "biz_tourism_slogans_info"."create_by" IS '创建人'; COMMENT ON COLUMN "biz_tourism_slogans_info"."create_time" IS '创建时间'; COMMENT ON COLUMN "biz_tourism_slogans_info"."update_by" IS '更新人'; COMMENT ON COLUMN "biz_tourism_slogans_info"."update_time" IS '更新时间'; COMMENT ON TABLE "biz_tourism_slogans_info" IS '旅游口号信息表,用于存储旅游口号信息';

        实际情况下起始可以加一些数据库的索引用来进行查询加速。

二、SpringBoot后端设计

        以上完成了数据库的设计和物理表结构的建模之后,接下来我们就可以围绕宣传口号表来进行实现。下面按照传统的MVC三层架构来进行说明。

1、模型层实现

        首先来简单介绍一下模型层,这里包括数据库表对应的JavaBean和数据库操作对象,即Mapper接口类。这三个类的具体代码如下所示:

package com.yelang.project.extend.scenicspot.domain; import java.io.Serializable; import java.util.Date; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; /** * - 旅游口号信息表,用于存储旅游口号信息 * @author 夜郎king * */ @TableName(value = "biz_tourism_slogans_info") @NoArgsConstructor @AllArgsConstructor @Setter @Getter @ToString public class TourismSlogansInfo implements Serializable { private static final long serialVersionUID = 5255612972674800046L; @TableId(value = "pk_id") private Long pkId;// 主键 @TableField(value = "province_code") private String provinceCode;// 省份code @TableField(value = "province_name") private String provinceName;// 省份名称 @TableField(value = "start_year") private Integer startYear;// 开始年份,-1表示没有具体年份 @TableField(value = "end_year") private Integer endYear;// 结束年份,9999表示 private String slogan;// 口号 @TableField(value = "activity_flag") private Integer activityFlag;// 生效标记,0 无效,1有效 @TableField(value = "create_by") private String createBy;// 创建人 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @TableField(value = "create_time") private Date createTime;// 创建时间 @TableField(value = "update_by") private String updateBy;// 更新人 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @TableField(value = "update_time") private Date updateTime;// 更新时间 public TourismSlogansInfo(String provinceCode, String provinceName, Integer startYear, Integer endYear, String slogan, Integer activityFlag, String createBy, Date createTime, String updateBy, Date updateTime) { super(); this.provinceCode = provinceCode; this.provinceName = provinceName; this.startYear = startYear; this.endYear = endYear; this.slogan = slogan; this.activityFlag = activityFlag; this.createBy = createBy; this.createTime = createTime; this.updateBy = updateBy; this.updateTime = updateTime; } }

        在Mapper接口中,为了方便在业务层对口号进行唯一性校验,这里我们增加一个根据口号和省份code的重复性查询接口,方法如下:

package com.yelang.project.extend.scenicspot.mapper; import java.util.List; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.yelang.project.extend.scenicspot.domain.TourismSlogansInfo; import com.yelang.project.extend.scenicspot.domain.TourismSlogansInfoVO; public interface TourismSlogansInfoMapper extends BaseMapper<TourismSlogansInfo>{ static final String FIND_SLOGANS_BYPROVINCECODE_SQL="<script>" + "select * from biz_tourism_slogans_info where province_code = #{provinceCode} and slogan = #{slogan} limit 1 " + "</script>"; @Select(FIND_SLOGANS_BYPROVINCECODE_SQL) TourismSlogansInfo findSlogansByProvinceCode(@Param("provinceCode")String provinceCode,@Param("slogan") String slogans); }

2、业务层实现

        业务层的方法实现比较简单,常规的增加、修改、删除操作跟其他的类操作一致,这里给出业务层的接口定义:

package com.yelang.project.extend.scenicspot.service; import java.util.List; import com.baomidou.mybatisplus.extension.service.IService; import com.yelang.project.extend.scenicspot.domain.TourismSlogansInfo; import com.yelang.project.extend.scenicspot.domain.TourismSlogansInfoVO; public interface ITourismSlogansInfoService extends IService<TourismSlogansInfo>{ public List<TourismSlogansInfo> selectList(TourismSlogansInfo tourismSlogansInfo); public int insertEntity(TourismSlogansInfo tourismSlogansInfo); public int updateEntity(TourismSlogansInfo tourismSlogansInfo); /** * -校验省份code和口号是否唯一 * @param tourismSlogansInfo 省份口号信息 * @return 结果 */ public String checkSlogansProvinceName(TourismSlogansInfo tourismSlogansInfo); public int deleteByIds(String ids); List<TourismSlogansInfoVO> findProvinceTourismSlogans(); }

        在业务实现类中,对于省级宣传口号的唯一性判断实现逻辑如下:

@Override public String checkSlogansProvinceName(TourismSlogansInfo tourismSlogansInfo) { Long pkId = null == tourismSlogansInfo.getPkId() ? -1L : tourismSlogansInfo.getPkId(); TourismSlogansInfo dbSlogans = this.baseMapper.findSlogansByProvinceCode(tourismSlogansInfo.getProvinceCode(), tourismSlogansInfo.getSlogan()); if (com.yelang.common.utils.StringUtils.isNotNull(dbSlogans) && dbSlogans.getPkId().longValue() != pkId.longValue()) { return UserConstants.DEFAULT_COMMON_NOT_UNIQUE; } return UserConstants.DEFAULT_COMMON_UNIQUE; }

3、控制层实现

        控制层实现比较简单,这里不一一列举,需要说明的是,为了保证前后端都对省份口号进行重复校验,我们不仅在前端会调用ajax来进行宣传口号的唯一性确认,在新增和编辑的接口中也增加相应的验证逻辑,对数据进行控制。核心代码如下所示:

@RequiresPermissions("sspot:tourismslogans:add") @Log(title = "旅游口号管理", businessType = BusinessType.INSERT) @PostMapping("/add") @ResponseBody public AjaxResult addSave(TourismSlogansInfo tourismSlogansInfo){ if (UserConstants.DEFAULT_COMMON_NOT_UNIQUE.equals(tourismslogansService.checkSlogansProvinceName(tourismSlogansInfo))) { return error("新增旅游口号'" + tourismSlogansInfo.getSlogan() + "'失败,口号已存在"); } return toAjax(tourismslogansService.insertEntity(tourismSlogansInfo)); } /** * -校验旅游口号 */ @PostMapping("/checkSlogansUnique") @ResponseBody public String checkSlogansUnique(TourismSlogansInfo tourismSlogansInfo) { return tourismslogansService.checkSlogansProvinceName(tourismSlogansInfo); } @RequiresPermissions("sspot:tourismslogans:edit") @Log(title = "旅游口号管理", businessType = BusinessType.UPDATE) @PostMapping("/edit") @ResponseBody public AjaxResult editSave(TourismSlogansInfo tourismSlogansInfo){ if (UserConstants.DEFAULT_COMMON_NOT_UNIQUE.equals(tourismslogansService.checkSlogansProvinceName(tourismSlogansInfo))) { return error("修改旅游口号'" + tourismSlogansInfo.getSlogan() + "'失败,口号已存在"); } return toAjax(tourismslogansService.updateEntity(tourismSlogansInfo)); }

        经过以上的代码就实现饿了SpringBoot的后台程序实现,接下来对前端界面的布局和要素设置进行简单介绍。

三、前端界面及成果展示

        本节将重点讲解前端页面的实现以及对列表界面和新增、编辑页面的成果示意介绍。

1、前端界面实现

        系统前端界面使用原生html页面来展示,整体框架采用Thymeleaf模板技术进行渲染。与其他的信息新增或者编辑窗口不一样的是,旅游口号信息页面中需要对省份的旅游口号进行重复性检测,并且在页面中会有省份的信息选择,因此有两个地方需要注意的,一个是下拉框的设置,第二个是需要调用后台的ajax进行校验。下拉框的设置代码如下:

<div> <label>省份信息:</label> <div> <input type="hidden" name="provinceName" /> <select name="provinceCode"> <option th:each="province : ${provinceList}" th:text="${province['name']}" th:value="${province['code']}"></option> </select> </div> </div>

        调用ajax请求进行验证的方法如下:

$("#form-tourismslogans-add").validate({ onkeyup: false, rules:{ slogan:{ remote: { url: prefix + "/checkSlogansUnique", type: "post", dataType: "json", data: { "slogan": function() { return $.common.trim($("#slogan").val()); }, "provinceCode": function() { return $("#provinceCode :selected").val(); } }, dataFilter: function(data, type) { return $.validate.unique(data); } } } }, messages: { "slogan": { remote: "旅游口号已经存在" } }, focusCleanup: true });

2、旅游口号列表界面

        下面来看一下完整的旅游口号列表管理界面,系统支持按照省份名称和口号信息来进行模糊查询。同时可以隐藏或者展示查询条件。

3、旅游口号新增、编辑

口号重复提示

四、总结

        以上就是本文的主要内容,本实践旨在探索SpringBoot与PostGIS在省级旅游口号管理中的应用,通过构建一个基于SpringBoot和PostGIS的省级旅游口号存储及检索系统,实现对旅游口号的高效存储、精准检索和便捷管理。通过本实践,期望为旅游行业的信息化建设提供一个可借鉴的案例,同时也为SpringBoot和PostGIS在地理信息系统领域的应用提供一个参考。博客详细介绍了如何进行数据库存储的设计,SpringBoot的后端实现以及面向Thyemeleaf的前端页面实现,最后提供了列表及新增、编辑页面示例。行文仓促,定有不足之处,欢迎各位朋友在评论区批评指正,不胜感激。

Read more

【Part 4 XR综合技术分享】第一节|技术上的抉择:三维实时渲染与VR全景视频的共生

【Part 4 XR综合技术分享】第一节|技术上的抉择:三维实时渲染与VR全景视频的共生

《VR 360°全景视频开发》专栏 将带你深入探索从全景视频制作到Unity眼镜端应用开发的全流程技术。专栏内容涵盖安卓原生VR播放器开发、Unity VR视频渲染与手势交互、360°全景视频制作与优化,以及高分辨率视频性能优化等实战技巧。 📝 希望通过这个专栏,帮助更多朋友进入VR 360°全景视频的世界! Part 4|XR综合技术分享 最后一Part了,我将分享一些关于当前常用的XR综合技术,内容涵盖三维实时渲染与全景视频的共生、多模态交互体验的融合,以及AI如何深度赋能XR应用,推动智能化发展。同时畅想通向全感知XR智能沉浸时代的未来,探索如何通过更先进的技术不断提升用户体验。毕竟,360°全景视频仅是XR应用中的冰山一角。 第一节|技术上的抉择:三维实时渲染与VR全景视频的共生 文章目录 * 《VR 360°全景视频开发》专栏 * Part 4|XR综合技术分享 * 第一节|技术上的抉择:三维实时渲染与VR全景视频的共生 * 1、VR内容形态的分化与融合 * 1.1 三维实时渲染的发展 * 1.2

By Ne0inhk

Neo4j图数据库整合MGeo:构建智能地理知识网络

Neo4j图数据库整合MGeo:构建智能地理知识网络 在城市计算、物流调度、位置服务等场景中,海量地址数据的标准化与实体对齐是构建高质量地理信息系统的前提。然而,中文地址存在表述多样、缩写习惯差异、层级结构不统一等问题,导致传统字符串匹配方法难以实现高精度的地址相似度识别。近年来,随着深度语义模型的发展,基于语义理解的地址匹配技术逐渐成为主流。阿里开源的 MGeo 模型正是这一方向的重要突破——它专为中文地址设计,能够精准捕捉“北京市朝阳区建国门外大街1号”与“北京朝阳建外1号”之间的语义一致性。 与此同时,如何将这些高置信度的地址匹配结果组织成可查询、可推理的知识体系,成为系统化应用的关键。本文提出一种创新方案:将 MGeo 生成的地址相似度匹配结果导入 Neo4j 图数据库,构建一个具备空间语义推理能力的智能地理知识网络。通过节点表示地址实体、边表示语义相似关系,我们不仅能实现高效去重与归一化,还能支持路径查询、社区发现、异常检测等高级分析功能。 MGeo 简介:面向中文地址的语义匹配引擎 核心能力与技术背景 MGeo(Map Geocoding Model)是由阿里巴

By Ne0inhk
[论文阅读] 代码也有社交圈?用意见动力学解码开源代码库的演化奥秘

[论文阅读] 代码也有社交圈?用意见动力学解码开源代码库的演化奥秘

代码也有社交圈?用意见动力学解码开源代码库的演化奥秘 论文信息 * 论文原标题:Social Life of Code: Modeling Evolution through Code Embedding and Opinion Dynamics * 主要作者:Yulong He, Nikita Verbina, Sergey Kovalchuk * 研究机构:Yulong He(圣彼得堡国立大学,俄罗斯);Nikita Verbina、Sergey Kovalchuk(ITMO大学,俄罗斯) * 发表信息:arXiv:2602.15412v1 [cs.SE],2026年2月17日 * APA引文格式:He, Y., Verbina, N., & Kovalchuk, S. (2026)

By Ne0inhk
Enterprise Architect 16 下载、安装与无限30天操作

Enterprise Architect 16 下载、安装与无限30天操作

文章目录 * Enterprise Architect 16 简介 * (一)支持多种建模语言和标准 * (二)强大的版本控制、协作和文档管理功能 * (三)增强的技术和用户体验 * (四)高级功能和扩展性 * 一,下载软件 * (一)官网 * (二)阿里云盘 * (三)百度网盘 * (四)迅雷 * 二,安装软件 * 三,无限30天设置 * (一)删除`fkey.dat`文件 * (二)删除注册表Kane文件夹 * (三)查看效果 Enterprise Architect 16 简介 Enterprise Architect 16是一款功能强大的企业级建模工具,它为企业和机构在系统设计、业务流程建模、数据建模以及软件开发等方面提供了全面的支持。以下是对Enterprise Architect 16的详细介绍:

By Ne0inhk