分布式NoSQL列存储数据库Hbase Java API(四)

简介: 分布式NoSQL列存储数据库Hbase Java API(四)

分布式NoSQL列存储数据库Hbase(四)

知识点01:课程回顾

  1. Hbase Java API DML
  • DML实现规则
  • step1:构建连接,客户端连接服务端通用的机制
Configuration:用于管理配置,例如服务端地址【Hbase的JavaAPI服务端地址是ZK的地址】
Connection:连接对象
  • MySQL:构建MySQL连接:hostname:3306
  • Hive:构建Hive连接:hostname:10000
  • step2:构建DML操作的表对象
Table
  • 构建DDL操作的管理员对象:HbaseAdmin
  • put
put   表名    rowkey    列族:列    值
  • step1:构建Put对象,指定rowkey
  • step2:指定put对象的列族、列、值
addColumn(列族、列、值)
  • step3:对表执行Put操作
table.put(Put)
table.put(List<Put>)
  • delete
delete    表名    rowkey    列族:列
  • step1:构建delete对象,指定rowkey
  • step2:指定删除的列或者列族
addColumn:删除指定列,最新版本
addColumns:删除指定列的所有版本
addFamily:删除指定列族
  • step3:执行删除操作
table.delete
  • get:最快
get   表名    rowkey    [列族:列]
  • 根据rowkey进行查询,Rowkey是索引,所有的查询都是走索引
  • step1:先构建Get对象,指定rowkey
  • step2:根据需求指定列族或者列
  • step3:返回整个Rowkey的所有数据
  • 返回值:Result:一个Result代表一个Rowkey的所有数据
20210101_001                  column=basic:age, timestamp=1616034013623, value=18                                   
 20210101_001                  column=basic:name, timestamp=1616034013623, value=laoda                               
 20210101_001                  column=other:addr, timestamp=1616034013623, value=shanghai                            
 20210101_001                  column=other:phone, timestamp=1616034013623, value=110 
  • 迭代取出每一列:Cell:一个Cell代表一列的数据
20210101_001                  column=basic:age, timestamp=1616034013623, value=18 
  • 一个Result包含一个Cell数组:rs.rawCells
  • 工具类
  • Bytes:用于实现类型转换
  • 将其他类型转换为字节类型:写
  • 将字节类型转换为其他类型:读
  • CellUtil:用于从Cell对象中取数据
  • scan:全表扫描,不常用
scan  表名
  • step1:构建Scan对象
  • step2:表执行Scan对象:getScanner
  • step3:获取返回值,多个Rowkey的数据
  • ResultScanner = Iter【Result】
  • Filter:条件查询,最常用的
scan 表名 Filter
  • step1:构建Scan对象
  • step2:根据查询条件构建过滤器
  • 范围过滤
  • STARTROW:指定从某个Rowkey开始,包含
  • STOPROW:指定到某个Rowkey结束,不包含
  • 过滤器:Filter
  • Rowkey过滤:PrefixFilter
  • 列值过滤:SingleColumnValueFilter
  • 列的过滤:MultipleColumnPrefixFilter
  • 组合过滤:FilterList
  • step3:表执行Scan对象:getScanner
  • step4:获取返回值,多个Rowkey的数据
  • ResultScanner = Iter【Result】
  1. 操作类知识点的学习方法
  • 命令:一般都是英文缩写,记住英文和语法,背一背
  • JavaAPI
  • 哪些类:每个类的作用和构建方式
  • 哪些方法:增删改查

知识点02:课程目标

  1. Hbase存储设计
  • 整个Hbase中的存储结构?
  • Hbase、Zookeeper、HDFS
  • Table与RegionServer的关系?
  • Table怎么实现分布式?划分Region的规则是什么呢?写入数据分配的规则?【重要】
  • Region内部的存储?【重要】
  • Hbase数据与HDFS的关系?
  1. Hbase最严重的问题:热点
  • 现象、原因
  • 解决方案【重要】
  • 预分区:一张表有多个Region分区
  • 表的设计:Rowkey的设计

知识点03:存储设计:存储架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yYfd67AX-1616633798599)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210317190105892.png)]

  • 问题:Hbase整体如何实现数据的存储?
  • 分析
  • Client:负责连接服务端
  • 提供开发接口,将用户的命令或者代码提交给服务端执行
  • 将服务端执行的结果返回给用户
  • Zookeeper:存储Hbase部分元数据
  • 所有Hbase客户端,都需要连接Zookeeper获取元数据
  • Hbase:分布式内存
  • HMaster:管理类功能
  • HRegionServer:负责数据的存储,对外提供客户端读写
  • 分布式内存
  • HDFS:分布式磁盘
  • DataNode:负责将Hbase内存中的数据写入磁盘

知识点04:存储设计:Table、Region、RegionServer的关系


  • 问题:客户端操作的是表,数据最终存在RegionServer中,表和RegionServer的关系是什么?
  • 分析
  • Table:是一个逻辑对象,物理上不存在,供用户实现逻辑操作,存储在元数据的一个概念
  • 类似于HDFS中文件
  • RegionServer:是一个物理对象,Hbase中的一个进程,管理一台机器的存储
  • 类似于HDFS中DataNode
  • Region:Hbase中数据存储的最小单元
  • 类似于HDFS中Block
  • 就是分区的概念,每张表都可以划分为多个Region,实现分布式存储
  • 默认一张表只有一个分区
  • 每个Region由一台RegionServer所管理,Region存储在RegionServer
  • 一台RegionServer可以管理多个Region
  • 观察监控
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JyhZT7gp-1616633798601)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319091350259.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u8AXyrI7-1616633798603)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319091417912.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WvMurhSI-1616633798606)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319091609104.png)]

知识点05:存储设计:Region的划分规则


  • 问题:一张表划分为多个Region,划分的规则是什么?写一条数据到表中,这条数据会写入哪个Region,分配规则是什么?
  • 分析
  • 回顾:HDFS划分规则
  • 划分分区的规则:按照大小划分,文件按照每128M划分一个Block
  • Hbase分区划分规则:范围划分【根据Rowkey范围】
  • 范围划分:从整个-oo ~ +oo区间上进行范围划分
  • 每个分区都会有一个范围:根据Rowkey属于哪个范围就写入哪个分区
[startKey,stopKey)
  • 前闭后开区间
  • 默认:一张表创建时,只有一个Region
  • 范围:-oo ~ +oo
  • 自定义:创建表时,指定有多少个分区,每个分区的范围
  • 举个栗子:创建一张表,有2个分区Region
  • region0:-oo ~ 50
  • region1: 50 ~ +oo
  • 举个栗子:创建一张表,有4个分区Region
  • region0:-oo ~ 30
  • region1: 30 ~ 60
  • region2: 60 ~ 90
  • region3: 90 ~ +oo
  • 数据分配的规则:根据Rowkey属于哪个范围就写入哪个分区
  • 举个栗子:创建一张表,有4个分区Region
  • region0:-oo ~ 30
  • region1: 30 ~ 60
  • region2: 60 ~ 90
  • region3: 90 ~ +oo
  • 写入数据的rowkey:比较是按照ASC码比较的,不是数值比较
  • 10 => Region0
  • 1000 => Region0
  • 033 => Region0
  • 789999999 => Region2
  • 91 => Region3
  • 观察监控
  • 只有1个分区
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fSsgCtLA-1616633798607)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319093313002.png)]
  • 多个分区的情况
create 'itcast:t3','cf',SPLITS => ['20', '40', '60', '80']
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eY7aX5N6-1616633798608)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319093457846.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nARHgEC6-1616633798608)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319093602323.png)]
put 'itcast:t3','0300000','cf:name','laoda'   =>  -oo ~ 20
put 'itcast:t3','7890000','cf:name','laoda'   =>  60 ~ 80
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SwnDDMT6-1616633798609)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319093903377.png)]

知识点06:存储设计:Region内部存储结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PMqZdtFr-1616633798610)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210317191716413.png)]

  • 问题:数据在Region的内部是如何存储的?
  • 分析
  • Table【逻辑】/ RegionServer【物理】
  • Region:分区层,根据rowkey判断属于哪个分区,就写入哪个Region
  • Store:存储层,对每个分区内部数据存储的划分,根据列族划分,一个列族就对应一个Store
  • 每个列族对应一个Store不同列族的数据存储在不同的Store中
  • 如果一张表,有2个列族,这张表的region中就会有两个Store
  • 优点:划分不同的数据存储
  • 假设有100列,如果没有列族,100列存储在一起,想查询其中1列,最多会比较100次
  • 假设有100列,如果有两个列族,50列存储在一起,想查询某个列族中的某1列,最多比较51次
  • 先比较我要查询哪个Store,比较1次
  • Store中的存储
  • 一个MemStore:Region中的内存区域,会为每个Store分配一部分
  • 数据先读写MemStore
  • 0个或者多个StoreFile文件:Store中的数据文件,如果Memstore存储达到阈值,就会将内存数据写入HDFS
  • StoreFile:逻辑上属于Store的
  • 物理上存储在HDFS上:本质上存储的是HFILE:有序的二进制文件
  • 总结
  • RegionServer:Region存储在Regionserver中
  • Region:一张表有多个Region,根据Rowkey判断写入哪个region
  • 一个表中有多个列族,每个列族对应一个Store,一个region中有多个store
  • Store:根据列族判断写入哪个Store
  • memstore:内存区域
  • storefile:HDFS上的文件

知识点07:存储设计:HDFS中的存储结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fLHCvTK8-1616633798610)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210317191754182.png)]

  • 问题:Hbase的数据在HDFS中是如何存储的?
  • 分析
  • 整个Hbase在HDFS中的存储目录:由配置决定
hbase.rootdir=hdfs://node1:8020/hbase
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LE98p1w6-1616633798611)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319103050484.png)]
  • Namespace的目录
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j0kiin6w-1616633798611)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319103216678.png)]
  • 表的目录
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MgYZIbnt-1616633798612)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319103307682.png)]
  • Region的目录
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYjAQ9yu-1616633798612)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319103437641.png)]
  • Store的目录:按照列族划分的
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cNt2Oxbn-1616633798612)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319103636158.png)]
  • 观察数据
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OwP9fqL8-1616633798613)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319103835828.png)]
hbase> flush 'TABLENAME'
  hbase> flush 'REGIONNAME'
  hbase> flush 'ENCODED_REGIONNAME'
  hbase> flush 'REGION_SERVER_NAME'
#强制将内存的数据写入HDFS变成StoreFile
flush 'itcast:t3'
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sNA9vzoZ-1616633798613)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319104124012.png)]

知识点08:热点问题:现象及原因

  • 现象:在某个时间段内,大量的读写请求全部集中在某个Region中,导致这台RegionServer的负载比较高,其他的Region和RegionServer比较空闲
  • 问题:这台RegionServer故障的概率就会增加,整体性能降低,效率比较差
  • 原因:本质上的原因,数据分配不均衡
  • 情况一:如果这张表只有一个分区
  • region0:-oo ~ +oo
  • 所有数据都是读写这一个分区
  • 肯定会出现热点
  • 情况二:如果这张表有多个分区,如果你的Rowkey写入时是连续的
  • region0:-oo ~ 30
  • region1:30 ~ 70
  • region2:70 ~ +oo
  • 写入的rowkey
  • 00000001
  • 00000002
  • 00000003
  • ……
  • 29999999:都在往Region0中写入
  • 30000000:开始写入region1
  • ……
  • 全部写region1
  • ……
  • 原因:region的设计是按照范围有序的,Rowkey也是有序的,连续的rowkey写入同一个region
  • 解决
  • 创建表的时候给定多个分区
  • Rowkey写入时不能是连续的

知识点09:分布式设计:预分区

  • 需求:在创建表的时候,指定一张表拥有多个Region分区
  • 分析
  • 划分多个分区,实现分布式并行读写,将无穷区间划分为几段
  • 段的划分的依据:Rowkey或者Rowkey的前缀来划分
  • 举个栗子:如果分区都是按照数值划分的
  • region0:-oo ~ 3
  • region1:3 ~ 7
  • region2:7 ~ +oo
  • Rowkey:都是以字母开头的
a143434343
ydfjdkfjd4
……
  • 出现了热点问题
  • 实现
  • 方式一:指定分隔段,实现预分区
create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40']
#将每个分割的段写在文件中,一行一个
create 't1', 'f1', SPLITS_FILE => 'splits.txt'
  • 方式二:指定Region个数,自动进行Hash划分:字母和数字的组合
#你的rowkey的前缀可能是字母可能是数字
create 'itcast:t4', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gEmrClkI-1616633798614)(20210319_分布式NoSQL列存储数据库Hbase(四).assets/image-20210319111755041.png)]
  • 方式三:Java API
HBASEAdmin admin = conn.getAdmin
admin.create(表的描述器对象,byte[][] splitsKey)
  • 总结
  • 原则:必须根据rowkey或者rowkey前缀来设计分区的划分
  • 方式:三种方式任何一种只要能满足需求都可以

知识点10:Hbase表设计:Rowkey设计

  • 问题
  • Rowkey功能
  • 唯一标识符
  • 作为Hbase唯一索引
  • 划分Region的标识,不能连续
  • 问题
  • Rowkey不重复
  • 尽量保证按照rowkey查询数据是最快的
  • Rowkey是散列的,无序的
  • 需求:根据业务需求,来合理的设计rowkey,实现高性能的数据存储
  • 分析:不同的业务需求的表,Rowkey设计都不一样
  • 设计规则
  • 业务原则:Rowkey设计必须贴合业务需求,尽量实现基于Rowkey数据检索,走索引
  • Rowkey是Hbase中的唯一索引,按照Rowkey的查询是按照前缀匹配实现的
  • 如果不按照Rowkey检索,就是全表扫描
  • 尽量将最常用的查询条件作为Rowkey的前缀
  • 地区
  • 时间
  • ID:订单ID、用户ID
  • 唯一原则:Rowkey必须唯一标识一条数据,Rowkey是不能重复的
  • 组合原则:尽量将最常用的几个查询条件组合作为Rowkey,最常用的那一个作为前缀
  • 常见的条件:时间、订单id、用户id
  • 最常用的:时间
  • Rowkey
1616124723000_user001_order001
  • 以下的查询都是走索引
  • 查询某个时间的所有订单数据
  • 查询某个时间某个人的所有订单数据
  • 查询某个时间某个人的某个订单数据
  • 以下的查询不走索引
  • 查询某个人的所有订单
  • 只能走全表扫描:慢
  • 问题:学习二级索引来解决
  • 散列原则:Rowkey不能是按照有序生成的,由于Region范围划分的,如果rowkey是有序的,会导致热点,必须构建无序的Rowkey
  • 问题:有序的rowkey,用时间作为前缀,时间是有序的
1616124723000_user001_order001
1616124723000_user002_order002
1616124723000_user003_order003
1616124723001_user001_order004
1616124723002_user001_order005
1616124723000_user001_order001
……
  • 解决
  • 方案一:不将连续的字段作为前缀,例如:将用户id作为前缀
user001_1616124723000_order001
user999_1616124723000_order002
  • 一个用户不可能在同一秒下多个订单
  • 所有用户在同一秒也不可能的连续的
  • 缺点:前缀不是最常用的查询条件
  • 方案二:基于有序的进行反转,将时间进行反转构建Rowkey
0003274216161_user001_order001
0003274216161_user002_order002
0003274216161_user003_order003
1003274216161_user001_order004
1003274216161_user001_order005
2003274216161_user001_order001
3003274216161
4003274216161
……
  • 缺点:每次查询时,也必须先反转,再查询
  • 方案三:编码,构建随机
1616124723000_user001_order001
1616124723000_user002_order002
1616124723000_user003_order003
1616124723001_user001_order004
1616124723002_user001_order005
1616124723000_user001_order001
……
|  通过对原来的rowkey进行加密,得到一个加密码
12345678_1616124723000_user001_order001
37483784_1616124723000_user002_order002
……
  • 缺点:每次查询时,也必须先编码
  • 方案四:加盐,给Rowkey前缀添加一个随机值
1616124723000_user001_order001
1616124723000_user002_order002
1616124723000_user003_order003
1616124723001_user001_order004
1616124723002_user001_order005
1616124723000_user001_order001
……
| 新的rowkey前缀是个随机值【0-9】
0_1616124723000_user001_order001
4_1616124723000_user002_order002
9_1616124723000_user003_order003
0_1616124723001_user001_order004
0_1616124723002_user001_order005
1_1616124723000_user001_order001
  • 缺点:每次查询时,挨个试,读的性能降低
  • 长度原则:Rowkey的长度不建议过长
  • 原则:能满足业务需求的情况下越短越好
  • 问题:如果rowkey越长,索引占用的空间越大,比较rowkey就越慢,性能就越差
  • rowkey在底层是冗余存储的
  • 建议:不超过100个字节
  • 如果超过100个字节,建议进行编码
  • 100位 =》 MD5 => 32位 、16位
  • 总结
  • 业务原则:保证前缀是最常用的查询字段
  • 唯一原则:每条rowkey表示一条数据
  • 组合原则:常用的查询条件作为Rowkey
  • 散列原则:rowkey构建不连续
  • 长度原则:满足业务需求越短越好

9】

0_1616124723000_user001_order001
    4_1616124723000_user002_order002
    9_1616124723000_user003_order003
    0_1616124723001_user001_order004
    0_1616124723002_user001_order005
    1_1616124723000_user001_order001
    ```
    - 缺点:每次查询时,挨个试,读的性能降低
  • 长度原则:Rowkey的长度不建议过长
  • 原则:能满足业务需求的情况下越短越好
  • 问题:如果rowkey越长,索引占用的空间越大,比较rowkey就越慢,性能就越差
  • rowkey在底层是冗余存储的
  • 建议:不超过100个字节
  • 如果超过100个字节,建议进行编码
  • 100位 =》 MD5 => 32位 、16位
  • 总结
  • 业务原则:保证前缀是最常用的查询字段
  • 唯一原则:每条rowkey表示一条数据
  • 组合原则:常用的查询条件作为Rowkey
  • 散列原则:rowkey构建不连续
  • 长度原则:满足业务需求越短越好


目录
相关文章
|
7月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
1046 161
|
8月前
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
307 5
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
8月前
|
NoSQL Java API
在Java环境下如何进行Redis数据库的操作
总的来说,使用Jedis在Java环境下进行Redis数据库的操作,是一种简单而高效的方法。只需要几行代码,就可以实现复杂的数据操作。同时,Jedis的API设计得非常直观,即使是初学者,也可以快速上手。
377 94
|
5月前
|
存储 JSON API
文本存储免费API接口教程
接口盒子提供免费文本存储服务,支持1000条记录,每条最多5000字符,适用于公告、日志、配置等场景,支持修改与读取。
193 0
|
8月前
|
SQL 存储 分布式数据库
分布式存储数据恢复—hbase和hive数据库数据恢复案例
分布式存储数据恢复环境: 16台某品牌R730xd服务器节点,每台服务器节点上有数台虚拟机。 虚拟机上部署Hbase和Hive数据库。 分布式存储故障: 数据库底层文件被误删除,数据库不能使用。要求恢复hbase和hive数据库。
303 12
|
8月前
|
Java 关系型数据库 MySQL
Java汽车租赁系统源码(含数据库脚本)
Java汽车租赁系统源码(含数据库脚本)
215 4
|
10月前
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
401 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
9月前
|
前端开发 JavaScript Java
[Java计算机毕设]基于ssm的OA办公管理系统的设计与实现,附源码+数据库+论文+开题,包安装调试
OA办公管理系统是一款基于Java和SSM框架开发的B/S架构应用,适用于Windows系统。项目包含管理员、项目管理人员和普通用户三种角色,分别负责系统管理、请假审批、图书借阅等日常办公事务。系统使用Vue、HTML、JavaScript、CSS和LayUI构建前端,后端采用SSM框架,数据库为MySQL,共24张表。提供完整演示视频和详细文档截图,支持远程安装调试,确保顺利运行。
407 17