From a3a4e3f52336614a38cb672544aef0069ef9b453 Mon Sep 17 00:00:00 2001 From: mmm8955405 Date: Tue, 20 Feb 2024 22:02:42 +0800 Subject: [PATCH] init --- .gitea/workflows/build.yml | 75 +++ .gitignore | 30 + Dockerfile | 19 + pom.xml | 548 ++++++++++++++++++ .../java/jj/tech/finance/Application.java | 91 +++ .../controller/ContractInfoController.java | 421 ++++++++++++++ .../biz/web/controller/ContractInfoDaily.java | 93 +++ .../web/controller/ContractInfoMinute.java | 68 +++ .../biz/web/controller/ContractInfoMonth.java | 81 +++ .../biz/web/controller/ContractInfoWeek.java | 88 +++ .../biz/web/controller/LoginController.java | 88 +++ .../biz/web/dao/ContractInfoSelectMapper.java | 28 + .../ContractInfoManageController.java | 267 +++++++++ .../ContractInfoScribeController.java | 342 +++++++++++ .../controller/GetFutDailyController.java | 463 +++++++++++++++ .../controller/SysAdminController.java | 172 ++++++ .../controller/SysAdminLoginController.java | 90 +++ .../controller/UserInfoController.java | 168 ++++++ .../biz/webadmin/dao/SelectMapper.java | 34 ++ .../biz/webadmin/service/DailyService.java | 139 +++++ .../biz/webadmin/task/ContractInfoTime.java | 137 +++++ .../biz/webadmin/task/FutDailyTime.java | 149 +++++ .../biz/webadmin/vo/ContractInfoStatu.java | 29 + .../webadmin/vo/ContractInfoStatuScribe.java | 32 + .../vo/ContractInfoStatuScribeStore.java | 15 + .../biz/webadmin/vo/FuturesZhSpot.java | 119 ++++ .../finance/biz/webadmin/vo/ScribeVo.java | 54 ++ .../biz/webadmin/vo/parm/Contract.java | 30 + .../finance/biz/webadmin/vo/parm/Daily.java | 51 ++ .../tech/finance/biz/webadmin/vo/parm/Id.java | 18 + .../finance/biz/webadmin/vo/parm/Ids.java | 20 + .../finance/biz/webadmin/vo/parm/Login.java | 28 + .../finance/biz/webadmin/vo/parm/Minute.java | 25 + .../tech/finance/biz/webadmin/vo/parm/P.java | 21 + .../biz/webadmin/vo/parm/UserName.java | 30 + .../config/datasource/DataSourceConfig.java | 64 ++ .../tech/finance/config/enums/Exchange.java | 15 + .../finance/config/enums/SysConfigGroup.java | 11 + .../tech/finance/config/jooq/JooqConfig.java | 134 +++++ .../config/jooq/JooqSpringTransaction.java | 23 + .../jooq/JooqSpringTransactionProvider.java | 55 ++ .../jj/tech/finance/config/jpa/JpaConfig.java | 51 ++ .../config/json/JacksonConfiguration.java | 46 ++ .../jj/tech/finance/config/security/Cors.java | 37 ++ .../config/security/SecurityAdminFilter.java | 103 ++++ .../config/security/SecurityWebFilter.java | 104 ++++ .../finance/config/swagger/SwaggerConfig.java | 144 +++++ .../tech/finance/config/ws/SocketHandler.java | 40 ++ .../finance/config/ws/WebSocketConfig.java | 30 + src/main/java/jj/tech/finance/utils/AES.java | 102 ++++ .../jj/tech/finance/utils/AlphaUtils.java | 66 +++ .../jj/tech/finance/utils/CookieUtil.java | 112 ++++ .../java/jj/tech/finance/utils/IDHelp.java | 124 ++++ .../java/jj/tech/finance/utils/JsonUtil.java | 110 ++++ .../java/jj/tech/finance/utils/JwtUtil.java | 149 +++++ src/main/java/jj/tech/finance/utils/Page.java | 69 +++ src/main/java/jj/tech/finance/utils/R.java | 73 +++ .../jj/tech/finance/utils/WebAdminUtil.java | 109 ++++ .../jj/tech/finance/utils/WebUserUtil.java | 105 ++++ .../mybatis/MybatisControllerPlugin.java | 187 ++++++ .../finance/utils/mybatis/PluginUtils.java | 142 +++++ .../jj/tech/finance/utils/mybatis/Sum.java | 41 ++ .../finance/utils/tushare/TushareConfig.java | 7 + src/main/resources/application-prod.yml | 68 +++ src/main/resources/application.yml | 70 +++ src/main/resources/bootstrap.yml | 22 + .../resources/generate/jooq/JooqConfig.xml | 50 ++ .../generate/mybatis/generatorConfig.xml | 114 ++++ src/main/resources/logback.xml | 44 ++ src/main/resources/sql/data-h2.sql | 25 + src/main/resources/sql/schema-h2.sql | 174 ++++++ .../biz/webadmin/service/RoomRuleImpTest.java | 22 + src/test/java/test/nw/BinaryTree.java | 295 ++++++++++ src/test/java/test/nw/StreamTest.java | 16 + src/test/java/test/nw/TimeTest.java | 32 + src/test/java/test/nw/UrlTest.java | 73 +++ src/test/resources/application.yml | 62 ++ src/test/resources/banner.txt | 17 + src/test/resources/bootstrap.yml | 22 + .../resources/generate/jooq/JooqConfig.xml | 41 ++ .../generate/mybatis/generatorConfig.xml | 91 +++ src/test/resources/logback.xml | 44 ++ src/test/resources/sql/V1_0__schema-h2.sql | 415 +++++++++++++ src/test/resources/xml/DaoHome.ftl | 218 +++++++ src/test/resources/xml/hibernate.cfg.xml | 31 + src/test/resources/xml/hibernate.properties | 12 + src/test/resources/xml/hibernate.reveng.xml | 16 + 87 files changed, 8290 insertions(+) create mode 100644 .gitea/workflows/build.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 pom.xml create mode 100644 src/main/java/jj/tech/finance/Application.java create mode 100644 src/main/java/jj/tech/finance/biz/web/controller/ContractInfoController.java create mode 100644 src/main/java/jj/tech/finance/biz/web/controller/ContractInfoDaily.java create mode 100644 src/main/java/jj/tech/finance/biz/web/controller/ContractInfoMinute.java create mode 100644 src/main/java/jj/tech/finance/biz/web/controller/ContractInfoMonth.java create mode 100644 src/main/java/jj/tech/finance/biz/web/controller/ContractInfoWeek.java create mode 100644 src/main/java/jj/tech/finance/biz/web/controller/LoginController.java create mode 100644 src/main/java/jj/tech/finance/biz/web/dao/ContractInfoSelectMapper.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/controller/ContractInfoManageController.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/controller/ContractInfoScribeController.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/controller/GetFutDailyController.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/controller/SysAdminController.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/controller/SysAdminLoginController.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/controller/UserInfoController.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/dao/SelectMapper.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/service/DailyService.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/task/ContractInfoTime.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/task/FutDailyTime.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatu.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatuScribe.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatuScribeStore.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/FuturesZhSpot.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/ScribeVo.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Contract.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Daily.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Id.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Ids.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Login.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Minute.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/parm/P.java create mode 100644 src/main/java/jj/tech/finance/biz/webadmin/vo/parm/UserName.java create mode 100644 src/main/java/jj/tech/finance/config/datasource/DataSourceConfig.java create mode 100644 src/main/java/jj/tech/finance/config/enums/Exchange.java create mode 100644 src/main/java/jj/tech/finance/config/enums/SysConfigGroup.java create mode 100644 src/main/java/jj/tech/finance/config/jooq/JooqConfig.java create mode 100644 src/main/java/jj/tech/finance/config/jooq/JooqSpringTransaction.java create mode 100644 src/main/java/jj/tech/finance/config/jooq/JooqSpringTransactionProvider.java create mode 100644 src/main/java/jj/tech/finance/config/jpa/JpaConfig.java create mode 100644 src/main/java/jj/tech/finance/config/json/JacksonConfiguration.java create mode 100644 src/main/java/jj/tech/finance/config/security/Cors.java create mode 100644 src/main/java/jj/tech/finance/config/security/SecurityAdminFilter.java create mode 100644 src/main/java/jj/tech/finance/config/security/SecurityWebFilter.java create mode 100644 src/main/java/jj/tech/finance/config/swagger/SwaggerConfig.java create mode 100644 src/main/java/jj/tech/finance/config/ws/SocketHandler.java create mode 100644 src/main/java/jj/tech/finance/config/ws/WebSocketConfig.java create mode 100644 src/main/java/jj/tech/finance/utils/AES.java create mode 100644 src/main/java/jj/tech/finance/utils/AlphaUtils.java create mode 100644 src/main/java/jj/tech/finance/utils/CookieUtil.java create mode 100644 src/main/java/jj/tech/finance/utils/IDHelp.java create mode 100644 src/main/java/jj/tech/finance/utils/JsonUtil.java create mode 100644 src/main/java/jj/tech/finance/utils/JwtUtil.java create mode 100644 src/main/java/jj/tech/finance/utils/Page.java create mode 100644 src/main/java/jj/tech/finance/utils/R.java create mode 100644 src/main/java/jj/tech/finance/utils/WebAdminUtil.java create mode 100644 src/main/java/jj/tech/finance/utils/WebUserUtil.java create mode 100644 src/main/java/jj/tech/finance/utils/mybatis/MybatisControllerPlugin.java create mode 100644 src/main/java/jj/tech/finance/utils/mybatis/PluginUtils.java create mode 100644 src/main/java/jj/tech/finance/utils/mybatis/Sum.java create mode 100644 src/main/java/jj/tech/finance/utils/tushare/TushareConfig.java create mode 100644 src/main/resources/application-prod.yml create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/bootstrap.yml create mode 100644 src/main/resources/generate/jooq/JooqConfig.xml create mode 100644 src/main/resources/generate/mybatis/generatorConfig.xml create mode 100644 src/main/resources/logback.xml create mode 100644 src/main/resources/sql/data-h2.sql create mode 100644 src/main/resources/sql/schema-h2.sql create mode 100644 src/test/java/jj/tech/paolu/biz/webadmin/service/RoomRuleImpTest.java create mode 100644 src/test/java/test/nw/BinaryTree.java create mode 100644 src/test/java/test/nw/StreamTest.java create mode 100644 src/test/java/test/nw/TimeTest.java create mode 100644 src/test/java/test/nw/UrlTest.java create mode 100644 src/test/resources/application.yml create mode 100644 src/test/resources/banner.txt create mode 100644 src/test/resources/bootstrap.yml create mode 100644 src/test/resources/generate/jooq/JooqConfig.xml create mode 100644 src/test/resources/generate/mybatis/generatorConfig.xml create mode 100644 src/test/resources/logback.xml create mode 100644 src/test/resources/sql/V1_0__schema-h2.sql create mode 100644 src/test/resources/xml/DaoHome.ftl create mode 100644 src/test/resources/xml/hibernate.cfg.xml create mode 100644 src/test/resources/xml/hibernate.properties create mode 100644 src/test/resources/xml/hibernate.reveng.xml diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..fb104dd --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,75 @@ +on: + #release: + #types: [published] + push: + branches: + - "master" + +jobs: + build-image: + runs-on: ubuntu-act-latest + steps: + - + name: Check Out Repo + uses: https://github.com/actions/checkout@v4 + #with: + #repository: jj/paolu-mybatis + #path: master + #token: '' + - name: Set Java Action + id: steps1 + uses: https://github.com/actions/setup-java@v3 + with: + distribution: temurin + java-version: 20 + #cache: maven + #cache-dependency-path: .pom.xml + - + name: Set Maven Action + uses: https://github.com/stCarolas/setup-maven@v4.5 + with: + maven-version: 3.9.5 + - + name: Cache + uses: actions/cache@v3 + id: cache1 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + #- name: Set repo-java-maven Env + #uses: https://github.com/s4u/setup-maven-action@v1.11.0 + #with: + #java-distribution: temurin + #java-version: 20 + #maven-version: 3.9.5 + - if: ${{ steps.cache1.outputs.cache-hit == 'true' }} + name: is hit cache + continue-on-error: true + run: echo " hit cache ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}" + - + name: Build With Maven + run: mvn -B package -Dmaven.test.skip + - name: Uzip + run: mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) + #- + #name: set up qemu + #uses: https://github.com/docker/setup-qemu-action@v3 + - + name: Set Docker Buildx + uses: https://github.com/docker/setup-buildx-action@v3 + - + name: Login To Zot + uses: https://github.com/docker/login-action@v3 + with: + registry: zot.164500.xyz + username: test + password: test + - + name: Build And Push Image To Zot + uses: https://github.com/docker/build-push-action@v5 + with: + context: . + push: true + tags: zot.164500.xyz/jj/finance:latest \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd49255 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + +.classpath +.project +.settings +target +/.factorypath diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1a075db --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +#FROM maven:3.9.1-eclipse-temurin-20-alpine as build +#WORKDIR /workspace +#COPY pom.xml . +#COPY src src +#RUN --mount=type=cache,target=/root/.m2,id=m2,sharing=locked \ +#mvn package -Dmaven.test.skip +#RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) +# +FROM docker.io/eclipse-temurin:20-jre-alpine +WORKDIR /app +COPY target/dependency/BOOT-INF/lib /app/lib +COPY target/dependency/META-INF /app/META-INF +COPY target/dependency/BOOT-INF/classes /app +RUN ls + +RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +RUN echo "Asia/Shanghai" > /etc/timezone + +ENTRYPOINT ["java","-cp","/app:/app/lib/*","jj.tech.finance.Application","--spring.profiles.active=prod"] \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..df2bb62 --- /dev/null +++ b/pom.xml @@ -0,0 +1,548 @@ + + + 4.0.0 + jj.tech.finance + finance + finance + jar + 1.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.2.0 + + + 20 + UTF-8 + + + + + + + + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-undertow + + + + + org.springframework.boot + spring-boot-starter-websocket + + + + org.springframework.boot + spring-boot-starter-jooq + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.3 + + + + org.mybatis.dynamic-sql + mybatis-dynamic-sql + 1.5.0 + + + org.mybatis.generator + mybatis-generator-core + 1.4.2 + + + + org.springframework.boot + spring-boot-starter-json + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.springframework.boot + spring-boot-starter-logging + + + + com.github.loki4j + loki-logback-appender + 1.4.1 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + 2.3.0 + + + org.springdoc + springdoc-openapi-starter-common + 2.3.0 + + + + com.h2database + h2 + + + + org.mariadb.jdbc + mariadb-java-client + + + + com.mysql + mysql-connector-j + + + + com.zaxxer + HikariCP + compile + + + + + com.github.penggle + kaptcha + 2.3.2 + + + + org.apache.commons + commons-lang3 + + + commons-codec + commons-codec + + + org.apache.commons + commons-collections4 + 4.4 + + + commons-io + commons-io + 2.15.1 + + + commons-beanutils + commons-beanutils + 1.9.4 + + + org.apache.httpcomponents + fluent-hc + 4.5.14 + + + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + + + + + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + it.ozimov + yaml-properties-maven-plugin + 1.1.3 + + + initialize + + read-project-properties + + + + src/main/resources/application.yml + + + + + + + + + + + + + + + org.jooq + jooq-codegen-maven + + + ${basedir}/src/main/resources/generate/jooq/JooqConfig.xml + + + + generate-jooq + generate-sources + + generate + + + + + + com.h2database + h2 + ${h2.version} + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb.version} + + + + + + + org.mybatis.generator + mybatis-generator-maven-plugin + 1.4.2 + + + true + ${basedir}/src/main/resources/generate/mybatis/generatorConfig.xml + + + + + + generate-myBatis + generate-sources + + generate + + + + + + com.h2database + h2 + ${h2.version} + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb.version} + + + com.mysql + mysql-connector-j + ${mysql.version} + + + + + + + + + + + + + + + + diff --git a/src/main/java/jj/tech/finance/Application.java b/src/main/java/jj/tech/finance/Application.java new file mode 100644 index 0000000..f77dd77 --- /dev/null +++ b/src/main/java/jj/tech/finance/Application.java @@ -0,0 +1,91 @@ +package jj.tech.finance; +import java.util.Arrays; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + + +/** + * @SpringBootApplication 是一个方便的注释, 它添加了以下所有内容: + * + @Configuration 将类标记为应用程序上下文的 bean 定义的源。 + @EnableAutoConfiguration 告诉 spring 引导开始根据类路径设置、其他 bean 和各种属性设置添加 bean。 + 通常你会为 spring mvc 应用程序添加 @EnableWebMvc, 但是 spring 引导在类路径上看到 spring WebMvc 时会自动添加它。这将应用程序标记为 web 应用程序, 并激活诸如设置 DispatcherServlet 之类的关键行为。 + @ComponentScan 告诉 spring 在 hello 包中查找其他组件、配置和服务, 使其能够找到控制器。 + + main () 方法使用 spring 引导的 SpringApplication. run () 方法来启动应用程序。 + 没有单行 xml?没有任何 web. xml 文件。此 web 应用程序是100% 纯 java, 您不必处理配置任何管道或基础结构。 + 还有一个标记为 @Bean 的 CommandLineRunner 方法, 并在启动时运行。它检索所有的 bean, 由您的应用程序创建或自动添加感谢春季启动。它的排序和打印出来。 + * @author Dou + * + */ + +@SpringBootApplication +//@EnableDiscoveryClient +@EnableScheduling +public class Application { + + + //打成war包需要继承 +// @SpringBootApplication +// public class Application extends SpringBootServletInitializer { +// +// @Override +// protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { +// return application.sources(Application.class); +// } +// +// public static void main(String[] args) { +// SpringApplication.run(Application.class, args); +// } + + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public CommandLineRunner commandLineRunner(ApplicationContext ctx) { + return args -> { + System.out.println("Let's inspect the beans provided by Spring Boot:"); + + String[] beanNames = ctx.getBeanDefinitionNames(); + Arrays.sort(beanNames); + for (String beanName : beanNames) { + System.err.println(beanName); + } + }; + } + + +// @StreamListener(IOrderProcessor.INPUT_ORDER) +// public void input(Message message) { +// System.out.println("一般监听收到:" + message.getPayload()); +// } + + + + +// public JdbcConnectionPool JdbcConnectionPool(){ +// String url = "jdbc:h2:~/test"; +// String user = "sa"; +// String password = ""; +// return JdbcConnectionPool.create(url, user, password); +// } + + +// @Bean +// @StreamMessageConverter +// public MessageConverter customMessageConverter() { +// return new MyCustomMessageConverter(); +// } + + +} diff --git a/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoController.java b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoController.java new file mode 100644 index 0000000..199ccf2 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoController.java @@ -0,0 +1,421 @@ +package jj.tech.finance.biz.web.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.*; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.fluent.Request; +import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.where.WhereApplier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.web.dao.ContractInfoSelectMapper; +import jj.tech.finance.biz.webadmin.dao.SelectMapper; +import jj.tech.finance.biz.webadmin.vo.ContractInfoStatu; +import jj.tech.finance.biz.webadmin.vo.ContractInfoStatuScribeStore; +import jj.tech.finance.biz.webadmin.vo.FuturesZhSpot; +import jj.tech.finance.biz.webadmin.vo.parm.Contract; +import jj.tech.finance.biz.webadmin.vo.parm.Id; +import jj.tech.finance.biz.webadmin.vo.parm.P; +import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +import jj.tech.finance.repository.mybatis.dao.ContractInfoStatusScribeMapper; +import jj.tech.finance.repository.mybatis.dao.ContractInfoUserMapper; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoStatusDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoStatusScribeDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoUserDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.ContractInfo; +import jj.tech.finance.repository.mybatis.entity.ContractInfoStatusScribe; +import jj.tech.finance.repository.mybatis.entity.ContractInfoUser; +import jj.tech.finance.repository.mybatis.entity.UserInfo; +import jj.tech.finance.utils.Page; +import jj.tech.finance.utils.R; +import jj.tech.finance.utils.WebUserUtil; + +@RestController +@Tag(name = "contractInfo", description = "PC合约信息") +@RequestMapping(value = "/web/contract", name = "PC合约信息") +public class ContractInfoController { + + @Autowired ObjectMapper objectMapper; + @Autowired ContractInfoMapper contractInfoMapper; + @Autowired ContractInfoUserMapper contractInfoUserMapper; + @Autowired ContractInfoSelectMapper contractInfoSelectMapper; + @Autowired ContractInfoStatusScribeMapper contractInfoStatusScribeMapper; + @Autowired SelectMapper selectMapper; + + @Operation(summary = "合约信息列表", description = " contract_status=1为禁用,其他是启用,scribe_status=1为禁用,其他是启用, store=null是未收藏,有值为已收藏" + + "exchange交易市场: cffex-中金所 dce-大商所 czce-郑商所 shfe-上期所 ine-上海国际能源交易中心 gfex-广州期货交易所。") + @PostMapping("/list") + public Object list(@RequestBody(required = true) Contract parm) { + + Page p = new Page(parm.getPageNum(), parm.getPageSize()); + + UserInfo user = WebUserUtil.getUser(); + if(user == null) { + return R.FALSE("not login"); + } + + var contractInfoUser = select(ContractInfoUserMapper.selectList) + .from(ContractInfoUserDynamicSqlSupport.contractInfoUser) + .where(ContractInfoUserDynamicSqlSupport.userid, isEqualTo(user.getId())) + ; + + + BasicColumn[] allContractInfo = BasicColumn.columnList(ContractInfoDynamicSqlSupport.contractInfo.allColumns()); + BasicColumn[] store = BasicColumn.columnList( + ContractInfoUserDynamicSqlSupport.id.qualifiedWith("contractInfoUser").as("store"), + ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), + ContractInfoStatusDynamicSqlSupport.scribe_status.qualifiedWith("contract_info_status"), + ContractInfoStatusDynamicSqlSupport.scribe_update_time.qualifiedWith("contract_info_status"), + ContractInfoStatusDynamicSqlSupport.scribe_number.qualifiedWith("contract_info_status") + ); + + + BasicColumn[] basic = ArrayUtils.addAll(allContractInfo,store); + String isLikeTsCode = null; + String isLikeSymbol = null; + if(StringUtils.isNotBlank(parm.getTs_code())) { + isLikeTsCode = "%"+parm.getTs_code()+"%"; + } + if(StringUtils.isNotBlank(parm.getSymbol())) { + isLikeSymbol = "%"+parm.getSymbol()+"%"; + } + + + var from = select(basic) + .from(ContractInfoDynamicSqlSupport.contractInfo, "contractInfo") + .leftJoin(contractInfoUser,"contractInfoUser") + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("contractInfo"), + equalTo(ContractInfoUserDynamicSqlSupport.ts_code.qualifiedWith("contractInfoUser"))) + .leftJoin(ContractInfoStatusDynamicSqlSupport.contractInfoStatus) + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("contractInfo"), + equalTo(ContractInfoStatusDynamicSqlSupport.ts_code.qualifiedWith("contract_info_status"))) + ; + var where = SqlBuilder.where(); + where.and( + ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), isNull(), + or(ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), isEqualTo(0))); + where.and(ContractInfoDynamicSqlSupport.contractInfo.ts_code, isLikeWhenPresent(isLikeTsCode), + or(ContractInfoDynamicSqlSupport.contractInfo.symbol, isLikeWhenPresent(isLikeSymbol))); + + + where.and(ContractInfoDynamicSqlSupport.contractInfo.exchange, isEqualToWhenPresent(parm.getExchange())); + + WhereApplier applier = where.toWhereApplier(); + SelectStatementProvider provider = from + .applyWhere(applier) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + List list = contractInfoSelectMapper.selectStroeMany(provider); + + + + + var count = select(count()) + .from(ContractInfoDynamicSqlSupport.contractInfo, "contractInfo") + .leftJoin(contractInfoUser,"contractInfoUser") + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("contractInfo"), + equalTo(ContractInfoUserDynamicSqlSupport.ts_code.qualifiedWith("contractInfoUser"))) + .leftJoin(ContractInfoStatusDynamicSqlSupport.contractInfoStatus) + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("contractInfo"), + equalTo(ContractInfoStatusDynamicSqlSupport.ts_code.qualifiedWith("contract_info_status"))) + .where( + ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), isNull(), + or(ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), isEqualTo(0))) + .and(ContractInfoDynamicSqlSupport.contractInfo.ts_code, isLikeWhenPresent(isLikeTsCode), + or(ContractInfoDynamicSqlSupport.contractInfo.symbol, isLikeWhenPresent(isLikeSymbol))) + .and(ContractInfoDynamicSqlSupport.contractInfo.exchange, isEqualToWhenPresent(parm.getExchange())) + .build() + .render(RenderingStrategies.MYBATIS3); + + long total = selectMapper.count(count); + p.setList(list); + p.setTotal(total); + return R.SUCCESS(p); + + + } + + + + + @Operation(summary = "收藏合约信息", description = "") + @PostMapping("/store") + public Object store(@Valid @RequestBody(required = true) Id id) { + + int contractid = id.getId(); + UserInfo user = WebUserUtil.getUser(); + if(user == null) { + return R.FALSE("not login"); + } + + Optional op = contractInfoMapper.selectByPrimaryKey(contractid); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+contractid); + } + ContractInfo contractInfo = op.get(); + + var contractInfoUser = select(ContractInfoUserMapper.selectList) + .from(ContractInfoUserDynamicSqlSupport.contractInfoUser) + .where(ContractInfoUserDynamicSqlSupport.userid, isEqualTo(user.getId())) + .and(ContractInfoUserDynamicSqlSupport.ts_code, isEqualTo(contractInfo.getTs_code())) + .build() + .render(RenderingStrategies.MYBATIS3); + ; + Optional opInfo = contractInfoUserMapper.selectOne(contractInfoUser); + if(opInfo.isPresent()) { + return R.SUCCESS("ok"); + } + + ContractInfoUser bean = new ContractInfoUser(); + bean.setUserid(user.getId()); + bean.setUsername(user.getUsername()); + bean.setTs_code(contractInfo.getTs_code()); + + contractInfoUserMapper.insertSelective(bean); + return R.SUCCESS("ok"); + } + + + + @Operation(summary = "取消收藏合约信息", description = "") + @PostMapping("/cancel") + public Object cancel(@Valid @RequestBody(required = true) Id id) { + int contractid = id.getId(); + + UserInfo user = WebUserUtil.getUser(); + if(user == null) { + return R.FALSE("not login"); + } + + Optional op = contractInfoMapper.selectByPrimaryKey(contractid); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+contractid); + } + ContractInfo contractInfo = op.get(); + + DeleteStatementProvider deleteStatement = deleteFrom(ContractInfoUserDynamicSqlSupport.contractInfoUser) + .where(ContractInfoUserDynamicSqlSupport.userid, isEqualTo(user.getId())) + .and(ContractInfoUserDynamicSqlSupport.ts_code,isEqualTo(contractInfo.getTs_code())) + .limit(1) + .build() + .render(RenderingStrategies.MYBATIS3); + + contractInfoUserMapper.delete(deleteStatement); + return R.SUCCESS("delete:"+contractid); + } + + + @Operation(summary = "获取当前合约实时数据", description = "获取当前合约实时数据,第三方接口返回数据无法和传入合约数据对应。 只能按一条获取") + @PostMapping("/current") + public Object current(@Valid @RequestBody(required = true) Id id) { + try { + int contractid = id.getId(); + + Optional op = contractInfoMapper.selectByPrimaryKey(contractid); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+contractid); + } + ContractInfo contractInfo = op.get(); + + String symbol = StringUtils.substringBefore(contractInfo.getTs_code(), "."); + String url = + "http://173.249.203.214:8080/api/public/futures_zh_spot?" + + "symbol=" + symbol; + System.out.println(url); + InputStream stean = Request.Get(url) + .connectTimeout(2500) + .socketTimeout(2500) + .execute() + .returnContent() + .asStream(); + //objectMapper.read + List futuresZhSpots = objectMapper.readValue(stean, List.class); + if(!futuresZhSpots.isEmpty()) { + return R.SUCCESS(futuresZhSpots.get(0)); + } + return R.SUCCESS("can not find current date"); + } catch (Exception e) { + + return R.SUCCESS("can not find current date"); + } + + } + + + @Operation(summary = "获取合约划线详情,按contractid获取", description = "") + @PostMapping("/get") + public Object get(@Valid @RequestBody(required = true) Id id) { + Optional op = contractInfoMapper.selectByPrimaryKey(id.getId()); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+id.getId()); + } + ContractInfo contractInfo = op.get(); + var select = select(ContractInfoStatusScribeMapper.selectList) + .from(ContractInfoStatusScribeDynamicSqlSupport.contractInfoStatusScribe) + .where(ContractInfoStatusDynamicSqlSupport.ts_code, isEqualTo(contractInfo.getTs_code())) + .build() + .render(RenderingStrategies.MYBATIS3); + + List list = contractInfoStatusScribeMapper.selectMany(select); + HashMap map = new HashMap(); + map.put("contractInfo", contractInfo); + map.put("scribeList", list); + return R.SUCCESS(map); + } + + + +// public Object current(List list) { +// try { +// +// String symbols = ""; +// for(Object o: list) { +// ContractInfoStatu info = (ContractInfoStatu) o; +// String symbol = StringUtils.substringBefore(info.getTs_code(), "."); +// symbols = symbols+symbol+","; +// }; +// +// String url = +// "http://173.249.203.214:8080/api/public/futures_zh_spot?" +// + "symbol=" + symbols; +// System.out.println(url); +// InputStream stean = Request.Get(url) +// .connectTimeout(2500) +// .socketTimeout(2500) +// .execute() +// .returnContent() +// .asStream(); +// //objectMapper.read +// List FuturesZhSpots = objectMapper.readValue(stean, List.class); +// +// +// +// for(Object o: list) { +// ContractInfoStatu info = (ContractInfoStatu) o; +// for(FuturesZhSpot i: FuturesZhSpots) { +// if(i.getSymbol() == info.getSymbol()) { +// info.setFuturesZhSpot(i); +// } +// } +// +// }; +// +// return list; +// } catch (Exception e) { +// e.printStackTrace(); +// return list; +// } +// +// } + + + + @Operation(summary = "我收藏的合约信息列表", description = "") + @PostMapping("/mylist") + public Object mylist(@RequestBody(required = true) P parm) { + + Page p = new Page(parm.getPageNum(), parm.getPageSize()); + + UserInfo user = WebUserUtil.getUser(); + if(user == null) { + return R.FALSE("not login"); + } + + var contractInfoUser = select(ContractInfoUserMapper.selectList) + .from(ContractInfoUserDynamicSqlSupport.contractInfoUser) + .where(ContractInfoUserDynamicSqlSupport.userid, isEqualTo(user.getId())) + ; + + + BasicColumn[] allContractInfo = BasicColumn.columnList(ContractInfoDynamicSqlSupport.contractInfo.allColumns()); + BasicColumn[] store = BasicColumn.columnList( + ContractInfoUserDynamicSqlSupport.id.qualifiedWith("contractInfoUser").as("store"), + ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), + ContractInfoStatusDynamicSqlSupport.scribe_status.qualifiedWith("contract_info_status"), + ContractInfoStatusDynamicSqlSupport.scribe_update_time.qualifiedWith("contract_info_status"), + ContractInfoStatusDynamicSqlSupport.scribe_number.qualifiedWith("contract_info_status") + ); + + + BasicColumn[] basic = ArrayUtils.addAll(allContractInfo,store); + + + var from = select(basic) + .from(ContractInfoDynamicSqlSupport.contractInfo, "contractInfo") + .leftJoin(contractInfoUser,"contractInfoUser") + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("contractInfo"), + equalTo(ContractInfoUserDynamicSqlSupport.ts_code.qualifiedWith("contractInfoUser"))) + .leftJoin(ContractInfoStatusDynamicSqlSupport.contractInfoStatus) + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("contractInfo"), + equalTo(ContractInfoStatusDynamicSqlSupport.ts_code.qualifiedWith("contract_info_status"))) + ; + var where = SqlBuilder.where(); + where.and( + ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), isNull(), + or(ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), isEqualTo(0))); + where.and(ContractInfoUserDynamicSqlSupport.userid.qualifiedWith("contractInfoUser"), isEqualTo(user.getId())); + + WhereApplier applier = where.toWhereApplier(); + SelectStatementProvider provider = from + .applyWhere(applier) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + var list = contractInfoSelectMapper.selectStroeMany(provider); + + + var count = select(count()) + .from(ContractInfoDynamicSqlSupport.contractInfo, "contractInfo") + .leftJoin(contractInfoUser,"contractInfoUser") + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("contractInfo"), + equalTo(ContractInfoUserDynamicSqlSupport.ts_code.qualifiedWith("contractInfoUser"))) + .leftJoin(ContractInfoStatusDynamicSqlSupport.contractInfoStatus) + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("contractInfo"), + equalTo(ContractInfoStatusDynamicSqlSupport.ts_code.qualifiedWith("contract_info_status"))) + .where( + ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), isNull(), + or(ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("contract_info_status"), isEqualTo(0))) + .and(ContractInfoUserDynamicSqlSupport.userid.qualifiedWith("contractInfoUser"), isEqualTo(user.getId())) + .build() + .render(RenderingStrategies.MYBATIS3); + + long total = selectMapper.count(count); + p.setList(list); + p.setTotal(total); + return R.SUCCESS(p); + + + } + +} diff --git a/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoDaily.java b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoDaily.java new file mode 100644 index 0000000..6b295f9 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoDaily.java @@ -0,0 +1,93 @@ +package jj.tech.finance.biz.web.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.isEqualToWhenPresent; +import static org.mybatis.dynamic.sql.SqlBuilder.isGreaterThanOrEqualToWhenPresent; +import static org.mybatis.dynamic.sql.SqlBuilder.isLessThanOrEqualToWhenPresent; +import static org.mybatis.dynamic.sql.SqlBuilder.select; + +import org.apache.commons.lang3.StringUtils; +import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.where.WhereApplier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jj.tech.finance.biz.webadmin.vo.parm.Daily; +import jj.tech.finance.repository.mybatis.dao.FutDailyMapper; +import jj.tech.finance.repository.mybatis.dao.support.FutDailyDynamicSqlSupport; +import jj.tech.finance.utils.Page; +import jj.tech.finance.utils.R; + +@RestController +@Tag(name = "contractInfoDaily", description = "合约日线行情") +@RequestMapping(value = "/web/daily", name = "合约日线行情") +public class ContractInfoDaily { + + @Autowired FutDailyMapper futDailyMapper; + + + + @Operation(summary = "日线列表", description = "ts_code合约代码, trade_date交易日期 (yyyy-MM-dd格式,下同)") + @PostMapping("/list") + public Object list(@RequestBody(required = true) Daily parm) { + + Page p = new Page(parm.getPageNum(), parm.getPageSize()); + + var from = select(FutDailyMapper.selectList) + .from(FutDailyDynamicSqlSupport.futDaily); + + if(StringUtils.isNoneBlank(parm.getTs_code()) + || parm.getTrade_date() !=null + || parm.getStart_date() != null + || parm.getEnd_date() != null + ) { + var where = SqlBuilder.where(); + where.and(FutDailyDynamicSqlSupport.ts_code, isEqualToWhenPresent(parm.getTs_code())); + where.and(FutDailyDynamicSqlSupport.trade_date, isEqualToWhenPresent(parm.getTrade_date())); + if(parm.getTrade_date() ==null) { + where.and(FutDailyDynamicSqlSupport.trade_date, isGreaterThanOrEqualToWhenPresent(parm.getStart_date())); + where.and(FutDailyDynamicSqlSupport.trade_date, isLessThanOrEqualToWhenPresent(parm.getEnd_date())); + } + + WhereApplier applier = where.toWhereApplier(); + SelectStatementProvider provider = from + .applyWhere(applier) + .orderBy(FutDailyDynamicSqlSupport.trade_date.descending()) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + var list = futDailyMapper.selectMany(provider); + long total = futDailyMapper.count(c->c.applyWhere(applier)); + p.setList(list); + p.setTotal(total); + return R.SUCCESS(p); + } + + + + SelectStatementProvider provider = from + .orderBy(FutDailyDynamicSqlSupport.trade_date.descending()) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + var list = futDailyMapper.selectMany(provider); + long total = futDailyMapper.count(c->c); + p.setList(list); + p.setTotal(total); + return R.SUCCESS(p); + + } + + + +} diff --git a/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoMinute.java b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoMinute.java new file mode 100644 index 0000000..0201a9e --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoMinute.java @@ -0,0 +1,68 @@ +package jj.tech.finance.biz.web.controller; + +import java.io.InputStream; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.fluent.Request; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jj.tech.finance.biz.webadmin.vo.parm.Minute; +import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +import jj.tech.finance.repository.mybatis.entity.ContractInfo; +import jj.tech.finance.utils.R; + +@RestController +@Tag(name = "contractInfoMinute", description = "合约分钟行情") +@RequestMapping(value = "/web/minute", name = "合约分钟行情") +public class ContractInfoMinute { + @Autowired ObjectMapper objectMapper; + @Autowired ContractInfoMapper contractInfoMapper; + + + @Operation(summary = "分钟列表", description = "id=合约ID; period= 1:1分钟,5:5分钟,15:15分钟,30:30分钟,60:60分钟") + @PostMapping("/list") + public Object list(@RequestBody(required = true) Minute parm) { + + Optional op = contractInfoMapper.selectByPrimaryKey(parm.getId()); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+parm.getId()); + } + ContractInfo contractInfo = op.get(); + String symbol = StringUtils.substringBefore(contractInfo.getTs_code(), "."); + if(parm.getPeriod() == null) { + parm.setPeriod(60); + } + try { + String url = + "http://173.249.203.214:8080/api/public/futures_zh_minute_sina?" + + "symbol=" + symbol + + "&period=" + parm.getPeriod(); + System.out.println(url); + InputStream stean = Request.Get(url) + .connectTimeout(10000) + .socketTimeout(10000) + .execute() + .returnContent() + .asStream(); + JsonNode root = objectMapper.readTree(stean); + return R.SUCCESS(root); + } catch (Exception e) { + e.printStackTrace(); + } + + + return R.SUCCESS("get akshare date fail"); + + } + +} diff --git a/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoMonth.java b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoMonth.java new file mode 100644 index 0000000..33370ec --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoMonth.java @@ -0,0 +1,81 @@ +package jj.tech.finance.biz.web.controller; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.mybatis.dynamic.sql.select.render.DefaultSelectStatementProvider; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.webadmin.dao.SelectMapper; +import jj.tech.finance.biz.webadmin.vo.parm.Id; +import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +import jj.tech.finance.repository.mybatis.dao.FutDailyMapper; +import jj.tech.finance.repository.mybatis.entity.ContractInfo; +import jj.tech.finance.utils.R; + +@RestController +@Tag(name = "contractInfoMonth", description = "合约月行情") +@RequestMapping(value = "/web/month", name = "合约月行情") +public class ContractInfoMonth { + @Autowired FutDailyMapper futDailyMapper; + @Autowired ContractInfoMapper contractInfoMapper; + @Autowired SelectMapper selectMapper; + + @Operation(summary = "月线列表", description = "按contractid获取") + @PostMapping("/list") + public Object list(@Valid @RequestBody(required = true) Id id) { + + Optional op = contractInfoMapper.selectByPrimaryKey(id.getId()); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+id.getId()); + } + ContractInfo contractInfo = op.get(); + + + String select_sql = + """ + SELECT a.*, b.open, c.close FROM ( + SELECT ts_code, MIN(low) AS low, + MAX(high) AS high, EXTRACT(YEAR_MONTH from trade_date) AS monthdate, + MIN(trade_date) AS mindate, MAX(trade_date) AS maxdate + FROM fut_daily + WHERE ts_code = #{parameters.ts_code} + GROUP BY EXTRACT(YEAR_MONTH from trade_date) + ) AS a + LEFT JOIN + ( + SELECT * FROM fut_daily WHERE ts_code = #{parameters.ts_code} + ) AS b + ON (a.mindate = b.trade_date) + LEFT JOIN + ( + SELECT * FROM fut_daily WHERE ts_code = #{parameters.ts_code} + ) AS c + ON (a.maxdate = c.trade_date) + GROUP BY monthdate + ORDER BY monthdate + LIMIT 2000 + """; + + Map p = new HashMap(); + p.put("ts_code", contractInfo.getTs_code()); + + + SelectStatementProvider provider = DefaultSelectStatementProvider + .withSelectStatement(select_sql) + .withParameters(p) + .build(); + var list = selectMapper.selectMany(provider); + return R.SUCCESS(list); + + } +} diff --git a/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoWeek.java b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoWeek.java new file mode 100644 index 0000000..c30cace --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/web/controller/ContractInfoWeek.java @@ -0,0 +1,88 @@ +package jj.tech.finance.biz.web.controller; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.mybatis.dynamic.sql.select.render.DefaultSelectStatementProvider; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.webadmin.dao.SelectMapper; +import jj.tech.finance.biz.webadmin.vo.parm.Id; +import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +import jj.tech.finance.repository.mybatis.dao.FutDailyMapper; +import jj.tech.finance.repository.mybatis.entity.ContractInfo; +import jj.tech.finance.utils.R; + +@RestController +@Tag(name = "contractInfoWeek", description = "合约周行情") +@RequestMapping(value = "/web/week", name = "合约周行情") +public class ContractInfoWeek { + + + @Autowired FutDailyMapper futDailyMapper; + @Autowired ContractInfoMapper contractInfoMapper; + @Autowired SelectMapper selectMapper; + + + + + @Operation(summary = "周线列表", description = "按contractid获取") + @PostMapping("/list") + public Object list(@Valid @RequestBody(required = true) Id id) { + + Optional op = contractInfoMapper.selectByPrimaryKey(id.getId()); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+id.getId()); + } + ContractInfo contractInfo = op.get(); + + + String select_sql = + """ + SELECT a.*, b.open, c.close FROM ( + SELECT ts_code, MIN(low) AS low, + MAX(high) AS high, YEARWEEK(trade_date, 1) AS weekdate, + MIN(trade_date) AS mindate, MAX(trade_date) AS maxdate + FROM fut_daily + WHERE ts_code = #{parameters.ts_code} + GROUP BY YEARWEEK(trade_date, 1) + ) AS a + LEFT JOIN + ( + SELECT * FROM fut_daily WHERE ts_code = #{parameters.ts_code} + ) AS b + ON (a.mindate = b.trade_date) + LEFT JOIN + ( + SELECT * FROM fut_daily WHERE ts_code = #{parameters.ts_code} + ) AS c + ON (a.maxdate = c.trade_date) + GROUP BY weekdate + ORDER BY weekdate + LIMIT 2000 + """; + + Map p = new HashMap(); + p.put("ts_code", contractInfo.getTs_code()); + + + SelectStatementProvider provider = DefaultSelectStatementProvider + .withSelectStatement(select_sql) + .withParameters(p) + .build(); + var list = selectMapper.selectMany(provider); + return R.SUCCESS(list); + + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/web/controller/LoginController.java b/src/main/java/jj/tech/finance/biz/web/controller/LoginController.java new file mode 100644 index 0000000..eabf05a --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/web/controller/LoginController.java @@ -0,0 +1,88 @@ +package jj.tech.finance.biz.web.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo; +import static org.mybatis.dynamic.sql.SqlBuilder.select; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.webadmin.vo.parm.Id; +import jj.tech.finance.biz.webadmin.vo.parm.Login; +import jj.tech.finance.repository.mybatis.dao.UserInfoMapper; +import jj.tech.finance.repository.mybatis.dao.support.UserInfoDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.UserInfo; +import jj.tech.finance.utils.R; +import jj.tech.finance.utils.WebUserUtil; + +@RestController +@Tag(name = "login", description = "用户前台登录") +@RequestMapping(value = "/web", name = "登录") +public class LoginController { + @Autowired UserInfoMapper userInfoMapper; + @Autowired ObjectMapper objectMapper; + + @Operation(summary = "前台pc登录", description = "测试:user 000000 或 user1 000000") + @PostMapping("/login") + public Object login(@Valid @RequestBody(required = true) Login parm) { + + + + String passwordEncode = DigestUtils.sha3_256Hex(parm.getPassword()); + + var provider = select(UserInfoMapper.selectList) + .from(UserInfoDynamicSqlSupport.userInfo) + .where(UserInfoDynamicSqlSupport.username, isEqualTo(parm.username)) + .build() + .render(RenderingStrategies.MYBATIS3); + + Optional op = userInfoMapper.selectOne(provider); + if(!op.isPresent()) { + return R.FALSE("用户不存在"); + } + UserInfo bean = op.get(); + if(!passwordEncode.equals(bean.getPassword())) { + return R.FALSE("密码错误"); + } + + if(bean.getId()!=1 && bean.getIslock() == 1) { + return R.FALSE("用户已被禁用"); + } + bean.setPassword(null); + + Map h = objectMapper.convertValue(bean, Map.class); + h.put("logintime", System.currentTimeMillis()); + String token = WebUserUtil.addToCookie(h); + HashMap map = new HashMap(); + map.put("webtoken", token); + map.put("admin", bean); + return R.SUCCESS(map); + } + + + + @Operation(summary = "登出", description = "") + @PostMapping("/logout") + public Object logout() { + WebUserUtil.deleteUser(); + return R.SUCCESS("logout is ok"); + } + + + +} diff --git a/src/main/java/jj/tech/finance/biz/web/dao/ContractInfoSelectMapper.java b/src/main/java/jj/tech/finance/biz/web/dao/ContractInfoSelectMapper.java new file mode 100644 index 0000000..15c64c2 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/web/dao/ContractInfoSelectMapper.java @@ -0,0 +1,28 @@ +package jj.tech.finance.biz.web.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.SelectProvider; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.util.SqlProviderAdapter; +import org.mybatis.dynamic.sql.util.mybatis3.CommonCountMapper; +import org.mybatis.dynamic.sql.util.mybatis3.CommonDeleteMapper; +import org.mybatis.dynamic.sql.util.mybatis3.CommonUpdateMapper; + +import jj.tech.finance.biz.webadmin.vo.ContractInfoStatu; +import jj.tech.finance.biz.webadmin.vo.ContractInfoStatuScribe; +import jj.tech.finance.biz.webadmin.vo.ContractInfoStatuScribeStore; + +@Mapper +public interface ContractInfoSelectMapper extends CommonCountMapper, CommonDeleteMapper, CommonUpdateMapper{ + + @SelectProvider(type=SqlProviderAdapter.class, method="select") + List selectStroeMany (SelectStatementProvider selectStatement); + + @SelectProvider(type=SqlProviderAdapter.class, method="select") + List selectStatuMany (SelectStatementProvider selectStatement); + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/controller/ContractInfoManageController.java b/src/main/java/jj/tech/finance/biz/webadmin/controller/ContractInfoManageController.java new file mode 100644 index 0000000..0451f39 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/controller/ContractInfoManageController.java @@ -0,0 +1,267 @@ +package jj.tech.finance.biz.webadmin.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.*; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; +import org.mybatis.dynamic.sql.select.SelectModel; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.where.WhereApplier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.web.dao.ContractInfoSelectMapper; +import jj.tech.finance.biz.webadmin.dao.SelectMapper; +import jj.tech.finance.biz.webadmin.vo.parm.Contract; +import jj.tech.finance.biz.webadmin.vo.parm.Ids; +import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +import jj.tech.finance.repository.mybatis.dao.ContractInfoStatusMapper; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoStatusDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.ContractInfo; +import jj.tech.finance.repository.mybatis.entity.ContractInfoStatus; +import jj.tech.finance.repository.mybatis.entity.SysAdmin; +import jj.tech.finance.utils.Page; +import jj.tech.finance.utils.R; +import jj.tech.finance.utils.WebAdminUtil; + +@RestController +@Tag(name = "contractInfoManage", description = "合约管理-已对接") +@RequestMapping(value = "/op/contract", name = "合约管理-已对接") +public class ContractInfoManageController { + + @Autowired ObjectMapper objectMapper; + @Autowired ContractInfoMapper contractInfoMapper; + @Autowired ContractInfoStatusMapper contractInfoStatusMapper; + @Autowired ContractInfoSelectMapper contractInfoSelectMapper; + + @Autowired SelectMapper selectMapper; + + + @Operation(summary = "合约信息列表", description = "ts_code合约代码, symbol交易代码,exchange交易所") + @PostMapping("/list") + public Object list(@RequestBody(required = true) Contract parm) { + +// SysAdmin admin = WebAdminUtil.getUser(); +// if(admin == null) { +// return R.FALSE("not login"); +// } + + Page p = new Page(parm.getPageNum(), parm.getPageSize()); + + BasicColumn[] info = BasicColumn.columnList(ContractInfoDynamicSqlSupport.contractInfo.allColumns()); + + BasicColumn[] statu = BasicColumn.columnList( + ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("status"), + ContractInfoStatusDynamicSqlSupport.scribe_status.qualifiedWith("status"), + ContractInfoStatusDynamicSqlSupport.scribe_update_time.qualifiedWith("status"), + ContractInfoStatusDynamicSqlSupport.scribe_number.qualifiedWith("status") + ); + + BasicColumn[] basic = ArrayUtils.addAll(info,statu); + + Function, QueryExpressionDSL.JoinSpecificationFinisher> function = + s -> { + + var from = s + .from(ContractInfoDynamicSqlSupport.contractInfo, "info") + .leftJoin(ContractInfoStatusDynamicSqlSupport.contractInfoStatus, "status") + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("info"), + equalTo(ContractInfoStatusDynamicSqlSupport.ts_code.qualifiedWith("status"))) + ; + + return from; + }; + + + if(StringUtils.isNoneBlank(parm.getTs_code()) + || StringUtils.isNoneBlank(parm.getSymbol()) + || StringUtils.isNoneBlank(parm.getExchange())) { + + + var where = SqlBuilder.where(); + String likename = null; + if(StringUtils.isNotBlank(parm.getTs_code())) { + likename = "%"+parm.getTs_code()+"%"; + } + where.and(ContractInfoDynamicSqlSupport.contractInfo.ts_code, isLikeWhenPresent(likename), + or(ContractInfoDynamicSqlSupport.contractInfo.name, isLikeWhenPresent(likename))); + where.and(ContractInfoDynamicSqlSupport.contractInfo.symbol, isEqualToWhenPresent(parm.getSymbol())); + where.and(ContractInfoDynamicSqlSupport.contractInfo.exchange, isEqualToWhenPresent(parm.getExchange())); + + WhereApplier applier = where.toWhereApplier(); + + SelectStatementProvider provider = function.apply(select(basic)) + .applyWhere(applier) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + SelectStatementProvider count = function.apply(select(count())) + .applyWhere(applier) + .build().render(RenderingStrategies.MYBATIS3); + + var list = contractInfoSelectMapper.selectStatuMany(provider); + + List l = + list.stream().map(i->{ + Map m = objectMapper.convertValue(i, Map.class); + m.put("idname", "ZGQH"+String.format("%04d", m.get("id"))); + return m; + }).collect(Collectors.toList()); + + long total = contractInfoSelectMapper.count(count); + p.setList(l); + p.setTotal(total); + return R.SUCCESS(p); + } + + + + SelectStatementProvider provider = function.apply(select(basic)) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + SelectStatementProvider count = function.apply(select(count())) + .build().render(RenderingStrategies.MYBATIS3); + + var list = contractInfoSelectMapper.selectStatuMany(provider); + List l = + list.stream().map(i->{ + Map m = objectMapper.convertValue(i, Map.class); + m.put("idname", "ZGQH"+String.format("%04d", m.get("id"))); + return m; + }).collect(Collectors.toList()); + long total = contractInfoSelectMapper.count(count); + p.setList(l); + p.setTotal(total); + return R.SUCCESS(p); + } + + + + + @Operation(summary = "启用合约信息", description = "传入contractid") + @PostMapping("/open") + public Object open(@Valid @RequestBody(required = true) Ids ids) { + + if(ids.getIds().size()<1 || ids.getIds().size() >100) { + return R.FALSE("1 <= contractids <= 100"); + } + + SysAdmin admin = WebAdminUtil.getUser(); + if(admin == null) { + return R.FALSE("not login"); + } + + for(Integer contractid : ids.getIds()){ + Optional op = contractInfoMapper.selectByPrimaryKey(contractid); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+contractid); + } + ContractInfo contractInfo = op.get(); + + var select = select(ContractInfoStatusMapper.selectList) + .from(ContractInfoStatusDynamicSqlSupport.contractInfoStatus) + .where(ContractInfoStatusDynamicSqlSupport.ts_code, isEqualTo(contractInfo.getTs_code())) + .limit(1) + .build() + .render(RenderingStrategies.MYBATIS3); + + Optional opStatu = contractInfoStatusMapper.selectOne(select); + + if(!opStatu.isPresent()) { + ContractInfoStatus bean = new ContractInfoStatus(); + bean.setTs_code(contractInfo.getTs_code()); + contractInfoStatusMapper.insertSelective(bean); + } + ContractInfoStatus info = opStatu.get(); + info.setContract_status(0); + info.setScribe_status(null); + info.setScribe_status(null); + info.setScribe_update_time(null); + info.setScribe_number(null); + info.setTs_code(null); + contractInfoStatusMapper.updateByPrimaryKeySelective(info); + } + + return R.SUCCESS("ok"); + } + + + + @Operation(summary = "关闭合约信息", description = "传入contractid") + @PostMapping("/close") + public Object close(@Valid @RequestBody(required = true) Ids ids) { + + if(ids.getIds().size()<1 || ids.getIds().size() >100) { + return R.FALSE("1 <= contractids <= 100"); + } + SysAdmin admin = WebAdminUtil.getUser(); + if(admin == null) { + return R.FALSE("not login"); + } + + for(Integer contractid : ids.getIds()){ + Optional op = contractInfoMapper.selectByPrimaryKey(contractid); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+contractid); + } + ContractInfo contractInfo = op.get(); + + + var select = select(ContractInfoStatusMapper.selectList) + .from(ContractInfoStatusDynamicSqlSupport.contractInfoStatus) + .where(ContractInfoStatusDynamicSqlSupport.ts_code, isEqualTo(contractInfo.getTs_code())) + .limit(1) + .build() + .render(RenderingStrategies.MYBATIS3); + + Optional opStatu = contractInfoStatusMapper.selectOne(select); + + if(!opStatu.isPresent()) { + ContractInfoStatus bean = new ContractInfoStatus(); + bean.setTs_code(contractInfo.getTs_code()); + bean.setContract_status(1); + contractInfoStatusMapper.insertSelective(bean); + } + ContractInfoStatus info = opStatu.get(); + info.setContract_status(1); + info.setScribe_status(null); + info.setScribe_status(null); + info.setScribe_update_time(null); + info.setScribe_number(null); + info.setTs_code(null); + contractInfoStatusMapper.updateByPrimaryKeySelective(info); + + } + + return R.SUCCESS("ok"); + } + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/controller/ContractInfoScribeController.java b/src/main/java/jj/tech/finance/biz/webadmin/controller/ContractInfoScribeController.java new file mode 100644 index 0000000..db147ce --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/controller/ContractInfoScribeController.java @@ -0,0 +1,342 @@ +package jj.tech.finance.biz.webadmin.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.*; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.QueryExpressionDSL; +import org.mybatis.dynamic.sql.select.SelectModel; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.where.WhereApplier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.web.dao.ContractInfoSelectMapper; +import jj.tech.finance.biz.webadmin.dao.SelectMapper; +import jj.tech.finance.biz.webadmin.vo.ScribeVo; +import jj.tech.finance.biz.webadmin.vo.parm.Contract; +import jj.tech.finance.biz.webadmin.vo.parm.Id; +import jj.tech.finance.biz.webadmin.vo.parm.Ids; +import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +import jj.tech.finance.repository.mybatis.dao.ContractInfoStatusMapper; +import jj.tech.finance.repository.mybatis.dao.ContractInfoStatusScribeMapper; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoStatusDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoStatusScribeDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.ContractInfo; +import jj.tech.finance.repository.mybatis.entity.ContractInfoStatus; +import jj.tech.finance.repository.mybatis.entity.ContractInfoStatusScribe; +import jj.tech.finance.repository.mybatis.entity.SysAdmin; +import jj.tech.finance.utils.Page; +import jj.tech.finance.utils.R; +import jj.tech.finance.utils.WebAdminUtil; + +@RestController +@Tag(name = "contractInfoScribe", description = "划线管理") +@RequestMapping(value = "/op/scribe", name = "划线管理") +public class ContractInfoScribeController { + + @Autowired ObjectMapper objectMapper; + @Autowired ContractInfoMapper contractInfoMapper; + @Autowired ContractInfoStatusMapper contractInfoStatusMapper; + @Autowired ContractInfoStatusScribeMapper contractInfoStatusScribeMapper; + @Autowired ContractInfoSelectMapper contractInfoSelectMapper; + @Autowired SelectMapper selectMapper; + + @Operation(summary = "合约信息列表", description = "ts_code合约代码, symbol交易代码,exchange交易所") + @PostMapping("/list") + public Object list(@RequestBody(required = true) Contract parm) { + +// SysAdmin admin = WebAdminUtil.getUser(); +// if(admin == null) { +// return R.FALSE("not login"); +// } + + Page p = new Page(parm.getPageNum(), parm.getPageSize()); + + BasicColumn[] info = BasicColumn.columnList(ContractInfoDynamicSqlSupport.contractInfo.allColumns()); + + BasicColumn[] statu = BasicColumn.columnList( + ContractInfoStatusDynamicSqlSupport.contract_status.qualifiedWith("status"), + ContractInfoStatusDynamicSqlSupport.scribe_status.qualifiedWith("status"), + ContractInfoStatusDynamicSqlSupport.scribe_update_time.qualifiedWith("status"), + ContractInfoStatusDynamicSqlSupport.scribe_number.qualifiedWith("status") + ); + + BasicColumn[] basic = ArrayUtils.addAll(info,statu); + + Function, QueryExpressionDSL.JoinSpecificationFinisher> function = + s -> { + + var from = s + .from(ContractInfoDynamicSqlSupport.contractInfo, "info") + .leftJoin(ContractInfoStatusDynamicSqlSupport.contractInfoStatus, "status") + .on(ContractInfoDynamicSqlSupport.ts_code.qualifiedWith("info"), + equalTo(ContractInfoStatusDynamicSqlSupport.ts_code.qualifiedWith("status"))) + ; + + return from; + }; + + var where = SqlBuilder.where(); + where.and(ContractInfoStatusDynamicSqlSupport.contractInfoStatus.contract_status.as("status"), isEqualTo(0), + or(ContractInfoStatusDynamicSqlSupport.contractInfoStatus.contract_status.as("status"), isNull()) + ); + + String likename = null; + if(StringUtils.isNotBlank(parm.getTs_code())) { + likename = "%"+parm.getTs_code()+"%"; + } + + where.and(ContractInfoDynamicSqlSupport.contractInfo.ts_code, isLikeWhenPresent(likename), + or(ContractInfoDynamicSqlSupport.contractInfo.name, isLikeWhenPresent(likename))); + where.and(ContractInfoDynamicSqlSupport.contractInfo.symbol, isEqualToWhenPresent(parm.getSymbol())); + where.and(ContractInfoDynamicSqlSupport.contractInfo.exchange, isEqualToWhenPresent(parm.getExchange())); + + WhereApplier applier = where.toWhereApplier(); + SelectStatementProvider provider = function.apply(select(basic)) + .applyWhere(applier) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + SelectStatementProvider count = function.apply(select(count())) + .applyWhere(applier) + .build().render(RenderingStrategies.MYBATIS3); + + var list = contractInfoSelectMapper.selectStatuMany(provider); + long total = contractInfoSelectMapper.count(count); + + + var l = + list.stream().map(i->{ + Map m = objectMapper.convertValue(i, Map.class); + m.put("idname", "ZGQH"+String.format("%04d", m.get("id"))); + return m; + }).collect(Collectors.toList()); + p.setList(l); + p.setTotal(total); + return R.SUCCESS(p); + } + + + + + @Operation(summary = "启用划线功能", description = "传入contractid") + @PostMapping("/open") + public Object open(@Valid @RequestBody(required = true) Ids ids) { + if(ids.getIds().size()<1 || ids.getIds().size() >100) { + return R.FALSE("1 <= contractids <= 100"); + } + SysAdmin admin = WebAdminUtil.getUser(); + if(admin == null) { + return R.FALSE("not login"); + } + + for(Integer contractid : ids.getIds()){ + Optional op = contractInfoMapper.selectByPrimaryKey(contractid); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+contractid); + } + ContractInfo contractInfo = op.get(); + + var select = select(ContractInfoStatusMapper.selectList) + .from(ContractInfoStatusDynamicSqlSupport.contractInfoStatus) + .where(ContractInfoStatusDynamicSqlSupport.ts_code, isEqualTo(contractInfo.getTs_code())) + .limit(1) + .build() + .render(RenderingStrategies.MYBATIS3); + + Optional opStatu = contractInfoStatusMapper.selectOne(select); + + if(!opStatu.isPresent()) { + ContractInfoStatus bean = new ContractInfoStatus(); + bean.setTs_code(contractInfo.getTs_code()); + bean.setContract_status(0); + bean.setScribe_status(0); + bean.setScribe_number(0); + bean.setScribe_update_time(LocalDateTime.now()); + contractInfoStatusMapper.insertSelective(bean); + } + ContractInfoStatus bean = opStatu.get(); + bean.setScribe_status(0); + bean.setScribe_update_time(LocalDateTime.now()); + bean.setScribe_number(null); + bean.setContract_status(null); + bean.setTs_code(null); + contractInfoStatusMapper.updateByPrimaryKeySelective(bean); + } + + + return R.SUCCESS("ok"); + } + + + + @Operation(summary = "禁用划线功能", description = "传入contractid") + @PostMapping("/close") + public Object close(@Valid @RequestBody(required = true) Ids ids) { + if(ids.getIds().size()<1 || ids.getIds().size() >100) { + return R.FALSE("1 <= contractids <= 100"); + } + SysAdmin admin = WebAdminUtil.getUser(); + if(admin == null) { + return R.FALSE("not login"); + } + + for(Integer contractid : ids.getIds()){ + Optional op = contractInfoMapper.selectByPrimaryKey(contractid); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+contractid); + } + ContractInfo contractInfo = op.get(); + + + var select = select(ContractInfoStatusMapper.selectList) + .from(ContractInfoStatusDynamicSqlSupport.contractInfoStatus) + .where(ContractInfoStatusDynamicSqlSupport.ts_code, isEqualTo(contractInfo.getTs_code())) + .limit(1) + .build() + .render(RenderingStrategies.MYBATIS3); + + Optional opStatu = contractInfoStatusMapper.selectOne(select); + + if(!opStatu.isPresent()) { + ContractInfoStatus bean = new ContractInfoStatus(); + bean.setTs_code(contractInfo.getTs_code()); + bean.setScribe_status(1); + bean.setScribe_update_time(LocalDateTime.now()); + contractInfoStatusMapper.insertSelective(bean); + } + ContractInfoStatus bean = opStatu.get(); + bean.setScribe_status(1); + bean.setScribe_update_time(LocalDateTime.now()); + bean.setContract_status(null); + bean.setTs_code(null); + contractInfoStatusMapper.updateByPrimaryKeySelective(bean); + } + + + + return R.SUCCESS("ok"); + } + + @Operation(summary = "添加或更新划线详情", description = "scribeids同一合约不能重复:1:普通/动态支撑,2:普通/动态压力,3:高级支撑,4:高级压力,5:高级重合位 6,7.....
scribe_value: 划线值
demo:
" + + "{contractid\": 1,\r\n" + + " \"list\": [\r\n" + + " {\r\n" + + " \"scribe_id\": 1,\r\n" + + " \"scribe_value\": 100\r\n" + + " }\r\n" + + " ]\r\n" + + "}") + @PostMapping("/add") + @Transactional + public Object add(@RequestBody(required = true) ScribeVo parm) { + + if(parm.getContractid() == null) { + return R.FALSE("contractid must not null"); + } + + + + SysAdmin admin = WebAdminUtil.getUser(); + if(admin == null) { + return R.FALSE("not login"); + } + Optional op = contractInfoMapper.selectByPrimaryKey(parm.getContractid()); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+parm.getContractid()); + } + ContractInfo info = op.get(); + + + Integer sum = 0; + for(ContractInfoStatusScribe i : parm.getList()) { + if(i.getScribe_id() >= 1 && i.getScribe_id() <= 9) { + ContractInfoStatusScribe entity = new ContractInfoStatusScribe(); + entity.setScribe_id(i.getScribe_id()); + entity.setScribe_value(i.getScribe_value()); + entity.setColour(i.getColour()); + entity.setTs_code(info.getTs_code()); + int s=0; + if(i.getId()==null) { + s = contractInfoStatusScribeMapper.insertSelective(entity); + }else { + entity.setId(i.getId()); + s = contractInfoStatusScribeMapper.updateByPrimaryKeySelective(entity); + } + + sum=s+sum; + } + + } + + return R.SUCCESS("add:"+sum); + } + + + + + @Operation(summary = "获取合约划线详情,按contractid获取", description = "") + @PostMapping("/get") + public Object get(@Valid @RequestBody(required = true) Id id) { + Optional op = contractInfoMapper.selectByPrimaryKey(id.getId()); + if(!op.isPresent()) { + return R.FALSE("cannot fine this contractid:"+id.getId()); + } + ContractInfo contractInfo = op.get(); + var select = select(ContractInfoStatusScribeMapper.selectList) + .from(ContractInfoStatusScribeDynamicSqlSupport.contractInfoStatusScribe) + .where(ContractInfoStatusDynamicSqlSupport.ts_code, isEqualTo(contractInfo.getTs_code())) + .build() + .render(RenderingStrategies.MYBATIS3); + + List list = contractInfoStatusScribeMapper.selectMany(select); + HashMap map = new HashMap(); + map.put("contractInfo", contractInfo); + map.put("scribeList", list); + return R.SUCCESS(map); + } + + @Operation(summary = "删除划线详情,按划线详情的ID删除", description = "") + @PostMapping("/delete") + public Object delete(@Valid @RequestBody(required = true) Id id) { + +// DeleteStatementProvider deleteStatement = deleteFrom(ContractInfoStatusScribeDynamicSqlSupport.contractInfoStatusScribe) +// .where(ContractInfoStatusScribeDynamicSqlSupport.ts_code, isEqualTo(info.getTs_code())) +// .limit(5) +// .build() +// .render(RenderingStrategies.MYBATIS3); +// +//contractInfoStatusScribeMapper.delete(deleteStatement); + int sum = contractInfoStatusScribeMapper.deleteByPrimaryKey(id.getId()); + return R.SUCCESS("delete :" + sum); + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/controller/GetFutDailyController.java b/src/main/java/jj/tech/finance/biz/webadmin/controller/GetFutDailyController.java new file mode 100644 index 0000000..5cb614c --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/controller/GetFutDailyController.java @@ -0,0 +1,463 @@ +package jj.tech.finance.biz.webadmin.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.*; + +import java.io.InputStream; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.client.fluent.Request; +import org.apache.http.entity.ContentType; +import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.render.DefaultSelectStatementProvider; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jj.tech.finance.biz.webadmin.service.DailyService; +import jj.tech.finance.config.enums.Exchange; +import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +import jj.tech.finance.repository.mybatis.dao.FutDailyMapper; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.dao.support.FutDailyDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.ContractInfo; +import jj.tech.finance.repository.mybatis.entity.FutDaily; +import jj.tech.finance.utils.R; +import jj.tech.finance.utils.tushare.TushareConfig; + +@RestController +@Tag(name = "futDaily", description = "获取日线信息") +public class GetFutDailyController { + private static Logger logger = LoggerFactory.getLogger(GetFutDailyController.class); + + + @Autowired ObjectMapper objectMapper; + @Autowired ContractInfoMapper contractInfoMapper; + @Autowired FutDailyMapper futDailyMapper; + + + @Autowired DailyService dailyService; + + +// @Operation(summary = "获取日线信息", description = "") +// @GetMapping("/getDate") +// public Object getDate() { +// +// var ts_codes = select(FutDailyDynamicSqlSupport.ts_code) +// .from(FutDailyDynamicSqlSupport.futDaily) +// .groupBy(FutDailyDynamicSqlSupport.futDaily.ts_code); +// +// var from = select(ContractInfoMapper.selectList) +// .from(ContractInfoDynamicSqlSupport.contractInfo) +// .where(ContractInfoDynamicSqlSupport.contractInfo.ts_code, isNotIn(ts_codes)) +// //.groupBy(ContractInfoDynamicSqlSupport.contractInfo.ts_code) +// .build() +// .render(RenderingStrategies.MYBATIS3); +// +// List contractInfos = contractInfoMapper.selectMany(from); +// +// contractInfos.forEach(i->{ +// try { +// HashMap h = new HashMap(); +// h.put("api_name", "fut_daily"); +// h.put("token", TushareConfig.TOKEN); +// HashMap params = new HashMap(); +// params.put("ts_code", i.getTs_code()); +// params.put("limit", 10000); +// h.put("params", params); +// logger.debug("tushare:" + objectMapper.writeValueAsString(h)); +// +// InputStream stean = +// Request.Post(TushareConfig.URL) +// .connectTimeout(20000) +// .socketTimeout(20000) +// .bodyString(objectMapper.writeValueAsString(h), ContentType.APPLICATION_JSON) +// .execute() +// .returnContent() +// .asStream(); +// JsonNode root = objectMapper.readTree(stean); +// JsonNode items = root.get("data").get("items"); +// +// ArrayList list = new ArrayList(); +// +// for(JsonNode jsonNode : items) { +// FutDaily bean = new FutDaily(); +// bean.setTs_code(jsonNode.get(0).asText()); +// +// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); +// LocalDate localDate = LocalDate.parse(jsonNode.get(1).asText(), formatter); +// +// bean.setTrade_date(localDate); +// bean.setPre_close(jsonNode.get(2).asDouble()); +// bean.setPre_settle(jsonNode.get(3).asDouble()); +// bean.setOpen(jsonNode.get(4).asDouble()); +// bean.setHigh(jsonNode.get(5).asDouble()); +// +// bean.setLow(jsonNode.get(6).asDouble()); +// bean.setClose(jsonNode.get(7).asDouble()); +// bean.setSettle(jsonNode.get(8).asDouble()); +// bean.setChange1(jsonNode.get(9).asDouble()); +// bean.setChange2(jsonNode.get(10).asDouble()); +// +// bean.setVol(jsonNode.get(11).asDouble()); +// bean.setAmount(jsonNode.get(12).asDouble()); +// bean.setOi(jsonNode.get(13).asDouble()); +// bean.setOi_chg(jsonNode.get(14).asDouble()); +// list.add(bean); +// } +// if(!list.isEmpty()) { +// futDailyMapper.insertMultiple(list); +// } +// +// //Thread.sleep(200); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// +// +// +// }); +// +// +// return R.SUCCESS("getDate is ok"); +// } + + + + @Operation(summary = "获取最新日线信息", description = "") + @GetMapping("/getDateNow") + public Object getDateNow() { + + LocalDate d = LocalDate.of(2024, 02, 20); + var from = select(ContractInfoMapper.selectList) + .from(ContractInfoDynamicSqlSupport.contractInfo) + .where(ContractInfoDynamicSqlSupport.contractInfo.delist_date, isGreaterThan(d)) + //.and(ContractInfoDynamicSqlSupport.ts_code, ) + .build() + .render(RenderingStrategies.MYBATIS3); + + + + + DeleteStatementProvider delete = deleteFrom(FutDailyDynamicSqlSupport.futDaily) + .where(FutDailyDynamicSqlSupport.ts_code, isIn(select(ContractInfoDynamicSqlSupport.ts_code) + .from(ContractInfoDynamicSqlSupport.contractInfo) + .where(ContractInfoDynamicSqlSupport.contractInfo.delist_date, isGreaterThan(d)))) + .build() + .render(RenderingStrategies.MYBATIS3); + futDailyMapper.delete(delete); + + + + List contractInfos = contractInfoMapper.selectMany(from); + + contractInfos.forEach(i->{ + try { + HashMap h = new HashMap(); + h.put("api_name", "fut_daily"); + h.put("token", TushareConfig.TOKEN); + HashMap params = new HashMap(); + params.put("ts_code", i.getTs_code()); + params.put("limit", 10000); + h.put("params", params); + logger.debug("tushare:" + objectMapper.writeValueAsString(h)); + + InputStream stean = + Request.Post(TushareConfig.URL) + .connectTimeout(15000) + .socketTimeout(15000) + .bodyString(objectMapper.writeValueAsString(h), ContentType.APPLICATION_JSON) + .execute() + .returnContent() + .asStream(); + JsonNode root = objectMapper.readTree(stean); + JsonNode items = root.get("data").get("items"); + + ArrayList list = new ArrayList(); + + for(JsonNode jsonNode : items) { + FutDaily bean = new FutDaily(); + bean.setTs_code(jsonNode.get(0).asText()); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + LocalDate localDate = LocalDate.parse(jsonNode.get(1).asText(), formatter); + + bean.setTrade_date(localDate); + bean.setPre_close(jsonNode.get(2).asDouble()); + bean.setPre_settle(jsonNode.get(3).asDouble()); + bean.setOpen(jsonNode.get(4).asDouble()); + bean.setHigh(jsonNode.get(5).asDouble()); + + bean.setLow(jsonNode.get(6).asDouble()); + bean.setClose(jsonNode.get(7).asDouble()); + bean.setSettle(jsonNode.get(8).asDouble()); + bean.setChange1(jsonNode.get(9).asDouble()); + bean.setChange2(jsonNode.get(10).asDouble()); + + bean.setVol(jsonNode.get(11).asDouble()); + bean.setAmount(jsonNode.get(12).asDouble()); + bean.setOi(jsonNode.get(13).asDouble()); + bean.setOi_chg(jsonNode.get(14).asDouble()); + list.add(bean); + } + if(!list.isEmpty()) { + dailyService.getCurr(i.getTs_code(), list); + } + + //Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + + + + }); + + + return R.SUCCESS("getDate is ok"); + } + + + + @Operation(summary = "获取主力日线信息", description = "") + @GetMapping("/getDate") + public Object getDate() { + + String select_sql = + """ + SELECT * FROM contract_info WHERE ts_code NOT REGEXP '[0-9]+' + """; + + + + SelectStatementProvider provider = DefaultSelectStatementProvider + .withSelectStatement(select_sql) + .build(); + List contractInfos = contractInfoMapper.selectMany(provider); + + contractInfos.forEach(i->{ + try { + HashMap h = new HashMap(); + h.put("api_name", "fut_daily"); + h.put("token", TushareConfig.TOKEN); + HashMap params = new HashMap(); + params.put("ts_code", i.getTs_code()); + params.put("limit", 10000); + h.put("params", params); + logger.debug("tushare:" + objectMapper.writeValueAsString(h)); + + InputStream stean = + Request.Post(TushareConfig.URL) + .connectTimeout(15000) + .socketTimeout(15000) + .bodyString(objectMapper.writeValueAsString(h), ContentType.APPLICATION_JSON) + .execute() + .returnContent() + .asStream(); + JsonNode root = objectMapper.readTree(stean); + JsonNode items = root.get("data").get("items"); + + ArrayList list = new ArrayList(); + + for(JsonNode jsonNode : items) { + FutDaily bean = new FutDaily(); + bean.setTs_code(jsonNode.get(0).asText()); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + LocalDate localDate = LocalDate.parse(jsonNode.get(1).asText(), formatter); + + bean.setTrade_date(localDate); + bean.setPre_close(jsonNode.get(2).asDouble()); + bean.setPre_settle(jsonNode.get(3).asDouble()); + bean.setOpen(jsonNode.get(4).asDouble()); + bean.setHigh(jsonNode.get(5).asDouble()); + + bean.setLow(jsonNode.get(6).asDouble()); + bean.setClose(jsonNode.get(7).asDouble()); + bean.setSettle(jsonNode.get(8).asDouble()); + bean.setChange1(jsonNode.get(9).asDouble()); + bean.setChange2(jsonNode.get(10).asDouble()); + + bean.setVol(jsonNode.get(11).asDouble()); + bean.setAmount(jsonNode.get(12).asDouble()); + bean.setOi(jsonNode.get(13).asDouble()); + bean.setOi_chg(jsonNode.get(14).asDouble()); + list.add(bean); + } + if(!list.isEmpty()) { + dailyService.getCurr(i.getTs_code(), list); + } + + //Thread.sleep(200); + } catch (Exception e) { + e.printStackTrace(); + } + + + + + }); + + + return R.SUCCESS("getDate is ok"); + } + + + + + + @Operation(summary = "合约信息", description = "") + @GetMapping("/init") + public Object init() throws Exception { + + List exchanges = Arrays.asList(Exchange.values()); + + exchanges.forEach(i->{ + HashMap h = new HashMap(); + h.put("api_name", "fut_basic"); + h.put("token", TushareConfig.TOKEN); + HashMap params = new HashMap(); + params.put("exchange", i); + h.put("params", params); + try { + this.getExchangeDate(i, h); + } catch (Exception e) { + e.printStackTrace(); + } + + }); + return R.SUCCESS("ok"); + + } + + public void getExchangeDate(Exchange exchange, HashMap parm) throws Exception{ + logger.debug("tushare:" + objectMapper.writeValueAsString(parm)); + + InputStream stean = + Request.Post(TushareConfig.URL) + .connectTimeout(15000) + .socketTimeout(15000) + .bodyString(objectMapper.writeValueAsString(parm), ContentType.APPLICATION_JSON) + .execute() + .returnContent() + .asStream(); +// .asString(StandardCharsets.UTF_8); + + JsonNode root = objectMapper.readTree(stean); + JsonNode items = root.get("data").get("items"); + + + ArrayList list = new ArrayList(); + for(JsonNode jsonNode : items) { + ContractInfo bean = new ContractInfo(); + bean.setTs_code(jsonNode.get(0).asText()); + bean.setSymbol(jsonNode.get(1).asText()); + bean.setExchange(jsonNode.get(2).asText()); + bean.setName(jsonNode.get(3).asText()); + bean.setFut_code(jsonNode.get(4).asText()); + bean.setMultiplier(jsonNode.get(5).asDouble()); + + bean.setTrade_unit(jsonNode.get(6).asText()); + bean.setPer_unit(jsonNode.get(7).asDouble()); + bean.setQuote_unit(jsonNode.get(8).asText()); + bean.setQuote_unit_desc(jsonNode.get(9).asText()); + bean.setD_mode_desc(jsonNode.get(10).asText()); + + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + String str11 = jsonNode.get(11).asText(); + String str12 = jsonNode.get(12).asText(); + String str14 = jsonNode.get(14).asText(); + LocalDate list_date = null; + LocalDate delist_date = null; + LocalDate last_ddate = null; + + if(StringUtils.isNoneBlank(str11) && !"null".equals(str11)) { + list_date = LocalDate.parse(str11, formatter); + }else { + list_date = LocalDate.ofInstant(Instant.ofEpochMilli(0), ZoneId.systemDefault()); + } + + if(StringUtils.isNoneBlank(str12) && !"null".equals(str12)) { + delist_date = LocalDate.parse(str12, formatter); + }else { + delist_date = LocalDate.ofInstant(Instant.ofEpochMilli(0), ZoneId.systemDefault()); + } + + if(StringUtils.isNoneBlank(str14) && !"null".equals(str14)) { + last_ddate = LocalDate.parse(str14, formatter); + }else { + last_ddate = LocalDate.ofInstant(Instant.ofEpochMilli(0), ZoneId.systemDefault()); + } + + bean.setList_date(list_date); + bean.setDelist_date(delist_date); + bean.setD_month(jsonNode.get(13).asText()); + bean.setLast_ddate(last_ddate); + + List exchanges = Arrays.asList(Exchange.values()); + for(Exchange i : exchanges) { + if(bean.getExchange().equals(i.toString())){ + bean.setExchange_name(i.getName()); + break; + } + } + + + + list.add(bean); + } + + + var from = select(ContractInfoMapper.selectList) + .from(ContractInfoDynamicSqlSupport.contractInfo) + .where(ContractInfoDynamicSqlSupport.exchange, isEqualTo(exchange.toString())) + .limit(8888) + .build() + .render(RenderingStrategies.MYBATIS3); + + List contractInfos = contractInfoMapper.selectMany(from); + Map local = + contractInfos.stream().collect( + Collectors.toMap(ContractInfo::getTs_code, i->i) + ); + //System.out.println(local); + + + List bath = new ArrayList(); + list.forEach(i->{ + if(local.get(i.getTs_code()) == null) { + bath.add(i); + } + }); + if(!bath.isEmpty()) { + contractInfoMapper.insertMultiple(bath); + } + + + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/controller/SysAdminController.java b/src/main/java/jj/tech/finance/biz/webadmin/controller/SysAdminController.java new file mode 100644 index 0000000..4721706 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/controller/SysAdminController.java @@ -0,0 +1,172 @@ +package jj.tech.finance.biz.webadmin.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo; +import static org.mybatis.dynamic.sql.SqlBuilder.isNotEqualTo; +import static org.mybatis.dynamic.sql.SqlBuilder.select; + +import java.util.Optional; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.where.WhereApplier; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.webadmin.vo.parm.Id; +import jj.tech.finance.biz.webadmin.vo.parm.UserName; +import jj.tech.finance.repository.mybatis.dao.SysAdminMapper; +import jj.tech.finance.repository.mybatis.dao.support.SysAdminDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.SysAdmin; +import jj.tech.finance.utils.Page; +import jj.tech.finance.utils.R; + + +@RestController +@RequestMapping(value = "/op/ad", name = "管理员列表") +@Tag(name = "sysAdmin", description = "管理员列表") +public class SysAdminController { + @Autowired SysAdminMapper sysAdminMapper; + + + + + @Operation(summary = "管理员列表,按内容搜索", description = "") + @PostMapping("/list") + public Object list(@RequestBody(required = true) UserName parm) { + + Page p = new Page(parm.getPageNum(), parm.getPageSize()); + + BasicColumn[] selectList = + BasicColumn.columnList(SysAdminDynamicSqlSupport.id, + SysAdminDynamicSqlSupport.realname, + SysAdminDynamicSqlSupport.username, + SysAdminDynamicSqlSupport.islock); + + var from = select(selectList) + .from(SysAdminDynamicSqlSupport.sysAdmin); + + + if(StringUtils.isNoneBlank(parm.getUsername()) || StringUtils.isNoneBlank(parm.getRealname()) || + parm.getIslock()!=null) { + var where = SqlBuilder.where(); + + + if(parm.getIslock()!=null) { + where.and(SysAdminDynamicSqlSupport.islock, isEqualTo(parm.getIslock())); + } + if(StringUtils.isNoneBlank(parm.getUsername())) { + where.and(SysAdminDynamicSqlSupport.username, isEqualTo(parm.getUsername())); + } + if(StringUtils.isNoneBlank(parm.getRealname())) { + where.and(SysAdminDynamicSqlSupport.realname, isEqualTo(parm.getRealname())); + } + + WhereApplier applier = where.toWhereApplier(); + SelectStatementProvider provider = from + .applyWhere(applier) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + var list = sysAdminMapper.selectMany(provider); + long total = sysAdminMapper.count(c->c.applyWhere(applier)); + p.setList(list); + p.setTotal(total); + return R.SUCCESS(p); + + } + + //var where = SqlBuilder.where(SysAdminDynamicSqlSupport.id, isNotEqualTo(1)).toWhereApplier(); + SelectStatementProvider provider = from +// .applyWhere(where) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + var list = sysAdminMapper.selectMany(provider); + long total = sysAdminMapper.count(c->c); + p.setList(list); + p.setTotal(total); + return R.SUCCESS(p); + } + + + @Operation(summary = "管理员更新和添加(ID不存在添加,否则更新)", description = "") + @PostMapping("/post") + public Object post(@RequestBody(required = true) SysAdmin parm) { + if(StringUtils.isEmpty(parm.getUsername())) { + return R.FALSE("用户名不能为空"); + } + String password = parm.getPassword(); + + + if(parm.getId() == null) { + + if(StringUtils.isEmpty(password)) { + return R.FALSE("密码不能为空"); + } + + String passwordEncode = DigestUtils.sha3_256Hex(password); + parm.setPassword(passwordEncode); + + + sysAdminMapper.insertSelective(parm); + return R.SUCCESS(parm); + } + if(parm.getId() == 1) { + return R.FALSE("超级管理不能修改"); + } + + if(StringUtils.isEmpty(password)) { + parm.setPassword(null); + }else { + String passwordEncode = DigestUtils.sha3_256Hex(password); + parm.setPassword(passwordEncode); + } + + sysAdminMapper.updateByPrimaryKeySelective(parm); + return R.SUCCESS("update:"+parm.getId()); + } + + @Operation(summary = "按管理员ID删除") + @PostMapping("/delete") + public Object delete(@Valid @RequestBody(required = true) Id id) { + if(id.getId()!=1) { + sysAdminMapper.deleteByPrimaryKey(id.getId()); + } + if(id.getId()==1) { + return R.FALSE("超级管理员不能删除"); + } + return R.SUCCESS("delete: "+id); + } + + + + @Operation(summary = "按管理员ID获取", description = "") + @PostMapping("/get") + public Object get(@Valid @RequestBody(required = true) Id id) { + Optional op = sysAdminMapper.selectByPrimaryKey(id.getId()); + if(op.isPresent()) { + SysAdmin u = op.get(); + u.setPassword(null); + return R.SUCCESS(u); + } + return R.SUCCESS("can no find"); + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/controller/SysAdminLoginController.java b/src/main/java/jj/tech/finance/biz/webadmin/controller/SysAdminLoginController.java new file mode 100644 index 0000000..5173844 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/controller/SysAdminLoginController.java @@ -0,0 +1,90 @@ +package jj.tech.finance.biz.webadmin.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo; +import static org.mybatis.dynamic.sql.SqlBuilder.select; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.webadmin.vo.parm.Login; +import jj.tech.finance.repository.mybatis.dao.SysAdminMapper; +import jj.tech.finance.repository.mybatis.dao.support.SysAdminDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.SysAdmin; +import jj.tech.finance.utils.R; +import jj.tech.finance.utils.WebAdminUtil; + +@RestController +@Tag(name = "login", description = "后端管理员登录") +@RequestMapping(value = "/op", name = "登录") +public class SysAdminLoginController { + @Autowired SysAdminMapper sysAdminMapper; + @Autowired ObjectMapper objectMapper; + + @Operation(summary = "登录", description = "测试:admin 000000") + @PostMapping("/login") + public Object login(@Valid @RequestBody(required = true) Login parm) { + + + + String passwordEncode = DigestUtils.sha3_256Hex(parm.getPassword()); + + var provider = select(SysAdminMapper.selectList) + .from(SysAdminDynamicSqlSupport.sysAdmin) + .where(SysAdminDynamicSqlSupport.username, isEqualTo(parm.getUsername())) + + .build() + .render(RenderingStrategies.MYBATIS3); + + Optional op = sysAdminMapper.selectOne(provider); + if(!op.isPresent()) { + return R.FALSE("管理员不存在"); + } + SysAdmin bean = op.get(); + if(!passwordEncode.equals(bean.getPassword())) { + return R.FALSE("密码错误"); + } + + if(bean.getId()!=1 && bean.getIslock() == 1) { + return R.FALSE("管理员已被禁用"); + } + bean.setPassword(null); + +// Map h = BeanUtils.describe(bean); +// Map h = new org.apache.commons.beanutils.BeanMap(bean); + Map h = objectMapper.convertValue(bean, Map.class); + h.put("logintime", System.currentTimeMillis()); + String token = WebAdminUtil.addToCookie(h); + HashMap map = new HashMap(); + map.put("token", token); + map.put("admin", bean); + return R.SUCCESS(map); + } + + + + @Operation(summary = "登出", description = "") + @PostMapping("/logout") + public Object logout() { + WebAdminUtil.deleteUser(); + return R.SUCCESS("logout is ok"); + } + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/controller/UserInfoController.java b/src/main/java/jj/tech/finance/biz/webadmin/controller/UserInfoController.java new file mode 100644 index 0000000..2101241 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/controller/UserInfoController.java @@ -0,0 +1,168 @@ +package jj.tech.finance.biz.webadmin.controller; + +import static org.mybatis.dynamic.sql.SqlBuilder.*; + +import java.util.Optional; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.StringUtils; +import org.mybatis.dynamic.sql.BasicColumn; +import org.mybatis.dynamic.sql.SqlBuilder; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.where.WhereApplier; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jj.tech.finance.biz.webadmin.vo.parm.Id; +import jj.tech.finance.biz.webadmin.vo.parm.UserName; +import jj.tech.finance.repository.mybatis.dao.UserInfoMapper; +import jj.tech.finance.repository.mybatis.dao.support.UserInfoDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.UserInfo; +import jj.tech.finance.utils.Page; +import jj.tech.finance.utils.R; + + +@RestController +@RequestMapping(value = "/op/user", name = "用户管理") +@Tag(name = "userInfo", description = "用户管理") +public class UserInfoController { + @Autowired UserInfoMapper userInfoMapper; + + + + + @Operation(summary = "用户列表,按内容搜索", description = "") + @PostMapping("/list") + public Object list(@RequestBody(required = true) UserName parm) { + + Page p = new Page(parm.getPageNum(), parm.getPageSize()); + + BasicColumn[] selectList = + BasicColumn.columnList(UserInfoDynamicSqlSupport.id, + UserInfoDynamicSqlSupport.realname, + UserInfoDynamicSqlSupport.username, + UserInfoDynamicSqlSupport.islock); + + var from = select(selectList) + .from(UserInfoDynamicSqlSupport.userInfo); + + + if(StringUtils.isNoneBlank(parm.getUsername()) || StringUtils.isNoneBlank(parm.getRealname()) || + parm.getIslock()!=null) { + var where = SqlBuilder.where(); + + + if(parm.getIslock()!=null) { + where.and(UserInfoDynamicSqlSupport.islock, isEqualTo(parm.getIslock())); + } + if(StringUtils.isNoneBlank(parm.getUsername())) { + where.and(UserInfoDynamicSqlSupport.username, isEqualTo(parm.getUsername())); + } + if(StringUtils.isNoneBlank(parm.getRealname())) { + where.and(UserInfoDynamicSqlSupport.realname, isEqualTo(parm.getRealname())); + } + + WhereApplier applier = where.toWhereApplier(); + SelectStatementProvider provider = from + .applyWhere(applier) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + var list = userInfoMapper.selectMany(provider); + long total = userInfoMapper.count(c->c.applyWhere(applier)); + p.setList(list); + p.setTotal(total); + return R.SUCCESS(p); + + } + + //var where = SqlBuilder.where(SysAdminDynamicSqlSupport.id, isNotEqualTo(1)).toWhereApplier(); + SelectStatementProvider provider = from +// .applyWhere(where) + .limit(p.getPageSize()) + .offset(p.limitStart()) + .build() + .render(RenderingStrategies.MYBATIS3); + + var list = userInfoMapper.selectMany(provider); + long total = userInfoMapper.count(c->c); + p.setList(list); + p.setTotal(total); + return R.SUCCESS(p); + } + + + @Operation(summary = "更新和添加(ID不存在添加,否则更新)", description = "") + @PostMapping("/post") + public Object post(@RequestBody(required = true) UserInfo parm) { + if(StringUtils.isEmpty(parm.getUsername())) { + return R.FALSE("用户名不能为空"); + } + String password = parm.getPassword(); + String username = parm.getUsername(); + if(StringUtils.isNotBlank(password)) { + String passwordEncode = DigestUtils.sha3_256Hex(password); + parm.setPassword(passwordEncode); + } + + if(parm.getId() == null) { + if(StringUtils.isBlank(password) || StringUtils.isBlank(username)) { + return R.FALSE("用户名/密码不能为空"); + } + + var from = select(UserInfoMapper.selectList) + .from(UserInfoDynamicSqlSupport.userInfo) + .where(UserInfoDynamicSqlSupport.username, isEqualTo(username)) + .limit(1) + .build() + .render(RenderingStrategies.MYBATIS3); + Optional op = userInfoMapper.selectOne(from); + if(op.isPresent()) { + return R.FALSE("该用户已经存在"); + } + + userInfoMapper.insertSelective(parm); + return R.SUCCESS(parm); + } + + + userInfoMapper.updateByPrimaryKeySelective(parm); + return R.SUCCESS("update:"+parm.getId()); + } + + @Operation(summary = "按用户ID删除") + @PostMapping("/delete") + public Object delete(@Valid @RequestBody(required = true) Id id) { + if(id.getId()!=1) { + userInfoMapper.deleteByPrimaryKey(id.getId()); + } + return R.SUCCESS("delete: "+id); + } + + + + @Operation(summary = "按用户ID获取", description = "") + @PostMapping("/get") + public Object get(@Valid @RequestBody(required = true) Id id) { + Optional op = userInfoMapper.selectByPrimaryKey(id.getId()); + if(op.isPresent()) { + UserInfo u = op.get(); + u.setPassword(null); + return R.SUCCESS(u); + } + return R.SUCCESS("can no find"); + } + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/dao/SelectMapper.java b/src/main/java/jj/tech/finance/biz/webadmin/dao/SelectMapper.java new file mode 100644 index 0000000..509682e --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/dao/SelectMapper.java @@ -0,0 +1,34 @@ +package jj.tech.finance.biz.webadmin.dao; + +import java.util.List; + +import org.apache.commons.collections4.map.CaseInsensitiveMap; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.SelectProvider; +import org.mybatis.dynamic.sql.select.render.SelectStatementProvider; +import org.mybatis.dynamic.sql.util.SqlProviderAdapter; +import org.mybatis.dynamic.sql.util.mybatis3.CommonCountMapper; +import org.mybatis.dynamic.sql.util.mybatis3.CommonDeleteMapper; +import org.mybatis.dynamic.sql.util.mybatis3.CommonUpdateMapper; + +@Mapper +public interface SelectMapper extends CommonDeleteMapper, CommonUpdateMapper { + + /** + * 没有映射,直接返回表字段 + * @param selectStatement + * @return + */ + @SelectProvider(type=SqlProviderAdapter.class, method="select") + List> selectMany (SelectStatementProvider selectStatement); +// @SelectProvider(type=SqlProviderAdapter.class, method="select") +// List> selectMany (SelectStatementProvider selectStatement); + + @SelectProvider(type = SqlProviderAdapter.class, method = "select") + Long count(SelectStatementProvider selectStatement); + + + + + +} \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/biz/webadmin/service/DailyService.java b/src/main/java/jj/tech/finance/biz/webadmin/service/DailyService.java new file mode 100644 index 0000000..a8f2922 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/service/DailyService.java @@ -0,0 +1,139 @@ +package jj.tech.finance.biz.webadmin.service; + +import static org.mybatis.dynamic.sql.SqlBuilder.deleteFrom; +import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo; +import static org.mybatis.dynamic.sql.SqlBuilder.isGreaterThan; +import static org.mybatis.dynamic.sql.SqlBuilder.select; + +import java.io.InputStream; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.http.client.fluent.Request; +import org.apache.http.entity.ContentType; +import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider; +import org.mybatis.dynamic.sql.render.RenderingStrategies; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +import jj.tech.finance.repository.mybatis.dao.FutDailyMapper; +import jj.tech.finance.repository.mybatis.dao.support.ContractInfoDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.dao.support.FutDailyDynamicSqlSupport; +import jj.tech.finance.repository.mybatis.entity.ContractInfo; +import jj.tech.finance.repository.mybatis.entity.FutDaily; +import jj.tech.finance.utils.R; +import jj.tech.finance.utils.tushare.TushareConfig; + +@Service +public class DailyService { + private static Logger logger = LoggerFactory.getLogger(DailyService.class); + + @Autowired ObjectMapper objectMapper; + @Autowired ContractInfoMapper contractInfoMapper; + @Autowired FutDailyMapper futDailyMapper; + +// public Object getDate() { +// +// var ts_codes = select(FutDailyDynamicSqlSupport.ts_code) +// .from(FutDailyDynamicSqlSupport.futDaily) +// .groupBy(FutDailyDynamicSqlSupport.futDaily.ts_code); +// +// var from = select(ContractInfoMapper.selectList) +// .from(ContractInfoDynamicSqlSupport.contractInfo) +// .where(ContractInfoDynamicSqlSupport.contractInfo.ts_code, isNotIn(ts_codes)) +// //.groupBy(ContractInfoDynamicSqlSupport.contractInfo.ts_code) +// .build() +// .render(RenderingStrategies.MYBATIS3); +// +// List contractInfos = contractInfoMapper.selectMany(from); +// +// contractInfos.forEach(i->{ +// try { +// HashMap h = new HashMap(); +// h.put("api_name", "fut_daily"); +// h.put("token", TushareConfig.TOKEN); +// HashMap params = new HashMap(); +// params.put("ts_code", i.getTs_code()); +// h.put("params", params); +// logger.debug("tushare:" + objectMapper.writeValueAsString(h)); +// +// InputStream stean = +// Request.Post(TushareConfig.URL) +// .connectTimeout(10000) +// .socketTimeout(10000) +// .bodyString(objectMapper.writeValueAsString(h), ContentType.APPLICATION_JSON) +// .execute() +// .returnContent() +// .asStream(); +// JsonNode root = objectMapper.readTree(stean); +// JsonNode items = root.get("data").get("items"); +// +// ArrayList list = new ArrayList(); +// +// for(JsonNode jsonNode : items) { +// FutDaily bean = new FutDaily(); +// bean.setTs_code(jsonNode.get(0).asText()); +// +// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); +// LocalDate localDate = LocalDate.parse(jsonNode.get(1).asText(), formatter); +// +// bean.setTrade_date(localDate); +// bean.setPre_close(jsonNode.get(2).asDouble()); +// bean.setPre_settle(jsonNode.get(3).asDouble()); +// bean.setOpen(jsonNode.get(4).asDouble()); +// bean.setHigh(jsonNode.get(5).asDouble()); +// +// bean.setLow(jsonNode.get(6).asDouble()); +// bean.setClose(jsonNode.get(7).asDouble()); +// bean.setSettle(jsonNode.get(8).asDouble()); +// bean.setChange1(jsonNode.get(9).asDouble()); +// bean.setChange2(jsonNode.get(10).asDouble()); +// +// bean.setVol(jsonNode.get(11).asDouble()); +// bean.setAmount(jsonNode.get(12).asDouble()); +// bean.setOi(jsonNode.get(13).asDouble()); +// bean.setOi_chg(jsonNode.get(14).asDouble()); +// list.add(bean); +// } +// if(!list.isEmpty()) { +// futDailyMapper.insertMultiple(list); +// } +// +// //Thread.sleep(200); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// +// +// +// }); +// +// +// return R.SUCCESS("getDate is ok"); +// } + + @Transactional + public void getCurr(String ts_code, ArrayList list) { + + DeleteStatementProvider delete = deleteFrom(FutDailyDynamicSqlSupport.futDaily) + .where(FutDailyDynamicSqlSupport.ts_code, isEqualTo(ts_code)) + .build() + .render(RenderingStrategies.MYBATIS3); + futDailyMapper.delete(delete); + futDailyMapper.insertMultiple(list); + + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/task/ContractInfoTime.java b/src/main/java/jj/tech/finance/biz/webadmin/task/ContractInfoTime.java new file mode 100644 index 0000000..ef9f50f --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/task/ContractInfoTime.java @@ -0,0 +1,137 @@ +//package jj.tech.finance.biz.webadmin.task; +// +//import static org.mybatis.dynamic.sql.SqlBuilder.*; +// +//import java.io.InputStream; +//import java.util.ArrayList; +//import java.util.Arrays; +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +//import java.util.stream.Collectors; +// +//import org.apache.http.client.fluent.Request; +//import org.apache.http.entity.ContentType; +//import org.mybatis.dynamic.sql.render.RenderingStrategies; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.scheduling.annotation.Scheduled; +//import org.springframework.stereotype.Component; +//import org.springframework.web.service.annotation.GetExchange; +// +//import com.fasterxml.jackson.databind.JsonNode; +//import com.fasterxml.jackson.databind.ObjectMapper; +// +//import jj.tech.finance.config.enums.Exchange; +//import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +//import jj.tech.finance.repository.mybatis.dao.support.ContractInfoDynamicSqlSupport; +//import jj.tech.finance.repository.mybatis.entity.ContractInfo; +//import jj.tech.finance.utils.tushare.TushareConfig; +// +// +//@Component +//public class ContractInfoTime { +// private static Logger logger = LoggerFactory.getLogger(ContractInfoTime.class); +// +// @Autowired ObjectMapper objectMapper; +// @Autowired ContractInfoMapper contractInfoMapper; +// +// /** +// * 同步tushare的合约信息 +// */ +//// @Scheduled(cron = "0 0 0/4 * * ?") //4小时一次 +//// @Scheduled(cron = "0/50 * * * * ?") //50秒一次 +// @Scheduled(cron = "0 0 8-17/4 * * ?") //8点到15点之间,4小时一次 +// public void checkUser() throws Exception { +// +// List exchanges = Arrays.asList(Exchange.values()); +// +// exchanges.forEach(i->{ +// HashMap h = new HashMap(); +// h.put("api_name", "fut_basic"); +// h.put("token", TushareConfig.TOKEN); +// HashMap params = new HashMap(); +// params.put("exchange", i); +// h.put("params", params); +// try { +// this.getExchangeDate(i, h); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// }); +// +// } +// +// public void getExchangeDate(Exchange exchange, HashMap parm) throws Exception{ +// logger.debug("tushare:" + objectMapper.writeValueAsString(parm)); +// +// InputStream stean = +// Request.Post(TushareConfig.URL) +// .connectTimeout(3000) +// .socketTimeout(3000) +// .bodyString(objectMapper.writeValueAsString(parm), ContentType.APPLICATION_JSON) +// .execute() +// .returnContent() +// .asStream(); +//// .asString(StandardCharsets.UTF_8); +// +// JsonNode root = objectMapper.readTree(stean); +// JsonNode items = root.get("data").get("items"); +// +// +// ArrayList list = new ArrayList(); +// for(JsonNode jsonNode : items) { +// ContractInfo bean = new ContractInfo(); +// bean.setTs_code(jsonNode.get(0).asText()); +// bean.setSymbol(jsonNode.get(1).asText()); +// bean.setExchange(jsonNode.get(2).asText()); +// bean.setName(jsonNode.get(3).asText()); +// bean.setFut_code(jsonNode.get(4).asText()); +// bean.setMultiplier(jsonNode.get(5).asDouble()); +// +// bean.setTrade_unit(jsonNode.get(6).asText()); +// bean.setPer_unit(jsonNode.get(7).asDouble()); +// bean.setQuote_unit(jsonNode.get(8).asText()); +// bean.setQuote_unit_desc(jsonNode.get(9).asText()); +// bean.setD_mode_desc(jsonNode.get(10).asText()); +// +// bean.setList_date(jsonNode.get(11).asText()); +// bean.setDelist_date(jsonNode.get(12).asText()); +// bean.setD_month(jsonNode.get(13).asText()); +// bean.setLast_ddate(jsonNode.get(14).asText()); +// list.add(bean); +// } +// +// +// var from = select(ContractInfoMapper.selectList) +// .from(ContractInfoDynamicSqlSupport.contractInfo) +// .where(ContractInfoDynamicSqlSupport.exchange, isEqualTo(exchange.toString())) +// .limit(8888) +// .build() +// .render(RenderingStrategies.MYBATIS3); +// +// List contractInfos = contractInfoMapper.selectMany(from); +// Map local = +// contractInfos.stream().collect( +// Collectors.toMap(ContractInfo::getTs_code, i->i) +// ); +// //System.out.println(local); +// +// +// List bath = new ArrayList(); +// list.forEach(i->{ +// if(local.get(i.getTs_code()) == null) { +// bath.add(i); +// } +// }); +// if(!bath.isEmpty()) { +// contractInfoMapper.insertMultiple(bath); +// } +// +// +// } +// +// +//} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/task/FutDailyTime.java b/src/main/java/jj/tech/finance/biz/webadmin/task/FutDailyTime.java new file mode 100644 index 0000000..c13c85e --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/task/FutDailyTime.java @@ -0,0 +1,149 @@ +//package jj.tech.finance.biz.webadmin.task; +// +//import static org.mybatis.dynamic.sql.SqlBuilder.*; +// +//import java.io.IOException; +//import java.io.InputStream; +//import java.util.ArrayList; +//import java.util.Arrays; +//import java.util.HashMap; +//import java.util.List; +//import java.util.Map; +//import java.util.stream.Collectors; +// +//import org.apache.http.client.ClientProtocolException; +//import org.apache.http.client.fluent.Request; +//import org.apache.http.entity.ContentType; +//import org.mybatis.dynamic.sql.SqlBuilder; +//import org.mybatis.dynamic.sql.render.RenderingStrategies; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.scheduling.annotation.Scheduled; +//import org.springframework.stereotype.Component; +// +//import com.fasterxml.jackson.core.JsonProcessingException; +//import com.fasterxml.jackson.databind.JsonNode; +//import com.fasterxml.jackson.databind.ObjectMapper; +// +//import jj.tech.finance.config.enums.Exchange; +//import jj.tech.finance.repository.mybatis.dao.ContractInfoMapper; +//import jj.tech.finance.repository.mybatis.dao.FutDailyMapper; +//import jj.tech.finance.repository.mybatis.dao.support.ContractInfoDynamicSqlSupport; +//import jj.tech.finance.repository.mybatis.dao.support.FutDailyDynamicSqlSupport; +//import jj.tech.finance.repository.mybatis.entity.ContractInfo; +//import jj.tech.finance.utils.tushare.TushareConfig; +// +//@Component +//public class FutDailyTime { +// private static Logger logger = LoggerFactory.getLogger(FutDailyTime.class); +// +// @Autowired ObjectMapper objectMapper; +// @Autowired ContractInfoMapper contractInfoMapper; +// @Autowired FutDailyMapper futDailyMapper; +// +// //@Scheduled(cron = "0 0/5 * * * ?") //5分钟 +// @Scheduled(cron = "0/50 * * * * ?") +// public void checkUser() throws Exception { +// +// List exchanges = Arrays.asList(Exchange.values()); +// +// exchanges.forEach(i->{ +// HashMap h = new HashMap(); +// h.put("api_name", "fut_daily"); +// h.put("token", TushareConfig.TOKEN); +// HashMap params = new HashMap(); +// params.put("ts_code", "RU2310.SHF"); +// h.put("params", params); +// try { +// this.getExchangeDate(i, h); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// }); +// +// } +// +// public void getExchangeDate(Exchange exchange, HashMap parm) throws Exception{ +// logger.debug("tushare:" + objectMapper.writeValueAsString(parm)); +// +// +// +// +// +// +// +// +// +// var ts_codes = select(FutDailyDynamicSqlSupport.ts_code) +// .from(FutDailyDynamicSqlSupport.futDaily) +// .groupBy(FutDailyDynamicSqlSupport.futDaily.ts_code); +// +// var from = select(ContractInfoMapper.selectList) +// .from(ContractInfoDynamicSqlSupport.contractInfo) +// .where(ContractInfoDynamicSqlSupport.contractInfo.ts_code, isNotIn(ts_codes)) +// .groupBy(ContractInfoDynamicSqlSupport.contractInfo.ts_code) +// .build() +// .render(RenderingStrategies.MYBATIS3); +// +// List contractInfos = contractInfoMapper.selectMany(from); +// +// contractInfos.forEach(i->{ +// try { +// HashMap h = new HashMap(); +// h.put("api_name", "fut_daily"); +// h.put("token", TushareConfig.TOKEN); +// HashMap params = new HashMap(); +// params.put("ts_code", i.getTs_code()); +// h.put("params", params); +// logger.debug("tushare:" + objectMapper.writeValueAsString(h)); +// +// InputStream stean = +// Request.Post(TushareConfig.URL) +// .connectTimeout(3000) +// .socketTimeout(3000) +// .bodyString(objectMapper.writeValueAsString(h), ContentType.APPLICATION_JSON) +// .execute() +// .returnContent() +// .asStream(); +// JsonNode root = objectMapper.readTree(stean); +// JsonNode items = root.get("data").get("items"); +// +// ArrayList list = new ArrayList(); +// for(JsonNode jsonNode : items) { +// ContractInfo bean = new ContractInfo(); +// bean.setTs_code(jsonNode.get(0).asText()); +// bean.setSymbol(jsonNode.get(1).asText()); +// bean.setExchange(jsonNode.get(2).asText()); +// bean.setName(jsonNode.get(3).asText()); +// bean.setFut_code(jsonNode.get(4).asText()); +// bean.setMultiplier(jsonNode.get(5).asDouble()); +// +// bean.setTrade_unit(jsonNode.get(6).asText()); +// bean.setPer_unit(jsonNode.get(7).asDouble()); +// bean.setQuote_unit(jsonNode.get(8).asText()); +// bean.setQuote_unit_desc(jsonNode.get(9).asText()); +// bean.setD_mode_desc(jsonNode.get(10).asText()); +// +// bean.setList_date(jsonNode.get(11).asText()); +// bean.setDelist_date(jsonNode.get(12).asText()); +// bean.setD_month(jsonNode.get(13).asText()); +// bean.setLast_ddate(jsonNode.get(14).asText()); +// list.add(bean); +// } +// +// Thread.sleep(300); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// +// +// +// }); +// +// +// } +// +//} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatu.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatu.java new file mode 100644 index 0000000..4c526f8 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatu.java @@ -0,0 +1,29 @@ +package jj.tech.finance.biz.webadmin.vo; + +import jj.tech.finance.repository.mybatis.entity.ContractInfo; + +public class ContractInfoStatu extends ContractInfo { + public Integer contract_status; + + public FuturesZhSpot futuresZhSpot; //合约当前实时数据 + + + + public Integer getContract_status() { + return contract_status; + } + + public void setContract_status(Integer contract_status) { + this.contract_status = contract_status; + } + + public FuturesZhSpot getFuturesZhSpot() { + return futuresZhSpot; + } + + public void setFuturesZhSpot(FuturesZhSpot futuresZhSpot) { + this.futuresZhSpot = futuresZhSpot; + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatuScribe.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatuScribe.java new file mode 100644 index 0000000..dbbec57 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatuScribe.java @@ -0,0 +1,32 @@ +package jj.tech.finance.biz.webadmin.vo; + +import java.time.LocalDateTime; + +public class ContractInfoStatuScribe extends ContractInfoStatu{ + public Integer scribe_status; + public Integer scribe_number; + public LocalDateTime scribe_update_time; + + + public Integer getScribe_status() { + return scribe_status; + } + public void setScribe_status(Integer scribe_status) { + this.scribe_status = scribe_status; + } + public Integer getScribe_number() { + return scribe_number; + } + public void setScribe_number(Integer scribe_number) { + this.scribe_number = scribe_number; + } + public LocalDateTime getScribe_update_time() { + return scribe_update_time; + } + public void setScribe_update_time(LocalDateTime scribe_update_time) { + this.scribe_update_time = scribe_update_time; + } + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatuScribeStore.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatuScribeStore.java new file mode 100644 index 0000000..be8f4fc --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/ContractInfoStatuScribeStore.java @@ -0,0 +1,15 @@ +package jj.tech.finance.biz.webadmin.vo; + +public class ContractInfoStatuScribeStore extends ContractInfoStatuScribe { + public Integer store; + + + public Integer getStore() { + return store; + } + public void setStore(Integer store) { + this.store = store; + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/FuturesZhSpot.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/FuturesZhSpot.java new file mode 100644 index 0000000..a9dbfe4 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/FuturesZhSpot.java @@ -0,0 +1,119 @@ +package jj.tech.finance.biz.webadmin.vo; + +public class FuturesZhSpot { + + public String symbol; + public String time; + public Double open; + public Double high; + public Double low; + public Double current_price; + public Double bid_price; + public Double ask_price; + public Double buy_vol; + public Double sell_vol; + public Double hold; + public Double volume; + public Double avg_price; + public Double last_close; + public Double last_settle_price; + + + + public String getSymbol() { + return symbol; + } + public void setSymbol(String symbol) { + this.symbol = symbol; + } + public String getTime() { + return time; + } + public void setTime(String time) { + this.time = time; + } + public Double getOpen() { + return open; + } + public void setOpen(Double open) { + this.open = open; + } + public Double getHigh() { + return high; + } + public void setHigh(Double high) { + this.high = high; + } + public Double getLow() { + return low; + } + public void setLow(Double low) { + this.low = low; + } + public Double getCurrent_price() { + return current_price; + } + public void setCurrent_price(Double current_price) { + this.current_price = current_price; + } + public Double getBid_price() { + return bid_price; + } + public void setBid_price(Double bid_price) { + this.bid_price = bid_price; + } + public Double getAsk_price() { + return ask_price; + } + public void setAsk_price(Double ask_price) { + this.ask_price = ask_price; + } + public Double getBuy_vol() { + return buy_vol; + } + public void setBuy_vol(Double buy_vol) { + this.buy_vol = buy_vol; + } + public Double getSell_vol() { + return sell_vol; + } + public void setSell_vol(Double sell_vol) { + this.sell_vol = sell_vol; + } + public Double getHold() { + return hold; + } + public void setHold(Double hold) { + this.hold = hold; + } + public Double getVolume() { + return volume; + } + public void setVolume(Double volume) { + this.volume = volume; + } + public Double getAvg_price() { + return avg_price; + } + public void setAvg_price(Double avg_price) { + this.avg_price = avg_price; + } + public Double getLast_close() { + return last_close; + } + public void setLast_close(Double last_close) { + this.last_close = last_close; + } + public Double getLast_settle_price() { + return last_settle_price; + } + public void setLast_settle_price(Double last_settle_price) { + this.last_settle_price = last_settle_price; + } + + + + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/ScribeVo.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/ScribeVo.java new file mode 100644 index 0000000..35c07f1 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/ScribeVo.java @@ -0,0 +1,54 @@ +package jj.tech.finance.biz.webadmin.vo; + +import java.util.List; + +import jj.tech.finance.repository.mybatis.entity.ContractInfoStatusScribe; + +public class ScribeVo { + public Integer contractid; + + public List list; + + public Integer getContractid() { + return contractid; + } + + public void setContractid(Integer contractid) { + this.contractid = contractid; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + + + + + + + +} + +class Scribe { + public Integer scribeid; + public Integer scribe_value; + + public Integer getScribeid() { + return scribeid; + } + public void setScribeid(Integer scribeid) { + this.scribeid = scribeid; + } + public Integer getScribe_value() { + return scribe_value; + } + public void setScribe_value(Integer scribe_value) { + this.scribe_value = scribe_value; + } + +}; \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Contract.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Contract.java new file mode 100644 index 0000000..f379380 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Contract.java @@ -0,0 +1,30 @@ +package jj.tech.finance.biz.webadmin.vo.parm; + +public class Contract extends P{ + + public String ts_code; + public String symbol; + public String exchange; + + public String getTs_code() { + return ts_code; + } + public void setTs_code(String ts_code) { + this.ts_code = ts_code; + } + public String getSymbol() { + return symbol; + } + public void setSymbol(String symbol) { + this.symbol = symbol; + } + public String getExchange() { + return exchange; + } + public void setExchange(String exchange) { + this.exchange = exchange; + } + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Daily.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Daily.java new file mode 100644 index 0000000..c023583 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Daily.java @@ -0,0 +1,51 @@ +package jj.tech.finance.biz.webadmin.vo.parm; + +import java.time.LocalDate; + +import org.springframework.format.annotation.DateTimeFormat; + +public class Daily extends P{ + + public String ts_code; + + @DateTimeFormat(pattern = "yyyy-MM-dd") + public LocalDate trade_date; + + //public String exchange; + + @DateTimeFormat(pattern = "yyyy-MM-dd") + public LocalDate start_date; + @DateTimeFormat(pattern = "yyyy-MM-dd") + public LocalDate end_date; + + + + public String getTs_code() { + return ts_code; + } + public void setTs_code(String ts_code) { + this.ts_code = ts_code; + } + public LocalDate getTrade_date() { + return trade_date; + } + public void setTrade_date(LocalDate trade_date) { + this.trade_date = trade_date; + } + public LocalDate getStart_date() { + return start_date; + } + public void setStart_date(LocalDate start_date) { + this.start_date = start_date; + } + public LocalDate getEnd_date() { + return end_date; + } + public void setEnd_date(LocalDate end_date) { + this.end_date = end_date; + } + + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Id.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Id.java new file mode 100644 index 0000000..c24adb8 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Id.java @@ -0,0 +1,18 @@ +package jj.tech.finance.biz.webadmin.vo.parm; + +import jakarta.validation.constraints.NotNull; + +public class Id { + @NotNull + public Integer id; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Ids.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Ids.java new file mode 100644 index 0000000..ecafb8c --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Ids.java @@ -0,0 +1,20 @@ +package jj.tech.finance.biz.webadmin.vo.parm; + +import java.util.List; + +import jakarta.validation.constraints.NotNull; + +public class Ids { + @NotNull + public List ids; + + public List getIds() { + return ids; + } + + public void setIds(List ids) { + this.ids = ids; + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Login.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Login.java new file mode 100644 index 0000000..527759c --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Login.java @@ -0,0 +1,28 @@ +package jj.tech.finance.biz.webadmin.vo.parm; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + +public class Login { + @NotEmpty + public String username; + @NotEmpty + public String password; + + + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Minute.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Minute.java new file mode 100644 index 0000000..e34ba46 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/Minute.java @@ -0,0 +1,25 @@ +package jj.tech.finance.biz.webadmin.vo.parm; + +public class Minute { + + public Integer id; //合约id + public Integer period; //1:1分钟,5:5分钟,15:15分钟,30:30分钟,60:60分钟 + + + public Integer getId() { + return id; + } + public void setId(Integer id) { + this.id = id; + } + public Integer getPeriod() { + return period; + } + public void setPeriod(Integer period) { + this.period = period; + } + + + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/P.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/P.java new file mode 100644 index 0000000..d4d4b4c --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/P.java @@ -0,0 +1,21 @@ +package jj.tech.finance.biz.webadmin.vo.parm; + +public class P { + public Integer pageNum; + public Integer pageSize; + + public Integer getPageNum() { + return pageNum; + } + public void setPageNum(Integer pageNum) { + this.pageNum = pageNum; + } + public Integer getPageSize() { + return pageSize; + } + public void setPageSize(Integer pageSize) { + this.pageSize = pageSize; + } + + +} diff --git a/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/UserName.java b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/UserName.java new file mode 100644 index 0000000..ac276d8 --- /dev/null +++ b/src/main/java/jj/tech/finance/biz/webadmin/vo/parm/UserName.java @@ -0,0 +1,30 @@ +package jj.tech.finance.biz.webadmin.vo.parm; + +public class UserName extends P{ + public String username; + public String realname; + public Integer islock; + + + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + public String getRealname() { + return realname; + } + public void setRealname(String realname) { + this.realname = realname; + } + public Integer getIslock() { + return islock; + } + public void setIslock(Integer islock) { + this.islock = islock; + } + + + +} diff --git a/src/main/java/jj/tech/finance/config/datasource/DataSourceConfig.java b/src/main/java/jj/tech/finance/config/datasource/DataSourceConfig.java new file mode 100644 index 0000000..f942fc8 --- /dev/null +++ b/src/main/java/jj/tech/finance/config/datasource/DataSourceConfig.java @@ -0,0 +1,64 @@ +package jj.tech.finance.config.datasource; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import com.zaxxer.hikari.HikariDataSource; + +/** + * 定义除spring提供的默认数据源以外的,自定义数据源 + * 参考: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto.data-access.configure-two-datasources + * https://github.com/spring-projects/spring-boot/issues/20814 + * https://github.com/spring-projects/spring-boot/issues/13325 + * @author Dou + */ +@Configuration(proxyBeanMethods=false) +public class DataSourceConfig { + + + + @Bean + @Primary + @ConditionalOnClass(HikariDataSource.class) + //@ConfigurationProperties("spring.datasource") + HikariDataSource dataSource(DataSourceProperties properties) { + + return (HikariDataSource) properties.initializeDataSourceBuilder() + .type(HikariDataSource.class).build(); + } + +// /** +// * 数据库名称url:需要改成jdbc-url,其他名称值和spring默认的一样 +// * 就可以自动注入 +// */ +// @Bean("dataSource2") +// @ConfigurationProperties("app.datasource") +// public HikariDataSource dataSource2() { +// return (HikariDataSource) DataSourceBuilder.create() +// .type(HikariDataSource.class).build(); +// } + + + +// /** +// * @p DataSourceProperties +// * @p 如果没有 显示的提供 url 用户名、密码; 创建一个默认的嵌入式的数据库 +// * @p 并提供url/jdbcUrl的转化 +// * @p @EnableConfigurationProperties(DataSourceProperties.class),这个注解可以不用加,因为 +// * spring 在初始化 DataSourceAutoConfiguration的时候,会初始化DataSourceProperties这个类到spring上下文 +// */ +// @Bean +// @Primary +// @ConfigurationProperties("spring.datasource") +// public DataSourceProperties dataSourceProperties() { +// return new DataSourceProperties(); +// } + + + + + +} \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/config/enums/Exchange.java b/src/main/java/jj/tech/finance/config/enums/Exchange.java new file mode 100644 index 0000000..0320b9b --- /dev/null +++ b/src/main/java/jj/tech/finance/config/enums/Exchange.java @@ -0,0 +1,15 @@ +package jj.tech.finance.config.enums; + +public enum Exchange { + CZCE("郑州商品交易所"), SHFE("上海期货交易所"), DCE("大连商品交易所"), + CFFEX("中国金融期货交易所"), INE("上海国际能源交易所"), GFEX("广州期货交易所"); + + public String name; + Exchange(String name) { + this.name=name; + } + public String getName() { + return this.name; + } + +} diff --git a/src/main/java/jj/tech/finance/config/enums/SysConfigGroup.java b/src/main/java/jj/tech/finance/config/enums/SysConfigGroup.java new file mode 100644 index 0000000..01ea586 --- /dev/null +++ b/src/main/java/jj/tech/finance/config/enums/SysConfigGroup.java @@ -0,0 +1,11 @@ +package jj.tech.finance.config.enums; + +public class SysConfigGroup { + public static String grup_rulenotice = "rulenotice"; + + + + public static String key_rulenotice_due = "rulenotice_due"; + + +} diff --git a/src/main/java/jj/tech/finance/config/jooq/JooqConfig.java b/src/main/java/jj/tech/finance/config/jooq/JooqConfig.java new file mode 100644 index 0000000..7cfc03e --- /dev/null +++ b/src/main/java/jj/tech/finance/config/jooq/JooqConfig.java @@ -0,0 +1,134 @@ +package jj.tech.finance.config.jooq; + +import javax.sql.DataSource; + +import org.jooq.ConnectionProvider; +import org.jooq.DSLContext; +import org.jooq.ExecuteListenerProvider; +import org.jooq.impl.DataSourceConnectionProvider; +import org.jooq.impl.DefaultConfiguration; +import org.jooq.impl.DefaultDSLContext; +import org.jooq.impl.DefaultExecuteListenerProvider; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.jooq.DefaultConfigurationCustomizer; +import org.springframework.boot.autoconfigure.jooq.JooqExceptionTranslator; +import org.springframework.boot.autoconfigure.jooq.JooqProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; +import org.springframework.transaction.PlatformTransactionManager; + + +/** + * jooq使用单个jdbc链接的时候:自己不管理数据库链接开关,也不管理事物的开关,由外部管理 + * jooq使用数据源的时候:每次执行先获取一个链接,执行完毕还给连接池 + * + * @注意该类参考:spring-boot-autoconfigure自动配置jooq包下的JooqAutoConfiguration + * 源码复制直接用, 因为spring自动配置包下大多数类不是public类,只能重写 + * + * @在单数据源情况下不用配置任何东西,spring boot 默认配置非常优秀 + * 需要注意的是事务的传播特性,spring boot jooq默认是嵌入事务 + * https://blog.jooq.org/nested-transactions-in-jooq/ + * @jooq代码中写sql + * https://blog.jooq.org/using-java-13-text-blocks-for-plain-sql-with-jooq/ + * + * @关于嵌入事务: 错误只回滚自己,其他成功的所有事务都成功 + * https://stackoverflow.com/questions/6683929/propagation-nested-vs-propagation-required-in-spring + * @jooq与jpa,按作者的表述,他不愿意支持ORM + * https://github.com/jOOQ/jOOQ/issues/11685 + * @jooq与r2dbc,胶水写法,脱裤子放屁 + * https://github.com/jOOQ/jOOQ/issues/11700 + * https://github.com/jOOQ/jOOQ/tree/main/jOOQ-examples + * https://blog.jooq.org/reactive-sql-with-jooq-3-15-and-r2dbc + * @examples + * https://github.com/jOOQ/jOOQ/tree/main/jOOQ-examples + * + * @Dou 2020/8/13 + */ +@ConditionalOnClass(DSLContext.class) +@ConditionalOnBean(DataSource.class) +@EnableConfigurationProperties(JooqProperties.class) +@Configuration(proxyBeanMethods = false) +public class JooqConfig { + + /** + * 创建使用默认数据源,和spring默认嵌入式事务管理器的DSLContext + */ + @Bean + DefaultDSLContext dsl(org.jooq.Configuration configuration) { + return new DefaultDSLContext(configuration); + } + + @Bean + DefaultConfiguration jooqConfiguration( + JooqProperties properties, + DataSource dataSource, + PlatformTransactionManager txManager){ + DefaultConfiguration configuration = new DefaultConfiguration(); + configuration.set(properties.determineSqlDialect(dataSource)); + configuration.set(new DataSourceConnectionProvider(new TransactionAwareDataSourceProxy(dataSource))); + configuration.set(new JooqSpringTransactionProvider(txManager)); //spring提供的默认嵌入式事务PROPAGATION_NESTED + configuration.set(new DefaultExecuteListenerProvider(new JooqExceptionTranslator())); + return configuration; + } + + +// +// /** +// * @spring的事物管理器 +// * 如果添加spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例 +// * 如果你添加的是 spring-boot-starter-data-jpa, 会注入 JpaTransactionManager +// * +// * @可以指定为:DataSourceTransactionManager,spring boot的自动配置没有指定,所以这里也不指定 +// * 直接指定DataSourceTransactionManager可以参考: https://www.jooq.org/doc/3.18/manual/sql-execution/transaction-management/ +// +// * @SpringTransactionProvider 已知bug,不适用于 jOOQ 的异步事务: https://github.com/jOOQ/jOOQ/issues/10850 +// * 并且r2dbc有同样的问题: https://github.com/spring-projects/spring-framework/issues/28133 +// * 可以取消SpringTransactionProvider事务管理并使用JOOP自己的事务管理解决: +// * this.dslContext = dslContext.configuration().derive((TransactionProvider) null).dsl(); +// */ +// @Bean +// JooqSpringTransactionProvider jooqSpringTransactionProvider( +// PlatformTransactionManager txManager) { +// return new JooqSpringTransactionProvider(txManager); +// } +// +// +// /** +// * jooq提供对对外的,使用外部的数据库链接,DataSourceConnectionProvider代理类 +// * 这里使用TransactionAwareDataSourceProxy 可以动态的发现spring 事物上下文transaction context +// */ +// @Bean +// DataSourceConnectionProvider dataSourceConnectionProvider( +// @Qualifier("dataSource2") DataSource dataSource2) { +// return new DataSourceConnectionProvider( +// new TransactionAwareDataSourceProxy(dataSource2)); +// } +// +// @Bean +// SQLDialect sQLDialect( +// JooqProperties properties, +// @Qualifier("dataSource2") DataSource dataSource2) { +// return properties.determineSqlDialect(dataSource2); +// } +// +// @Bean("dsl2") +// DSLContext dsl2( +// DataSourceConnectionProvider dataSourceConnectionProvider, +// SQLDialect sQLDialect, +// JooqSpringTransactionProvider jooqSpringTransactionProvider) { +// +// DefaultConfiguration config = new DefaultConfiguration(); +// config.set(sQLDialect); +// config.set(dataSourceConnectionProvider); +// config.set(jooqSpringTransactionProvider); //spring提供的默认嵌入式事务PROPAGATION_NESTED +// config.set(new DefaultExecuteListenerProvider(new JooqExceptionTranslator())); +// return new DefaultDSLContext(config); +// } + + +} \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/config/jooq/JooqSpringTransaction.java b/src/main/java/jj/tech/finance/config/jooq/JooqSpringTransaction.java new file mode 100644 index 0000000..879ec1e --- /dev/null +++ b/src/main/java/jj/tech/finance/config/jooq/JooqSpringTransaction.java @@ -0,0 +1,23 @@ +package jj.tech.finance.config.jooq; + +import org.jooq.Transaction; +import org.springframework.transaction.TransactionStatus; + +/** + * @ 直接复制 org.springframework.boot.autoconfigure.jooq.SpringTransaction类 + * 因为不是public,只能自己写一个 + * @author Dou + */ +public class JooqSpringTransaction implements Transaction{ + // Based on the jOOQ-spring-example from https://github.com/jOOQ/jOOQ + + private final TransactionStatus transactionStatus; + + JooqSpringTransaction(TransactionStatus transactionStatus) { + this.transactionStatus = transactionStatus; + } + + TransactionStatus getTxStatus() { + return this.transactionStatus; + } +} diff --git a/src/main/java/jj/tech/finance/config/jooq/JooqSpringTransactionProvider.java b/src/main/java/jj/tech/finance/config/jooq/JooqSpringTransactionProvider.java new file mode 100644 index 0000000..6f6dddb --- /dev/null +++ b/src/main/java/jj/tech/finance/config/jooq/JooqSpringTransactionProvider.java @@ -0,0 +1,55 @@ +package jj.tech.finance.config.jooq; + +import org.jooq.TransactionContext; +import org.jooq.TransactionProvider; +import org.jooq.tools.JooqLogger; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +/** + * 修改默认事务传播行为成:PROPAGATION_REQUIRED + * 参考 org.springframework.boot.autoconfigure.jooq.SpringTransactionProvider + * 修改TransactionDefinition.PROPAGATION_NESTED 为 PROPAGATION_REQUIRED + * @author Dou + * + */ +public class JooqSpringTransactionProvider implements TransactionProvider{ + + // Based on the jOOQ-spring-example from https://github.com/jOOQ/jOOQ + + private static final JooqLogger log = JooqLogger.getLogger(JooqSpringTransactionProvider.class); + + private final PlatformTransactionManager transactionManager; + + public JooqSpringTransactionProvider(PlatformTransactionManager transactionManager) { + this.transactionManager = transactionManager; + } + + @Override + public void begin(TransactionContext context) { + log.info("--> begin transaction --->"); + TransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_NESTED); //PROPAGATION_REQUIRED + TransactionStatus status = this.transactionManager.getTransaction(definition); + context.transaction(new JooqSpringTransaction(status)); + } + + @Override + public void commit(TransactionContext ctx) { + log.info("--> commit transaction --->"); + this.transactionManager.commit(getTransactionStatus(ctx)); + } + + @Override + public void rollback(TransactionContext ctx) { + log.error("<-- rollback transaction <---"); + this.transactionManager.rollback(getTransactionStatus(ctx)); + } + + private TransactionStatus getTransactionStatus(TransactionContext ctx) { + JooqSpringTransaction transaction = (JooqSpringTransaction) ctx.transaction(); + return transaction.getTxStatus(); + } + +} diff --git a/src/main/java/jj/tech/finance/config/jpa/JpaConfig.java b/src/main/java/jj/tech/finance/config/jpa/JpaConfig.java new file mode 100644 index 0000000..9239ce9 --- /dev/null +++ b/src/main/java/jj/tech/finance/config/jpa/JpaConfig.java @@ -0,0 +1,51 @@ +//package jj.tech.dcang.config.jpa; +// +//import javax.sql.DataSource; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +//import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +//import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +//import org.springframework.orm.jpa.JpaTransactionManager; +//import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +//import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +//import org.springframework.transaction.PlatformTransactionManager; +///** +// * JPA多数据源配置,单一数据源由spring boot默认配置 +// * https://github.com/spring-projects/spring-data-examples/blob/main/jpa/multiple-datasources/src/main/java/example/springdata/jpa/multipleds/customer/CustomerConfig.java +// * @author Dou +// * +// */ +////@Configuration +////@EnableJpaRepositories(entityManagerFactoryRef = "customerEntityManagerFactory", +//// transactionManagerRef = "customerTransactionManager") +//public class JpaConfig { +//// @Bean +//// PlatformTransactionManager customerTransactionManager() { +//// return new JpaTransactionManager(customerEntityManagerFactory().getObject()); +//// } +//// +//// @Bean +//// LocalContainerEntityManagerFactoryBean customerEntityManagerFactory() { +//// +//// var jpaVendorAdapter = new HibernateJpaVendorAdapter(); +//// jpaVendorAdapter.setGenerateDdl(true); +//// +//// var factoryBean = new LocalContainerEntityManagerFactoryBean(); +//// +//// factoryBean.setDataSource(customerDataSource()); +//// factoryBean.setJpaVendorAdapter(jpaVendorAdapter); +//// factoryBean.setPackagesToScan(JpaConfig.class.getPackage().getName()); +//// +//// return factoryBean; +//// } +//// +//// @Bean +//// DataSource customerDataSource() { +//// return new EmbeddedDatabaseBuilder().// +//// setType(EmbeddedDatabaseType.HSQL).// +//// setName("customers").// +//// build(); +//// } +//} diff --git a/src/main/java/jj/tech/finance/config/json/JacksonConfiguration.java b/src/main/java/jj/tech/finance/config/json/JacksonConfiguration.java new file mode 100644 index 0000000..c3114e9 --- /dev/null +++ b/src/main/java/jj/tech/finance/config/json/JacksonConfiguration.java @@ -0,0 +1,46 @@ +package jj.tech.finance.config.json; + +import java.time.format.DateTimeFormatter; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; + +@Configuration +public class JacksonConfiguration { + + @Value("${spring.jackson.date-format}") + public String DATETIME_FORMAT; + + /** + * LoaclTime格式化字符串 + */ + public String TIME_FORMAT = "HH:mm:ss"; + + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { + + return builder -> { + + // formatter + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATETIME_FORMAT); + DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_FORMAT); + + // deserializers + builder.deserializers(new LocalDateTimeDeserializer(dateTimeFormatter)); + builder.deserializers(new LocalTimeDeserializer(timeFormatter)); + + // serializers + builder.serializers(new LocalDateTimeSerializer(dateTimeFormatter)); + builder.serializers(new LocalTimeSerializer(timeFormatter)); + }; + } + +} diff --git a/src/main/java/jj/tech/finance/config/security/Cors.java b/src/main/java/jj/tech/finance/config/security/Cors.java new file mode 100644 index 0000000..febdd5c --- /dev/null +++ b/src/main/java/jj/tech/finance/config/security/Cors.java @@ -0,0 +1,37 @@ +package jj.tech.finance.config.security; + +import java.util.List; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +@Configuration +public class Cors { + + @Bean + CorsFilter corsFilter() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.addAllowedOriginPattern("*"); +// corsConfiguration.addAllowedOrigin("file:///C:/Users/lenovo/Desktop/x.html"); +// corsConfiguration.addAllowedOrigin("http://localhost:8080"); +// corsConfiguration.addAllowedOrigin("http://localhost:80"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + corsConfiguration.setAllowCredentials(true); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(source); + } + + @Bean + public FilterRegistrationBean filterRegistrationBean(CorsFilter corsFilter) { + FilterRegistrationBean bean = new FilterRegistrationBean<>(corsFilter); + bean.setOrder(1); + return bean; + } + +} diff --git a/src/main/java/jj/tech/finance/config/security/SecurityAdminFilter.java b/src/main/java/jj/tech/finance/config/security/SecurityAdminFilter.java new file mode 100644 index 0000000..ac30e72 --- /dev/null +++ b/src/main/java/jj/tech/finance/config/security/SecurityAdminFilter.java @@ -0,0 +1,103 @@ +package jj.tech.finance.config.security; + + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.web.filter.OncePerRequestFilter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jj.tech.finance.utils.CookieUtil; +import jj.tech.finance.utils.JsonUtil; +import jj.tech.finance.utils.JwtUtil; +import jj.tech.finance.utils.WebAdminUtil; + +/** + * cors开头命名,为了使该过滤器在CorsFilter之后执行 + * @author admin + * + */ +@Component +@Order(Ordered.LOWEST_PRECEDENCE) +public class SecurityAdminFilter extends OncePerRequestFilter { + AntPathMatcher matcher = new AntPathMatcher(); + /** + * 不需要token就能访问的url + */ + List allowUrls = Arrays.asList( + "/web/**", + "/ws**/**", + "/swagger-ui/index.html", "/swagger-ui/**", "/v3/**", + "/favicon.ico", + "/op/login","/op/logout", + "/h2-console**/**"); + + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + // 忽略的urls + if (this.isIgnoreUrl(request.getRequestURI())) { + // 向后执行 + filterChain.doFilter(request, response); + return; + } + + // 更新token的有效时间 + Boolean verify = WebAdminUtil.verify(request, response); + if(verify == false) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + this.authError(request, response); + return; + } + filterChain.doFilter(request, response); + } + + /** + * 判断当前 requestURI 是否需要token访问 + * + * @param requestURI uri + * @return + */ + protected Boolean isIgnoreUrl(String requestURI) { + for (String i : allowUrls) { + if (matcher.match(i, requestURI)) { + return true; + } + } + return false; + } + + /** + * 无token返回 + * + * @param request + * @param response + */ + protected void authError(HttpServletRequest request, HttpServletResponse response) { + //request + response.setContentType("application/json;charset=UTF-8"); + String msg = "请求访问:" + request.getRequestURI() + ",token验证失败,无法访问资源"; + HashMap map = new HashMap<>(); + map.put("code", 401); + map.put("msg", msg); + try { + response.getWriter().write(JsonUtil.writeValueAsString(map)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + + +} diff --git a/src/main/java/jj/tech/finance/config/security/SecurityWebFilter.java b/src/main/java/jj/tech/finance/config/security/SecurityWebFilter.java new file mode 100644 index 0000000..d1b713b --- /dev/null +++ b/src/main/java/jj/tech/finance/config/security/SecurityWebFilter.java @@ -0,0 +1,104 @@ +package jj.tech.finance.config.security; + + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.util.AntPathMatcher; +import org.springframework.web.filter.OncePerRequestFilter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jj.tech.finance.utils.CookieUtil; +import jj.tech.finance.utils.JsonUtil; +import jj.tech.finance.utils.JwtUtil; +import jj.tech.finance.utils.WebAdminUtil; +import jj.tech.finance.utils.WebUserUtil; + +/** + * cors开头命名,为了使该过滤器在CorsFilter之后执行 + * @author admin + * + */ +@Component +@Order(Ordered.LOWEST_PRECEDENCE) +public class SecurityWebFilter extends OncePerRequestFilter { + AntPathMatcher matcher = new AntPathMatcher(); + /** + * 不需要token就能访问的url + */ + List allowUrls = Arrays.asList( + "/op/**", + "/ws**/**", + "/swagger-ui/index.html", "/swagger-ui/**", "/v3/**", + "/favicon.ico", + "/web/login","/web/logout", + "/h2-console**/**"); + + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + // 忽略的urls + if (this.isIgnoreUrl(request.getRequestURI())) { + // 向后执行 + filterChain.doFilter(request, response); + return; + } + + // 更新token的有效时间 + Boolean verify = WebUserUtil.verify(request, response); + if(verify == false) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + this.authError(request, response); + return; + } + filterChain.doFilter(request, response); + } + + /** + * 判断当前 requestURI 是否需要token访问 + * + * @param requestURI uri + * @return + */ + protected Boolean isIgnoreUrl(String requestURI) { + for (String i : allowUrls) { + if (matcher.match(i, requestURI)) { + return true; + } + } + return false; + } + + /** + * 无token返回 + * + * @param request + * @param response + */ + protected void authError(HttpServletRequest request, HttpServletResponse response) { + //request + response.setContentType("application/json;charset=UTF-8"); + String msg = "请求访问:" + request.getRequestURI() + ",token验证失败,无法访问资源"; + HashMap map = new HashMap<>(); + map.put("code", 401); + map.put("msg", msg); + try { + response.getWriter().write(JsonUtil.writeValueAsString(map)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + + +} diff --git a/src/main/java/jj/tech/finance/config/swagger/SwaggerConfig.java b/src/main/java/jj/tech/finance/config/swagger/SwaggerConfig.java new file mode 100644 index 0000000..b45dfe7 --- /dev/null +++ b/src/main/java/jj/tech/finance/config/swagger/SwaggerConfig.java @@ -0,0 +1,144 @@ +package jj.tech.finance.config.swagger; + + + +import java.util.Collections; + +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; + +/** + * swagger配置 + * 加入分组功能(默认注释掉) + * + * @author Dou + * @date 2022/6/30 + **/ +@Configuration +public class SwaggerConfig { + + + @Bean + OpenAPI springShopOpenAPI() { + + + SecurityScheme securityScheme = new SecurityScheme(); + securityScheme.type(SecurityScheme.Type.HTTP) + .scheme("bearer").bearerFormat("JWT") + .in(SecurityScheme.In.HEADER) + .scheme("basic"); + + Components compoenents = new Components(); + compoenents.addSecuritySchemes("bearer-key", securityScheme); + + return new OpenAPI() +// .components(compoenents) + .info(new Info().title("JJ Finance 接口文档") + .description("Spring application") + .version("v1.0.0") + .license(new License().name("Apache 2.0").url("http://springdoc.org"))) +// .security(Collections.singletonList(new SecurityRequirement().addList("bearer-key"))) + ; + } + + +// @Bean +// @Profile("prod") +// GroupedOpenApi prodApi(OpenAPI openAPI) { +// return GroupedOpenApi.builder() +// .group("user-test-api") +// .pathsToMatch("/null") +// .addOpenApiCustomizer(api -> { +// api = openAPI; +// }) +// .pathsToExclude("/health/*") +// .build(); +// } + + +// @Bean +// //@Profile("!prod") +// GroupedOpenApi loginApi(OpenAPI openAPI) { +// String paths[] = {"/op/login", "/op/logout"}; +// return GroupedOpenApi.builder() +// .group("login") +//// .packagesToScan("tech.bcnew.modular.authaudit.controller") +// .pathsToMatch(paths) +// .addOpenApiCustomizer(api -> { +// api = openAPI; +// }) +// .pathsToExclude("/health/*") +// .build(); +// } + +// @Bean +// @Profile("!prod") +// GroupedOpenApi jpaApi(OpenAPI openAPI) { +// String packagesToscan[] = {"jj.tech.dcang.repository"}; +// return GroupedOpenApi.builder() +// .group("jpa") +// .packagesToScan(packagesToscan) +// .addOpenApiCustomizer(api -> { +// api = openAPI; +// }) +// .pathsToExclude("/health/*") +// .build(); +// } + + + +// @Bean +// @Profile("!prod") +// GroupedOpenApi webApi(OpenAPI openAPI) { +// return GroupedOpenApi.builder() +// .group("web") +// .pathsToMatch("/web/**") +// //.packagesToScan("/jj/tech/paolu/biz/**") +// .addOpenApiCustomizer(api -> { +// api = openAPI; +// }) +// .pathsToExclude("/health/*","/jpa*") +// .build(); +// } + + + @Bean + //@Profile("!prod") + GroupedOpenApi webAdminApi(OpenAPI openAPI) { + return GroupedOpenApi.builder() + .group("op") + .pathsToMatch("/op/**") + //.pathsToExclude("/op/login", "/op/logout") + //.packagesToScan("/jj/tech/paolu/biz/**") + .addOpenApiCustomizer(api -> { + api = openAPI; + }) + .pathsToExclude("/health/*","/jpa*") + .build(); + } + + @Bean + //@Profile("!prod") + GroupedOpenApi webApi(OpenAPI openAPI) { + return GroupedOpenApi.builder() + .group("web") + .pathsToMatch("/web/**") + //.packagesToScan("/jj/tech/paolu/biz/**") + .addOpenApiCustomizer(api -> { + api = openAPI; + }) + .pathsToExclude("/health/*","/jpa*") + .build(); + } + + +} diff --git a/src/main/java/jj/tech/finance/config/ws/SocketHandler.java b/src/main/java/jj/tech/finance/config/ws/SocketHandler.java new file mode 100644 index 0000000..41f4299 --- /dev/null +++ b/src/main/java/jj/tech/finance/config/ws/SocketHandler.java @@ -0,0 +1,40 @@ +//package jj.tech.dcang.config.ws; +// +//import java.util.HashMap; +//import java.util.Map; +// +//import org.apache.commons.lang3.StringUtils; +//import org.springframework.web.socket.CloseStatus; +//import org.springframework.web.socket.TextMessage; +//import org.springframework.web.socket.WebSocketSession; +//import org.springframework.web.socket.handler.TextWebSocketHandler; +// +//public class SocketHandler extends TextWebSocketHandler { +// +// public final Map sessions = new HashMap<>(); +// +// @Override +// public void afterConnectionEstablished(WebSocketSession session) throws Exception { +// String path = StringUtils.substringAfterLast(session.getUri().getPath(), "/"); +// System.out.println(path); +// sessions.put(path, session); +// +// super.afterConnectionEstablished(session); +// } +// +// @Override +// protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { +// String payload = message.getPayload(); +// System.out.println(payload); +//// for (Map.Entry otherSession : sessions.entrySet()) { +//// if (otherSession.getKey().equals(session.getId())) continue; +//// otherSession.getValue().sendMessage(new TextMessage("ssss"+payload)); +//// } +// } +// +// @Override +// public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { +// sessions.remove(session.getId()); +// super.afterConnectionClosed(session, status); +// } +//} \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/config/ws/WebSocketConfig.java b/src/main/java/jj/tech/finance/config/ws/WebSocketConfig.java new file mode 100644 index 0000000..422e6e8 --- /dev/null +++ b/src/main/java/jj/tech/finance/config/ws/WebSocketConfig.java @@ -0,0 +1,30 @@ +//package jj.tech.dcang.config.ws; +// +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.web.socket.WebSocketHandler; +//import org.springframework.web.socket.config.annotation.EnableWebSocket; +//import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +//import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; +// +//@Configuration +//@EnableWebSocket +//public class WebSocketConfig implements WebSocketConfigurer { +// +// +// public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { +// registry.addHandler(myHandler(), "/ws/{id}", "/ws") +// .setAllowedOrigins("*") +//// .setAllowedOrigins("file:///E:/ss.html") +//// .setAllowedOriginPatterns("*") +// ; +//// .withSockJS(); +// } +// +// @Bean +// public WebSocketHandler myHandler() { +// return new SocketHandler(); +// } +// +//} \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/utils/AES.java b/src/main/java/jj/tech/finance/utils/AES.java new file mode 100644 index 0000000..cae66ee --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/AES.java @@ -0,0 +1,102 @@ +package jj.tech.finance.utils; + + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; + +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.Charset; + +public class AES { + + private Cipher CBC; + private Cipher ECB; + private IvParameterSpec ivParameterSpec; + private SecretKeySpec secretKeySpec; + + public AES(){ + this("ssdkF$HUy2A#D%kd","weJiSEvR5yAC5ftB"); + } + public AES(String KEY, String IV){ + try { + this.CBC = Cipher.getInstance("AES/CBC/PKCS5PADDING"); + this.ECB = Cipher.getInstance("AES/ECB/PKCS5PADDING"); + this.ivParameterSpec = new IvParameterSpec(IV.getBytes(Charset.defaultCharset())); + this.secretKeySpec = new SecretKeySpec(KEY.getBytes(Charset.defaultCharset()), "AES"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + + public String encryptCBC(String toBeEncrypt){ + try { + CBC.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); + byte[] encrypted = CBC.doFinal(toBeEncrypt.getBytes()); + return Base64.encodeBase64URLSafeString(encrypted); + }catch(Exception e) { + e.printStackTrace(); + return null; + } + } + + + public String decryptCBC(String encrypted){ + try { + CBC.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); + byte[] decryptedBytes = CBC.doFinal(Base64.decodeBase64(encrypted)); + return new String(decryptedBytes); + }catch(Exception e) { + e.printStackTrace(); + return null; + } + } + + public String encrypt(String toBeEncrypt){ + try { + ECB.init(Cipher.ENCRYPT_MODE, secretKeySpec); + byte[] encrypted = ECB.doFinal(toBeEncrypt.getBytes()); + return Base64.encodeBase64URLSafeString(encrypted); + }catch(Exception e) { + e.printStackTrace(); + return null; + } + } + public String decrypt(String encrypted){ + try { + ECB.init(Cipher.DECRYPT_MODE, secretKeySpec); + byte[] decryptedBytes = ECB.doFinal(Base64.decodeBase64(encrypted)); + return new String(decryptedBytes); + }catch(Exception e) { + e.printStackTrace(); + return null; + } + } + + public static void main(String[] args) { + AES a = new AES(); + String s = a.encryptCBC("111"); + String v = a.decryptCBC(s); + System.out.println(s); + System.out.println(v); + + + String bb = a.encrypt("222"); + String cc = a.decrypt(bb); + System.out.println(bb); + System.out.println(cc); + + + String m = DigestUtils.sha3_256Hex("000000"); + System.out.println("sha3256:"+m); + + + System.out.println(a.encrypt("555555555551")); + System.out.println(a.decrypt(a.encrypt("555555555551"))); + + } + +} diff --git a/src/main/java/jj/tech/finance/utils/AlphaUtils.java b/src/main/java/jj/tech/finance/utils/AlphaUtils.java new file mode 100644 index 0000000..34b290f --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/AlphaUtils.java @@ -0,0 +1,66 @@ +package jj.tech.finance.utils; + +import java.util.Arrays; + +import org.apache.commons.lang3.StringUtils; + +public class AlphaUtils { + public static String getNext(String charSeqStr) { + + String nextCharSeqStr = null; + char[] charSeqArr = null; + boolean isResetAllChar = false; + boolean isResetAfterIndex = false; + Integer resetAfterIndex = 0; + + if (StringUtils.isBlank(charSeqStr)) { + charSeqArr = new char[] { 'A' }; + } else { + charSeqArr = charSeqStr.toCharArray(); + Integer charSeqLen = charSeqArr.length; + + for (int index = charSeqLen - 1; index >= 0; index--) { + char charAtIndex = charSeqArr[index]; + + if (Character.getNumericValue(charAtIndex) % 35 == 0) { + if (index == 0) { + charSeqArr = Arrays.copyOf(charSeqArr, charSeqLen + 1); + isResetAllChar = true; + } else { + continue; + } + } else { + char nextCharAtIndex = (char) (charAtIndex + 1); + charSeqArr[index] = nextCharAtIndex; + if (index + 1 < charSeqLen) { + isResetAfterIndex = true; + resetAfterIndex = index; + } + break; + } + } + charSeqLen = charSeqArr.length; + if (isResetAllChar) { + for (int index = 0; index < charSeqLen; index++) { + charSeqArr[index] = 'A'; + } + } else if (isResetAfterIndex) { + for (int index = resetAfterIndex + 1; index < charSeqLen; index++) { + charSeqArr[index] = 'A'; + } + } + } + + nextCharSeqStr = String.valueOf(charSeqArr); + return nextCharSeqStr; + } + + public static void main(String args[]) { + String nextAlphaSequence = null; + + for (int index = 0; index < 55; index++) { + nextAlphaSequence = AlphaUtils.getNext(nextAlphaSequence); + System.out.println(nextAlphaSequence); + } + } +} diff --git a/src/main/java/jj/tech/finance/utils/CookieUtil.java b/src/main/java/jj/tech/finance/utils/CookieUtil.java new file mode 100644 index 0000000..dc12626 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/CookieUtil.java @@ -0,0 +1,112 @@ +package jj.tech.finance.utils; + +import java.io.UnsupportedEncodingException; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +public class CookieUtil { + private static final String DEFAULT_PATH = "/"; + private static final int DEFAULT_AGE = -1; + + private static String path = DEFAULT_PATH; + private static int age = DEFAULT_AGE; + + /** + * 添加cookie + * @param name + * @param value + * @param response + * @param maxAge + * @throws UnsupportedEncodingException + */ + public static void add(String name, String value,HttpServletResponse response){ + try { +// Cookie cookie = new Cookie(name,URLEncoder.encode(value,"utf-8")); +// byte[] compressed =Snappy.compress(value.getBytes("UTF-8"));//压缩 + Cookie cookie = new Cookie(name, value); + cookie.setMaxAge(age); + cookie.setPath(path); +// cookie.setDomain("localhost"); + response.addCookie(cookie); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 删除cookie + * @param name + * @param response + */ + public static void delete(HttpServletResponse response,String name){ + Cookie cookie = new Cookie(name,""); + cookie.setMaxAge(0); + cookie.setPath(path); + response.addCookie(cookie); + } + + public static void deleteAll(HttpServletRequest request, HttpServletResponse response){ + Cookie[] cookies = request.getCookies(); + if(cookies != null){ + for(Cookie cookie : cookies){ + cookie.setMaxAge(0); + cookie.setPath(path); + response.addCookie(cookie); + } + } + } + + /** + * 改变cookie的值 + * @param cookie + * @param value + */ + public static void edit(Cookie cookie,String value){ + if(cookie != null) cookie.setValue(value); + } + + /** + * 更加cookie名称查找,返回其值 + * 找不到返回null + * @param request + * @param name + * @return + */ + public static String fine(HttpServletRequest request,String name){ + try { + Cookie[] cookies = request.getCookies(); + if(cookies != null){ + for(Cookie cookie : cookies){ + if(name.equals(cookie.getName())) + { + +// byte[] cookitValue = Base64.decodeBase64(cookie.getValue()); +// byte[] uncompressed = Snappy.uncompress(cookitValue); +// return URLDecoder.decode(cookie.getValue(), "utf-8"); +// return new String (uncompressed,"UTF-8"); + return cookie.getValue(); + } + } + } + return null; + } catch (Exception e) { + return null; + } + + } + + public static Cookie get(HttpServletRequest request,String name){ + + Cookie[] cookies = request.getCookies(); + if(cookies != null){ + for(Cookie cookie : cookies){ + if(name.equals(cookie.getName())) + return cookie; + } + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/utils/IDHelp.java b/src/main/java/jj/tech/finance/utils/IDHelp.java new file mode 100644 index 0000000..459c9e0 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/IDHelp.java @@ -0,0 +1,124 @@ +package jj.tech.finance.utils; + + +import org.springframework.stereotype.Component; + +import java.util.Random; + +/** + * Twitter的SnowFlake算法 + * 1111111111111111111111111100000000000000000000000 42位时间 + * 1111111111111111111111111111111100000000000000000 5位数据中心ID + * 1111111111111111111111111111111111111000000000000 5位机器ID + * 0000000000000000000000000000000000000111111111111 12位sequenceBits + * 4个值或运算组成一个新的Long + * @DOU + */ +@Component +public class IDHelp { + +// private static final Logger LOG = LoggerFactory.getLogger(IDHelp.class); + private static IDHelp instance; + + private long workerId = 1; //只有五位,0<=workerId<32 + private long datacenterId = 1; //只有5位, 0<=datacenterId<32 + + + + private long startTime = 1661370468606L; //42位bit,第1位固定正数0,开始后最大能使用69年 + private long workerIdBits = 5L; //5bit机器ID + private long datacenterIdBits = 5L; //5bit数据中心ID + private long sequenceBits = 12L; //12位bit,同毫秒内产生的不同id + + private long workerIdLeft = sequenceBits; //左移量 + private long datacenterIdLeft = sequenceBits + workerIdBits; + private long timestampLeft = sequenceBits + workerIdBits + datacenterIdBits; //22位,64-22=42位 + + + private long sequence = 0L; //每毫秒初始值 + private long lastTimestamp = -1L; //上一次当前毫秒 + private long sequenceMax = -1L ^ (-1L << sequenceBits); //sequenceMax 最大值 4095 + + + private IDHelp() { + + } + + + public synchronized Long nextId() { + long timestamp = timeGen(); + + if (timestamp < lastTimestamp) { +// LOG.error(String.format("clock is moving backwards. Rejecting requests until %d.", lastTimestamp)); + } + + if (lastTimestamp == timestamp) { + sequence = (sequence + 1) & sequenceMax; + if (sequence == 0) { + timestamp = tilNextMillis(lastTimestamp); + } + } else { + sequence = 0L; + } + + lastTimestamp = timestamp; +// String.valueOf(((timestamp - startTime) << timestampLeft) | (datacenterId << datacenterIdLeft) | (workerId << workerIdLeft) | sequence) + return ((timestamp - startTime) << timestampLeft) | (datacenterId << datacenterIdLeft) | (workerId << workerIdLeft) | sequence; + } + + private long tilNextMillis(long lastTimestamp) { + long timestamp = timeGen(); + while (timestamp <= lastTimestamp) { + timestamp = timeGen(); + } + return timestamp; + } + + private long timeGen() { + return System.currentTimeMillis(); + } + + + /** + * @param workerId 机器ID + * @param datacenterId 数据中心ID + * @return + */ + public static IDHelp getInstance(Integer workerId, Integer datacenterId) { + if(workerId<0 || datacenterId<0) { + throw new RuntimeException("workerId || datacenterId < 0"); + } + + if(workerId>31 || datacenterId>31) { + throw new RuntimeException("workerId || datacenterId > 31"); + } + if(instance==null){ + IDHelp bean= new IDHelp(); + bean.workerId = workerId; + bean.datacenterId = datacenterId; + instance = bean; + } + return instance; + } + public static IDHelp getInstance() { + Random r = new Random(); + r.nextInt(32); + return IDHelp.getInstance(r.nextInt(32), r.nextInt(32)); + } + + public static IDHelp getDefInstance() { + return IDHelp.getInstance(0, 0); + } + + + + public static void main(String[] args) { + System.err.println(System.currentTimeMillis()); + IDHelp id = IDHelp.getDefInstance(); + for(int i=0; i<100000; i++) { + System.out.println(id.nextId()); + } + + } + +} \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/utils/JsonUtil.java b/src/main/java/jj/tech/finance/utils/JsonUtil.java new file mode 100644 index 0000000..b907313 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/JsonUtil.java @@ -0,0 +1,110 @@ +package jj.tech.finance.utils; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * json转换工具类 + */ +public class JsonUtil { + private static Logger log = LoggerFactory.getLogger(JsonUtil.class); + + private static ObjectMapper objectMapper = new ObjectMapper(); + static { +// //将对象的所有字段全部列入 +// objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.ALWAYS); +// +// //取消默认转换timestamps形式,false使用日期格式转换,true不使用日期转换,结果是时间的数值157113793535 +// objectMapper.configure(SerializationConfig.Feature.WRITE_DATE_KEYS_AS_TIMESTAMPS,false); //默认值true +// +// //忽略空Bean转json的错误 +// objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS,false); +// +// //所有的日期格式统一样式: yyyy-MM-dd HH:mm:ss +// objectMapper.setDateFormat(new SimpleDateFormat(DateTimeUtil.STANDARD_FORMAT)); +// +// //忽略 在json字符串中存在,但是在对象中不存在对应属性的情况,防止错误。 +// // 例如json数据中多出字段,而对象中没有此字段。如果设置true,抛出异常,因为字段不对应;false则忽略多出的字段,默认值为null,将其他字段反序列化成功 +// objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES,false); + JavaTimeModule javaTimeModule = new JavaTimeModule(); + javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + objectMapper.configure(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS, false); + objectMapper.registerModule(javaTimeModule); + + } + + //将单个对象转换成json格式的字符串(没有格式化后的json) + public static String writeValueAsString(T obj){ + if (obj == null){ + return null; + } + try { + return obj instanceof String ? (String) obj:objectMapper.writeValueAsString(obj); + } catch (IOException e) { + log.warn("Parse object to String error", e); + return null; + } + } + + //将单个对象转换成json格式的字符串(格式化后的json) + public static String writeValueAsStringPretty(T obj){ + if (obj == null){ + return null; + } + try { + return obj instanceof String ? (String) obj:objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj); + } catch (IOException e) { + log.warn("Parse object to String error", e); + return null; + } + } + //将json形式的字符串数据转换成单个对象 + public static T readValueToObj(String str, Class clazz){ + if (StringUtils.isEmpty(str) || clazz == null){ + return null; + } + try { + return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str,clazz); + } catch (IOException e) { + log.warn("Parse object to Object error", e); + return null; + } + } + + //将json形式的字符串数据转换成多个对象 +// public static T string2Obj(String str, TypeReference typeReference){ +// if (StringUtils.isEmpty(str) || typeReference == null){ +// return null; +// } +// try { +// return typeReference.getType().equals(String.class) ? (T) str : (T) objectMapper.readValue(str, typeReference); +// } catch (IOException e) { +// log.warn("Parse object to Object error", e); +// return null; +// } +// } + + //将json形式的字符串数据转换成多个对象 + public static T readValueToList(String str, Class collectionClass, Class... elementClasses){ + try { + return objectMapper.readValue(str, objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses)); + } catch (IOException e) { + log.warn("Parse object to Object error", e); + return null; + } + } + + +} diff --git a/src/main/java/jj/tech/finance/utils/JwtUtil.java b/src/main/java/jj/tech/finance/utils/JwtUtil.java new file mode 100644 index 0000000..f85dabb --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/JwtUtil.java @@ -0,0 +1,149 @@ +package jj.tech.finance.utils; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.*; +import io.jsonwebtoken.jackson.io.JacksonDeserializer; +import io.jsonwebtoken.jackson.io.JacksonSerializer; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.time.Instant; +import java.util.Base64; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +public class JwtUtil { + private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class); + private static final String CLAIM_KEY_CREATED = "created"; + public static final String HMACSHA256 = "HMACSHA256"; + public static final String SECRET = "fn4hIX5+d29jYW8seWFtYWRpZSx3YW5kYW5sZX5+ISF+fg=="; + public static final SecretKey DEFAULT_SECRET_KEY = new SecretKeySpec(Base64.getDecoder().decode(SECRET), HMACSHA256); + public static ObjectMapper objectMapper = new ObjectMapper(); + + private static long exp = 10 * 60 * 60 * 1000; //过期时间 + + /** + * 根据负责生成JWT的token + */ + public static String generateToken(Map claims) { + claims.put(CLAIM_KEY_CREATED, new Date()); + JwtBuilder builder = Jwts.builder() + .setClaims(claims) + .compressWith(CompressionCodecs.GZIP) + .serializeToJsonWith(new JacksonSerializer(objectMapper)) + .signWith(JwtUtil.DEFAULT_SECRET_KEY); + if (exp > 0) { + long nowMillis = System.currentTimeMillis(); + builder.setExpiration(new Date(nowMillis + exp)); + } + return builder.compact(); + } + + /** + * 当原来的token没过期时是可以刷新的 + * + * @param oldToken 带tokenHead的token + */ + public static String refreshHeadToken(String oldToken) { + if(StringUtils.isEmpty(oldToken)){ + return null; + } + //token校验不通过 + Claims claims = getClaimsFromToken(oldToken); + if(claims==null){ + return null; + } + //如果token已经过期,不支持刷新 + Date expiredDate = claims.getExpiration(); + if(expiredDate.before(new Date())){ + return null; + } + //如果token在30分钟之内刚刷新过,返回原token + if(tokenRefreshJustBefore(oldToken,30*60)){ + return oldToken; + }else{ + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + } + + /** + * 判断token在指定时间内是否刚刚刷新过 + * @param token 原token + * @param time 指定时间(秒) + */ + public static boolean tokenRefreshJustBefore(String token, int time) { + Claims claims = getClaimsFromToken(token); + Date created = claims.get(CLAIM_KEY_CREATED, Date.class); + Date refreshDate = new Date(); + //刷新时间在创建时间的指定时间内 + if(refreshDate.after(created)&&refreshDate.before(DateUtils.addSeconds(created,time))){ + return true; + } + return false; + } + + /** + * 从token中获取JWT中的负载 + */ + public static Claims getClaimsFromToken(String token) { + Claims claims = null; + try { + claims = Jwts.parser() + .setSigningKey(SECRET) + .parseClaimsJws(token) + .getBody(); + } catch (Exception e) { + logger.info("JWT格式验证失败:{}", token); + } + return claims; + } + + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public JwtBuilder jwtBuilder() { + return Jwts.builder() + .compressWith(CompressionCodecs.GZIP) + .serializeToJsonWith(new JacksonSerializer(objectMapper)) + .signWith(JwtUtil.DEFAULT_SECRET_KEY); + + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public JwtParser jwtParser() { + return Jwts.parserBuilder() + .deserializeJsonWith(new JacksonDeserializer(objectMapper)) + .setSigningKey(DEFAULT_SECRET_KEY) + .build(); + } + + @SuppressWarnings("unchecked") + public static void main(String[] args) { + JwtUtil jwtUtil = new JwtUtil(); + + //Create the TOKEN + HashMap b = new HashMap(); + b.put("x", "11"); + b.put("y", "22"); + Claims claim = Jwts.claims(); + claim.put("a", "aa"); + claim.put("b", b); + claim.setExpiration(Date.from(Instant.now().plusSeconds(2L))); + + var encoder = jwtUtil.jwtBuilder().setClaims(claim).compact(); + System.out.println(encoder); + + //Decode the TOKEN + var jwtParser = jwtUtil.jwtParser(); + jwtParser.isSigned(encoder); + Jws claims = (Jws) jwtParser.parse(encoder); + System.out.println(claims.getBody()); + } + +} diff --git a/src/main/java/jj/tech/finance/utils/Page.java b/src/main/java/jj/tech/finance/utils/Page.java new file mode 100644 index 0000000..13fab15 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/Page.java @@ -0,0 +1,69 @@ +package jj.tech.finance.utils; + +import java.util.List; + + +public class Page { + + private Integer pageSize=20; //页多少条 + private Integer pageNum=1; //第几页 + private Long total=0L; //一共多少条 + private Long totalPage; //一共几页 + + private List list; + + public Page(){ + + } + + public Page(Integer pageNum,Integer pageSize){ + this.setPageNum(pageNum); + this.setPageSize(pageSize); + } + + + public int getPageSize() { + return pageSize; + } + public void setPageSize(Integer pageSize) { + if(pageSize != null && pageSize >= 1 && pageSize<20000){ + this.pageSize = pageSize; + } + } + public int getPageNum() { + return pageNum; + } + public void setPageNum(Integer pageNum) { + if(pageNum != null && pageNum >= 1){ + this.pageNum = pageNum; + } + } + public Long getTotal() { + return total; + } + public void setTotal(Long total) { + if(total!=null) { + this.total = total; + } + } + public Long getTotalPage() { + Integer t = (int) Math.ceil((double) total / pageSize); + totalPage = t.longValue(); + return totalPage; + } + public void setTotalPage(Long totalPage) { + this.totalPage = totalPage; + } + public List getList() { + return list; + } + public void setList(List list) { + this.list = list; + } + + + public int limitStart(){ + return (pageNum - 1) * pageSize; + } + +} diff --git a/src/main/java/jj/tech/finance/utils/R.java b/src/main/java/jj/tech/finance/utils/R.java new file mode 100644 index 0000000..f54a782 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/R.java @@ -0,0 +1,73 @@ +package jj.tech.finance.utils; + + +public class R { + public Boolean isOk; + public String message; + public Object data; + public String code; + + public R() { + } + + public R(Boolean isOk, String message, Object data) { + this.isOk=isOk; + this.message=message; + this.data=data; + } + + public static R SUCCESS(){ + return new R(true,"", null); + } + + public static R SUCCESS(String message){ + return new R(true, message==null ? "" : message, null); + } + + public static R SUCCESS(String message, Object data){ + return new R(true, message==null ? "" : message, data); + } + public static R SUCCESS(Object data){ + return new R(true, "" , data); + } + + + + public static R FALSE(){ + return new R(false,"", null); + } + public static R FALSE(String message){ + return new R(false, message==null ? "" : message, null); + } + public static R FALSE(String message, Object data){ + return new R(false, message==null ? "" : message, data); + } + public static R FALSE(Object data){ + return new R(true, "" , data); + } + + + public Boolean getIsOk() { + return isOk; + } + + public void setIsOk(Boolean isOk) { + this.isOk = isOk; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } +} diff --git a/src/main/java/jj/tech/finance/utils/WebAdminUtil.java b/src/main/java/jj/tech/finance/utils/WebAdminUtil.java new file mode 100644 index 0000000..efcc0b3 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/WebAdminUtil.java @@ -0,0 +1,109 @@ +package jj.tech.finance.utils; + +import java.time.LocalDateTime; +import java.util.HashMap; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jj.tech.finance.repository.mybatis.entity.SysAdmin; + +public class WebAdminUtil { + private static Logger logger = LoggerFactory.getLogger(WebAdminUtil.class); + private static ObjectMapper objectMapper = new ObjectMapper(); + public static String TOKEN = "token"; + public static long exp = 5 * 60 * 60 * 1000; //过期时间5小时 + static { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + + + @SuppressWarnings("unchecked") + public static Boolean verify(HttpServletRequest request, HttpServletResponse response) { + try { + String token = CookieUtil.fine(request, TOKEN); + if (StringUtils.isBlank(token)) { + return false; + } + AES aes = new AES(); + String jsonUser = aes.decrypt(token); + HashMap map = objectMapper.readValue(jsonUser, HashMap.class); + Long logintime = (Long)map.get("logintime"); + Long now = System.currentTimeMillis(); + + if(now-logintime > exp) { + return false; + } + + //大于30分钟,更新一下用户token + if(now-logintime > 30 * 60 * 1000) { + map.put("logintime", now); + WebAdminUtil.addToCookie(map); + } + + SysAdmin bean = new SysAdmin(); + BeanUtils.populate(bean, map); + request.setAttribute(TOKEN, bean); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public static SysAdmin getUser() { + try { + ServletRequestAttributes servlet = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = servlet.getRequest(); + SysAdmin curr = (SysAdmin)request.getAttribute(TOKEN); + return curr; + }catch(Exception e) { + e.printStackTrace(); + logger.info(e.getMessage()); + return null; + } + } + + public static String addToCookie(Object obj) { + try { + ServletRequestAttributes servlet = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + HttpServletResponse response = servlet.getResponse(); + + String userJson = objectMapper.writeValueAsString(obj); + AES aes = new AES(); + String token = aes.encrypt(userJson); + CookieUtil.add(TOKEN, token, response); + return token; + }catch(Exception e) { + logger.info(e.getMessage()); + return null; + } + } + + public static void deleteUser() { + try { + ServletRequestAttributes servlet = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + HttpServletResponse response = servlet.getResponse(); + CookieUtil.delete(response, TOKEN); + }catch(Exception e) { + logger.info(e.getMessage()); + } + } + + + + +} diff --git a/src/main/java/jj/tech/finance/utils/WebUserUtil.java b/src/main/java/jj/tech/finance/utils/WebUserUtil.java new file mode 100644 index 0000000..5d2eae7 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/WebUserUtil.java @@ -0,0 +1,105 @@ +package jj.tech.finance.utils; + +import java.util.HashMap; + +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jj.tech.finance.repository.mybatis.entity.UserInfo; + +public class WebUserUtil { + private static Logger logger = LoggerFactory.getLogger(WebAdminUtil.class); + private static ObjectMapper objectMapper = new ObjectMapper(); + public static String TOKEN = "webtoken"; + public static long exp = 5 * 60 * 60 * 1000; //过期时间5小时 + static { + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + } + + + + @SuppressWarnings("unchecked") + public static Boolean verify(HttpServletRequest request, HttpServletResponse response) { + try { + String token = CookieUtil.fine(request, TOKEN); + if (StringUtils.isBlank(token)) { + return false; + } + AES aes = new AES(); + String jsonUser = aes.decrypt(token); + HashMap map = objectMapper.readValue(jsonUser, HashMap.class); + Long logintime = (Long)map.get("logintime"); + Long now = System.currentTimeMillis(); + + if(now-logintime > exp) { + return false; + } + + //大于30分钟,更新一下用户token + if(now-logintime > 30 * 60 * 1000) { + map.put("logintime", now); + WebUserUtil.addToCookie(map); + } + + UserInfo bean = new UserInfo(); + BeanUtils.populate(bean, map); + request.setAttribute(TOKEN, bean); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public static UserInfo getUser() { + try { + ServletRequestAttributes servlet = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = servlet.getRequest(); + UserInfo curr = (UserInfo)request.getAttribute(TOKEN); + return curr; + }catch(Exception e) { + e.printStackTrace(); + logger.info(e.getMessage()); + return null; + } + } + + public static String addToCookie(Object obj) { + try { + ServletRequestAttributes servlet = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + HttpServletResponse response = servlet.getResponse(); + + String userJson = objectMapper.writeValueAsString(obj); + AES aes = new AES(); + String token = aes.encrypt(userJson); + CookieUtil.add(TOKEN, token, response); + return token; + }catch(Exception e) { + logger.info(e.getMessage()); + return null; + } + } + + public static void deleteUser() { + try { + ServletRequestAttributes servlet = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + HttpServletResponse response = servlet.getResponse(); + CookieUtil.delete(response, TOKEN); + }catch(Exception e) { + logger.info(e.getMessage()); + } + } + + + + +} diff --git a/src/main/java/jj/tech/finance/utils/mybatis/MybatisControllerPlugin.java b/src/main/java/jj/tech/finance/utils/mybatis/MybatisControllerPlugin.java new file mode 100644 index 0000000..cb97a2f --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/mybatis/MybatisControllerPlugin.java @@ -0,0 +1,187 @@ +package jj.tech.finance.utils.mybatis; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Properties; + +import org.mybatis.generator.api.GeneratedJavaFile; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.MyBatisGenerator; +import org.mybatis.generator.api.PluginAdapter; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.api.dom.java.JavaVisibility; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.Parameter; +import org.mybatis.generator.api.dom.java.TopLevelClass; +import org.mybatis.generator.config.Configuration; +import org.mybatis.generator.config.PropertyRegistry; +import org.mybatis.generator.config.xml.ConfigurationParser; +import org.mybatis.generator.internal.DefaultShellCallback; +import org.mybatis.generator.internal.util.StringUtility; +import org.springframework.util.StringUtils; + +/** + * 生成Controller + * @author Dou + */ +public class MybatisControllerPlugin extends PluginAdapter { + + + private String targetProject = null; + + private String targetPackage = null; + + + @Override + public boolean validate(List warnings) { + return true; + } + + @Override + public void setProperties(Properties properties) { + super.setProperties(properties); + targetProject = properties.getProperty("targetProject"); + targetPackage = properties.getProperty("targetPackage"); + } + + @Override + public List contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) { + if (Objects.nonNull(targetPackage) && Objects.nonNull(targetProject)) { + + String daoMapperName = introspectedTable.getMyBatis3SqlMapNamespace(); + + String recordType = introspectedTable.getBaseRecordType(); + String[] entityPackage = recordType.split("\\."); + String entityName = entityPackage[entityPackage.length - 1]; + + String first = String.valueOf(entityName.charAt(0)); + String lowerEntityName = entityName.replaceFirst(first, first.toLowerCase()); + String lowerEntityNameMapper = lowerEntityName + "Mapper"; + + TopLevelClass controllerClass = new TopLevelClass(targetPackage + "." + entityName + "Controller"); + + controllerClass.addImportedType("java.lang.Object"); + controllerClass.addImportedType("org.springframework.web.bind.annotation.*"); + controllerClass.addImportedType("org.springframework.stereotype.Controller"); + controllerClass.addImportedType(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired")); + controllerClass.addImportedType(daoMapperName); + + controllerClass.addAnnotation("@Controller"); + controllerClass.setVisibility(JavaVisibility.PUBLIC); + //controllerClass.addAnnotation("@RestController"); + + + controllerClass.addAnnotation("@RequestMapping(\"" + lowerEntityName + "\")"); + + //daoMapper inject + FullyQualifiedJavaType daoMapper = new FullyQualifiedJavaType(daoMapperName); + Field serviceField = new Field(lowerEntityNameMapper , daoMapper); + serviceField.addJavaDocLine(""); + serviceField.addAnnotation("@Autowired"); + serviceField.setVisibility(JavaVisibility.PRIVATE); + controllerClass.addField(serviceField); + + + + //Add Method + + FullyQualifiedJavaType respondJavaType = new FullyQualifiedJavaType("Object"); + controllerClass.addImportedType(respondJavaType); + controllerClass.addImportedType(new FullyQualifiedJavaType(recordType)); + + //primaryKeyType + Optional optional = PluginUtils.primaryKeyType(introspectedTable); + //primaryKeyTypeName + Optional keyNameOptional = PluginUtils.primaryKeyName(introspectedTable); + if (optional.isPresent() && keyNameOptional.isPresent()) { + FullyQualifiedJavaType primaryKeyType = optional.get(); + String primaryKeyName = keyNameOptional.get(); + if (primaryKeyType.isExplicitlyImported()) { + controllerClass.addImportedType(primaryKeyType); + } + + //findById + Method findByIdMethod = new Method("findById"); + findByIdMethod.setReturnType(respondJavaType); + findByIdMethod.addAnnotation("@PostMapping(\"findById/{" + primaryKeyName + "}\")"); + Parameter idParameter = new Parameter(primaryKeyType, primaryKeyName); + idParameter.addAnnotation("@PathVariable"); + findByIdMethod.addParameter(idParameter); + findByIdMethod.addBodyLine("return " + lowerEntityNameMapper+".selectByPrimaryKey("+primaryKeyName+");"); + controllerClass.addMethod(findByIdMethod); + + //save + Method saveMethod = new Method("save"); + saveMethod.setReturnType(respondJavaType); + saveMethod.addAnnotation("@PostMapping(\"save\")"); + Parameter saveParameter = new Parameter(new FullyQualifiedJavaType(recordType), "record"); + saveParameter.addAnnotation("@RequestBody"); + saveMethod.addParameter(saveParameter); + saveMethod.addBodyLine("return " + lowerEntityNameMapper+".insertSelective(record);"); + controllerClass.addMethod(saveMethod); + + //update + Method updateMethod = new Method("update"); + updateMethod.setReturnType(respondJavaType); + updateMethod.addAnnotation("@PutMapping(\"update\")"); + Parameter updateParameter = new Parameter(new FullyQualifiedJavaType(recordType), "record"); + updateParameter.addAnnotation("@RequestBody"); + updateMethod.addParameter(saveParameter); + updateMethod.addBodyLine("return " + lowerEntityNameMapper+".updateByPrimaryKeySelective(record);"); + controllerClass.addMethod(updateMethod); + + //delete + Method deleteMethod = new Method("delete"); + deleteMethod.setReturnType(respondJavaType); + deleteMethod.addAnnotation("@DeleteMapping(\"delete/{" + primaryKeyName + "}\")"); + Parameter deleteIdParameter = new Parameter(primaryKeyType, primaryKeyName); + deleteIdParameter.addAnnotation("@PathVariable"); + deleteMethod.addParameter(deleteIdParameter); + deleteMethod.addBodyLine("return " + lowerEntityNameMapper+".deleteByPrimaryKey(id);"); + controllerClass.addMethod(deleteMethod); + + //page + /* + * Method pageMethod = new Method("page"); + * pageMethod.addAnnotation("@PostMapping(\"page\")"); + * pageMethod.setReturnType(respondJavaType); Parameter pageNum = new + * Parameter(new FullyQualifiedJavaType("int"), "pageNum"); + * pageNum.addAnnotation("@RequestParam(defaultValue = \"1\")"); + * pageMethod.addParameter(pageNum); Parameter pageSize = new Parameter(new + * FullyQualifiedJavaType("int"), "pageSize"); + * pageSize.addAnnotation("@RequestParam(defaultValue = \"15\")"); + * pageMethod.addParameter(pageSize); pageMethod.addBodyLine("return null;"); + * controllerClass.addMethod(pageMethod); + */ + } + + + GeneratedJavaFile javaFile = new GeneratedJavaFile(controllerClass, targetProject, + context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING), + context.getJavaFormatter()); + + List files = new ArrayList<>(); + files.add(javaFile); + return files; + } + return Collections.emptyList(); + } + + public static void main(String[] args) throws Exception { + + List warnings = new ArrayList(); + boolean overwrite = true; + File configFile = new File("src/main/resources/generate/mybatis/generatorConfig.xml"); + ConfigurationParser cp = new ConfigurationParser(warnings); + Configuration config = cp.parseConfiguration(configFile); + DefaultShellCallback callback = new DefaultShellCallback(overwrite); + MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); + myBatisGenerator.generate(null); + } + +} diff --git a/src/main/java/jj/tech/finance/utils/mybatis/PluginUtils.java b/src/main/java/jj/tech/finance/utils/mybatis/PluginUtils.java new file mode 100644 index 0000000..1496615 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/mybatis/PluginUtils.java @@ -0,0 +1,142 @@ +package jj.tech.finance.utils.mybatis; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.mybatis.generator.api.IntrospectedColumn; +import org.mybatis.generator.api.IntrospectedTable; +import org.mybatis.generator.api.dom.java.Field; +import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; +import org.mybatis.generator.api.dom.java.InnerClass; +import org.mybatis.generator.api.dom.java.Interface; +import org.mybatis.generator.api.dom.java.JavaVisibility; +import org.mybatis.generator.api.dom.java.Method; +import org.mybatis.generator.api.dom.java.TopLevelClass; +import org.mybatis.generator.config.GeneratedKey; + +public class PluginUtils { + + private PluginUtils() { + + } + + public static Optional primaryKeyType(IntrospectedTable introspectedTable) { + Optional generatedKey = introspectedTable.getGeneratedKey(); + if (generatedKey.isPresent()) { + String primaryKey = generatedKey.get().getColumn(); + Optional optional = introspectedTable.getColumn(primaryKey); + if (optional.isPresent()) { + IntrospectedColumn keyColumn = optional.get(); + return Optional.ofNullable(keyColumn.getFullyQualifiedJavaType()); + } + } + return Optional.empty(); + } + + public static Optional primaryKeyName(IntrospectedTable introspectedTable) { + Optional generatedKey = introspectedTable.getGeneratedKey(); + if (generatedKey.isPresent()) { + String primaryKey = generatedKey.get().getColumn(); + Optional optional = introspectedTable.getColumn(primaryKey); + if (optional.isPresent()) { + IntrospectedColumn keyColumn = optional.get(); + return Optional.ofNullable(keyColumn.getJavaProperty()); + } + } + return Optional.empty(); + } + + public static void restfulMethod(Method method, boolean rest) { + if (!rest) { + method.addAnnotation("@ResponseBody"); + } + method.setVisibility(JavaVisibility.PUBLIC); + } + + public static void removeGeneratedAnnotation(Object object) { + if (Objects.nonNull(object)) { + if (object instanceof TopLevelClass) { + TopLevelClass topLevelClass = (TopLevelClass) object; + Set importedTypes = topLevelClass.getImportedTypes(); + if (Objects.nonNull(importedTypes) && !importedTypes.isEmpty()) { + importedTypes.removeIf(importedType -> Objects.equals(importedType.getFullyQualifiedName(), "javax.annotation.Generated")); + } + List fields = topLevelClass.getFields(); + if (Objects.nonNull(fields) && !fields.isEmpty()) { + fields.get(0).addJavaDocLine(""); + actionRemoveGeneratedAnnotation(fields); + } + List methods = topLevelClass.getMethods(); + if (Objects.nonNull(methods) && !methods.isEmpty()) { + actionRemoveGeneratedAnnotation(topLevelClass.getMethods()); + } + List innerClasses = topLevelClass.getInnerClasses(); + if (Objects.nonNull(innerClasses) && !innerClasses.isEmpty()) { + actionRemoveGeneratedAnnotation(innerClasses); + } + } else if (object instanceof Interface) { + Interface anInterface = (Interface) object; + Set importedTypes = anInterface.getImportedTypes(); + if (Objects.nonNull(importedTypes) && !importedTypes.isEmpty()) { + importedTypes.removeIf(importedType -> Objects.equals(importedType.getFullyQualifiedName(), "javax.annotation.Generated")); + } + List fields = anInterface.getFields(); + if (Objects.nonNull(fields) && !fields.isEmpty()) { + fields.get(0).addJavaDocLine(""); + actionRemoveGeneratedAnnotation(fields); + } + List methods = anInterface.getMethods(); + if (Objects.nonNull(methods) && !methods.isEmpty()) { + actionRemoveGeneratedAnnotation(anInterface.getMethods()); + } + List innerClasses = anInterface.getInnerClasses(); + if (Objects.nonNull(innerClasses) && !innerClasses.isEmpty()) { + actionRemoveGeneratedAnnotation(innerClasses); + } + } + } + } + + private static void actionRemoveGeneratedAnnotation(List objects) { + String delete = "@Generated(\"org.mybatis.generator.api.MyBatisGenerator\")"; + if (Objects.nonNull(objects) && !objects.isEmpty()) { + for (Object object : objects) { + if (object instanceof Method) { + Method method = (Method) object; + List annotations = method.getAnnotations(); + if (Objects.nonNull(annotations) && !annotations.isEmpty()) { + for (int i = 0; i < annotations.size(); i++) { + if (Objects.equals(annotations.get(i), delete)) { + annotations.remove(i); + break; + } + } + } + } else if (object instanceof Field) { + Field field = (Field) object; + List annotations = field.getAnnotations(); + if (Objects.nonNull(annotations) && !annotations.isEmpty()) { + for (int i = 0; i < annotations.size(); i++) { + if (Objects.equals(annotations.get(i), delete)) { + annotations.remove(i); + break; + } + } + } + } else if (object instanceof InnerClass) { + InnerClass innerClass = (InnerClass) object; + List annotations = innerClass.getAnnotations(); + if (Objects.nonNull(annotations) && !annotations.isEmpty()) { + for (int i = 0; i < annotations.size(); i++) { + if (Objects.equals(annotations.get(i), delete)) { + annotations.remove(i); + break; + } + } + } + } + } + } + }} diff --git a/src/main/java/jj/tech/finance/utils/mybatis/Sum.java b/src/main/java/jj/tech/finance/utils/mybatis/Sum.java new file mode 100644 index 0000000..46e0bf4 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/mybatis/Sum.java @@ -0,0 +1,41 @@ +package jj.tech.finance.utils.mybatis; +import org.mybatis.dynamic.sql.BindableColumn; +import org.mybatis.dynamic.sql.ColumnAndConditionCriterion; +import org.mybatis.dynamic.sql.SqlCriterion; +import org.mybatis.dynamic.sql.VisitableCondition; +import org.mybatis.dynamic.sql.render.TableAliasCalculator; +import org.mybatis.dynamic.sql.select.function.AbstractUniTypeFunction; +import org.mybatis.dynamic.sql.where.render.CriterionRenderer; + +public class Sum extends AbstractUniTypeFunction> { + + private final VisitableCondition condition; + + private Sum(BindableColumn column, VisitableCondition condition) { + super(column); + this.condition = condition; + } + + @Override + public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) { +// ColumnAndConditionCriterion.withColumn(column).withCondition(condition).build(). + ColumnAndConditionCriterion criteion = ColumnAndConditionCriterion + .withColumn(column) + .withCondition(condition).build(); + + + return "sum(" //$NON-NLS-1$ + + column.renderWithTableAlias(tableAliasCalculator) +// + s + + ")"; //$NON-NLS-1$ + } + + @Override + protected Sum copy() { + return new Sum<>(column, condition); + } + + public static Sum of(BindableColumn column, VisitableCondition condition) { + return new Sum<>(column, condition); + } +} \ No newline at end of file diff --git a/src/main/java/jj/tech/finance/utils/tushare/TushareConfig.java b/src/main/java/jj/tech/finance/utils/tushare/TushareConfig.java new file mode 100644 index 0000000..9334ec6 --- /dev/null +++ b/src/main/java/jj/tech/finance/utils/tushare/TushareConfig.java @@ -0,0 +1,7 @@ +package jj.tech.finance.utils.tushare; + +public class TushareConfig { + + public static String TOKEN = "843c785973fd04c932ac9612184e43f4d8f23eb2540d498e7b82154e"; + public static String URL = "http://api.tushare.pro"; +} diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..b1dfd2a --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,68 @@ +##约定大于配置,请勿重复造轮 +server: #服务端口 + port: 8083 + forward-headers-strategy: framework +##spring---------- +spring: + application: + name: zwyy + datasource: + type: com.zaxxer.hikari.HikariDataSource + #url: jdbc:h2:./test;AUTO_SERVER=TRUE #连接池Database 嵌入模式:jdbc:h2:~/test-jooq FILE_LOCK=SOCKET MODE=MySQL;;AUTO_SERVER=TRUE +# url: jdbc:h2:./test;MODE=MySQL;AUTO_SERVER=TRUE +# username: sa +# password: +# hikari: +# driver-class-name: org.h2.Driver + url: jdbc:mariadb://mariadb:3306/finance + username: root + password: open123 + hikari: + driver-class-name: org.mariadb.jdbc.Driver + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 +# serialization: +# fail-on-empty-beans: false +# deserialization: +# FAIL_ON_UNKNOWN_PROPERTIES: false + + h2: + console: + enabled: true #开启h2数据库的浏览器管理界面 + settings: + web-allow-others: true + trace: true #是否可以远程web + #path: /h2-console #h2浏览器管理访问路径,默认:/h2-console +# sql: +# init: +# mode: never ##加载脚本datasource.initialize已弃用,spring.sql.init.mode=never/always +# continue-on-error: true #初始化错误,继续执行 +# encoding: utf-8 #加载sql文件的编码连接池ue #初始化错误,继续执行 +# data-locations: classpath:/sql/data-h2.sql +# schema-locations: classpath:/sql/schema-h2.sql #spring boot 默认启动使用springJDBC初始化数据脚本, 加载类路径下的 schema-${platform}.sql \ data-${platform}.sql数据 +# platform: h2 + #elasticsearch: + #jest: + #uris: http://loalhost:9200 + #read-timeout: 1000 +# 多数据源 +# app: +# datasource: +# type: com.zaxxer.hikari.HikariDataSource +# jdbcUrl: jdbc:h2:~/test-jooq;AUTO_SERVER=TRUE +# username: sa +# password: +# ##连接池 +# hikari: +# driver-class-name: org.h2.Driver + + +logging: + level: + root: info +# org.jooq: debug +# org.springframework.amqp: debug +# org.mybatis: debug +# org.mybatis.dynamic.sql: debug +# jj.tech.dcang: debug diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..373e8fd --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,70 @@ +##约定大于配置,请勿重复造轮 +server: #服务端口 + port: 8083 + forward-headers-strategy: framework + +##spring---------- +spring: + application: + name: zwyy + datasource: + type: com.zaxxer.hikari.HikariDataSource + #url: jdbc:h2:./test;AUTO_SERVER=TRUE #连接池Database 嵌入模式:jdbc:h2:~/test-jooq FILE_LOCK=SOCKET MODE=MySQL;;AUTO_SERVER=TRUE +# url: jdbc:h2:./finance;MODE=MySQL;AUTO_SERVER=TRUE;DATABASE_TO_LOWER=TRUE +# username: sa +# password: +# hikari: +# driver-class-name: org.h2.Driver + url: jdbc:mariadb://106.53.186.11:3306/finance + username: root + password: open123 + hikari: + driver-class-name: org.mariadb.jdbc.Driver + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: CST +# serialization: +# write-dates-as-timestamps: false +# fail-on-empty-beans: false +# deserialization: +# FAIL_ON_UNKNOWN_PROPERTIES: false + + h2: + console: + enabled: true #开启h2数据库的浏览器管理界面 + settings: + web-allow-others: true + trace: true #是否可以远程web + #path: /h2-console #h2浏览器管理访问路径,默认:/h2-console + sql: + init: + mode: never ##加载脚本datasource.initialize已弃用,spring.sql.init.mode=never/always + continue-on-error: true #初始化错误,继续执行 + encoding: utf-8 #加载sql文件的编码连接池ue #初始化错误,继续执行 + data-locations: classpath:/sql/data-h2.sql + schema-locations: classpath:/sql/schema-h2.sql #spring boot 默认启动使用springJDBC初始化数据脚本, 加载类路径下的 schema-${platform}.sql \ data-${platform}.sql数据 + platform: h2 + #elasticsearch: + #jest: + #uris: http://loalhost:9200 + #read-timeout: 1000 +# 多数据源 +# app: +# datasource: +# type: com.zaxxer.hikari.HikariDataSource +# jdbcUrl: jdbc:h2:~/test-jooq;AUTO_SERVER=TRUE +# username: sa +# password: +# ##连接池 +# hikari: +# driver-class-name: org.h2.Driver + + +logging: + level: + root: info + org.jooq: debug + org.springframework.amqp: debug + org.mybatis: debug + org.mybatis.dynamic.sql: debug + jj.tech.dcang: debug \ No newline at end of file diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..a168470 --- /dev/null +++ b/src/main/resources/bootstrap.yml @@ -0,0 +1,22 @@ +#spring: +# cloud: +# consul: +# scheme: https +# host: consul.164500.xyz +# port: 443 +# discovery: +# acl-token: b2gs44ddr3 +## service-name: ${spring.application.name} +## https://github.com/spring-cloud/spring-cloud-consul/pull/590#issuecomment-1473038044 +# heartbeat: +# enabled: true +# deregister: true +# health-check-critical-timeout: 30s +# +## config: +## acl-token: b1gs33cr3t +# #discovery: +# #register-health-check: true +## discovery: +## ip-address: 192.168.43.15 +## #hostname: doudou \ No newline at end of file diff --git a/src/main/resources/generate/jooq/JooqConfig.xml b/src/main/resources/generate/jooq/JooqConfig.xml new file mode 100644 index 0000000..a89db97 --- /dev/null +++ b/src/main/resources/generate/jooq/JooqConfig.xml @@ -0,0 +1,50 @@ + + + + + org.mariadb.jdbc.Driver + jdbc:mariadb://106.53.186.11:3306/finance + root + open123 + + + + + + + + + scripts + src/main/resources/sql/schema-h2.sql + + + + + finance + + .* + + + + + + + true + true + + true + + + true + + + + + jj.tech.finance.repository.jooq + target/generated-sources/repository + + + \ No newline at end of file diff --git a/src/main/resources/generate/mybatis/generatorConfig.xml b/src/main/resources/generate/mybatis/generatorConfig.xml new file mode 100644 index 0000000..9d26970 --- /dev/null +++ b/src/main/resources/generate/mybatis/generatorConfig.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..0812646 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,44 @@ + + + + + + http://192.168.0.123:3100/loki/api/v1/push + + + + + + %d{yyyy-MM-dd HH-mm-ss.SSSXXX} [%thread] %-5level %logger{36} -%kvp- %msg%n + + true + + + + + + + %d{yyyy-MM-dd HH-mm-ss.SSSXXX} [%thread] %-5level %logger{36} -%kvp- %msg%n + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/sql/data-h2.sql b/src/main/resources/sql/data-h2.sql new file mode 100644 index 0000000..fd8e28d --- /dev/null +++ b/src/main/resources/sql/data-h2.sql @@ -0,0 +1,25 @@ +insert into sys_admin values (1,'超级管理员','admin','fe9bdf42857f0fdfba26b120a42e04a0f331c711870656bea9d088bfcd1e8328',0); +insert into sys_admin values (2,'测试角色','admin1','fe9bdf42857f0fdfba26b120a42e04a0f331c711870656bea9d088bfcd1e8328',0); +insert into sys_role values (1,'超级管理员','技术部'); +insert into sys_admin_role values (1,1,1); + + + +insert into user_info values (1,'葫芦娃1', '大娃', 'user','fe9bdf42857f0fdfba26b120a42e04a0f331c711870656bea9d088bfcd1e8328',0, 3,''); + + +insert into sys_resource values (1,0,0,'菜单根目录','系统菜单','/url','',false,null); +insert into sys_resource values (2,1,1,'商品管理','系统菜单','/admin/goods','fa fa-sitemap fa-fw',false,null); +insert into sys_resource values (3,1,2,'订单管理','系统菜单','/admin/order','fa fa-edit fa-fw',false,null); +insert into sys_resource values (4,1,3,'用户管理','系统菜单','/admin/user','fa fa-dashboard fa-fw',false,null); +insert into sys_resource values (5,1,4,'营销管理','系统菜单','/admin/sales','fa fa-files-o fa-fw',false,null); +insert into sys_resource values (6,1,5,'统计','系统菜单','/admin/count','fa fa-bar-chart-o fa-fw',false,null); +insert into sys_resource values (7,1,6,'系统设置','系统菜单','/admin/system','fa fa-wrench fa-fw',true,null); +insert into sys_resource values (8,2,1,'品牌管理','系统菜单','/shop','fa fa-dashboard fa-fw',false,null); +insert into sys_resource values (9,2,2,'库存管理','系统菜单','/shop','fa fa-dashboard fa-fw',false,null); +insert into sys_resource values (10,2,3,'商品分类','系统菜单','/shop','fa fa-dashboard fa-fw',false,null); +insert into sys_resource values (11,2,4,'商品属性','系统菜单','/shop','fa fa-dashboard fa-fw',false,null); +insert into sys_resource values (12,7,1,'角色管理','系统菜单','/sys/role','fa fa-dashboard fa-fw',false,null); +insert into sys_resource values (13,7,2,'资源管理','系统菜单','/admin/system/resouce','fa fa-dashboard fa-fw',false,null); +insert into sys_resource values (14,7,3,'管理员','系统菜单','/admin/system/admin','fa fa-dashboard fa-fw',false,null); +insert into sys_resource values (15,7,2,'首页','系统菜单','/shop','fa fa-dashboard fa-fw',false,null); \ No newline at end of file diff --git a/src/main/resources/sql/schema-h2.sql b/src/main/resources/sql/schema-h2.sql new file mode 100644 index 0000000..f4a4fdc --- /dev/null +++ b/src/main/resources/sql/schema-h2.sql @@ -0,0 +1,174 @@ +-- drop all objects; + +drop table if exists sys_admin; +create table sys_admin +( + id int not null auto_increment, + realname varchar(100) not null, + username varchar(100) not null, + password varchar(100) not null comment 'sha3_256hex', + islock int default 0 comment '0正常,1锁定', + primary key (id), + unique (username) +); + +drop table if exists sys_role; +create table sys_role +( + id int not null auto_increment, + rolename varchar(50) not null, + department varchar(50) not null, + primary key (id) +); + +drop table if exists sys_admin_role; +create table sys_admin_role ( + id int not null auto_increment, + adminid int not null, + roleid int not null, + primary key (id) +); + +drop table if exists sys_urls; +create table sys_urls ( + id int not null auto_increment, + pid int comment '父类id', + types int default 1 comment '1:url,2:菜单', + level int default 0 comment '0:url,1:一级菜单, 2:二级菜单', + url varchar(300) default null, + name varchar(200) default null, + method varchar(200) default null, + primary key (id), + unique (url) +); + +drop table if exists sys_role_url; +create table sys_role_url ( + id int not null auto_increment, + roleid int not null, + url varchar(300) not null comment '对应sys_urls的url', + urltypes int not null comment '1:url,2:菜单', + primary key (id) +); + +-- 系统配置表 +drop table if exists sys_config; +create table sys_config +( + id int not null auto_increment, + subgroup varchar(500) not null comment '分组', + k varchar(1000) not null comment '键', + val varchar(14000) comment '值', + adminid int not null comment '管理员id', + adminname varchar(100) not null comment '管理员名称', + edittime datetime default current_timestamp on update current_timestamp comment '最后编辑时间', + primary key (id), + unique (k) +); + + + + +-- 用户信息 +drop table if exists user_info; +create table user_info ( + id int not null auto_increment, + realname varchar(200) comment '真实姓名', + nickname varchar(200) comment '昵称', + username varchar(200) not null comment '用户名', + password varchar(70) not null comment '密码', + islock int default 0 comment '0正常,1锁定', + source int default 0 comment '来源:0注册,1第三方,3管理员添加', + head_img varchar(1000), + primary key (id), + unique (username) +); + + +-- 合约信息 +drop table if exists contract_info; +create table contract_info +( + id int not null auto_increment, + ts_code varchar(50) not null comment '合约代码', + symbol varchar(50) not null comment '交易代码', + exchange varchar(50) comment '交易市场: cffex-中金所 dce-大商所 czce-郑商所 shfe-上期所 ine-上海国际能源交易中心 gfex-广州期货交易所', + name varchar(50) not null comment '中文简称', + fut_code varchar(100) not null comment '合约产品代码', + multiplier double comment '合约乘数(只适用于国债期货、指数期货)', + trade_unit varchar(50) not null comment '交易计量单位', + per_unit double comment '交易单位(每手)', + quote_unit varchar(50) not null comment '报价单位', + quote_unit_desc varchar(50) not null comment '最小报价单位说明', + d_mode_desc varchar(200) not null comment '交割方式说明', + list_date date not null default '1970-01-01' comment '上市日期', + delist_date date not null default '1970-01-01' comment '最后交易日期', + d_month varchar(50) not null comment '交割月份', + last_ddate date not null default '1970-01-01' comment '最后交割日', + exchange_name varchar(50) comment '交易所名称', + primary key (id), + unique (ts_code) +); + +-- 合约信息状态表 +drop table if exists contract_info_status; +create table contract_info_status +( + id int not null auto_increment, + ts_code varchar(50) not null comment 'ts合约代码', + contract_status int default 0 comment '合约状态:0启用,1禁用', + scribe_status int default 0 comment '划线开关:0启用,1禁用', + scribe_update_time datetime default null comment '划线更新时间', + scribe_number int default 0 comment '划线数量', + primary key (id), + unique (ts_code) +); + +-- 合约信息状态划线表 +drop table if exists contract_info_status_scribe; +create table contract_info_status_scribe +( + id int not null auto_increment, + ts_code varchar(50) not null comment 'ts合约代码', + scribe_id int default 1 comment '1:普通/动态支撑,2:普通/动态压力,3:高级支撑,4:高级压力,5:高级重合位', + scribe_value int not null comment '划线值', + colour varchar(50) not null default '#FF00003' comment '划线颜色', + primary key (id) +); + +-- 合约日线行情 +drop table if exists fut_daily; +create table fut_daily +( + id int not null auto_increment, + ts_code varchar(50) not null comment 'ts合约代码', + trade_date date not null comment '交易日期', + pre_close double comment '昨收盘价', + pre_settle double not null comment '昨结算价', + open double not null comment '开盘价', + high double comment '最高价', + low double not null comment '最低价', + close double comment '收盘价', + settle double not null comment '结算价', + change1 double not null comment '涨跌1 收盘价-昨结算价', + change2 double not null comment '涨跌2 结算价-昨结算价', + vol double not null comment '成交量(手)', + amount double not null comment '成交金额(万元)', + oi double not null comment '持仓量(手)', + oi_chg double not null comment '持仓量变化', + primary key (id), + unique (ts_code,trade_date) +); + + +-- 管理员收藏合约信息表 +drop table if exists contract_info_user; +create table contract_info_user +( + id int not null auto_increment, + userid int not null comment '用户ID', + username varchar(100) not null comment '用户名', + ts_code varchar(50) not null comment 'ts合约代码', + primary key (id), + unique (userid, ts_code) +); \ No newline at end of file diff --git a/src/test/java/jj/tech/paolu/biz/webadmin/service/RoomRuleImpTest.java b/src/test/java/jj/tech/paolu/biz/webadmin/service/RoomRuleImpTest.java new file mode 100644 index 0000000..61d7a51 --- /dev/null +++ b/src/test/java/jj/tech/paolu/biz/webadmin/service/RoomRuleImpTest.java @@ -0,0 +1,22 @@ +package jj.tech.paolu.biz.webadmin.service; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RoomRuleImpTest { + +public static void main(String[] args) { + + + String dateStr = "20210719"; // 输入日期字符串 + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); // 定义日期格式化模式 + LocalDate localDate = LocalDate.parse(dateStr, formatter); // 将字符串按指定格式解析为LocalDate对象 + + System.out.println(localDate); // 打印结果 +} + +} diff --git a/src/test/java/test/nw/BinaryTree.java b/src/test/java/test/nw/BinaryTree.java new file mode 100644 index 0000000..3a9e111 --- /dev/null +++ b/src/test/java/test/nw/BinaryTree.java @@ -0,0 +1,295 @@ +package test.nw; + +import java.util.Stack; + +public class BinaryTree { + + + private TreeNode root=null; + + + public BinaryTree(){ + root=new TreeNode(1,"rootNode(A)"); + } + + /** + * 创建一棵二叉树 + *
 
+     *          A 
+     *     B          C 
+     *  D     E            F 
+     *  
+ * @param root + * @author WWX + */ + public void createBinTree(TreeNode root){ + TreeNode newNodeB = new TreeNode(2,"B"); + TreeNode newNodeC = new TreeNode(3,"C"); + TreeNode newNodeD = new TreeNode(4,"D"); + TreeNode newNodeE = new TreeNode(5,"E"); + TreeNode newNodeF = new TreeNode(6,"F"); + root.leftChild=newNodeB; + root.rightChild=newNodeC; + root.leftChild.leftChild=newNodeD; + root.leftChild.rightChild=newNodeE; + root.rightChild.rightChild=newNodeF; + } + + + public boolean isEmpty(){ + return root==null; + } + + //树的高度 + public int height(){ + return height(root); + } + + //节点个数 + public int size(){ + return size(root); + } + + + private int height(TreeNode subTree){ + if(subTree==null) + return 0;//递归结束:空树高度为0 + else{ + int i=height(subTree.leftChild); + int j=height(subTree.rightChild); + return (i stack=new Stack(); + TreeNode node=p; + while(node!=null||stack.size()>0){ + while(node!=null){ + visted(node); + stack.push(node); + node=node.leftChild; + } + while(stack.size()>0){ + node=stack.pop(); + node=node.rightChild; + } + } + } + + //中序遍历的非递归实现 + public void nonRecInOrder(TreeNode p){ + Stack stack =new Stack(); + TreeNode node =p; + while(node!=null||stack.size()>0){ + //存在左子树 + while(node!=null){ + stack.push(node); + node=node.leftChild; + } + //栈非空 + if(stack.size()>0){ + node=stack.pop(); + visted(node); + node=node.rightChild; + } + } + } + + //后序遍历的非递归实现 + public void noRecPostOrder(TreeNode p){ + Stack stack=new Stack(); + TreeNode node =p; + while(p!=null){ + //左子树入栈 + for(;p.leftChild!=null;p=p.leftChild){ + stack.push(p); + } + //当前结点无右子树或右子树已经输出 + while(p!=null&&(p.rightChild==null||p.rightChild==node)){ + visted(p); + //纪录上一个已输出结点 + node =p; + if(stack.empty()) + return; + p=stack.pop(); + } + //处理右子树 + stack.push(p); + p=p.rightChild; + } + } + + + public void visted(TreeNode subTree){ + subTree.isVisted=true; + System.out.println("key:"+subTree.key+"--name:"+subTree.data);; + } + + + /** + * 二叉树的节点数据结构 + * @author WWX + */ + private class TreeNode{ + private int key=0; + private String data=null; + private boolean isVisted=false; + private TreeNode leftChild=null; + private TreeNode rightChild=null; + + public TreeNode(){} + + /** + * @param key 层序编码 + * @param data 数据域 + */ + public TreeNode(int key,String data){ + this.key=key; + this.data=data; + this.leftChild=null; + this.rightChild=null; + } + + + } + + + //测试 + public static void main(String[] args) { + + BinaryTree bt = new BinaryTree(); + bt.createBinTree(bt.root); +// TreeNode newNodeB = new TreeNode(2,"B"); +// TreeNode newNodeC = new TreeNode(3,"C"); +// TreeNode newNodeD = new TreeNode(4,"D"); +// TreeNode newNodeE = new TreeNode(5,"E"); +// TreeNode newNodeF = new TreeNode(6,"F"); +// bt.root.leftChild=newNodeB; +// bt.root.rightChild=newNodeC; +// bt.root.leftChild.leftChild=newNodeD; +// bt.root.leftChild.rightChild=newNodeE; +// bt.root.rightChild.rightChild=newNodeF; + + + + System.out.println("the size of the tree is " + bt.size()); + System.out.println("the height of the tree is " + bt.height()); + + System.out.println("*******(前序遍历)[ABDECF]遍历*****************"); + bt.preOrder(bt.root); + + System.out.println("*******(中序遍历)[DBEACF]遍历*****************"); + bt.inOrder(bt.root); + + System.out.println("*******(后序遍历)[DEBFCA]遍历*****************"); + bt.postOrder(bt.root); + +// System.out.println("***非递归实现****(前序遍历)[ABDECF]遍历*****************"); +// bt.nonRecPreOrder(bt.root); +// +// System.out.println("***非递归实现****(中序遍历)[DBEACF]遍历*****************"); +// bt.nonRecInOrder(bt.root); +// +// System.out.println("***非递归实现****(后序遍历)[DEBFCA]遍历*****************"); +// bt.noRecPostOrder(bt.root); + + + + } + +} diff --git a/src/test/java/test/nw/StreamTest.java b/src/test/java/test/nw/StreamTest.java new file mode 100644 index 0000000..72d81db --- /dev/null +++ b/src/test/java/test/nw/StreamTest.java @@ -0,0 +1,16 @@ +package test.nw; + +import java.lang.reflect.Type; +import java.util.List; + +import org.springframework.core.ParameterizedTypeReference; + + +public class StreamTest { + public static void main(String[] args) { + ParameterizedTypeReference> typeRef = new ParameterizedTypeReference>() {}; + + Type type = typeRef.getType(); // 获取泛型类型 + System.out.println("泛型类型为:" + type); + } +} diff --git a/src/test/java/test/nw/TimeTest.java b/src/test/java/test/nw/TimeTest.java new file mode 100644 index 0000000..9281c41 --- /dev/null +++ b/src/test/java/test/nw/TimeTest.java @@ -0,0 +1,32 @@ +package test.nw; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; + +import org.apache.commons.lang3.StringUtils; + +public class TimeTest { + + public static void main(String[] args) { +// LocalDateTime now = LocalDateTime.now(); +// now = now.truncatedTo(ChronoUnit.SECONDS); +// System.out.println(now.plusMinutes(120)); +// System.out.println(now.minusMinutes(61)); +// FastDateFormat s = FastDateFormat.getInstance(); +// LocalDateTime ordertime = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS); +// System.out.println(ordertime.with(LocalTime.MAX)); + +// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); +// LocalDate d = LocalDate.parse("null", formatter); +// System.out.println(d); + +// LocalDate l = LocalDate.ofInstant(Instant.ofEpochMilli(0), ZoneId.systemDefault()); +// System.out.println(l); + +// + System.out.println(String.format("%03d", 1)); + + } + +} diff --git a/src/test/java/test/nw/UrlTest.java b/src/test/java/test/nw/UrlTest.java new file mode 100644 index 0000000..bceb984 --- /dev/null +++ b/src/test/java/test/nw/UrlTest.java @@ -0,0 +1,73 @@ +//package test.nw; +// +//import java.nio.file.Paths; +//import java.util.List; +// +//import org.apache.commons.lang3.StringUtils; +//import org.springframework.web.util.UriComponentsBuilder; +// +//import jj.tech.dcang.biz.demo.controller.TestController; +// +//public class UrlTest { +// public static void main(String[] args) { +// String uri = "/zz/v3/s/api-docs.yaml/{group}"; +// uri="/t/s/bbb"; +// +//// +//// UriComponentsBuilder.fromUriString(uri).build().getPathSegments() +//// .stream().forEach(s->{ +//// System.out.println(s); +//// }); +// +//// PathContainer pathContainer = PathContainer.parsePath(uri); +//// +//// System.out.println(pathContainer.subPath(0)); +//// System.out.println(pathContainer.subPath(1)); +//// System.out.println(pathContainer.subPath(2)); +//// System.out.println(pathContainer.subPath(3)); +//// System.out.println(pathContainer.subPath(4)); +//// System.out.println(pathContainer.subPath(5)); +//// System.out.println( Paths.get(UriComponentsBuilder.fromUriString("file://"+uri).build().toUri()).getParent()); +//// System.out.println( Paths.get(UriComponentsBuilder.fromUriString("file://"+uri).build().toUri()).getParent().getParent()); +//// System.out.println( Paths.get(UriComponentsBuilder.fromUriString("file://"+uri).build().toUri()).getParent().getParent().getParent()); +//// System.out.println( Paths.get(UriComponentsBuilder.fromUriString("file://"+uri).build().toUri()).getParent().getParent().getParent().getParent()); +// +// +// +//// URI uu = UriComponentsBuilder.fromUriString("file://"+uri).build().toUri(); +//// +//// +//// List list = UriComponentsBuilder.fromUriString("file://"+uri).build().getPathSegments(); +//// List paths = new ArrayList(); +//// Path path = Paths.get(uu); +//// paths.add(path); +////// list.stream().map(i->{ +////// i="/"+i; +////// return i; +////// }).forEach(System.out::println); +//// for(int i=0;i parents = TestController.getAllParents("/a/b/c/d"); +// System.out.println(parents); +// +// for(int i=parents.size()-1; i>=0; i--) { +//// if(i>0) { +// System.err.println(i+" "+parents.get(i)); +//// } +// } +// +// +// System.err.println(StringUtils.startsWith("a/b/c", "/")); +// +//// DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" ); +//// Instant.now().atZone(ZoneOffset.systemDefault()).format(formatter); +//// System.out.println(); +//// System.out.println(DateUtils.truncate(new Date(), Calendar.SECOND)); +// +// +// } +//} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 0000000..42a68f8 --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,62 @@ +##约定大于配置,请勿重复造轮 +server: #服务端口 + port: 8083 +##spring---------- +spring: + application: + name: zwyy + datasource: + type: com.zaxxer.hikari.HikariDataSource + #url: jdbc:h2:./test;AUTO_SERVER=TRUE #连接池Database 嵌入模式:jdbc:h2:~/test-jooq FILE_LOCK=SOCKET MODE=MySQL;;AUTO_SERVER=TRUE + url: jdbc:h2:./test;MODE=MySQL;AUTO_SERVER=TRUE + username: sa + password: + hikari: + driver-class-name: org.h2.Driver +# url: jdbc:mariadb://173.249.203.214:3306/test +# username: root +# password: open123 +# hikari: +# driver-class-name: org.mariadb.jdbc.Driver + jackson: + date-format: yyyy-MM-dd HH:mm:ss + + h2: + console: + enabled: true #开启h2数据库的浏览器管理界面 + settings: + web-allow-others: true + trace: true #是否可以远程web + #path: /h2-console #h2浏览器管理访问路径,默认:/h2-console + sql: + init: + mode: never ##加载脚本datasource.initialize已弃用,spring.sql.init.mode=never/always + continue-on-error: true #初始化错误,继续执行 + encoding: utf-8 #加载sql文件的编码连接池ue #初始化错误,继续执行 + data-locations: classpath:/sql/data-h2.sql + schema-locations: classpath:/sql/schema-h2.sql #spring boot 默认启动使用springJDBC初始化数据脚本, 加载类路径下的 schema-${platform}.sql \ data-${platform}.sql数据 + platform: h2 + #elasticsearch: + #jest: + #uris: http://loalhost:9200 + #read-timeout: 1000 +# 多数据源 +# app: +# datasource: +# type: com.zaxxer.hikari.HikariDataSource +# jdbcUrl: jdbc:h2:~/test-jooq;AUTO_SERVER=TRUE +# username: sa +# password: +# ##连接池 +# hikari: +# driver-class-name: org.h2.Driver + + +#logging: +# level: +# root: info +# org.jooq: debug +# org.springframework.amqp: debug +# org.mybatis: debug +# org.mybatis.dynamic.sql: debug +# jj.tech.paolu: debug diff --git a/src/test/resources/banner.txt b/src/test/resources/banner.txt new file mode 100644 index 0000000..df4ef43 --- /dev/null +++ b/src/test/resources/banner.txt @@ -0,0 +1,17 @@ +/ \ + /X/ \X\ +|XX\ _____ /XX| +|XXX\ _/ \_ /XXX|___________ + \XXXXXXX XXXXXXX/ \\\ + \XXXX / \ XXXXX/ \\\ + | 0 0 | \ + | | \ + \ / |______// + \ / | + | O_O | \ | + \ _ / \________________ | + | | | | \ / + No Bullshit, / | / | \______/ + Please... \ | \ | \ | \ | + __| |__| | __| |__| | + |___||___| |___||___| \ No newline at end of file diff --git a/src/test/resources/bootstrap.yml b/src/test/resources/bootstrap.yml new file mode 100644 index 0000000..8e04bc1 --- /dev/null +++ b/src/test/resources/bootstrap.yml @@ -0,0 +1,22 @@ +spring: + cloud: + consul: + scheme: https + host: consul.164500.xyz + port: 443 + discovery: + acl-token: b2gs44ddr3 +# service-name: ${spring.application.name} +# https://github.com/spring-cloud/spring-cloud-consul/pull/590#issuecomment-1473038044 + heartbeat: + enabled: true + deregister: true + health-check-critical-timeout: 30s + +# config: +# acl-token: b1gs33cr3t + #discovery: + #register-health-check: true +# discovery: +# ip-address: 192.168.43.15 +# #hostname: doudou diff --git a/src/test/resources/generate/jooq/JooqConfig.xml b/src/test/resources/generate/jooq/JooqConfig.xml new file mode 100644 index 0000000..bde4094 --- /dev/null +++ b/src/test/resources/generate/jooq/JooqConfig.xml @@ -0,0 +1,41 @@ + + + + + + org.h2.Driver + jdbc:h2:~/test;MODE=MySQL;AUTO_SERVER=TRUE + sa + + + + + + + PUBLIC + + .* + + + + + + true + true + + true + + + true + + + + + jj.tech.dcang.repository.jooq + target/generated-sources/repository + + + \ No newline at end of file diff --git a/src/test/resources/generate/mybatis/generatorConfig.xml b/src/test/resources/generate/mybatis/generatorConfig.xml new file mode 100644 index 0000000..8afbd19 --- /dev/null +++ b/src/test/resources/generate/mybatis/generatorConfig.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml new file mode 100644 index 0000000..46ada04 --- /dev/null +++ b/src/test/resources/logback.xml @@ -0,0 +1,44 @@ + + + + + + http://192.168.0.123:3100/loki/api/v1/push + + + + + + %d{yyyy-MM-dd HH-mm-ss.SSSXXX} [%thread] %-5level %logger{36} -%kvp- %msg%n + + true + + + + + + + %d{yyyy-MM-dd HH-mm-ss.SSSXXX} [%thread] %-5level %logger{36} -%kvp- %msg%n + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/sql/V1_0__schema-h2.sql b/src/test/resources/sql/V1_0__schema-h2.sql new file mode 100644 index 0000000..27aa437 --- /dev/null +++ b/src/test/resources/sql/V1_0__schema-h2.sql @@ -0,0 +1,415 @@ + DROP ALL OBJECTS; + +DROP TABLE IF EXISTS sys_admin; +CREATE TABLE sys_admin +( + id INT NOT NULL auto_increment, + realname VARCHAR(50) NOT NULL, + username VARCHAR(50) NOT NULL, + password VARCHAR(70) NOT NULL COMMENT 'sha3_256Hex', + islock INT DEFAULT 0 COMMENT '0正常,1锁定', + PRIMARY KEY (id) +); + +DROP TABLE IF EXISTS sys_role; +CREATE TABLE sys_role +( + id INT NOT NULL auto_increment, + rolename VARCHAR(50) NOT NULL, + department VARCHAR(50) NOT NULL, + PRIMARY KEY (id) +); + +DROP TABLE IF EXISTS sys_admin_role; +CREATE TABLE sys_admin_role ( + id INT NOT NULL auto_increment, + admin_id INT NOT NULL, + role_id INT NOT NULL, + PRIMARY KEY (id) +); + +DROP TABLE IF EXISTS `sys_resource`; +CREATE TABLE `sys_resource` ( + id INT NOT NULL auto_increment, + parent_id INT DEFAULT NULL, + level smallint DEFAULT NULL COMMENT '菜单排列顺序', + name VARCHAR(50) DEFAULT NULL, + types VARCHAR(40) DEFAULT NULL COMMENT '资源类型', + url VARCHAR(200) DEFAULT NULL, + icon VARCHAR(100) DEFAULT NULL COMMENT '菜单图标', + ishide tinyint DEFAULT '0' COMMENT '是否折叠隐藏', + description VARCHAR(200) DEFAULT NULL, + PRIMARY KEY (`id`) +); + +DROP TABLE IF EXISTS `sys_role_resource`; +CREATE TABLE `sys_role_resource` ( + `role_id` INT NOT NULL, + `res_id` INT NOT NULL, + PRIMARY KEY (`role_id`,`res_id`) +); + +DROP TABLE IF EXISTS SYS_URLS; +CREATE TABLE SYS_URLS ( + id INT NOT NULL auto_increment, + pid INT COMMENT '父类ID', + types INT DEFAULT 1 COMMENT '1:url,2:菜单', + level INT DEFAULT 0 COMMENT '0:url,1:一级菜单, 2:二级菜单', + url VARCHAR(300) DEFAULT NULL, + name VARCHAR(200) DEFAULT NULL, + method VARCHAR(200) DEFAULT NULL, + PRIMARY KEY (id), + UNIQUE (url) +); + +DROP TABLE IF EXISTS sys_role_url; +CREATE TABLE sys_role_url ( + id INT NOT NULL auto_increment, + role_id INT NOT NULL, + url VARCHAR(300) NOT NULL COMMENT '对应SYS_URLS的url', + urltypes INT NOT NULL COMMENT '1:url,2:菜单', + PRIMARY KEY (id) +); + + + + + + + + + +DROP TABLE IF EXISTS SCHOOL; +CREATE TABLE SCHOOL +( + id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(200) COMMENT '学校名称', + sort INT NOT NULL AUTO_INCREMENT COMMENT '学校排序', + inshow INT DEFAULT 1 COMMENT '是否显示:0不显示,1显示', + PRIMARY KEY (id) +); + + +DROP TABLE IF EXISTS SCHOOL_DISTRICT; +CREATE TABLE SCHOOL_DISTRICT +( + id INT NOT NULL AUTO_INCREMENT, + schoolid INT NOT NULL COMMENT '所属学校ID', + district VARCHAR(200) COMMENT '校区名称', + sort INT NOT NULL AUTO_INCREMENT COMMENT '校区排序', + inshow INT DEFAULT 1 COMMENT '是否显示:0不显示,1显示', + edittime DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后编辑时间', + PRIMARY KEY (id) +); + + +DROP TABLE IF EXISTS SCHOOL_DISTRICT_BUILDING; +CREATE TABLE SCHOOL_DISTRICT_BUILDING +( + id INT NOT NULL AUTO_INCREMENT, + districtid INT COMMENT '所属分校ID', + building VARCHAR(200) COMMENT '建筑名称', + sort INT NOT NULL AUTO_INCREMENT COMMENT '楼排序', + inshow int DEFAULT 1 COMMENT '是否显示:0不显示,1显示', + PRIMARY KEY (id) +); + + +DROP TABLE IF EXISTS SCHOOL_DISTRICT_BUILDING_FLOOR; +CREATE TABLE SCHOOL_DISTRICT_BUILDING_FLOOR +( + id INT NOT NULL AUTO_INCREMENT, + buildingid INT COMMENT '所属建筑ID', + floor VARCHAR(200) COMMENT '楼层名称', + sort INT NOT NULL AUTO_INCREMENT COMMENT '楼层排序', + inshow int DEFAULT 1 COMMENT '是否显示:0不显示,1显示', + PRIMARY KEY (id) +); + + + +DROP TABLE IF EXISTS ROOM; +CREATE TABLE ROOM +( + id INT NOT NULL AUTO_INCREMENT, + + districtid INT COMMENT '所属分校ID', + districtname VARCHAR(200) COMMENT '分校名称', + buildingid INT COMMENT '所属建筑ID', + buildingname VARCHAR(200) COMMENT '建筑名称', + floorid INT COMMENT '所属楼层ID', + floorname VARCHAR(200) COMMENT '楼层名称', + + room VARCHAR(200) COMMENT '房间名称', + frontname VARCHAR(200) COMMENT '正前方名称', + sort INT NOT NULL AUTO_INCREMENT COMMENT '房间排序', + inshow INT DEFAULT 1 COMMENT '是否显示:0不显示,1显示', + rols INT DEFAULT 10 COMMENT '一共多少行', + cols INT DEFAULT 10 COMMENT '一共多少列', + seatscount INT DEFAULT 0 COMMENT '一共多少个座位', + edittime DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后编辑时间', + PRIMARY KEY (id) +); + +-- 房间对应的座位 +DROP TABLE IF EXISTS ROOM_SEATS; +CREATE TABLE ROOM_SEATS +( + id INT NOT NULL AUTO_INCREMENT, + seatname VARCHAR(200) COMMENT '座位名称', + seatvalue VARCHAR(200) COMMENT '座位选中后的值', + roomid INT NOT NULL COMMENT '房间ID', + roomname VARCHAR(200) COMMENT '房间名称', + typesid INT DEFAULT 0 COMMENT '关联SEATS_TYPE', + inshow INT DEFAULT 1 COMMENT '是否显示:0禁用,1可用', + rol INT COMMENT '行', + col INT COMMENT '列', + PRIMARY KEY (id) +); + + +-- 座位类型 +DROP TABLE IF EXISTS SEATS_TYPE; +CREATE TABLE SEATS_TYPE +( + id INT NOT NULL AUTO_INCREMENT, + typename VARCHAR(50) COMMENT '名称: 普通,研究生,教师, 勤工助学区等', + typeval VARCHAR(50) COMMENT '值: 1身份, 2座位区域,对应所有身份', + colour VARCHAR(50) COMMENT '座位颜色', + isapply INT DEFAULT 1 COMMENT '0不启用,1启用', + PRIMARY KEY (id), + UNIQUE (colour) +); + +-- 座位相关设备 +DROP TABLE IF EXISTS SEATS_DEVICE; +CREATE TABLE SEATS_DEVICE +( + id INT NOT NULL AUTO_INCREMENT, + seatsid INT NOT NULL COMMENT '座位ID', + deviceid INT NOT NULL COMMENT '设备ID', + devicename INT NOT NULL COMMENT '设备名称', + PRIMARY KEY (id) +); + +-- 设备表 +DROP TABLE IF EXISTS DEVICE; +CREATE TABLE DEVICE +( + id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(50) COMMENT '名称: 0电源, 1网口, ...', + val INT DEFAULT 0 COMMENT '值: 0电源, 1网口, ...', + isapply INT DEFAULT 1 COMMENT '0不启用,1启用', + PRIMARY KEY (id) +); + +-- 模板 +DROP TABLE IF EXISTS TEMPLATE; +CREATE TABLE TEMPLATE +( + id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(200) COMMENT '模板名称', + frontname VARCHAR(200) COMMENT '正前方名称', + rols INT COMMENT '一共多少行', + cols INT COMMENT '一共多少列', + seatscount INT DEFAULT 0 COMMENT '一共多少个座位', + PRIMARY KEY (id) +); + +-- 模板的座位 +DROP TABLE IF EXISTS TEMPLATE_SEATS; +CREATE TABLE TEMPLATE_SEATS +( + id INT NOT NULL AUTO_INCREMENT, + templateid INT NOT NULL COMMENT '模板ID', + seatname VARCHAR(200) COMMENT '座位名称', + seatvalue VARCHAR(200) COMMENT '座位选中后的值', + typesid INT DEFAULT 0 COMMENT '关联SEATS_TYPE', + inshow INT DEFAULT 1 COMMENT '是否显示:0禁用,1可用', + rol INT COMMENT '行', + col INT COMMENT '列', + PRIMARY KEY (id) +); + + + +-- 用户信息 +DROP TABLE IF EXISTS USER_INFO; +CREATE TABLE USER_INFO ( + id INT NOT NULL AUTO_INCREMENT, + realname VARCHAR(200) NOT NULL, + nickname VARCHAR(200) NOT NULL, + username VARCHAR(200) NOT NULL, + password VARCHAR(70) NOT NULL, + usertypeid INT DEFAULT 0 COMMENT '0本科生,1研究生,2教师,3其他', + islock INT DEFAULT 0 COMMENT '0正常,1锁定', + source INT DEFAULT 0 COMMENT '0注册,1第三方,3管理员添加', + head_img VARCHAR(1000), + PRIMARY KEY (id), + UNIQUE (username) +); + +-- 用户类型 +DROP TABLE IF EXISTS USER_INFO_TYPE; +CREATE TABLE USER_INFO_TYPE ( + id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(50) COMMENT '名称: 0本科生,1研究生,2教师,3其他', + val VARCHAR(50) COMMENT '值: 0本科生,1研究生,2教师,3其他', + isapply INT DEFAULT 1 COMMENT '0不启用,1启用', + PRIMARY KEY (id) +); + +-- 用户座位预约 +DROP TABLE IF EXISTS USER_SEATS; +CREATE TABLE USER_SEATS ( + id INT NOT NULL AUTO_INCREMENT, + userid INT NOT NULL, + username VARCHAR(200) NOT NULL, + roomid INT NOT NULL COMMENT '所属房间ID', + room VARCHAR(200) COMMENT '房间名称', + seatid INT NOT NULL COMMENT '座位ID', + seatname VARCHAR(200) COMMENT '座位名称', + seatvalue VARCHAR(200) COMMENT '座位选中后的值', + duetime DATETIME COMMENT '预约下单时间', + duestartime DATETIME COMMENT '预约座位开始时间', + dueendtime DATETIME COMMENT '预约座位结束时间', + duestatu INT DEFAULT 1 COMMENT '预约状态:1预约成功,2签到成功,3结束', + PRIMARY KEY (id) +); + +-- 用户投诉表 +DROP TABLE IF EXISTS USER_COMPLAIN; +CREATE TABLE USER_COMPLAIN ( + id INT NOT NULL AUTO_INCREMENT, + userid INT NOT NULL, + username VARCHAR(200) NOT NULL, + usertypeid INT DEFAULT 0 COMMENT '0本科生,1研究生,2教师,3职工', + complain VARCHAR(4000), + committime DATETIME COMMENT '提交时间', + isdelete INT DEFAULT 0 COMMENT '0未删除,1已删除', + PRIMARY KEY (id) +); + +-- 用户座位维修表 +DROP TABLE IF EXISTS USER_REPAIR; +CREATE TABLE USER_REPAIR ( + id INT NOT NULL AUTO_INCREMENT, + userid INT NOT NULL, + username VARCHAR(200) NOT NULL, + usertypeid INT DEFAULT 0 COMMENT '0本科生,1研究生,2教师,3职工', + repair VARCHAR(4000), + committime DATETIME COMMENT '提交时间', + isdelete INT DEFAULT 0 COMMENT '0未删除,1已删除', + PRIMARY KEY (id) +); + + +-- 预约规则 +DROP TABLE IF EXISTS RULE; +CREATE TABLE RULE ( + id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(200) NOT NULL, + startime DATETIME COMMENT '规则开始时间', + endtime DATETIME COMMENT '规则结束时间', + circle INT DEFAULT 0 COMMENT '0单次,1每年循环', + types INT DEFAULT 0 COMMENT '0网络预约,1现场预约', + signedtimeout INT COMMENT '签到超时分钟', + stepawaytimeout INT COMMENT '可以暂时离开分钟', + bookdate INT COMMENT '可预约天数', + opentime DATETIME COMMENT '可预约放号时间', + renewaltime INT COMMENT '续座时间分钟', + canceltime INT DEFAULT 20 COMMENT '预约后可以取消的时间', + cancelnumber INT DEFAULT 5 COMMENT '预约后可以取消次数', + PRIMARY KEY (id) +); + +-- 预约规则对应的用户类型 +DROP TABLE IF EXISTS RULE_USERTYPE; +CREATE TABLE RULE_USERTYPE ( + id INT NOT NULL AUTO_INCREMENT, + ruleid INT NOT NULL COMMENT '预约规则ID', + usertypeid INT NOT NULL COMMENT '用户类型ID', + PRIMARY KEY (id) +); + + +-- 预约规则违约对应的访问区域 +DROP TABLE IF EXISTS RULE_REGION; +CREATE TABLE RULE_REGION ( + id INT NOT NULL AUTO_INCREMENT, + ruleid INT NOT NULL COMMENT '预约规则ID', + roomid INT NOT NULL COMMENT '所属房间ID', + PRIMARY KEY (id) +); + +-- 房间对应的预约规则 +DROP TABLE IF EXISTS ROOM_RULE; +CREATE TABLE ROOM_RULE ( + id INT NOT NULL AUTO_INCREMENT, + roomid INT NOT NULL COMMENT '房间ID', + ruleid INT NOT NULL COMMENT '预约规则ID', + PRIMARY KEY (id) +); + + + +-- 违反预约规则记录 +DROP TABLE IF EXISTS ILLEGA_RECORD; +CREATE TABLE ILLEGA_RECORD ( + id INT NOT NULL AUTO_INCREMENT, + userid INT NOT NULL, + username VARCHAR(200) NOT NULL, + ruleid INT NOT NULL COMMENT '预约规则ID', + reason VARCHAR(200) COMMENT '违规原因', + illegatime DATETIME COMMENT '违规时间', + PRIMARY KEY (id) +); + +-- 黑名单列表 +DROP TABLE IF EXISTS USER_BLACKLIST; +CREATE TABLE USER_BLACKLIST ( + id INT NOT NULL AUTO_INCREMENT, + userid INT NOT NULL, + username VARCHAR(200) NOT NULL, + types INT DEFAULT 0 COMMENT '0本科生,1研究生,2教师,3其他', + reason VARCHAR(500) COMMENT '拉黑原因', + committime DATETIME COMMENT '提交时间', + isrelease INT DEFAULT 0 COMMENT '是否释放:0否,1释放', + PRIMARY KEY (id) +); + +-- 用户消息 +DROP TABLE IF EXISTS MESSAGE_USER; +CREATE TABLE MESSAGE_USER ( + id INT NOT NULL AUTO_INCREMENT, + userid INT NOT NULL, + username VARCHAR(200) NOT NULL, + types INT DEFAULT 0 COMMENT '0本科生,1研究生,2教师,3职工', + messagetypes INT DEFAULT 0 COMMENT '0系统,1短信', + message VARCHAR(4000), + committime DATETIME COMMENT '提交时间', + isdelete INT DEFAULT 0 COMMENT '0未删除,1已删除', + PRIMARY KEY (id) +); + +-- 管理员消息 +DROP TABLE IF EXISTS MESSAGE_ADMIN; +CREATE TABLE MESSAGE_ADMIN ( + id INT NOT NULL AUTO_INCREMENT, + adminid INT NOT NULL, + adminname VARCHAR(200) NOT NULL, + types INT DEFAULT 0 COMMENT '0本科生,1研究生,2教师,3职工', + messagetypes INT DEFAULT 0 COMMENT '0系统,1短信', + message VARCHAR(4000), + committime DATETIME COMMENT '提交时间', + isdelete INT DEFAULT 0 COMMENT '0未删除,1已删除', + PRIMARY KEY (id) +); + +-- 门禁打卡记录 +DROP TABLE IF EXISTS ACCESS_CONTROL_RECORD; +CREATE TABLE ACCESS_CONTROL_RECORD ( + id INT NOT NULL AUTO_INCREMENT, + accesstime DATETIME COMMENT '刷卡时间', + PRIMARY KEY (id) +); \ No newline at end of file diff --git a/src/test/resources/xml/DaoHome.ftl b/src/test/resources/xml/DaoHome.ftl new file mode 100644 index 0000000..6a1e4b6 --- /dev/null +++ b/src/test/resources/xml/DaoHome.ftl @@ -0,0 +1,218 @@ +<#assign package = pojo.getPackageDeclaration()> +${package?substring(0,package?length-1)}.daos; +// Generated ${date} by Hibernate Tools ${version} + +import ${pojo.getQualifiedDeclarationName()}; +<#assign classbody> +<#assign declarationName = pojo.importType(pojo.getDeclarationName())>/** + * Home object for domain model class ${declarationName}. + * @see ${pojo.getQualifiedDeclarationName()} + * @author Hibernate Tools + */ +<#if ejb3> + +@${pojo.importType("javax.ejb.Stateless")} + + + +<#if pojo.hasIdentifierProperty()> +${pojo.getJavaTypeName(clazz.identifierProperty, jdk5)} + +public class ${declarationName}Dao { + + private static final ${pojo.importType("java.util.logging.Logger")} logger = ${pojo.importType("Logger")}.getLogger(${pojo.getDeclarationName()}Dao.class.getName()); + +<#if ejb3> + @${pojo.importType("jakarta.persistence.PersistenceContext")} private ${pojo.importType("jakarta.persistence.EntityManager")} entityManager; + + public void persist(${declarationName} transientInstance) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "persisting ${declarationName} instance"); + try { + entityManager.persist(transientInstance); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "persist successful"); + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "persist failed", re); + throw re; + } + } + + public void remove(${declarationName} persistentInstance) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "removing ${declarationName} instance"); + try { + entityManager.remove(persistentInstance); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "remove successful"); + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "remove failed", re); + throw re; + } + } + + public ${declarationName} merge(${declarationName} detachedInstance) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "merging ${declarationName} instance"); + try { + ${declarationName} result = entityManager.merge(detachedInstance); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "merge successful"); + return result; + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "merge failed", re); + throw re; + } + } + +<#if clazz.identifierProperty?has_content> + public ${declarationName} findById( ${pojo.getJavaTypeName(clazz.identifierProperty, jdk5)} id) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "getting ${declarationName} instance with id: " + id); + try { + ${declarationName} instance = entityManager.find(${pojo.getDeclarationName()}.class, id); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "get successful"); + return instance; + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "get failed", re); + throw re; + } + } + +<#else> + private final ${pojo.importType("org.hibernate.SessionFactory")} sessionFactory = getSessionFactory(); + + protected ${pojo.importType("org.hibernate.SessionFactory")} getSessionFactory() { + try { + return (${pojo.importType("org.hibernate.SessionFactory")}) new ${pojo.importType("javax.naming.InitialContext")}().lookup("sessionFactoryName"); + } + catch (Exception e) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "Could not locate SessionFactory in JNDI", e); + throw new IllegalStateException("Could not locate SessionFactory in JNDI"); + } + } + + public void persist(${declarationName} transientInstance) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "persisting ${declarationName} instance"); + try { + sessionFactory.getCurrentSession().persist(transientInstance); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "persist successful"); + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "persist failed", re); + throw re; + } + } + + public void attachDirty(${declarationName} instance) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "attaching dirty ${declarationName} instance"); + try { + sessionFactory.getCurrentSession().saveOrUpdate(instance); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "attach successful"); + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "attach failed", re); + throw re; + } + } + + public void attachClean(${declarationName} instance) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "attaching clean ${declarationName} instance"); + try { + sessionFactory.getCurrentSession().lock(instance, ${pojo.importType("org.hibernate.LockMode")}.NONE); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "attach successful"); + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "attach failed", re); + throw re; + } + } + + public void delete(${declarationName} persistentInstance) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "deleting ${declarationName} instance"); + try { + sessionFactory.getCurrentSession().delete(persistentInstance); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "delete successful"); + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "delete failed", re); + throw re; + } + } + + public ${declarationName} merge(${declarationName} detachedInstance) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "merging ${declarationName} instance"); + try { + ${declarationName} result = (${declarationName}) sessionFactory.getCurrentSession() + .merge(detachedInstance); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "merge successful"); + return result; + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "merge failed", re); + throw re; + } + } + +<#if clazz.identifierProperty?has_content> + public ${declarationName} findById( ${c2j.getJavaTypeName(clazz.identifierProperty, jdk5)} id) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "getting ${declarationName} instance with id: " + id); + try { + ${declarationName} instance = (${declarationName}) sessionFactory.getCurrentSession() + .get("${clazz.entityName}", id); + if (instance==null) { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "get successful, no instance found"); + } + else { + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "get successful, instance found"); + } + return instance; + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "get failed", re); + throw re; + } + } + + + + + +<#if false> +/** +TODO: +<#if jdk5> + public ${pojo.importType("java.util.List")}<${declarationName}> findByExample(${declarationName} instance) { +<#else> + public ${pojo.importType("java.util.List")} findByExample(${declarationName} instance) { + + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "finding ${declarationName} instance by example"); + try { +<#if jdk5> + ${pojo.importType("java.util.List")}<${declarationName}> results = (List<${declarationName}>) sessionFactory.getCurrentSession() +<#else> + ${pojo.importType("java.util.List")} results = sessionFactory.getCurrentSession() + + .createCriteria("${clazz.entityName}") +<#if jdk5> + .add( ${pojo.staticImport("org.hibernate.criterion.Example", "create")}(instance) ) +<#else> + .add(${pojo.importType("org.hibernate.criterion.Example")}.create(instance)) + + .list(); + logger.log(${pojo.importType("java.util.logging.Level")}.INFO, "find by example successful, result size: " + results.size()); + return results; + } + catch (RuntimeException re) { + logger.log(${pojo.importType("java.util.logging.Level")}.SEVERE, "find by example failed", re); + throw re; + } + } +**/ + + + + + +} + + +${pojo.generateImports()} +${classbody} diff --git a/src/test/resources/xml/hibernate.cfg.xml b/src/test/resources/xml/hibernate.cfg.xml new file mode 100644 index 0000000..8cb32c3 --- /dev/null +++ b/src/test/resources/xml/hibernate.cfg.xml @@ -0,0 +1,31 @@ + + + + + + + org.hibernate.dialect.MySQLDialect + + + org.mariadb.jdbc.Driver + + + + + jdbc:mariadb://192.168.0.123:3306/book + + + root + + + test000000 + + true + + + + + + + \ No newline at end of file diff --git a/src/test/resources/xml/hibernate.properties b/src/test/resources/xml/hibernate.properties new file mode 100644 index 0000000..c03960d --- /dev/null +++ b/src/test/resources/xml/hibernate.properties @@ -0,0 +1,12 @@ +#hibernate.dialect=org.hibernate.dialect.MySQLDialect +#hibernate.connection.driver_class=org.mariadb.jdbc.Driver +#hibernate.connection.url=jdbc:mariadb://192.168.0.123:3306/book +#hibernate.connection.username=root +#hibernate.connection.password=test000000 + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.url=jdbc:h2:~/test-jooq;MODE=MySQL;AUTO_SERVER=TRUE +hibernate.connection.username=sa +hibernate.connection.password= +hibernate.user_sql_comments=true \ No newline at end of file diff --git a/src/test/resources/xml/hibernate.reveng.xml b/src/test/resources/xml/hibernate.reveng.xml new file mode 100644 index 0000000..7c0306b --- /dev/null +++ b/src/test/resources/xml/hibernate.reveng.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + \ No newline at end of file