SpringBoot笔记:SpringBoot 集成 Dataway 多数据源配置(二)

文章目录

  • 前言
  • 核心代码和配置
    • yml 配置
    • 注入多数据源
    • 常用Spi实现
    • swagger 配置
    • 自定义 Udf
    • 指定数据源进行查询

前言

之前简单介绍了一下 Dataway 使用,本文继续介绍一下它的多数据源配置和使用。

核心代码和配置

yml 配置

# springboot多环境配置
#端口,项目上下文
server:
  port: 8080
  servlet:
    context-path: /springboot-dataway
    # 全局服务编码设置
    encoding:
      charset: utf-8
      enabled: true
      force: true


# mysql 连接信息配置
spring:
  # mysql 数据库连接信息,本地使用 mysql 服务版本为:8.0.28
  datasource:
    username: root
    password: 6tojyh*A3eQ6
    url: jdbc:mysql://localhost:3306/dataway?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    # druid 数据连接池配置
    druid:
      initial-size: 3
      min-idle: 3
      max-active: 10
      max-wait: 6000
      # 配置druid监控页
      aop-patterns: com.demo.* #监控springBean
      stat-view-servlet: # 配置监控页功能
        enabled: true # 默认开启,这里显示说明
        login-username: admin # 登录名
        login-password: 6tojyh*A3eQ6 # 登录密码
        reset-enable: false # 禁用重置按钮
      web-stat-filter: # 监控 web
        enabled: true
        url-pattern: /* # 监控所有
        exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'  #放行
      filter:
        stat: # 对上面 filters 里的 stat 的详细配置
          slow-sql-millis: 1000 # 慢 sql 时间是毫秒单位的,执行时间 1 秒以上的为慢 SQL
          log-slow-sql: true # 日志记录
          enabled: true
        wall:
          enabled: true
          config:
            drop-table-allow: false # 禁用删除表的 sql
        # 除主数据源外,第1个数据源
    db1:
      username: root
      password: 6tojyh*A3eQ6
      url: jdbc:mysql://localhost:3306/console?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
      driver-class-name: com.mysql.cj.jdbc.Driver
    # 除主数据源外,第 2 个数据源
    db2:
      username: postgres
      password: UFWOd75qD7
      url: jdbc:postgresql://localhost:32770/postgres?binaryTransfer=false&forceBinary=false&reWriteBatchedInserts=true
      driver-class-name: org.postgresql.Driver

# mdataway 配置
# 是否启用 Dataway 功能(必选:默认false)
HASOR_DATAQL_DATAWAY: true
# 开启 ui 管理功能(注意生产环境必须要设置为 false,否则会造成严重的生产安全事故)
HASOR_DATAQL_DATAWAY_ADMIN: true
# dataway  API工作路径(可选,默认:/api/)
HASOR_DATAQL_DATAWAY_API_URL: /api/
# dataway-ui 的工作路径(可选,默认:/interface-ui/)
HASOR_DATAQL_DATAWAY_UI_URL: /interface-ui/
# SQL执行器方言设置(可选,建议设置)
HASOR_DATAQL_FX_PAGE_DIALECT: mysql
# 登陆认证方式在 basic 模式下的时候,配置的登陆账号
HASOR_DATAQL_DATAWAY_AUTHORIZATION_USERNAME: admin
# 登陆认证方式在 basic 模式下的时候,配置的登陆密码,默认密码admin
HASOR_DATAQL_DATAWAY_AUTHORIZATION_PASSWORD: 6tojyh*A3eQ6

# 日志输出配置
logging:
  level:
    root: debug
    org:
      springframework:
        security: WARN
        web: ERROR
    # 设置自己的 com.demo.mapper 目录 输出sql日志
    com.demo.mapper: debug
  file:
    path: ./logs
    name: './logs/springboot-dataway.log'
  pattern:
    file: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n'
    console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n'

注入多数据源

package com.demo.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.demo.chain.*;
import net.hasor.core.ApiBinder;
import net.hasor.core.DimModule;
import net.hasor.core.TypeSupplier;
import net.hasor.dataql.Finder;
import net.hasor.dataql.QueryApiBinder;
import net.hasor.dataql.fx.db.FxSqlCheckChainSpi;
import net.hasor.dataway.spi.LoginPerformChainSpi;
import net.hasor.dataway.spi.LoginTokenChainSpi;
import net.hasor.dataway.spi.PreExecuteChainSpi;
import net.hasor.dataway.spi.ResultProcessChainSpi;
import net.hasor.db.JdbcModule;
import net.hasor.db.Level;
import net.hasor.spring.SpringModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;


/**
 * @Classname DatawayModule
 * @Description 将Hasor模块注入spring,并注入数据源
 * @Date 2023/7/28 11:43
 * @Created by Leo825
 */
@DimModule  // Hasor 中的标签,表明是一个Hasor的model
@Component  // Spring 中的标签,表明是一个组件
public class DatawayModule implements SpringModule,TypeSupplier {
    // 默认数据源
    @Autowired
    private DataSource dataSource;
    // 数据源1的配置信息
    @Value("${spring.datasource.db1.url}")
    private String jdbcUrl1;
    @Value("${spring.datasource.db1.driver-class-name}")
    private String driver1;
    @Value("${spring.datasource.db1.username}")
    private String username1;
    @Value("${spring.datasource.db1.password}")
    private String password1;

    // 数据源2的配置信息
    @Value("${spring.datasource.db2.url}")
    private String jdbcUrl2;
    @Value("${spring.datasource.db2.driver-class-name}")
    private String driver2;
    @Value("${spring.datasource.db2.username}")
    private String username2;
    @Value("${spring.datasource.db2.password}")
    private String password2;

    @Resource
    private ApplicationContext applicationContext;

    @Override
    public <T> T get(Class<? extends T> targetType) {
        return applicationContext.getBean(targetType);
    }

    @Override
    public <T> boolean test(Class<? extends T> targetType) {
        return applicationContext.getBeanNamesForType(targetType).length > 0;
    }

    @Override
    public void loadModule(ApiBinder apiBinder) throws Throwable {
        // .DataSource form Spring boot into Hasor
        apiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));
        // 注入数据源
        apiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));
        apiBinder.installModule(new JdbcModule(Level.Full, "dataSource1", getDataSource(jdbcUrl1, driver1, username1, password1)));
        apiBinder.installModule(new JdbcModule(Level.Full, "dataSource2", getDataSource(jdbcUrl2, driver2, username2, password2)));

        // 打印sql日志
        apiBinder.bindSpiListener(FxSqlCheckChainSpi.class, FxSqlCheckChain.getInstance());
        // 数据权限参数
        apiBinder.bindSpiListener(PreExecuteChainSpi.class, PreExecuteChain.getInstance());
        // 返回结果
        apiBinder.bindSpiListener(ResultProcessChainSpi.class, ResultProcessChain.getInstance());
//        // 登录过滤
//        apiBinder.bindSpiListener(LoginPerformChainSpi.class, LoginPerformChain.getInstance());
        // 登录 token 过滤
//        apiBinder.bindSpiListener(LoginTokenChainSpi.class, LoginTokenChain.getInstance());

        // udf/udfSource/import 指令 的类型创建委托给 spring
        QueryApiBinder queryBinder = apiBinder.tryCast(QueryApiBinder.class);
        queryBinder.bindFinder(Finder.TYPE_SUPPLIER.apply(this));
    }


    /**
     * 注入数据源
     *
     * @param
     * @param driver
     * @param username
     * @param password
     * @return
     */
    private DruidDataSource getDataSource(String jdbcUrl, String driver, String username, String password) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driver);
        // 用来检测连接是否有效
        dataSource.setValidationQuery("SELECT 1");
        // 借用连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
        dataSource.setTestOnBorrow(false);
        // 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
        dataSource.setTestOnReturn(false);
        // 连接空闲时检测,如果连接空闲时间大于timeBetweenEvictionRunsMillis指定的毫秒,
        // 执行validationQuery指定的SQL来检测连接是否有效
        // 如果检测失败,则连接将被从池中去除
        dataSource.setTestWhileIdle(true);
        dataSource.setTimeBetweenEvictionRunsMillis(60000);//1分钟
        dataSource.setMaxActive(20);
        dataSource.setInitialSize(5);
        return dataSource;
    }
}


常用Spi实现

FxSqlCheckChainSpi,这里主要用来打印 sql

package com.demo.chain;

import lombok.extern.slf4j.Slf4j;
import net.hasor.dataql.fx.db.FxSqlCheckChainSpi;
import net.hasor.utils.StringUtils;

/**
 * @Classname FxSqlCheckChain
 * @Description 打印sql
 * @Date 2023/8/3 20:35
 * @Created by Leo825
 */
@Slf4j
public class FxSqlCheckChain implements FxSqlCheckChainSpi {

    public static FxSqlCheckChain getInstance() {
        return new FxSqlCheckChain();
    }

    @Override
    public int doCheck(FxSqlInfo fxSqlInfo) throws Throwable {
        String sourceName = fxSqlInfo.getSourceName();
        if (StringUtils.isNotEmpty(sourceName)) {
            log.info("【dataway】dataSource ==>:{}", sourceName);
        }
        log.info("【dataway】sql ==>:{}", fxSqlInfo.getQueryString().trim());
        log.info("【dataway】params ==>: {}", fxSqlInfo.getQueryParams());
        // 如果存在后续,那么继续执行检查,否则使用 EXIT 常量控制退出后续的检查。
        return FxSqlCheckChainSpi.NEXT;
    }
}

PreExecuteChainSpi,这里主要是在接口执行前进行一些权限参数控制

package com.demo.chain;

import lombok.extern.slf4j.Slf4j;
import net.hasor.dataway.spi.ApiInfo;
import net.hasor.dataway.spi.PreExecuteChainSpi;
import net.hasor.utils.future.BasicFuture;
import org.apache.commons.collections4.MapUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @Classname PreExecuteChain
 * @Description 接口执行前
 * @Date 2023/8/3 20:37
 * @Created by Leo825
 */
@Slf4j
public class PreExecuteChain implements PreExecuteChainSpi {

    public static PreExecuteChain getInstance() {
        return new PreExecuteChain();
    }

    /**
     * sql 直接前
     * @param apiInfo
     * @param basicFuture
     */
    @Override
    public void preExecute(ApiInfo apiInfo, BasicFuture<Object> basicFuture) {
        Map<String, Object> parameter = apiInfo.getParameterMap();

        // 注入用户权限参数
        parameter.putAll(MapUtils.emptyIfNull(loginUserAuthParams()));
    }


    /**
     * 获取登录用户权限参数
     * @return
     */
    private Map<String, Object> loginUserAuthParams () {
        Map<String, Object> authParams = new HashMap<>();
        // todo 注入登录用户 权限参数
        return authParams;
    }
}

ResultProcessChainSpi,主要是返回值进行一些封装

package com.demo.chain;
import com.demo.common.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import net.hasor.dataway.spi.ApiInfo;
import net.hasor.dataway.spi.ResultProcessChainSpi;
/**
 * @Classname ReturnProcessChain
 * @Description 兼
 * 容 4.1.5之前 dataway版本 dataway 执行结果处理, 让 structure 配置仅使用于   dataway页面调试使用
 * @Date 2023/8/3 20:47
 * @Created by Leo825
 */
@Slf4j
public class ResultProcessChain implements ResultProcessChainSpi {

    public static ResultProcessChain getInstance() {
        return new ResultProcessChain();
    }


    /**
     * 对返回结果进行处理
     * @param formPre
     * @param apiInfo
     * @param result
     * @return
     */
    @Override
    public Object callAfter(boolean formPre, ApiInfo apiInfo, Object result) {
        // apiInfo.isPerform() 为 true 表示,API 调用是从 UI 界面发起的。
        if (apiInfo.isPerform() || apiInfo.getParameterMap().containsKey("SELF_CALL")) {
            return result;
        }
        apiInfo.getOptionMap().put("resultStructure", false);
        return AjaxResult.success(result);
    }

    /**
     * 异常
     * @param formPre
     * @param apiInfo
     * @param e
     * @return
     */
    @Override
    public Object callError(boolean formPre, ApiInfo apiInfo, Throwable e) {
        if (apiInfo.isPerform()) {
            return ResultProcessChainSpi.super.callError(formPre, apiInfo, e);
        }
        apiInfo.getOptionMap().put("resultStructure", false);
        return AjaxResult.error( "系统繁忙");
    }
}

swagger 配置

package com.demo.config;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import java.util.ArrayList;
import java.util.List;

/**
 * swagger配置
 */
@Component
@Primary
public class SwaggerProvider implements SwaggerResourcesProvider {
    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        resources.add(swaggerResource("应用接口", "/v2/api-docs", "1.0"));
        resources.add(swaggerResource("Dataway接口", "/interface-ui/api/docs/swagger2.json", "1.0"));
        return resources;
    }

    private SwaggerResource swaggerResource(String name, String location, String version) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion(version);
        return swaggerResource;
    }
}

将 Dataway 里面的接口发布到 swagger里面

package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * swagger配置
 */
@EnableSwagger2
@Configuration()
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)//
                .apiInfo(apiInfo())//
                .select()//
                .apis(RequestHandlerSelectors.basePackage("com.demo"))//
                .paths(PathSelectors.any())//
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()//
                .title("Spring Boot中使用Swagger2构建RESTful APIs")//
                .description("参考手册:https://www.hasor.net/doc/display/dataql/")//
                .termsOfServiceUrl("https://www.hasor.net/doc/display/dataql/")//
                .contact("zyc@hasor.net").version("1.0")//
                .build();
    }
}

自定义 Udf

可以使用自定义udf,并且在管理页面可以直接访问

package com.demo.udf;

import com.demo.config.SpringContextUtil;
import com.demo.service.MyUdfService;
import lombok.extern.slf4j.Slf4j;
import net.hasor.dataql.DimUdf;
import net.hasor.dataql.Hints;
import net.hasor.dataql.Udf;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 自定义 udf,需要在 DatawayModule 添加以下配置代码,否则会出现注入为 null 问题
 * // udf/udfSource/import 指令 的类型创建委托给 spring
 * QueryApiBinder queryBinder = apiBinder.tryCast(QueryApiBinder.class);
 * queryBinder.bindFinder(Finder.TYPE_SUPPLIER.apply(this));
 */
@Slf4j
@DimUdf("myNameUdf")
@Service
public class MyNameUdf implements Udf {

    @Resource
    private MyUdfService myUdfService;

    @Override
    public Object call(Hints readOnly, Object... params) {
        log.info("获取当前服务信息: " + myUdfService.myName());
        return "张三";
    }
}

web管理页面调用方式如下:

import 'com.demo.udf.MyNameUdf' as myNameUdf;
return myNameUdf();

示意图1

据官方文档说可以通过 import ‘bean’ 方式引入,但是尝试了没有成功。

指定数据源进行查询

主要通过 FRAGMENT_SQL_DATA_SOURCE 来指定数据源:

// springboot 整合Dataway 多数据源配置。使用示例:
hint FRAGMENT_SQL_DATA_SOURCE = "dataSource2";
var query = @@sql()<%
    select * from subjects
%>
return query()

测试2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/68461.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

企业服务器器中了360后缀勒索病毒怎么解决,勒索病毒解密数据恢复

随着网络威胁的增加&#xff0c;企业服务器成为黑客攻击的目标之一。近期&#xff0c;上海某知名律师事务所的数据库遭到了360后缀的勒索病毒攻击&#xff0c;导致企业服务器内的数据库被360后缀勒索病毒加密。许多重要的数据被锁定无法正常读取&#xff0c;严重影响了企业的正…

【Mybatis】调试查看执行的 SQL 语句

1. 问题场景&#xff1a; 记录日常开发过程中 Mybatis 调试 SQL 语句&#xff0c;想要查看Mybatis 中执行的 SQL语句&#xff0c;导致定位问题困难 2. 解决方式 双击shift找到mybatis源码中的 MappedStatement的getBoundSql()方法 public BoundSql getBoundSql(Object para…

Stable Diffusion - 人物坐姿 (Sitting) 的提示词组合 与 LoRA 和 Embeddings 配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132201960 拍摄人物坐姿时&#xff0c;需要注意&#xff1a; 选择一个舒适和自然的坐姿&#xff0c;符合个性和心情。可以坐在椅子、沙发、长凳、…

手机app测试

一、安装、卸载、更新、运行 1.安装、卸载 应用是否可以正常安装&#xff08;命令行安装&#xff1b;apk&#xff0f;ipa安装包安装&#xff09;&#xff08;有网&#xff0c;无网是否都正常&#xff09;卸载过程中出现死机&#xff0c;断电&#xff0c;重启等意外的情况&…

Wisej.NET Crack,Wisej.NET的核心功能

Wisej.NET Crack&#xff0c;Wisej.NET的核心功能 Wisej.NET是一个跨平台的web框架&#xff0c;用于使用.NET和C#/VB.NET而不是HTML和JavaScript构建现代HTML5应用程序。它包含创建任务关键型web应用程序所需的一切&#xff0c;包括UI组件、会话处理、状态管理和后端集成。借助…

仿到位|独立版家政上门预约服务小程序家政保洁师傅上门服务小程序上门服务在线派单源码

上门预约服务派单小程序家政 小程序 同城预约 开源代码 独立版. 程序完整,经过安装检测,可放心下载安装。 适合本地的一款上门预约服务小程序,功能丰富,适用多种场景。 程序功能:城市管理/小程序DIY/服务订单/师傅管理/会员卡功能/营销功能/文章功能等等

vmwera中安装的centos8出现ifconfig不可用

刚刚在虚拟机中装好centos结果发现自己的ifconfig命令不可用。 看一下环境变量里有没有ifconfig命令的路径&#xff0c;因为ifconfig是在/sbin路径下的&#xff0c;root用户登录进去才可以运行&#xff0c;先看一下root用户的环境变量。 root用户的环境变量里是有/sbin路径的&a…

javaScript:分支语句的理解与使用(附带案例)

目录 前言 补充 另一种说法 分支语句 1.if语句 a.单分支语句 注意 b.双分支语句 注意点 c.多分支语句&#xff08;分支语句的联级语句&#xff09; 补充 2.三元运算符 三元运算符 &#xff1f; &#xff1a; 使用场景 3.switch语句 解释 释义&#xff1a…

将本地项目上传至gitee的详细步骤

将本地项目上传至gitee的详细步骤 1.在gitee上创建以自己项目名称命名的空项目2.进入想上传的项目的文件夹&#xff0c;然后右键点击3. 初始化本地环境&#xff0c;把该项目变成可被git管理的仓库4.添加该项目下的所有文件5.使用如下命令将文件添加到仓库中去6.将本地代码库与远…

最小生成树—Kruskal算法

什么是最小生成树&#xff1f; 首先&#xff0c;最小生成树一定数无向图&#xff0c;并且在不影响所有点都连通的情况下&#xff0c;所有边的权重加起来最小值是多少。 比如说&#xff1a;无向图abcp如下图所示&#xff0c;每条边权重也标记出来了。最小生成树就如右侧所示。 …

ModaHub魔搭社区——Milvus Cloud向量数据库

向量数据库:在AI时代的快速发展与应用 摘要: 随着人工智能技术的不断进步,向量数据库在处理大规模数据方面发挥着越来越重要的作用。本文介绍了向量数据库的基本概念、应用场景和技术挑战,并详细阐述了Milvus Cloud作为典型的向量数据库产品的技术特点、性能优化和应用案例…

yolov5的报错

【定期水一期】 &#xff08;这个问题很抓马&#xff0c;可以看一下这篇文章&#xff1a;Git Bash 教程&#xff01;【不是所有人都会用Git】&#xff09; 一&#xff1a;没有cv2这个模块 解决方案&#xff1a; pip install opencv-python -i http://pypi.douban.com/simple/…

内网穿透实战应用-配置固定的远程桌面地址【内网穿透、无需公网IP】

配置固定的远程桌面地址【内网穿透、无需公网IP】 文章目录 配置固定的远程桌面地址【内网穿透、无需公网IP】第一步&#xff1a;保留TCP地址第二步&#xff1a;为远程桌面隧道配置固定的TCP地址第三步&#xff1a;使用固定TCP地址远程桌面 使用免费的cpolar生成的远程桌面公网…

【计算机组成原理】24王道考研笔记——第三章 存储系统

第三章 存储系统 一、存储系统概述 现代计算机的结构&#xff1a; 1.存储器的层次结构 2.存储器的分类 按层次&#xff1a; 按介质&#xff1a; 按存储方式&#xff1a; 按信息的可更改性&#xff1a; 按信息的可保存性&#xff1a; 3.存储器的性能指标 二、主存储器 1.基本…

STM32 F103C8T6学习笔记3:串口配置—串口收发—自定义Printf函数

今日学习使用STM32 C8T6的串口&#xff0c;我们在经过学习笔记2的总结归纳可知&#xff0c;STM32 C8T6最小系统板上有三路串口&#xff0c;如下图&#xff1a; 今日我们就着手学习如何配置开通这些串口进行收发&#xff0c;这里不讲串口通信概念与基础&#xff0c;可以自行网上…

连续两年增收不增利,比亚迪电子靠新能源汽车业务再次起飞?

在净利润连续两年下挫之后&#xff0c;比亚迪电子&#xff08;00285.HK&#xff09;终于迎来了好消息。 不久前比亚迪电子发布2023年中期盈利预告显示&#xff0c;上半年净利润同比增加115%-146%&#xff08;2022年上半年的净利润显示6.34亿元&#xff09;。 这主要受益于大客…

vue+springboot基于web的火车高铁铁路订票管理系统

铁路订票管理系统按照权限的类型进行划分&#xff0c;分为用户和管理员两个模块。管理员模块主要针对整个系统的管理进行设计&#xff0c;提高了管理的效率和标准。主要功能包括个人中心、用户管理、火车类型管理、火车信息管理、车票预订管理、车票退票管理、系统管理等&#…

【Rust】Rust学习 第八章常见集合

Rust 标准库中包含一系列被称为 集合&#xff08;collections&#xff09;的非常有用的数据结构。大部分其他数据类型都代表一个特定的值&#xff0c;不过集合可以包含多个值。不同于内建的数组和元组类型&#xff0c;这些集合指向的数据是储存在堆上的&#xff0c;这意味着数据…

Spring Initailizr--快速入门--SpringBoot的选择

&#x1f600;前言 本篇博文是关于IDEA使用Spring Initializer快速创建Spring Boot项目的说明&#xff0c;希望能够帮助到您&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可…

AES加密(1):AES基础知识和计算过程

从产品代码的安全角度考虑&#xff0c;我们需要对代码、数据进行加密。加密的算法有很多种&#xff0c;基于速度考虑&#xff0c;我们一般使用对称加密算法&#xff0c;其中有一种常见的对称加密算法&#xff1a;AES(Advanced Encryption Standard)。在一些高端的MCU&#xff0…