0


基于SpringBoot的商业航班执飞飞机机型信息管理

前言

    在之前的信息中,我们对商业飞行航班信息进行了追踪,同时对所有的执飞飞机的各种机型进行了梳理。通过梳理不同的航班信息,不仅可以构建出飞行航班的商业版图,可以看到不同的航空公司的航班使用的具体机型是什么?对于全球的航空布局构建有数据支撑的基础。在之前的博客当中,我们只通过获取一天某时刻的正在飞行的航班的飞机数据进行了采集。通过这种采集方式,其实是有漏洞的。如果当前采集的航班使用的飞机是大多数的,少采集一班或者两班,对于最终的飞机机型影响不大,对于构建全球的执飞航班飞机种类收集也影响不大。但是对于一些航班,尤其是每天只有少数的航班而言,如果刚好在系统采集的周期里没有航班,从而导致采集程序漏掉了这种机型。

    因此为了防止这种情况出现,我们打算采用长时序的数据抓取来实现。即通过至少连续一个月甚至3个月或6个月来定期采集,同时将考虑到中国内地和其他地区的时间差,由此导致的白天黑夜对飞行的影响,我们会每天定时早晚来进行采集,这样就能极大的避免由于时间和日期对飞行航班的影响,从而导致飞行机型的漏采的情况。

    本文主要讲解如何使用SpringBoot开发一套商业航班执飞飞机机型的管理系统。首先讲解数据库的设计,如何存储飞机的机型信息,以及每天的固定频率的数据采集;然后讲解如何在程序采集的时候进行数据去重,如何将不同的飞机机型信息进行消歧等操作,最后通过一个Web管理功能来实现其信息的管理,为后续的知识应用和商业飞行知识构建提供坚实的基础。

一、数据库模型的设计与实现

    由于飞机的机型是比较有限的,数据量的规模也是比较小的。因此在进行数据存储的选型时,我们选择关系统数据库,这样子的话。使用起来比较方便。这里主要分两个方面开展,第一个方面是讲解如何进行表结构的设计,第二是讲解如何进行数据的去重和消歧处理。

1、表结构设计

    在之前的博文中,我们只介绍了如何爬取某一天的数据。由于每天的航班安排都是不一样的,尤其是一些非热门的航班,可能一周只有1到2次。因此我们需要依赖持久化的关系型数据库来进行数据的重复。比如根据飞机的code进行过滤,根据每天爬取的飞机机型数据,通过code来识别,如果code已经存在,则无需重复插入。在飞行航班管理中,相关的数据库表有两张,下面直接提供数据库的模型及sql脚本。

      相关表物理结构脚本如下:biz_aircraft_type主要使用来存储飞机机型种类信息表。
CREATE TABLE "public"."biz_aircraft_type" (
  "pk_id" int8 NOT NULL,
  "code" varchar(6) COLLATE "pg_catalog"."default" NOT NULL,
  "cn_name" varchar(50) COLLATE "pg_catalog"."default",
  "en_name" varchar(50) COLLATE "pg_catalog"."default",
  "cn_feature_name" varchar(50) COLLATE "pg_catalog"."default",
  "en_feature_name" varchar(50) COLLATE "pg_catalog"."default",
  "remark" varchar(255) COLLATE "pg_catalog"."default",
  CONSTRAINT "pk_biz_aircraft_type" PRIMARY KEY ("pk_id")
);
COMMENT ON COLUMN "public"."biz_aircraft_type"."code" IS '编码,如A320';
COMMENT ON COLUMN "public"."biz_aircraft_type"."cn_name" IS '中文名,如空中客车 A320';
COMMENT ON COLUMN "public"."biz_aircraft_type"."en_name" IS '英文名,如:Airbus A320';
COMMENT ON COLUMN "public"."biz_aircraft_type"."cn_feature_name" IS '中文机型特点,如双发活塞式';
COMMENT ON COLUMN "public"."biz_aircraft_type"."en_feature_name" IS '英文机型特点';
COMMENT ON COLUMN "public"."biz_aircraft_type"."remark" IS '备注';
COMMENT ON TABLE "public"."biz_aircraft_type" IS '飞机机型种类信息表';
    单日航班采集信息表,biz_aircraft_number_of_daily主要用来存储每天获取的数据。
CREATE TABLE "public"."biz_aircraft_number_of_daily" (
  "pk_id" int8 NOT NULL,
  "code" varchar(6) COLLATE "pg_catalog"."default" NOT NULL,
  "flights_number" int4 NOT NULL,
  "collection_time" timestamp(6),
  CONSTRAINT "pk_biz_aircraft_number_of_dail" PRIMARY KEY ("pk_id")
);
COMMENT ON COLUMN "public"."biz_aircraft_number_of_daily"."pk_id" IS 'pk_id';
COMMENT ON COLUMN "public"."biz_aircraft_number_of_daily"."code" IS '编码';
COMMENT ON COLUMN "public"."biz_aircraft_number_of_daily"."flights_number" IS '航班数';
COMMENT ON COLUMN "public"."biz_aircraft_number_of_daily"."collection_time" IS '采集时间';
COMMENT ON TABLE "public"."biz_aircraft_number_of_daily" IS '飞行单日航班数据表';

2、数据去重和消歧

    在上面的把数据库表结构进行重点介绍之后,下面主要针对两个小知识点来进行讲解,结合数据库物理结构来讲解。首先来讲解去重,在第一节中已经讲解了去重的简单方式,即查询是否有重复的code,有重复的数据则不进行入库。
select count(1) from biz_aircraft_type where code = 'KIS4';
    再结合业务层代码来讲解:
@Override
public void deduplication(List<AircraftType> dataList) {
    List<AircraftType> saveList = new ArrayList<AircraftType>();
    for (AircraftType data : dataList) {
        Long size = this.getSizeByCode(data.getCode());
        if(size >= 1) {
            continue;//记录数大于1,表示数据中有记录
        }
        saveList.add(data);
    }
    if(saveList.size() > 0) {
        this.saveBatch(saveList, 300);
    }
}
    通过上面的方式已经实现重复的消除。但是有一些例如,777和波音777飞机,其实是一种飞机机型。这种情况下,不能一概而论,如何正确的找到重复的数据,同时进行准确的消歧,我们在后续的相关章节中再进行讲解。这里可以给出一些思路,可以通过求两个字符串的相似度,比如各种距离。也可以计算余弦相似度,也可以计算向量。

二、后台应用程序设计

    本节重点介绍后台的应用程序设计方案。

1、实体类设计

    实体类的设计包括数据库类、mappep查询类。代码比较简单,不做过多的介绍:
package com.yelang.project.transportation.flight.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 lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
 * * 飞行单日航班数据表
 * @author 夜郎king
 */
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@TableName(value ="biz_aircraft_number_of_daily")
public class AircraftNumberOfDaily implements Serializable{
    private static final long serialVersionUID = 1289275813330753153L;
    @TableId(value = "pk_id")
    private Long pkId;//主键
    private String code;//编码
    @TableField(value = "flights_number")
    private Integer flightsNumber;//航班数
    @TableField(value = "collection_time")
    private Date collectionTime;//采集时间
}
package com.yelang.project.transportation.flight.domain;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
 * * 飞机机型种类信息表
 * @author 夜郎king
 *
 */
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@TableName(value ="biz_aircraft_type")
public class AircraftType implements Serializable{
    private static final long serialVersionUID = 8439614590527608025L;
    @TableId(value = "pk_id")
    private Long pkId;//主键
    private String code;//编码
    @TableField(value = "cn_name")
    private String cnName;//中文名,如空中客车 A320
    @TableField(value = "en_name")
    private String enName;//英文名,如:Airbus A320
    @TableField(value = "cn_feature_name")
    private String cnFeatureName;//中文机型特点,如双发活塞式
    @TableField(value = "en_feature_name")
    private String enFeatureName;//英文机型特点
    private String remark;//备注
}

2、业务层及控制层设计与实现

    业务层的方法比较简单,这里不进行过多的介绍。业务层主要提供的是针对飞机机型的增删改查的方法,同时也包括了上述的去重逻辑的实现,业务层为控制层提供业务能力的支撑。
package com.yelang.project.transportation.flight.service.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yelang.common.utils.text.Convert;
import com.yelang.project.transportation.flight.domain.AircraftType;
import com.yelang.project.transportation.flight.mapper.AircraftTypeMapper;
import com.yelang.project.transportation.flight.service.IAircraftTypeService;

@Service
public class AircraftTypeServiceImpl extends ServiceImpl<AircraftTypeMapper, AircraftType> implements IAircraftTypeService{
    @Override
    public Long getSizeByCode(String code) {
        QueryWrapper<AircraftType> wrapper = new QueryWrapper<AircraftType>();
        wrapper.eq("code", code);
        return this.baseMapper.selectCount(wrapper);
    }
    @Override
    public void deduplication(List<AircraftType> dataList) {
        xxx
    }
    @Override
    public AircraftType selecById(Long id) {
        return this.baseMapper.selectById(id);
    }
    @Override
    public List<AircraftType> selectList(AircraftType aircraftType) {
        QueryWrapper<AircraftType> queryWrapper = new QueryWrapper<AircraftType>();
        if(StringUtils.isNotBlank(aircraftType.getCode())){
            queryWrapper.like("code", aircraftType.getCode());
        }
        if(StringUtils.isNotBlank(aircraftType.getEnName())){
            queryWrapper.like("en_name", aircraftType.getEnName());
        }
        if(StringUtils.isNotBlank(aircraftType.getCnName())){
            queryWrapper.like("cn_name", aircraftType.getCnName());
        }
        queryWrapper.orderByAsc("code");
        return this.getBaseMapper().selectList(queryWrapper);
    }
    @Override
    @Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
    public int insertAircraftType(AircraftType aircraftType) {
        return this.baseMapper.insert(aircraftType);
    }
    @Override
    @Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
    public int updateAircraftType(AircraftType aircraftType) {
        return this.baseMapper.updateById(aircraftType);
    }
    @Override
    @Transactional(propagation=Propagation.REQUIRED,rollbackFor=Exception.class)
    public int deleteAircraftTypeByIds(String ids) {
        List<Long> removeList = Arrays.asList(Convert.toLongArray(ids));
        return this.removeByIds(removeList) ? 1 : 0;
    }
}
    控制层的代码为显示层提供支持,主要提供页面的跳转、数据的展示与控制。
package com.yelang.project.transportation.flight.controller;

import java.util.List;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.yelang.common.utils.poi.ExcelUtil;
import com.yelang.framework.aspectj.lang.annotation.Log;
import com.yelang.framework.aspectj.lang.enums.BusinessType;
import com.yelang.framework.web.controller.BaseController;
import com.yelang.framework.web.domain.AjaxResult;
import com.yelang.framework.web.page.TableDataInfo;
import com.yelang.project.transportation.flight.domain.AircraftType;
import com.yelang.project.transportation.flight.service.IAircraftTypeService;

/**
 *    交通运输管理之飞机类型管理Controller
 * @author 夜郎king
 * @date 2024-07-26
 */
@Controller
@RequestMapping("/trans/flight/aircrafttype")
public class AircraftTypeController extends BaseController{
    private Logger logger = LoggerFactory.getLogger(AircraftTypeController.class);
    private String prefix = "trans/flight/aircrafttype";
    @Autowired
    private IAircraftTypeService aircraftTypeService;

    @RequiresPermissions("trans:flight:aircrafttype:view")
    @GetMapping()
    public String index(){
        return prefix + "/index";
    }

    /**
     *     查询飞机机型列表
     */
    @RequiresPermissions("trans:flight:aircrafttype:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(AircraftType aircraftType){
        logger.debug("这是debugg日志");
        startPage();
        List<AircraftType> list = aircraftTypeService.selectList(aircraftType);
        return getDataTable(list);
    }

    /**
     *     新增飞机机型
     */
    @GetMapping("/add")
    public String add(){
        return prefix + "/add";
    }

    @RequiresPermissions("trans:flight:aircrafttype:add")
    @Log(title = "飞机机型管理", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(AircraftType aircraftType){
        return toAjax(aircraftTypeService.insertAircraftType(aircraftType));
    }

    /**
     *     修改飞机机型信息
     */
    @RequiresPermissions("trans:flight:aircrafttype:edit")
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") Long id, ModelMap mmap){
        AircraftType aircraftType = aircraftTypeService.selecById(id);
        mmap.put("aircraftType", aircraftType);
        return prefix + "/edit";
    }

    /**
     *     修改保存飞机机型信息
     */
    @RequiresPermissions("trans:flight:aircrafttype:edit")
    @Log(title = "飞机机型信息管理", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(AircraftType aircraftType){
        return toAjax(aircraftTypeService.updateAircraftType(aircraftType));
    }
}

3、视图层的实现

    视图层采用thymeleaf来实现,没有采用vue等前端框架,对传统技术栈的程序员技术友好。当然,您有兴趣改造成新的前端框架也是可以的。传统的技术架构简单,不做过多的赘述,这里仅提供主要列表页面的展示,如果有对其他页面的代码感兴趣的,可以私聊联系。
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <th:block th:include="include :: header('飞机机型信息管理')" />
</head>
<body class="gray-bg">
     <div class="container-div">
        <div class="row">
            <div class="col-sm-12 search-collapse">
                <form id="formId">
                    <div class="select-list">
                        <ul>
                            <li>
                                <label>代码:</label>
                                <input type="text" name="code"/>
                            </li>
                            <li>
                                <label>英文名:</label>
                                <input type="text" name="enName"/>
                            </li>
                            <li>
                                <label>中文名:</label>
                                <input type="text" name="cnName"/>
                            </li>
                            <li>
                                <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
                                <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
                            </li>
                        </ul>
                    </div>
                </form>
            </div>

            <div class="btn-group-sm" id="toolbar" role="group">
                <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="trans:flight:aircrafttype:add">
                    <i class="fa fa-plus"></i> 添加
                </a>
                <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="trans:flight:aircrafttype:edit">
                    <i class="fa fa-edit"></i> 修改
                </a>
                <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="trans:flight:aircrafttype:remove">
                    <i class="fa fa-remove"></i> 删除
                </a>
                <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="trans:flight:aircrafttype:export">
                    <i class="fa fa-download"></i> 导出
                </a>
            </div>
            <div class="col-sm-12 select-table table-striped">
                <table id="bootstrap-table"></table>
            </div>
        </div>
    </div>
    <th:block th:include="include :: footer" />
    <script th:inline="javascript">
        var editFlag = [[${@permission.hasPermi('trans:flight:aircrafttype:edit')}]];
        var removeFlag = [[${@permission.hasPermi('trans:flight:aircrafttype:remove')}]];
        var prefix = ctx + "/trans/flight/aircrafttype";

        $(function() {
            var options = {
                url: prefix + "/list",
                createUrl: prefix + "/add",
                updateUrl: prefix + "/edit/{id}",
                removeUrl: prefix + "/remove",
                exportUrl: prefix + "/export",
                modalName: "飞机机型信息",
                columns: [{
                    checkbox: true
                },
                {
                    field: 'pkId',
                    title: '',
                    visible: false
                },
                {
                    field: 'code',
                    title: '编码'
                },
                {
                    field: 'enName',
                    title: '英文名'
                },
                {
                    field: 'cnName',
                    title: '中文名'
                },
                {
                    field: 'cnFeatureName',
                    title: '中文机型特点'
                },
                {
                    field: 'enFeatureName',
                    title: '英文机型特点'
                },
                {
                    title: '操作',
                    align: 'center',
                    formatter: function(value, row, index) {
                        var actions = [];
                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.pkId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.pkId + '\')"><i class="fa fa-remove"></i>删除</a>');
                        return actions.join('');
                    }
                }]
            };
            $.table.init(options);
        });
    </script>
</body>
</html>
    到此,我们完全实现了数据库物理模型的设计、后台模型层、业务层、控制层、视图层的设计与实现。 下面一节将对实现的效果做一个简单介绍。

三、系统成果展示

    本节将对系统成果及相关功能模块进行一个简单介绍,方便大家理解相关功能。

1、飞机机型管理列表

    飞机机型管理列表支持对飞机机型进行查询,查询条件支持按照飞机编码、中文名、英文名进行模糊查询。查询界面如下所示:

    为了方便于后续的领域知识的发现和挖掘,我们同时搜集了飞机机型编码,英文名和中文名,以及中文的机型特点和英文的机型特点。 在列表中除了信息的展示,还集成了编辑、删除等管理功能。

2、机型信息编辑

    刚开始从网上采集的飞机机型信息中,只有飞机的编码、英文名的信息,其它的信息是没有的。因此需要我们从互联网上采集后进行补齐。我们可以在百科中查询相关信息,然后利用机型的编辑功能进行信息补全。在上面的列表界面中,点击“编辑”按钮打开编辑页面,在打开的界面中输入待修改的信息。

    输入完毕后,点击确定即可完成当前机型的信息录入功能。

四、总结

    以上就是本文的主要内容,本文主要讲解如何使用SpringBoot开发一套商业航班执飞飞机机型的管理系统。首先讲解数据库的设计,如何存储飞机的机型信息,以及每天的固定频率的数据采集;然后讲解如何在程序采集的时候进行数据去重,如何将不同的飞机机型信息进行消歧等操作,最后通过一个Web管理功能来实现其信息的管理,为后续的知识应用和商业飞行知识构建提供坚实的基础。行文仓促,定有不足之处,欢迎各位专家朋友在评论区留言指正交流,不胜感激。

本文转载自: https://blog.csdn.net/yelangkingwuzuhu/article/details/140742512
版权归原作者 夜郎king 所有, 如有侵权,请联系我们删除。

“基于SpringBoot的商业航班执飞飞机机型信息管理”的评论:

还没有评论