Spring Boot集成ShardingSphere实现数据加密及数据脱敏 | Spring Cloud 48

news2024/11/25 0:53:49

一、前言

通过以下系列章节:

Spring Boot集成ShardingSphere实现数据分片(一) | Spring Cloud 40

Spring Boot集成ShardingSphere实现数据分片(二) | Spring Cloud 41

Spring Boot集成ShardingSphere实现数据分片(三) | Spring Cloud 42

Spring Boot集成ShardingSphere实现读写分离 | Spring Cloud 43

Spring Boot集成ShardingSphere实现按月数据分片及创建自定义分片算法 | Spring Cloud 44

Spring Boot集成ShardingSphere分片利器 AutoTable (一)—— 简单体验 | Spring Cloud 45

Spring Boot集成ShardingSphere分片利器 AutoTable (二)—— 自动分片算法示例 | Spring Cloud 46

ShardingSphere 5.3 系列Spring 配置升级指南 | Spring Cloud 47

ShardingSphere的数据分片、各分片算法应用、读写分离、最新版本升级等情况有了详细的了解,今天我们继续对其:数据加密数据脱敏功能进行演示学习。

本章节中会应用以上系列章节的部分成功

二、背景

2.1 数据加密

安全控制一直是治理的重要环节,数据加密属于安全控制的范畴。 无论对互联网公司还是传统行业来说,数据安全一直是极为重视和敏感的话题。 数据加密是指对某些敏感信息通过加密规则进行数据的变形,实现敏感隐私数据的可靠保护。 涉及客户安全数据或者一些商业性敏感数据,如身份证号、手机号、卡号、客户号等个人信息按照相关部门规定,都需要进行数据加密。

对于数据加密的需求,在现实的业务场景中一般分为两种情况:

  • 新业务上线,安全部门规定需将涉及用户敏感信息,例如银行、手机号码等进行加密后存储到数据库,在使用的时候再进行解密处理。因为是全新系统,因而没有存量数据清洗问题,所以实现相对简单。

  • 已上线业务,之前一直将明文存储在数据库中。相关部门突然需要对已上线业务进行加密整改。这种场景一般需要处理 3 个问题:

    • 历史数据需要如何进行加密处理,即洗数。
    • 如何能在不改动业务 SQL 和逻辑情况下,将新增数据进行加密处理,并存储到数据库;在使用时,再进行解密取出。
    • 如何较为安全、无缝、透明化地实现业务系统在明文与密文数据间的迁移。

2.2 数据脱敏

随着《网络安全法》的颁布施行,对个人隐私数据的保护已经上升到法律层面。传统的应用系统普遍缺少对个人隐私数据的保护措施。数据脱敏,可实现在不需要对生产数据库中的数据进行任何改变的情况下,依据用户定义的脱敏规则,对生产数据库返回的数据进行专门的加密、遮盖和替换,确保生产环境的敏感数据能够得到保护。

三、使用示例

示例采用springboot集成shardingsphere-jdbc方式搭建。

3.1 项目总体结构

在这里插入图片描述

3.2 Maven依赖

shading-sphere/shading-encrypt-mask-5.3/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>shading-sphere</artifactId>
        <groupId>com.gm</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shading-encrypt-mask-5.3</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core</artifactId>
            <version>5.3.2</version>
        </dependency>

        <!-- 解决Mybatis中LocalDateTime和SQL中datetime的交互 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-typehandlers-jsr310</artifactId>
            <version>1.0.2</version>
        </dependency>

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

        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
            <version>1.33</version>
        </dependency>
    </dependencies>

</project>
  • shardingsphere-jdbc-core使用最新的5.3.2版本

  • JDBCORM 框架选用mybatis-plus

3.3 配置文件

src/main/resources/application.yml:

server:
  port: 8844

spring:
  application:
    name: @artifactId@
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    url: jdbc:shardingsphere:classpath:shading-auto-tables-encrypt-mask.yaml
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

src/main/resources/shading-auto-tables-encrypt-mask.yaml

dataSources:
  ds1:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://192.168.0.35:3306/db1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
    username: root
    password: '1qaz@WSX'
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1

  ds2:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    jdbcUrl: jdbc:mysql://192.168.0.46:3306/db2?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai
    username: root
    password: '1qaz@WSX'
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
rules:
  - !SHARDING
    autoTables:
      # 取模
      t_auto_user_info_mod:
        actualDataSources: ds$->{1..2}
        shardingStrategy:
          standard:
            shardingColumn: user_id
            shardingAlgorithmName: auto_user_info_mod
        # 分布式序列策略
        keyGenerateStrategy:
          # 自增列名称,缺省表示不使用自增主键生成器
          column: user_id
          # 分布式序列算法名称
          keyGeneratorName: snowflake
    # 分片算法配置
    shardingAlgorithms:
      # 取模
      auto_user_info_mod:
        type: MOD
        props:
          sharding-count: 2
    # 分布式序列算法配置(如果是自动生成的,在插入数据的sql中就不要传id,null也不行,直接插入字段中就不要有主键的字段)
    keyGenerators:
      # 分布式序列算法名称
      snowflake:
        # 分布式序列算法类型
        type: SNOWFLAKE
  - !MASK
    tables:
      t_auto_user_info_mod:
        columns:
          password:
            maskAlgorithm: md5_mask
          email:
            maskAlgorithm: mask_before_special_chars_mask
          telephone:
            maskAlgorithm: keep_first_n_last_m_mask
    maskAlgorithms:
      md5_mask:
        type: MD5
      mask_before_special_chars_mask:
        type: MASK_BEFORE_SPECIAL_CHARS
        props:
          special-chars: '@'
          replace-char: '*'
      keep_first_n_last_m_mask:
        type: KEEP_FIRST_N_LAST_M
        props:
          first-n: 3
          last-m: 4
          replace-char: '*'

  - !ENCRYPT
    tables:
      t_auto_user_info_mod:
        columns:
          password: # 加密列名称
            cipherColumn: password # 密文列名称
            encryptorName: password_encryptor # 密文列加密算法名称
            assistedQueryColumn: assisted_query_password # 查询辅助列名称
            assistedQueryEncryptorName: assisted_encryptor # 查询辅助列加密算法名称
          id_card:
            plainColumn: id_card_plain # 原文列名称(ShardingSphere自动创建列)
            cipherColumn: id_card # 密文列名称
            encryptorName: aes_encryptor # 密文列加密算法名称
            assistedQueryColumn: assisted_query_id_card  # 查询辅助列名称(ShardingSphere自动创建列,使用时: ..and id_card = '123...' and ..)
            assistedQueryEncryptorName: assisted_encryptor # 查询辅助列加密算法名称
            likeQueryColumn: like_query_id_card # 模糊查询列名称(ShardingSphere自动创建列,使用时: .. and id_card like '%123%' and ..)
            likeQueryEncryptorName: like_encryptor # 模糊查询列加密算法名称
    encryptors:
      aes_encryptor:
        type: AES
        props:
          aes-key-value: 123456abc
      assisted_encryptor:
        type: AES
        props:
          aes-key-value: 123456abc
      password_encryptor:
        type: MD5
      like_encryptor:
        type: CHAR_DIGEST_LIKE

props:
  sql-show: true

配置简要说明:

逻辑表 t_auto_user_info_mod按照user_id分片键使用MOD自动分片算法进行分片,
其中数据脱敏对:

  • password采用基于 MD5 的数据脱敏算法
  • email采用特殊字符前遮盖数据脱敏算法
  • telephone采用保留前 nm 数据脱敏算法

其中数据加密对:.

  • id_card开启原文列、查询辅助列、模糊查询列,以上这些列在基于shardingsphere-jdbc-core建表时会自动创建,在操作逻辑表的id_card列时shardingsphere-jdbc-core自动对其余列进行数据维护。
  • password开启查询辅助列,此列在基于shardingsphere-jdbc-core建表时会自动创建,在操作逻辑表的password列时shardingsphere-jdbc-core自动对其余列进行数据维护。

ShardingSphere更多数据脱敏配置,请见官网:
https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/yaml-config/rules/mask/

ShardingSphere内置提供了多种数据脱敏算法,请见官网:
https://shardingsphere.apache.org/document/current/cn/dev-manual/mask/

ShardingSphere更多数据加密配置,请见官网:
https://shardingsphere.apache.org/document/5.3.0/cn/user-manual/shardingsphere-jdbc/java-api/rules/encrypt/

ShardingSphere内置提供了多种数据加密算法,请见官网:
https://shardingsphere.apache.org/document/current/cn/dev-manual/encrypt/

3.4 实体类

com/gm/shading/encrypt/mask/entity/AutoUserInfoMod.java

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("t_auto_user_info_mod")
public class AutoUserInfoMod {

    @TableId(type = IdType.ASSIGN_ID)
    private Long userId;
    // 身份证,存储加密
    private String idCard;
    // 密码,存储加密
    private String password;
    // 电话,数据脱敏
    private String telephone;
    // 电子邮箱,数据脱敏
    private String email;
}

3.5 Mapper

com/gm/shading/encrypt/mask/mapper/AutoUserInfoModMapper.java

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.gm.shading.encrypt.mask.entity.AutoUserInfoMod;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface AutoUserInfoModMapper extends BaseMapper<AutoUserInfoMod> {
    void save(AutoUserInfoMod autoOrder);
}

src/main/resources/mapper/AutoUserInfoModMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.gm.shading.encrypt.mask.mapper.AutoUserInfoModMapper">
    <insert id="save" parameterType="com.gm.shading.encrypt.mask.entity.AutoUserInfoMod">
        insert into t_auto_user_info_mod (id_card,password,telephone,email)
        values (#{idCard}, #{password}, #{telephone}, #{email})
    </insert>
</mapper>

3.6 启动类

com/gm/shading/encrypt/mask/ShadingEncryptMaskApplication.java

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.gm.shading.encrypt.mask.mapper")
public class ShadingEncryptMaskApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShadingEncryptMaskApplication.class, args);
    }
}

3.7 单元测试

src/test/java/com/gm/shading/encrypt/mask/ShadingEncryptMaskApplicationTests.java

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gm.shading.encrypt.mask.entity.AutoUserInfoMod;
import com.gm.shading.encrypt.mask.mapper.AutoUserInfoModMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@SpringBootTest
@Slf4j
public class ShadingEncryptMaskApplicationTests {

    @Autowired
    AutoUserInfoModMapper autoUserInfoModMapper;

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Test
    public void testCreateAutUserInfoMod() {
        jdbcTemplate.execute("CREATE TABLE `t_auto_user_info_mod` (\n" +
                " `user_id` bigint(20) NOT NULL COMMENT '用户id',\n" +
                " `id_card` varchar(50) NOT NULL COMMENT '身份证',\n" +
                " `password` varchar(50) NOT NULL COMMENT '用户密码',\n" +
                " `telephone` varchar(50) NOT NULL COMMENT '电话',\n" +
                " `email` varchar(50) NOT NULL COMMENT '邮箱',\n" +
                " PRIMARY KEY (`user_id`) USING BTREE\n" +
                ") ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;");
    }
    
    @Test
    public void testInsertAutoUserInfoMod() {

        List<String> idCards = Arrays.asList("34122119920825123", "42122319870601123", "32072319750626123",
                "34120219900429123", "15222319970119123", "32038219891112123", "32072319950606123", "32038219900219123", "37132419880902123");
        for (int i = 1; i < 6; i++) {
            AutoUserInfoMod userInfo = new AutoUserInfoMod();
            userInfo.setIdCard(idCards.get(i) + i);
            userInfo.setPassword("abcdefg1234567" + 1);
            userInfo.setTelephone("18645026410");
            userInfo.setEmail("1025304567@qq.com");
            autoUserInfoModMapper.save(userInfo);
        }
    }
    
    @Test
    public void testSelectAutoUserInfoModAll() {
        List<AutoUserInfoMod> list = autoUserInfoModMapper.selectList(new QueryWrapper<AutoUserInfoMod>());
        for (AutoUserInfoMod userInfo : list) {
            log.info("{}", userInfo);
        }
    }

    @Test
    public void testSelectAutoUserInfoModByIdCard() {

        List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from t_auto_user_info_mod where id_card='320723197506261232'");
        for (Map<String, Object> map : list) {
            log.info("{}", map);
        }

        list = jdbcTemplate.queryForList("select * from t_auto_user_info_mod where id_card like '%3412%'");
        for (Map<String, Object> map : list) {
            log.info("{}", map);
        }
    }
}

  • 执行testCreateAutUserInfoMod方法根据自动配置的分片规则进行建表

查看逻辑表的真实表结构:

在这里插入图片描述

此次会发现配置文件中定义原文列、查询辅助列、模糊查询列会自动完成创建

  • 执行testInsertAutoUserInfoMod方法完成数据插入,数据加密规则生效

在这里插入图片描述

  • 执行testSelectAutoUserInfoModAll方法完成数据查询,数据脱敏规则生效

在这里插入图片描述

  • 执行testSelectAutoUserInfoModByIdCard方法完成数据查询,数据加密查询辅助列、模糊查询列规则生效

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++实现AVL树和红黑树(插入部分)

文章目录 前言1.AVL树的相关介绍2.AVL树的旋转1.失衡状态2.旋转调整 3.代码实AVL树1.节点的插入2.插入部分的验证 4.红黑树的相关介绍5.红黑树的插入调整1.处理方式2.代码实现 6.红黑树的检查7.总结 前言 之前介绍了二叉搜索树&#xff0c;本文主要是对AVL树和红黑树进行介绍。…

中国人民大学与加拿大女王大学金融硕士任晋红:热血中年

任晋红 中国人民大学-加拿大女王大学金融硕士 2021-2022级行业高管班 丰汇租赁有限公司 租赁事业部总经理 2021年9月初的一个傍晚&#xff0c;日暮四合&#xff0c;风轻轻亲了一下叶子&#xff0c;晚霞看见了&#xff0c;悄悄红了脸。线下上课时&#xff0c;窗外的晚霞是最美…

如何使用ADAudit Plus增强你的网络安全措施

网络安全是当今社会中至关重要的话题&#xff0c;因为互联网在我们生活中扮演着越来越重要的角色&#xff0c;人们对网络的依赖程度也越来越高。在这种情况下&#xff0c;网络内部安全威胁也变得越来越普遍。本文将介绍ADAudit Plus&#xff0c;它是一种用于检测和防范网络内部…

【RS专题】eval层混淆和逻辑完整分析 - 扣代码终结篇

如有侵权、联系本人下架 首先明确一下目标,我们要先获取网页200的源代码,RS5代第一次响应为412,第二次为200。如果是200就表示正常 以下为某 yjj RS5请求成功的结果,具体流程请看完文章,源-码–答-案也会在末 尾公 布 前面是定义了非常多和函数,一直往下拉,直到出现v…

游戏开发需要具备哪些技术

游戏开发需要具备哪些技术 大家好我是艾西&#xff0c;今天跟大家闲聊一下。开发一款游戏在没有参照物或是底板的情况下开发一款游戏都需要具备哪些技术&#xff0c;在开发过程中我们又会涉及到哪些板块或是领域。 一款游戏的开发需要一个总的游戏策划人&#xff0c;为游戏编写…

起重机安装拆除安全技术规范

为贯彻安全第一、预防为主、综合治理的方针&#xff0c;确保塔式起重机在安装、使用、拆卸时的安全&#xff0c;制定本规程。 本规程适用于房屋建筑工程、市政工程所用塔式起重机的安装、使用和拆卸。 本规程规定了塔式起重机的安装、使用和拆卸的基本技术要求。当本规程与国…

一些注意事项

1&#xff1a;Collection 子接口 1&#xff1a;List 鉴于 Java 中数组用来存储数据的局限性&#xff0c;我们通常使用 java.util.List 替代数组 List 集合类中元素有序、且可重复&#xff0c;集合中的每个元素都有其对应的顺序索引 1.1 List 接口主要实现类&#xff1a;Arra…

历经3个月,二战华为成功上岸,要个27k应该不过分吧~

先说下我基本情况&#xff0c;本科不是计算机专业&#xff0c;现在是学通信&#xff0c;然后做图像处理&#xff0c;可能面试官看我不是科班出身没有问太多计算机相关的问题&#xff0c;因为第一次找工作&#xff0c;华为的游戏专场又是最早开始的&#xff0c;就投递了&#xf…

嵌入式五大通信协议详解 (一) UART

嵌入式C语言学习进阶系列文章 GUN C编译器拓展语法学习笔记(一&#xff09;GNU C特殊语法部分详解 GUN C编译器拓展语法学习笔记(二&#xff09;属性声明 GUN C编译器拓展语法学习笔记(三&#xff09;内联函数、内建函数与可变参数宏 数组存储与指针学习笔记(一&#xff09;数…

Spring MVC 和 WebFlux 上传文件

WebFlux 上传文件 1. 表单上传方式1.1 Spring MVC1.2 Spring WebFlux 2. 二进制流2.1 Spring MVC2.2 Spring WebFlux 开发环境&#xff1a;jdk 11 WebFlux&#xff1a;jdk 8 1. 表单上传方式 1.1 Spring MVC multipart大小限制 spring:servlet:multipart:max-file-size: 512…

IS220PPRFH1B输电线路的先导继电器保护

​ IS220PPRFH1B输电线路的先导继电器保护 导引线差动继电器是专为保护配电线路和输电线路而设计的高速继电器&#xff0c;主要用于40公里以内的短线路。它是开关设备继电器中速度最快的功率继电器&#xff0c;该方案的工作需要通信通道&#xff0c;以便它可以将系统电压和电流…

2023.05.11-使用纯CPU来运行RWKV大语言模型

1. 简介 使用CPU来运行C版本的RWKV rwkv.cpp 可以将 RWKV 原始模型的参数转化为 float16&#xff0c;并量化到 int4&#xff0c;可以在 CPU 上更快地运行&#xff0c;也可以节省更多的内存。 2. 下载项目 ## git clone --recursive https://github.com/saharNooby/rwkv.cpp…

PostgreSQL11 | 视图

上一篇讲了索引&#xff0c;索引提高了表查询的速度&#xff0c;这一篇讲视图。 视图 视图&#xff0c;数据库中的一个虚拟表。 目录 视图 视图概述 前期准备 创建视图 单表视图 多表视图 查询视图 删除视图 视图概述 视图同真实表一样具有表的功能&#xff0c;但是…

spring事务失效的12种场景

前言 对于从事java开发工作的同学来说&#xff0c;spring的事务肯定再熟悉不过了。 在某些业务场景下&#xff0c;如果一个请求中&#xff0c;需要同时写入多张表的数据。为了保证操作的原子性&#xff08;要么同时成功&#xff0c;要么同时失败&#xff09;&#xff0c;避免…

H. Binary Craziness

题目链接 2023 Hubei Provincial Collegiate Programming Contest Examples input 6 6 1 3 2 3 1 4 2 5 3 6 4 6 output 30 input 6 4 1 2 3 5 2 4 3 6 output 0 题目大意&#xff1a; 给出结点个数 n n n和边的个数 m m m 下面依此给出 m m m个边&#xff0c;边是无向的&am…

Linux三种网络模式 | 仅主机、桥接、NAT

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Linux三种网络模式 仅主机模式&#xff1a;虚拟机只能访问物理机&#xff0c;不能上网 桥接模式&#xff1a;虚拟机和物理机连接同一网络&#xff0c;虚拟机和物理机…

字典核心底层原理

字典对象的核心是散列表。散列表是一个稀疏数组&#xff08;总是有空白元素的数组&#xff09;&#xff0c;数组的每个单元叫做bucket。每个bucket有两部分&#xff1a;一个是键对象的引用&#xff0c;一个是值对象的引用。 由于&#xff0c;所有bucket结构和大小一致&#xf…

服装厂的管理系统如何选?内行人:这4点一定要注意!

服装厂管理水平偏低&#xff0c;耗费大量时间和资金成本&#xff0c;导致利润越来越低&#xff0c;是现在很多中小服装厂普遍面临的痛点。 依靠传统的管理模式&#xff0c;口头询问生产进度&#xff0c;手写统计数量&#xff0c;很显然不适合现代工厂的管理模式&#xff0c;服装…

java开发记录V1

编辑器vscode 在vscode中安装配置springboot 下载安装jdk oracle jdk BellSoft Liberica JDK version 17 在vscode编辑器中安装相关组件Extension Pack for Java、Spring Boot Extension Pack、Spring Initializr Java Support 创建springboot项目&#xff1a;ctrlshiftp后…

【Midjourney】Midjourney 辅助工具 ① ( 自定义命令工具 | 设置描述词 | 设置风格 | 设置灯光 | 设置相机 | 设置艺术家 )

文章目录 一、Midjourney Prompt Tool 自定义命令工具1、设置描述词2、设置风格3、设置灯光4、设置相机参数5、设置艺术家参数 Midjourney 提示词命令 可以使用 辅助工具 进行生成 , 辅助工具如下 : Midjourney Prompt Tool 自定义命令工具Midjourney Prompt Generator 命令生…