Git Product home page Git Product logo

luckysheetserver's Introduction

Luckysheet Server

English| 简体中文

Introduction

💻Luckysheet official Java version backend.

Demo

Development

Use MySQL Tutorial for Beginners

Deploy

Requirements

jdk >= 1.8

postgre >= 10 (Support jsonb version)

redis >= 3

nginx >= 1.12

maven >= 3.6

IntelliJ IDEA >= 12 (not necessary)

Database initialization

Create database

CREATE DATABASE luckysheetdb

Create sequence

DROP SEQUENCE IF EXISTS "public"."luckysheet_id_seq";
CREATE SEQUENCE "public"."luckysheet_id_seq"
INCREMENT 1
MINVALUE  1
MAXVALUE 9999999999999
START 1
CACHE 10;

Create table

DROP TABLE IF EXISTS "public"."luckysheet";
CREATE TABLE "luckysheet" (
  "id" int8 NOT NULL,
  "block_id" varchar(200) COLLATE "pg_catalog"."default" NOT NULL,
  "row_col" varchar(50),
  "index" varchar(200) COLLATE "pg_catalog"."default" NOT NULL,
  "list_id" varchar(200) COLLATE "pg_catalog"."default" NOT NULL,
  "status" int2 NOT NULL,
  "json_data" jsonb,
  "order" int2,
  "is_delete" int2
);
CREATE INDEX "block_id" ON "public"."luckysheet" USING btree (
  "block_id" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST,
  "list_id" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
CREATE INDEX "index" ON "public"."luckysheet" USING btree (
  "index" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST,
  "list_id" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
CREATE INDEX "is_delete" ON "public"."luckysheet" USING btree (
  "is_delete" "pg_catalog"."int2_ops" ASC NULLS LAST
);
CREATE INDEX "list_id" ON "public"."luckysheet" USING btree (
  "list_id" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);
CREATE INDEX "order" ON "public"."luckysheet" USING btree (
  "list_id" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST,
  "order" "pg_catalog"."int2_ops" ASC NULLS LAST
);
CREATE INDEX "status" ON "public"."luckysheet" USING btree (
  "list_id" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST,
  "status" "pg_catalog"."int2_ops" ASC NULLS LAST
);
ALTER TABLE "public"."luckysheet" ADD CONSTRAINT "luckysheet_pkey" PRIMARY KEY ("id");

Insert initialization statement

INSERT INTO "public"."luckysheet" VALUES (nextval('luckysheet_id_seq'), 'fblock', '', '1', '1079500#-8803#7c45f52b7d01486d88bc53cb17dcd2c3', 1, '{"row":84,"name":"Sheet1","chart":[],"color":"","index":"1","order":0,"column":60,"config":{},"status":0,"celldata":[],"ch_width":4748,"rowsplit":[],"rh_height":1790,"scrollTop":0,"scrollLeft":0,"visibledatarow":[],"visibledatacolumn":[],"jfgird_select_save":[],"jfgrid_selection_range":{}}', 0, 0);
INSERT INTO "public"."luckysheet" VALUES (nextval('luckysheet_id_seq'), 'fblock', '', '2', '1079500#-8803#7c45f52b7d01486d88bc53cb17dcd2c3', 0, '{"row":84,"name":"Sheet2","chart":[],"color":"","index":"2","order":1,"column":60,"config":{},"status":0,"celldata":[],"ch_width":4748,"rowsplit":[],"rh_height":1790,"scrollTop":0,"scrollLeft":0,"visibledatarow":[],"visibledatacolumn":[],"jfgird_select_save":[],"jfgrid_selection_range":{}}', 1, 0);
INSERT INTO "public"."luckysheet" VALUES (nextval('luckysheet_id_seq'), 'fblock', '', '3', '1079500#-8803#7c45f52b7d01486d88bc53cb17dcd2c3', 0, '{"row":84,"name":"Sheet3","chart":[],"color":"","index":"3","order":2,"column":60,"config":{},"status":0,"celldata":[],"ch_width":4748,"rowsplit":[],"rh_height":1790,"scrollTop":0,"scrollLeft":0,"visibledatarow":[],"visibledatacolumn":[],"jfgird_select_save":[],"jfgrid_selection_range":{}}', 2, 0);

nginx configuration

http block configuration

#websocket configuration
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream ws_dataluckysheet {
      server [Project ip]: [port];
}    

server block configuration

#websocket configuration
location /luckysheet/websocket/luckysheet {
    proxy_pass http://ws_dataluckysheet/luckysheet/websocket/luckysheet;

    proxy_set_header Host $host;
    proxy_set_header X-real-ip $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    #websocket
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}       

#Dynamic resource configuration
location /luckysheet/ {
    proxy_pass http://ws_dataluckysheet;
}

#Static resource configuration
location /luckysheet/demo/ {
    root /usr/share/nginx/html;
    index  index.html index.htm;
}

Access test

  • Access the static homepage through [project ip]:[port]
  • Access the collaborative editing homepage through [project ip]:[port]?share

Project usage

application.yml Project configuration

server:
  port: [Project port]
  servlet:
    context-path: /[Project path]
redis.channel: [redis channel name]
row_size: [The number of rows in the table, default 500]
col_size: [Number of columns in the table, default 500]
pgSetUp: [Whether to enable pgsql as storage data (0 for yes, 1 for no), currently can only be set to 0]

application-dev.yml Database configuration

spring:
  redis:
    host: [ip address]
    port: [port]
    password: [password]
    
db:
  postgre:
    druid:
      url: jdbc:postgresql://[ip address]: [port]/luckysheetdb?useSSL=false
      driverClassName: org.postgresql.Driver
      username: [username]
      password: [password]    

logback-spring.xml Log configuration

 <property name="log.path" value="[Log output directory]"/>

project instruction

Luckysheet module main class description

com.xc.luckysheet.WebApplication Project startup

com.xc.luckysheet.controller

JfGridFileController Table data loading class
TestController  postgre redis Test class 

com.xc.luckysheet.entity

SheetOperationEnum Table operation type
JfGridConfigModel Table block object
LuckySheetGridModel Tabular database objects
PgGridDataModel Table database object

com.xc.luckysheet.postgre

PostgresGridFileDao postgre database operation
PostgresGridFileGetService Record operation
PostgresJfGridUpdateService Update processing

com.xc.luckysheet.redisserver

RedisLock redis lock
RedisMessageListener Pipeline monitoring class
RedisMessagePublish Pipeline release class

com.xc.luckysheet.service

ConfigerService Configuration class
ScheduleService Initialize the timing database

com.xc.luckysheet.utils

GzipHandle Information compression
Pako_GzipUtils WebSocket information compression

com.xc.luckysheet.websocket

IpAndPortUtil Get the IP and port of the current service
MyWebSocketHandler Socket processor (including methods for sending information, receiving information, and information errors.)
MyWebSocketInterceptor Socket connection (handshake) and disconnection
WebSocketConfig Register WebSocket, Set the address of WebSocket
WSUserModel WebSocket object

Main class description of common module

com.xc.common.config.datasource.DataSourceConfig Data source configuration class
com.xc.common.config.redis.RedisConfig redis configuration class

Links

Authors and acknowledgment

Team

License

Please consult the attached LICENSE file for details. All rights not explicitly granted by the Apache 2.0 License are reserved by the Original Author.

luckysheetserver's People

Contributors

iamxuchen800117 avatar lmzh0414 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

luckysheetserver's Issues

[BUG]无法运行

修改配置为mysql运行不了,发现application-mysql.yml里面的db配置都是写错的,修改正确后依然
image

[Feature request]长链接通信部分实现独立化,使用者可以自行替换自己的实现

您的功能请求与问题有关吗?
LuckysheetServer对于各端之间通信使用的websocket长链接实现比较简单,只能在试验demo中使用,而且该部分实现与消息的合并代码耦合比较严重,使用者想使用自己的长链接通信实现修改起来比较复杂。

描述您想要的解决方案
可不可以将长链接通信部分抽离出来与消息的合并部分隔离开(比如模块化或者插件化),使用者可以很方便的将长链接通信部分替换成自己的实现(比如我们就是使用了自己的消息服务)。

其他内容
其他说明

mysql 数据库版本的sql中的 jsontest 字段

你好

我这边用的是mysql的版本,在更新表格数据的部分sql中有 jsontest 这个字段,但是数据库中并没有这个字段
请问这个字段是缺失的么,或者说可以用表中存在的 json_data 字段替换呢
例如 RecordDataUpdataHandle 类中的 updateJsonbForInsertNull 方法中
image

谢谢。

[Feature request]对于其他数据库的扩展支持

您的功能请求与问题有关吗?
当前仅实现了DB为postgre的版本(有群里询问过是出于postgre的jsonb操作有事务保证),是否可以考虑对其他数据库进行扩展支持。

描述您想要的解决方案
看到代码里有预留一个if{}else{}的位置给其他DB存储的实现,但这种方式不够优雅甚至说有点丑陋,建议是可以参考dubbo的插件化思路,将不同DB存储的实现逻辑解耦。

其他内容

[Feature request]关于对sheet分块存储的后续维护问题

您的功能请求与问题有关吗?
当前服务端按照配置的块大小(比如LuckysheetServer是硬编码成了500*500)将一个sheet划分成一个个块的集合(List),这个实现有效控制了DB中单行数据的规模,但是也带来一个问题:假设项目起初对于块大小的预估有误,导致后续的迭代中需要修改配置的块大小值,那么已经保存到DB中的数据的blockId值也需要同步进行清洗,否则CRUD会有错误。而通常情况下,已经保存的数据规模是比较大的,对全量的已保存数据进行清洗成本、风险都比较大。

描述您想要的解决方案
针对上述问题场景,是否有风险、成本更低的解决思路,而不需要清洗旧数据。

其他内容
想到的一种比较直接的思路是新增一个版本属性,它表示当前是使用的哪种块大小配置,后续就算修改了配置的块大小值也能在业务代码层面应对。

[BUG]json_data->>'$.column' AS `column`

luckysheet-mysql\src\main\java\com\xc\luckysheet\mysql\impl\RecordSelectHandle.java
public JSONObject getCelldataByGridKey(String listId, String index, String blockId) {
............
String sql="select index,json_data->>'$.celldata' AS celldata,json_data->>'$.column' AS column,json_data->>'$.row' AS row from "+JfGridConfigModel.TABLENAME+" p where p.list_id=? and p.index=? and p.block_id=? and p.is_delete=0 ORDER BY p.id DESC LIMIT 1 ";
Map<String, Object> map= luckySheetJdbcTemplate.queryForMap(sql, new Object[]{listId,index,blockId});
............
}
DataTable sheet [docssheet ] fields:id,block_id,row_col,index,list_id,status,order,json_data,is_delete
json_data : {"celldata": [{"c": 6, "r": 30, "v": {"m": "l", "v": "l", "ct": {"t": "g", "fa": "General"}}}]}

Mysql:
select id,index,json_data->>'$.celldata' AS celldata,json_data->>'$.column' AS column,json_data->>'$.row' AS row from docssheet p where p.list_id='45794d3ceb1f0054a2b6d47b0ac82212' and p.index='Sheet_6aokgc2qSWWH20210505161959' and p.block_id='30_6' and p.is_delete=0 ORDER BY p.id DESC LIMIT 1 ;
Query Result:
id :183152282723028992
index :Sheet_6aokgc2qSWWH20210505161959
celldata:[{"c": 6, "r": 30, "v": {"m": "l", "v": "l", "ct": {"t": "g", "fa": "General"}}}]
column: (NULL)
row : (NULL)

Map<String, Object> map= luckySheetJdbcTemplate.queryForMap(sql, new Object[]{listId,index,blockId});
ERROR Incorrect result size: expected 1, actual 0

problem 1: json_data->>'$.column' Or json_data->>'$.c' ?
problem 2: record count 1; but warning ERROR Incorrect result size: expected 1, actual 0 ?

[BUG]doubt ? NumberFormatException Find a bug

file: src\main\java\com\xc\luckysheet\entity\GridRecordDataModel.java {
......
/**
* sheet序号
*/
String index;
......
}

file: src\main\java\com\xc\luckysheet\db\server\JfGridUpdateService.java
private String Operation_sha(String gridKey, JSONObject bson) {
......
Integer _sheetPosition = JfGridFileUtil.getSheetPositionByIndex(_dbObject, index);
......
}

file: luckysheet-db\src\main\java\com\xc\luckysheet\util\JfGridFileUtil.java
public static Integer getSheetPositionByIndex(List _list,String index){
......
Integer _index=Integer.parseInt(_o.get("index").toString());
_o.get("index").toString() : "Sheet_0ekpfWe00zbx_1619100520312"
java.lang.NumberFormatException
......
}

Integer.parseInt() java.lang.NumberFormatException
What went wrong?

项目是不是缺少跨域支持

静态html存在跨域问题,
把跨域解决了吧
@bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("");
config.setAllowCredentials(true);
config.addAllowedMethod("
");
config.addAllowedHeader("*");
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}

表格删除操作无效

版本情况:
前端:uckysheetv2.13
后台:最新main分支

luckysheet前后端部署后在协同模式下测试发现如下问题:
1、表格清除内容无效,清除后重新刷新页面数据还存在;
2、表格删除行,删除后重新刷新页面数据还是存在;
3、删除标签,标签同样存在

[BUG]发现了个bug

描述错误
清楚简洁地描述错误是什么。
删除行列没有效果

重现
重现错误的步骤:
1.第一步操作
直接删除就行
4.最后看到了什么错误
代码没有报错 应该是后端代码没有写全
期望的结果
对您期望发生的结果简洁明了的描述。
删除成功
屏幕截图或演示
方便的话,贴上屏幕截图或在线链接复现问题,我们复测时会更精准

最新

备注
其他说明
我本地改了 可以交流一下

[BUG]发现了个bug

描述错误
{ status: "0", msg: "Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: url not set", data: "{}", code: "SYS0" }

重现
重现错误的步骤:
1.本地启动LuckysheetServer,数据库客户端正常访问,application-dev.yml修改正确
2.http://127.0.0.1:9004/luckysheet/test/dbInit
{ status: "0", msg: "Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: url not set", data: "{}", code: "SYS0" }

期望的结果
http://127.0.0.1:9004/luckysheet/test/dbInit
能正常返回。

屏幕截图或演示
方便的话,贴上屏幕截图或在线链接复现问题,我们复测时会更精准
image

image

环境:
-操作系统:[Windows,Linux]
-浏览器 版本号:[例如 Chrome 版本 87.0.4147.105(正式版本) (64 位)]
-Luckysheet版本:[最新]

备注
其他说明

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.