From 49e06769c3a92a113e6ee0a6e2f4adfecddefc28 Mon Sep 17 00:00:00 2001 From: XinYi Song <2037158277@qq.com> Date: Thu, 10 Feb 2022 16:18:48 +0800 Subject: [PATCH] =?UTF-8?q?=E8=92=99=E9=98=B4=E5=8E=BF=E7=81=AB=E7=82=B9?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 33 + .mvn/wrapper/MavenWrapperDownloader.java | 117 +++ .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 50710 bytes .mvn/wrapper/maven-wrapper.properties | 2 + mvnw | 310 ++++++ mvnw.cmd | 182 ++++ pom.xml | 262 +++++ .../java/com/xkrs/MengYinFireApplication.java | 26 + .../common/account/AccountCredentials.java | 36 + .../account/CustomAuthenticationProvider.java | 123 +++ .../common/account/GrantedAuthorityImpl.java | 25 + .../account/JwtAuthenticationFilter.java | 28 + .../xkrs/common/account/JwtLoginFilter.java | 149 +++ .../account/TokenAuthenticationService.java | 161 +++ .../com/xkrs/common/config/CorsConfig.java | 23 + .../xkrs/common/config/CorsInterceptor.java | 29 + .../com/xkrs/common/config/MvcConfig.java | 37 + .../config/RedisCacheAutoConfiguration.java | 30 + .../com/xkrs/common/config/RedisConfig.java | 187 ++++ .../com/xkrs/common/config/RedisUtil.java | 533 ++++++++++ .../xkrs/common/config/RestConfiguration.java | 24 + .../common/config/RestTemplateConfig.java | 91 ++ .../xkrs/common/config/WebSecurityConfig.java | 83 ++ .../config/WebSocketSecurityConfig.java | 25 + .../encapsulation/EncapsulationObejct.java | 59 ++ .../encapsulation/OutputEncapsulation.java | 96 ++ .../encapsulation/PromptMessageEnum.java | 65 ++ .../com/xkrs/common/tool/CompareVersion.java | 33 + .../java/com/xkrs/common/tool/EntityUtil.java | 98 ++ .../java/com/xkrs/common/tool/TokenUtil.java | 51 + .../com/xkrs/controller/FileController.java | 118 +++ .../controller/FireAndRangerController.java | 58 + .../xkrs/controller/FirePointController.java | 386 +++++++ .../controller/ForestRangerController.java | 57 + .../xkrs/controller/SysUserController.java | 292 ++++++ src/main/java/com/xkrs/dao/CityDao.java | 63 ++ src/main/java/com/xkrs/dao/CountyDao.java | 44 + src/main/java/com/xkrs/dao/FilePathDao.java | 21 + .../java/com/xkrs/dao/FireAndRangerDao.java | 55 + src/main/java/com/xkrs/dao/FireDao.java | 34 + src/main/java/com/xkrs/dao/FirePointDao.java | 97 ++ src/main/java/com/xkrs/dao/FireTaskDao.java | 18 + .../java/com/xkrs/dao/FireTaskPhotoDao.java | 29 + .../java/com/xkrs/dao/ForestRangerDao.java | 63 ++ src/main/java/com/xkrs/dao/NationwideDao.java | 40 + .../com/xkrs/dao/RelRoleAuthorityDao.java | 22 + .../java/com/xkrs/dao/RelUserRoleDao.java | 10 + .../java/com/xkrs/dao/SysAuthorityDao.java | 32 + src/main/java/com/xkrs/dao/SysRoleDao.java | 60 ++ src/main/java/com/xkrs/dao/SysUserDao.java | 165 +++ .../com/xkrs/model/entity/CityEntity.java | 137 +++ .../com/xkrs/model/entity/CountyEntity.java | 104 ++ .../java/com/xkrs/model/entity/FilePath.java | 135 +++ .../com/xkrs/model/entity/FireAndRanger.java | 151 +++ .../java/com/xkrs/model/entity/FirePoint.java | 258 +++++ .../xkrs/model/entity/FirePointEntity.java | 261 +++++ .../java/com/xkrs/model/entity/FireTask.java | 91 ++ .../com/xkrs/model/entity/FireTaskPhoto.java | 74 ++ .../com/xkrs/model/entity/ForestRanger.java | 155 +++ .../com/xkrs/model/entity/LandEntity.java | 56 + .../com/xkrs/model/entity/Nationwide.java | 137 +++ .../model/entity/RelRoleAuthorityEntity.java | 71 ++ .../xkrs/model/entity/RelUserRoleEntity.java | 60 ++ .../xkrs/model/entity/SysAuthorityEntity.java | 72 ++ .../com/xkrs/model/entity/SysRoleEntity.java | 72 ++ .../com/xkrs/model/entity/SysUserEntity.java | 285 +++++ .../java/com/xkrs/model/qo/FirePointQo.java | 185 ++++ .../java/com/xkrs/model/qo/SysUserQo.java | 168 +++ .../model/validation/SysUserQoInsert.java | 8 + .../model/validation/SysUserQoUpdate.java | 8 + .../java/com/xkrs/model/vo/AppPhotoVo.java | 33 + .../java/com/xkrs/model/vo/AppTaskBodyVo.java | 70 ++ .../com/xkrs/model/vo/FileServerResultVo.java | 67 ++ .../java/com/xkrs/model/vo/SysUserVo.java | 156 +++ .../xkrs/service/FireAndRangerService.java | 34 + .../com/xkrs/service/FirePointService.java | 167 +++ .../com/xkrs/service/ForestRangerService.java | 31 + .../java/com/xkrs/service/RedisService.java | 992 ++++++++++++++++++ .../com/xkrs/service/SysAuthorityService.java | 23 + .../java/com/xkrs/service/SysRoleService.java | 19 + .../java/com/xkrs/service/SysUserService.java | 178 ++++ .../impl/FireAndRangerServiceImpl.java | 174 +++ .../service/impl/FirePointServiceImpl.java | 572 ++++++++++ .../service/impl/ForestRangerServiceImpl.java | 83 ++ .../service/impl/SysAuthorityServiceImpl.java | 39 + .../xkrs/service/impl/SysRoleServiceImpl.java | 25 + .../xkrs/service/impl/SysUserServiceImpl.java | 437 ++++++++ .../java/com/xkrs/utils/AddressUtils.java | 293 ++++++ .../java/com/xkrs/utils/AliYunSmsUtils.java | 67 ++ src/main/java/com/xkrs/utils/BeanUtils.java | 73 ++ .../com/xkrs/utils/CopyPropertiesUtil.java | 54 + .../java/com/xkrs/utils/DateTimeUtil.java | 228 ++++ .../com/xkrs/utils/EncryptDecryptUtil.java | 66 ++ .../com/xkrs/utils/EntityManagerUtil.java | 36 + .../java/com/xkrs/utils/ExcelImportUtil.java | 193 ++++ src/main/java/com/xkrs/utils/FileFastDfs.java | 477 +++++++++ src/main/java/com/xkrs/utils/FileUtil.java | 250 +++++ src/main/java/com/xkrs/utils/HashUtil.java | 40 + src/main/java/com/xkrs/utils/IpUtil.java | 42 + src/main/java/com/xkrs/utils/NumberUtil.java | 21 + .../com/xkrs/utils/ObjectToBeanUtils.java | 152 +++ src/main/java/com/xkrs/utils/OpenGeoUtil.java | 37 + src/main/java/com/xkrs/utils/PhotoUtil.java | 190 ++++ src/main/java/com/xkrs/utils/Query.java | 236 +++++ src/main/java/com/xkrs/utils/RandomUtil.java | 71 ++ src/main/java/com/xkrs/utils/RequestUtil.java | 300 ++++++ .../java/com/xkrs/utils/RestTemplateUtil.java | 94 ++ .../java/com/xkrs/utils/SnowFlakeUtil.java | 124 +++ .../weather/controller/WeatherController.java | 31 + .../com/xkrs/weather/entity/Forecast.java | 78 ++ .../java/com/xkrs/weather/entity/Weather.java | 87 ++ .../xkrs/weather/entity/WeatherResponse.java | 55 + .../com/xkrs/weather/entity/Yesterday.java | 68 ++ .../weather/service/WeatherDataService.java | 24 + .../service/impl/WeatherDataServiceImpl.java | 53 + .../config/WebSocketBrokerConfig.java | 25 + .../websocket/config/WebSocketConfig.java | 16 + .../controller/WebSocketController.java | 49 + .../websocket/server/WebSocketServer.java | 129 +++ src/main/resources/application.properties | 81 ++ src/main/resources/i18n/messages.properties | 162 +++ .../resources/i18n/messages_en_US.properties | 162 +++ .../resources/i18n/messages_zh_CN.properties | 162 +++ src/main/resources/log4j2.xml | 100 ++ 124 files changed, 14496 insertions(+) create mode 100644 .gitignore create mode 100644 .mvn/wrapper/MavenWrapperDownloader.java create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 src/main/java/com/xkrs/MengYinFireApplication.java create mode 100644 src/main/java/com/xkrs/common/account/AccountCredentials.java create mode 100644 src/main/java/com/xkrs/common/account/CustomAuthenticationProvider.java create mode 100644 src/main/java/com/xkrs/common/account/GrantedAuthorityImpl.java create mode 100644 src/main/java/com/xkrs/common/account/JwtAuthenticationFilter.java create mode 100644 src/main/java/com/xkrs/common/account/JwtLoginFilter.java create mode 100644 src/main/java/com/xkrs/common/account/TokenAuthenticationService.java create mode 100644 src/main/java/com/xkrs/common/config/CorsConfig.java create mode 100644 src/main/java/com/xkrs/common/config/CorsInterceptor.java create mode 100644 src/main/java/com/xkrs/common/config/MvcConfig.java create mode 100644 src/main/java/com/xkrs/common/config/RedisCacheAutoConfiguration.java create mode 100644 src/main/java/com/xkrs/common/config/RedisConfig.java create mode 100644 src/main/java/com/xkrs/common/config/RedisUtil.java create mode 100644 src/main/java/com/xkrs/common/config/RestConfiguration.java create mode 100644 src/main/java/com/xkrs/common/config/RestTemplateConfig.java create mode 100644 src/main/java/com/xkrs/common/config/WebSecurityConfig.java create mode 100644 src/main/java/com/xkrs/common/config/WebSocketSecurityConfig.java create mode 100644 src/main/java/com/xkrs/common/encapsulation/EncapsulationObejct.java create mode 100644 src/main/java/com/xkrs/common/encapsulation/OutputEncapsulation.java create mode 100644 src/main/java/com/xkrs/common/encapsulation/PromptMessageEnum.java create mode 100644 src/main/java/com/xkrs/common/tool/CompareVersion.java create mode 100644 src/main/java/com/xkrs/common/tool/EntityUtil.java create mode 100644 src/main/java/com/xkrs/common/tool/TokenUtil.java create mode 100644 src/main/java/com/xkrs/controller/FileController.java create mode 100644 src/main/java/com/xkrs/controller/FireAndRangerController.java create mode 100644 src/main/java/com/xkrs/controller/FirePointController.java create mode 100644 src/main/java/com/xkrs/controller/ForestRangerController.java create mode 100644 src/main/java/com/xkrs/controller/SysUserController.java create mode 100644 src/main/java/com/xkrs/dao/CityDao.java create mode 100644 src/main/java/com/xkrs/dao/CountyDao.java create mode 100644 src/main/java/com/xkrs/dao/FilePathDao.java create mode 100644 src/main/java/com/xkrs/dao/FireAndRangerDao.java create mode 100644 src/main/java/com/xkrs/dao/FireDao.java create mode 100644 src/main/java/com/xkrs/dao/FirePointDao.java create mode 100644 src/main/java/com/xkrs/dao/FireTaskDao.java create mode 100644 src/main/java/com/xkrs/dao/FireTaskPhotoDao.java create mode 100644 src/main/java/com/xkrs/dao/ForestRangerDao.java create mode 100644 src/main/java/com/xkrs/dao/NationwideDao.java create mode 100644 src/main/java/com/xkrs/dao/RelRoleAuthorityDao.java create mode 100644 src/main/java/com/xkrs/dao/RelUserRoleDao.java create mode 100644 src/main/java/com/xkrs/dao/SysAuthorityDao.java create mode 100644 src/main/java/com/xkrs/dao/SysRoleDao.java create mode 100644 src/main/java/com/xkrs/dao/SysUserDao.java create mode 100644 src/main/java/com/xkrs/model/entity/CityEntity.java create mode 100644 src/main/java/com/xkrs/model/entity/CountyEntity.java create mode 100644 src/main/java/com/xkrs/model/entity/FilePath.java create mode 100644 src/main/java/com/xkrs/model/entity/FireAndRanger.java create mode 100644 src/main/java/com/xkrs/model/entity/FirePoint.java create mode 100644 src/main/java/com/xkrs/model/entity/FirePointEntity.java create mode 100644 src/main/java/com/xkrs/model/entity/FireTask.java create mode 100644 src/main/java/com/xkrs/model/entity/FireTaskPhoto.java create mode 100644 src/main/java/com/xkrs/model/entity/ForestRanger.java create mode 100644 src/main/java/com/xkrs/model/entity/LandEntity.java create mode 100644 src/main/java/com/xkrs/model/entity/Nationwide.java create mode 100644 src/main/java/com/xkrs/model/entity/RelRoleAuthorityEntity.java create mode 100644 src/main/java/com/xkrs/model/entity/RelUserRoleEntity.java create mode 100644 src/main/java/com/xkrs/model/entity/SysAuthorityEntity.java create mode 100644 src/main/java/com/xkrs/model/entity/SysRoleEntity.java create mode 100644 src/main/java/com/xkrs/model/entity/SysUserEntity.java create mode 100644 src/main/java/com/xkrs/model/qo/FirePointQo.java create mode 100644 src/main/java/com/xkrs/model/qo/SysUserQo.java create mode 100644 src/main/java/com/xkrs/model/validation/SysUserQoInsert.java create mode 100644 src/main/java/com/xkrs/model/validation/SysUserQoUpdate.java create mode 100644 src/main/java/com/xkrs/model/vo/AppPhotoVo.java create mode 100644 src/main/java/com/xkrs/model/vo/AppTaskBodyVo.java create mode 100644 src/main/java/com/xkrs/model/vo/FileServerResultVo.java create mode 100644 src/main/java/com/xkrs/model/vo/SysUserVo.java create mode 100644 src/main/java/com/xkrs/service/FireAndRangerService.java create mode 100644 src/main/java/com/xkrs/service/FirePointService.java create mode 100644 src/main/java/com/xkrs/service/ForestRangerService.java create mode 100644 src/main/java/com/xkrs/service/RedisService.java create mode 100644 src/main/java/com/xkrs/service/SysAuthorityService.java create mode 100644 src/main/java/com/xkrs/service/SysRoleService.java create mode 100644 src/main/java/com/xkrs/service/SysUserService.java create mode 100644 src/main/java/com/xkrs/service/impl/FireAndRangerServiceImpl.java create mode 100644 src/main/java/com/xkrs/service/impl/FirePointServiceImpl.java create mode 100644 src/main/java/com/xkrs/service/impl/ForestRangerServiceImpl.java create mode 100644 src/main/java/com/xkrs/service/impl/SysAuthorityServiceImpl.java create mode 100644 src/main/java/com/xkrs/service/impl/SysRoleServiceImpl.java create mode 100644 src/main/java/com/xkrs/service/impl/SysUserServiceImpl.java create mode 100644 src/main/java/com/xkrs/utils/AddressUtils.java create mode 100644 src/main/java/com/xkrs/utils/AliYunSmsUtils.java create mode 100644 src/main/java/com/xkrs/utils/BeanUtils.java create mode 100644 src/main/java/com/xkrs/utils/CopyPropertiesUtil.java create mode 100644 src/main/java/com/xkrs/utils/DateTimeUtil.java create mode 100644 src/main/java/com/xkrs/utils/EncryptDecryptUtil.java create mode 100644 src/main/java/com/xkrs/utils/EntityManagerUtil.java create mode 100644 src/main/java/com/xkrs/utils/ExcelImportUtil.java create mode 100644 src/main/java/com/xkrs/utils/FileFastDfs.java create mode 100644 src/main/java/com/xkrs/utils/FileUtil.java create mode 100644 src/main/java/com/xkrs/utils/HashUtil.java create mode 100644 src/main/java/com/xkrs/utils/IpUtil.java create mode 100644 src/main/java/com/xkrs/utils/NumberUtil.java create mode 100644 src/main/java/com/xkrs/utils/ObjectToBeanUtils.java create mode 100644 src/main/java/com/xkrs/utils/OpenGeoUtil.java create mode 100644 src/main/java/com/xkrs/utils/PhotoUtil.java create mode 100644 src/main/java/com/xkrs/utils/Query.java create mode 100644 src/main/java/com/xkrs/utils/RandomUtil.java create mode 100644 src/main/java/com/xkrs/utils/RequestUtil.java create mode 100644 src/main/java/com/xkrs/utils/RestTemplateUtil.java create mode 100644 src/main/java/com/xkrs/utils/SnowFlakeUtil.java create mode 100644 src/main/java/com/xkrs/weather/controller/WeatherController.java create mode 100644 src/main/java/com/xkrs/weather/entity/Forecast.java create mode 100644 src/main/java/com/xkrs/weather/entity/Weather.java create mode 100644 src/main/java/com/xkrs/weather/entity/WeatherResponse.java create mode 100644 src/main/java/com/xkrs/weather/entity/Yesterday.java create mode 100644 src/main/java/com/xkrs/weather/service/WeatherDataService.java create mode 100644 src/main/java/com/xkrs/weather/service/impl/WeatherDataServiceImpl.java create mode 100644 src/main/java/com/xkrs/websocket/config/WebSocketBrokerConfig.java create mode 100644 src/main/java/com/xkrs/websocket/config/WebSocketConfig.java create mode 100644 src/main/java/com/xkrs/websocket/controller/WebSocketController.java create mode 100644 src/main/java/com/xkrs/websocket/server/WebSocketServer.java create mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/i18n/messages.properties create mode 100644 src/main/resources/i18n/messages_en_US.properties create mode 100644 src/main/resources/i18n/messages_zh_CN.properties create mode 100644 src/main/resources/log4j2.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..e76d1f3 --- /dev/null +++ b/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054 GIT binary patch literal 50710 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 EfAhh=DF6Tf literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..a9f1ef8 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..a16b543 --- /dev/null +++ b/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..c8d4337 --- /dev/null +++ b/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..121fbc2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,262 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.1 + + + com.xkrs + MengYinFire + 0.0.1-SNAPSHOT + MengYinFire + Demo project for Spring Boot + + 5.19 + 0.11.2 + 4.5.12 + 6.1.5.Final + 5.4.20.Final + UTF-8 + UTF-8 + 11 + 11 + 11 + 1.2.76 + 2.10.5 + 2.10.5 + 5.0.0 + 5.0.0 + 4.5.2 + 5.0.0 + 5.0.0 + 2.0.4 + 4.4.3 + 0.4.0 + + + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security + spring-security-messaging + + + org.springframework.boot + spring-boot-starter-websocket + provided + + + org.springframework.boot + spring-boot-devtools + true + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + org.apache.commons + commons-pool2 + + + org.postgresql + postgresql + + + mysql + mysql-connector-java + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + runtime + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + runtime + + + nl.basjes.parse.useragent + yauaa + ${yauaa.version} + + + org.apache.httpcomponents + httpmime + ${httpmime.version} + + + org.hibernate.validator + hibernate-validator + ${hibernate-validator.version} + + + org.hibernate + hibernate-spatial + ${hibernate-spatial.version} + + + com.alibaba + fastjson + ${fastjson.version} + + + + + io.springfox + springfox-swagger-ui + ${springfox-swagger-ui.version} + + + + io.springfox + springfox-swagger2 + ${springfox-swagger2.version} + + + + + org.apache.poi + poi + ${poi.version} + + + + org.apache.poi + poi-ooxml + ${poi-ooxml.version} + + + + net.sf.json-lib + json-lib + 2.4 + jdk15 + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + + org.apache.poi + poi + ${poi.version} + + + + org.apache.poi + poi-ooxml + ${poi-ooxml.version} + + + + + com.aliyun + aliyun-java-sdk-core + 4.0.6 + + + com.aliyun + aliyun-java-sdk-dysmsapi + 1.1.0 + + + cn.hutool + hutool-all + ${hutool-all.version} + + + io.tus.java.client + tus-java-client + ${tus-client.version} + + + org.springframework.kafka + spring-kafka + 2.5.10.RELEASE + + + + + + + + + src/main/java + + **/*.properties + **/*.xml + + false + + + src/main/resources + + **/*.properties + **/*.xml + **/*.txt + + false + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.4.1 + + + + + diff --git a/src/main/java/com/xkrs/MengYinFireApplication.java b/src/main/java/com/xkrs/MengYinFireApplication.java new file mode 100644 index 0000000..6b8b214 --- /dev/null +++ b/src/main/java/com/xkrs/MengYinFireApplication.java @@ -0,0 +1,26 @@ +package com.xkrs; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; + +@SpringBootApplication +public class MengYinFireApplication { + + public static void main(String[] args) { + SpringApplication.run(MengYinFireApplication.class, args); + } + + @Bean + public RestTemplate restTemplate() { + //Apache Httpclient + RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); + restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + return restTemplate; + } +} diff --git a/src/main/java/com/xkrs/common/account/AccountCredentials.java b/src/main/java/com/xkrs/common/account/AccountCredentials.java new file mode 100644 index 0000000..8513b0f --- /dev/null +++ b/src/main/java/com/xkrs/common/account/AccountCredentials.java @@ -0,0 +1,36 @@ +package com.xkrs.common.account; + +/** + * 账户实体 + * @author tajochen + */ +public class AccountCredentials { + + private String userName; + private String password; + private boolean remember; + + 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; + } + + public boolean isRemember() { + return remember; + } + + public void setRemember(boolean remember) { + this.remember = remember; + } +} diff --git a/src/main/java/com/xkrs/common/account/CustomAuthenticationProvider.java b/src/main/java/com/xkrs/common/account/CustomAuthenticationProvider.java new file mode 100644 index 0000000..ca5130e --- /dev/null +++ b/src/main/java/com/xkrs/common/account/CustomAuthenticationProvider.java @@ -0,0 +1,123 @@ +package com.xkrs.common.account; + +import com.xkrs.model.entity.SysAuthorityEntity; +import com.xkrs.model.entity.SysUserEntity; +import com.xkrs.service.SysAuthorityService; +import com.xkrs.service.SysRoleService; +import com.xkrs.service.SysUserService; +import com.xkrs.utils.DateTimeUtil; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import static com.xkrs.utils.EncryptDecryptUtil.encry256; + +/** + * 自定义认证Provider + * @author tajochen + */ +@Component +public class CustomAuthenticationProvider implements AuthenticationProvider { + + @Resource + private SysUserService sysUserService; + + @Resource + private SysRoleService sysRoleService; + + @Resource + private SysAuthorityService sysAuthorityService; + + /** + * 初使化时将已静态化的Service实例化 + */ + protected static CustomAuthenticationProvider customAuthenticationProvider; + + /** + * 通过@PostConstruct实现初始化bean之前进行的操作 + */ + @PostConstruct + public void init() { + customAuthenticationProvider = this; + customAuthenticationProvider.sysUserService = this.sysUserService; + customAuthenticationProvider.sysRoleService = this.sysRoleService; + customAuthenticationProvider.sysAuthorityService = this.sysAuthorityService; + } + + /** + * 用户认证授权 + * @param authentication + * @return + * @throws AuthenticationException + */ + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + // 获取认证的用户名 & 密码 + String userName = authentication.getName(); + String password = authentication.getCredentials().toString(); + + SysUserEntity userEntity = customAuthenticationProvider.sysUserService.getSysUserByUserName(userName); + + // 检查用户是否存在 + if(userEntity == null){ + throw new BadCredentialsException("账号不存在或错误,请您确认注册"); + } + + // 检查用户是否激活 + if(userEntity.getActiveFlag().intValue() != 0){ + throw new DisabledException("该账号还未激活,请联系管理员"); + } + + //检查用户状态是否正常 + if(userEntity.getStatusCode() != 0){ + throw new DisabledException("用户状态不正常,请联系管理员"); + } + + if(userEntity.getDayNum() == 7){ + if(DateTimeUtil.dateTimeToString(LocalDateTime.now()).compareTo(userEntity.getOverTime()) > 0){ + throw new DisabledException("该账号已过期,请联系管理员"); + } + } + + // 认证逻辑 + String encryptPassword = encry256(password + userEntity.getSalt()); + if (encryptPassword.equals(userEntity.getPassword())) { + // 设置权限列表 + ArrayList permissions = new ArrayList<>(); + List integers = customAuthenticationProvider.sysAuthorityService.selectAuthorityByUserId(userEntity.getId()); + List permissionList = customAuthenticationProvider.sysAuthorityService.findAllByIdIn(integers); + for(SysAuthorityEntity sysAuthorityEntity : permissionList) { + permissions.add(new GrantedAuthorityImpl(sysAuthorityEntity.getAuthorityName())); + } + customAuthenticationProvider.sysUserService.updateLoginNum(userEntity.getId(),userEntity.getLoginNum() + 1); + customAuthenticationProvider.sysUserService.updateLoginLastTime(userEntity.getId(),DateTimeUtil.dateTimeToString(LocalDateTime.now())); + // 生成令牌 + Authentication authToken = new UsernamePasswordAuthenticationToken(userName, encryptPassword, permissions); + return authToken; + } + else { + throw new BadCredentialsException("用户密码错误,请重新输入"); + } + } + + /** + * 是否可以提供输入类型的认证服务 + * @param authentication + * @return + */ + @Override + public boolean supports(Class authentication) { + return authentication.equals(UsernamePasswordAuthenticationToken.class); + } +} diff --git a/src/main/java/com/xkrs/common/account/GrantedAuthorityImpl.java b/src/main/java/com/xkrs/common/account/GrantedAuthorityImpl.java new file mode 100644 index 0000000..318a217 --- /dev/null +++ b/src/main/java/com/xkrs/common/account/GrantedAuthorityImpl.java @@ -0,0 +1,25 @@ +package com.xkrs.common.account; + +import org.springframework.security.core.GrantedAuthority; + +/** + * 权限认证服务 + * @author tajochen + */ +public class GrantedAuthorityImpl implements GrantedAuthority { + + private String authority; + + public GrantedAuthorityImpl(String authority) { + this.authority = authority; + } + + public void setAuthority(String authority) { + this.authority = authority; + } + + @Override + public String getAuthority() { + return this.authority; + } +} diff --git a/src/main/java/com/xkrs/common/account/JwtAuthenticationFilter.java b/src/main/java/com/xkrs/common/account/JwtAuthenticationFilter.java new file mode 100644 index 0000000..da3a512 --- /dev/null +++ b/src/main/java/com/xkrs/common/account/JwtAuthenticationFilter.java @@ -0,0 +1,28 @@ +package com.xkrs.common.account; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.GenericFilterBean; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * 拦截所有需要JWT的请求,然后调用TokenAuthenticationService类的静态方法去做JWT验证 + * @author tajochen + */ +public class JwtAuthenticationFilter extends GenericFilterBean { + + @Override + public void doFilter(ServletRequest request, + ServletResponse response, + FilterChain filterChain) throws IOException, ServletException { + Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest)request); + SecurityContextHolder.getContext().setAuthentication(authentication); + filterChain.doFilter(request,response); + } +} diff --git a/src/main/java/com/xkrs/common/account/JwtLoginFilter.java b/src/main/java/com/xkrs/common/account/JwtLoginFilter.java new file mode 100644 index 0000000..09cc773 --- /dev/null +++ b/src/main/java/com/xkrs/common/account/JwtLoginFilter.java @@ -0,0 +1,149 @@ +package com.xkrs.common.account; + +import com.xkrs.common.encapsulation.OutputEncapsulation; +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.model.vo.SysUserVo; +import com.xkrs.service.SysUserService; +import com.xkrs.utils.IpUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.annotation.Resource; +import javax.servlet.FilterChain; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * jwt登录过滤器 + * @author tajochen + */ +public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter { + + private static final Logger logger = LoggerFactory.getLogger(JwtLoginFilter.class); + + + @Resource + private SysUserService sysUserService; + + public JwtLoginFilter(String url, AuthenticationManager authManager) { + super(new AntPathRequestMatcher(url)); + setAuthenticationManager(authManager); + } + + /** + * 登录时验证 + * @param req + * @param res + * @return + */ + @Override + public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws UnsupportedEncodingException { + req.setCharacterEncoding("UTF-8"); + res.setHeader("Access-Control-Allow-Origin","*"); + res.setHeader("Access-Control-Allow-Credentials", "false"); + AccountCredentials creds = new AccountCredentials(); + //获取表单数据 + String userName = req.getParameter("userName"); + String password = req.getParameter("password"); + String rememberMe = req.getParameter("remember"); + //如果用户名密码为空 + if(userName == null||password == null|| userName.trim().isEmpty()||password.trim().isEmpty()){ + throw new BadCredentialsException("user or password is null"); + } + if(rememberMe == null||rememberMe.isEmpty()){ + rememberMe = "false"; + } + creds.setUserName(userName.trim()); + creds.setPassword(password.trim()); + creds.setRemember(Boolean.parseBoolean(rememberMe)); + // 返回一个验证令牌 + return getAuthenticationManager().authenticate( + new UsernamePasswordAuthenticationToken( + creds.getUserName(), + creds.getPassword() + ) + ); + } + + /** + * 验证成功后调用 + * @param req + * @param response + * @param chain + * @param auth + * @throws IOException + * @throws ServletException + */ + @Override + protected void successfulAuthentication( + HttpServletRequest req, HttpServletResponse response, FilterChain chain, Authentication auth) { + if(sysUserService==null){ + ServletContext servletContext = req.getServletContext(); + WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext); + sysUserService = webApplicationContext.getBean(SysUserService.class); + } + //更新用户登录信息 + sysUserService.updateSysUserLogin(auth.getName(), IpUtil.getIpAddr(req)); + SysUserVo userByUserName = sysUserService.getUserByUserName(auth.getName()); + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "false"); + response.setContentType("application/json"); + response.setCharacterEncoding("UTF-8"); + Map map = new HashMap(3); + if(userByUserName.getCountyCode().substring(2).equals("0000")){ + List> cityByProCode = sysUserService.findCityByProCode(userByUserName.getCountyCode()); + map.put("city",cityByProCode); + List> countyByProCode = sysUserService.findCountyByProCode(userByUserName.getCountyCode()); + map.put("county",countyByProCode); + TokenAuthenticationService.addAuthentication(response, auth.getName(),auth.getAuthorities(),userByUserName,map); + }else if(userByUserName.getCountyCode().substring(4).equals("00") && !userByUserName.getCountyCode().substring(2).equals("0000")) { + List> countyByCityCode = sysUserService.findCountyByCityCode(userByUserName.getCountyCode()); + map.put("county",countyByCityCode); + TokenAuthenticationService.addAuthentication(response, auth.getName(),auth.getAuthorities(),userByUserName,map); + }else { + map.put("county",null); + TokenAuthenticationService.addAuthentication(response, auth.getName(),auth.getAuthorities(),userByUserName,map); + } + } + + /** + * 验证失败后调用 + * @param request + * @param response + * @param failed + * @throws IOException + */ + @Override + protected void unsuccessfulAuthentication(HttpServletRequest request, + HttpServletResponse response, + AuthenticationException failed) throws IOException { + Locale locale = LocaleContextHolder.getLocale(); + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "false"); + response.setContentType("application/json"); + response.setCharacterEncoding("UTF-8"); + // 将 JWT 写入 body + PrintWriter out = response.getWriter(); + out.append(OutputEncapsulation.outputEncapsulationObject(PromptMessageEnum.DATA_WRONG, failed.getLocalizedMessage(), locale)); + response.setStatus(HttpServletResponse.SC_OK); + } +} diff --git a/src/main/java/com/xkrs/common/account/TokenAuthenticationService.java b/src/main/java/com/xkrs/common/account/TokenAuthenticationService.java new file mode 100644 index 0000000..6db61f5 --- /dev/null +++ b/src/main/java/com/xkrs/common/account/TokenAuthenticationService.java @@ -0,0 +1,161 @@ +package com.xkrs.common.account; + +import com.xkrs.common.encapsulation.OutputEncapsulation; +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.model.vo.SysUserVo; +import com.xkrs.utils.DateTimeUtil; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; + +import javax.crypto.SecretKey; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.*; + +/** + * token认证服务 + * @author tajochen + */ +public class TokenAuthenticationService { + + private static final Logger logger = LoggerFactory.getLogger(TokenAuthenticationService.class); + + /** + * 加密密钥 + */ + static public final String SECRET_KEY = "0Y9H364Q9Y908262F25LMXGIKIN5N858XM3674GWL2DD8X1DS4W6I722IRY8PS4XPNB6U303" + + "45HBVCUL94STG8C3Z53T7A09JJ100I56YE9894CI11PX9J71HIZ8L5Y2O504C4E2K8276425UA8734833F45K36878FXAG799QV9LXU" + + "JOI3XA2046UPG8TB2OT84R5T6ZB127N9ZPJ7AJMC41JVHB2WK2B6H8NL45LZNAZ666KHZH3QUT65UX6F8"; + /** + * Token前缀 + */ + static public final String TOKEN_PREFIX = "Bearer"; + + /** + * 存放Token的Header Key + */ + static final String HEADER_STRING = "Authorization"; + static SecretKey key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); + + /** + * JWT生成方法 + * @param response + * @param userName + * @param authorities + */ + static void addAuthentication(HttpServletResponse response, String userName, + Collection authorities, SysUserVo sysUserEntity, Map map1) { + + Locale locale = new Locale("zh", "CN"); + Map map = new HashMap(3); + StringBuffer auths = new StringBuffer(); + String authsList = ""; + for(GrantedAuthority r : authorities) { + auths.append("," + r.getAuthority()); + } + authsList = auths.toString(); + if(authsList.length()>1){ + authsList=authsList.substring(1,authsList.length()); + }else{ + logger.warn(userName +" has no permission!"); + } + if(sysUserEntity.getDayNum() == 7){ + // 结束的时间 + LocalDateTime overTime = DateTimeUtil.stringToDateTime(sysUserEntity.getOverTime()); + // 计算距离结束时间的天数作为token + Duration duration = Duration.between(LocalDateTime.now(), overTime); + /** + * 动态设置过期时间 + */ + final long EXPIRATIONTIME = 60 * 60 * (duration.toDays()+1) * 24_000 ; + + // 生成JWT + String jwt = Jwts.builder() + .setSubject(userName) + .setIssuer("https://www.microservice.com") + .setAudience(userName) + // 保存权限 + .claim("auths", authsList) + // 有效期设置 + .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME)) + // 签名设置 + .signWith(key) + .compact(); + map.put("token",jwt); + map.put("user",sysUserEntity); + map.put("cityAndCounty",map1); + }else { + /** + * 过期时间6小时 + */ + final long EXPIRATIONTIME = 21_600_000; + + // 生成JWT + String jwt = Jwts.builder() + .setSubject(userName) + .setIssuer("https://www.microservice.com") + .setAudience(userName) + // 保存权限 + .claim("auths", authsList) + // 有效期设置 + .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME)) + // 签名设置 + .signWith(key) + .compact(); + map.put("token",jwt); + map.put("user",sysUserEntity); + map.put("cityAndCounty",map1); + } + // 将 JWT 写入 body + PrintWriter out = null; + try { + out = response.getWriter(); + } + catch (IOException e) { + e.printStackTrace(); + } + response.setStatus(HttpServletResponse.SC_OK); + out.append(OutputEncapsulation.outputEncapsulationObject(PromptMessageEnum.SUCCESS, map, locale)); + } + + /** + * JWT验证方法 + * @param request + * @return + */ + static Authentication getAuthentication(HttpServletRequest request) { + // 从Header中拿到token + String token = request.getHeader(HEADER_STRING); + if (token != null) { + try { + // 解析 Token + Claims claims = Jwts.parserBuilder() + .setSigningKey(key).build() + // 去掉 Bearer + .parseClaimsJws(token.replace(TOKEN_PREFIX, "")) + .getBody(); + // 获取用户名 + String userName = claims.getSubject(); + // 获取权限 + List authorities = AuthorityUtils.commaSeparatedStringToAuthorityList((String) claims.get("auths")); + return new UsernamePasswordAuthenticationToken(userName, null, authorities); + } catch(Exception e) { + // the sub field was missing or did not have a value + return null; + } + } else { + return null; + } + } +} diff --git a/src/main/java/com/xkrs/common/config/CorsConfig.java b/src/main/java/com/xkrs/common/config/CorsConfig.java new file mode 100644 index 0000000..7f8c32f --- /dev/null +++ b/src/main/java/com/xkrs/common/config/CorsConfig.java @@ -0,0 +1,23 @@ +package com.xkrs.common.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import javax.annotation.Resource; + +/** + * 系统跨域配置 + * @author tajochen + */ +@Configuration +public class CorsConfig implements WebMvcConfigurer { + + @Resource + private CorsInterceptor corsInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(corsInterceptor); + } +} diff --git a/src/main/java/com/xkrs/common/config/CorsInterceptor.java b/src/main/java/com/xkrs/common/config/CorsInterceptor.java new file mode 100644 index 0000000..e2103c5 --- /dev/null +++ b/src/main/java/com/xkrs/common/config/CorsInterceptor.java @@ -0,0 +1,29 @@ +package com.xkrs.common.config; + +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 跨域处理 + * @author tajochen + */ +@Component +public class CorsInterceptor implements HandlerInterceptor { + + @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + + //添加跨域CORS + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Access-Control-Allow-Credentials", "false"); + response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); + response.setHeader("Access-Control-Allow-Headers", "Content-Type , Authorization," + + "Accept,Origin,X-Requested-With"); + response.setHeader("Access-Control-Max-Age", "216000"); + response.setHeader("Content-Type","application/json;charset=UTF-8"); + return true; + } +} + diff --git a/src/main/java/com/xkrs/common/config/MvcConfig.java b/src/main/java/com/xkrs/common/config/MvcConfig.java new file mode 100644 index 0000000..edce463 --- /dev/null +++ b/src/main/java/com/xkrs/common/config/MvcConfig.java @@ -0,0 +1,37 @@ +package com.xkrs.common.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * WebMVC配置 + * @author Tajochen + */ +@Configuration +public class MvcConfig implements WebMvcConfigurer { + + /** + * 放行跨域请求 + */ + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowedMethods("*") + .allowedHeaders("*"); + } + + /** + * 定时任务线程池更改,防止多个任务并行 + */ + @Bean + public TaskScheduler taskScheduler() { + final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.setPoolSize(5); + return scheduler; + } +} diff --git a/src/main/java/com/xkrs/common/config/RedisCacheAutoConfiguration.java b/src/main/java/com/xkrs/common/config/RedisCacheAutoConfiguration.java new file mode 100644 index 0000000..6a0970b --- /dev/null +++ b/src/main/java/com/xkrs/common/config/RedisCacheAutoConfiguration.java @@ -0,0 +1,30 @@ +package com.xkrs.common.config; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.io.Serializable; + +/** + * Redis 缓存自动配置 + * @author tajochen + */ +@Configuration +@AutoConfigureAfter(RedisAutoConfiguration.class) +public class RedisCacheAutoConfiguration { + + @Bean + public RedisTemplate redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + template.setConnectionFactory(redisConnectionFactory); + return template; + } +} diff --git a/src/main/java/com/xkrs/common/config/RedisConfig.java b/src/main/java/com/xkrs/common/config/RedisConfig.java new file mode 100644 index 0000000..fb6641d --- /dev/null +++ b/src/main/java/com/xkrs/common/config/RedisConfig.java @@ -0,0 +1,187 @@ +package com.xkrs.common.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.interceptor.CacheErrorHandler; +import org.springframework.cache.interceptor.CacheResolver; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.*; + +import javax.annotation.Resource; +import java.io.IOException; +import java.time.Duration; + +/** + * redis配置 + * @author tajochen + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport{ + + private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class); + + @Resource + private LettuceConnectionFactory lettuceConnectionFactory; + + private static final Duration TIME_TO_LIVE = Duration.ofSeconds(3600*6); + + @Bean + @Override + public KeyGenerator keyGenerator() { + + // 设置自动key的生成规则,配置spring boot的注解,进行方法级别的缓存 + return (target, method, params) -> { + StringBuilder sb = new StringBuilder(); + sb.append(target.getClass().getName()); + sb.append(":"); + sb.append(method.getName()); + for (Object obj : params) { + sb.append(":").append(obj); + } + // logger.info("自动生成Redis Key -> [{}]", rsToUse); + return String.valueOf(sb); + }; + } + + @Bean + @Override + public CacheManager cacheManager() { + // 关键点,spring cache的注解使用的序列化都从这来,没有这个配置的话使用的jdk自己的序列化 + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + //key序列化方式 + .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer())) + //value序列化方式 + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())) + .disableCachingNullValues() + .entryTtl(TIME_TO_LIVE); + + RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder + .fromConnectionFactory(lettuceConnectionFactory) + .cacheDefaults(config) + .transactionAware(); + + return builder.build(); + } + + + /** + * RedisTemplate配置 在单独使用redisTemplate的时候 重新定义序列化方式 + */ + @Bean(name = "redisTemplate") + public RedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { + // 设置序列化 + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + // 配置null值序列化成空字符串 + om.getSerializerProvider().setNullValueSerializer(new JsonSerializer<>() { + @Override + public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + jsonGenerator.writeString(""); + } + }); + // 解决jackson无法反序列化LocalDateTime的问题,引入jsr310标准 + JavaTimeModule javaTimeModule = new JavaTimeModule(); + om.registerModule(javaTimeModule); + om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + // 其他设置 + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , + ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + jackson2JsonRedisSerializer.setObjectMapper(om); + // 配置redisTemplate + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(lettuceConnectionFactory); + RedisSerializer stringSerializer = new StringRedisSerializer(); + redisTemplate.setKeySerializer(stringSerializer); + redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); + redisTemplate.setHashKeySerializer(stringSerializer); + redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); + redisTemplate.afterPropertiesSet(); + return redisTemplate; + } + + private RedisSerializer keySerializer() { + return new StringRedisSerializer(); + } + + private RedisSerializer valueSerializer() { + // 设置序列化 + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>( + Object.class); + ObjectMapper om = new ObjectMapper(); + // 解决jackson无法反序列化LocalDateTime的问题,引入jsr310标准 + JavaTimeModule javaTimeModule = new JavaTimeModule(); + om.registerModule(javaTimeModule); + om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + // 其他设置 + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , + ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + jackson2JsonRedisSerializer.setObjectMapper(om); + return jackson2JsonRedisSerializer; + } + + @Override + public CacheResolver cacheResolver() { + return null; + } + + /** + * 设置数据存入 redis 的序列化方式,并开启事务 + * + * @param redisTemplate + * @param factory + */ + private void initRedisTemplate(RedisTemplate redisTemplate, RedisConnectionFactory factory) { + //如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String! + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashKeySerializer(new StringRedisSerializer()); + redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); + redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); + // 开启事务 + redisTemplate.setEnableTransactionSupport(true); + redisTemplate.setConnectionFactory(factory); + } + + /** + * 注入封装RedisTemplate 给RedisUtil提供操作类 + * @param redisTemplate + * @return RedisUtil + */ + @Bean(name = "redisUtil") + public RedisUtil redisUtil(RedisTemplate redisTemplate) { + RedisUtil redisUtil = new RedisUtil(); + redisUtil.setRedisTemplate(redisTemplate); + return redisUtil; + } + + @Override + @Bean + public CacheErrorHandler errorHandler() { + // 异常处理,当Redis发生异常时,打印日志,但是程序正常走 + logger.info("初始化 -> [{}]", "Redis CacheErrorHandler"); + return null; + } + +} diff --git a/src/main/java/com/xkrs/common/config/RedisUtil.java b/src/main/java/com/xkrs/common/config/RedisUtil.java new file mode 100644 index 0000000..25bd3a7 --- /dev/null +++ b/src/main/java/com/xkrs/common/config/RedisUtil.java @@ -0,0 +1,533 @@ +package com.xkrs.common.config; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +/** + * redis工具类 + * @author tajochen + */ +public class RedisUtil { + + private RedisTemplate redisTemplate; + + public void setRedisTemplate(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + /** + * 指定缓存失效时间 + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key,long time){ + try { + if(time>0){ + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * @param key 键 不能为null + * @return 时间(秒) 返回0 代表为永久有效 + */ + public long getExpire(String key){ + return redisTemplate.getExpire(key,TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key){ + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String ... key){ + if(key!=null&&key.length>0){ + if(key.length==1){ + redisTemplate.delete(key[0]); + }else{ + redisTemplate.delete(String.valueOf(CollectionUtils.arrayToList(key))); + } + } + } + + //============================String============================= + /** + * 普通缓存获取 + * @param key 键 + * @return 值 + */ + public Object get(String key){ + return key==null?null:redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key,Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + } + + /** + * 普通缓存放入并设置时间 + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key,Object value,long time){ + try { + if(time>0){ + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 递增 + * @param key 键 + * @param delta 要增加几(大于0) + * @return + */ + public long incr(String key, long delta){ + if(delta<0){ + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * @param key 键 + * @param delta 要减少几(小于0) + * @return + */ + public long decr(String key, long delta){ + if(delta<0){ + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + //================================Map================================= + /** + * HashGet + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key,String item){ + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key){ + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map){ + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time){ + try { + redisTemplate.opsForHash().putAll(key, map); + if(time>0){ + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key,String item,Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key,String item,Object value,long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if(time>0){ + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item){ + redisTemplate.opsForHash().delete(key,item); + } + + /** + * 判断hash表中是否有该项的值 + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item){ + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item,double by){ + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item,double by){ + return redisTemplate.opsForHash().increment(key, item,-by); + } + + //============================set============================= + /** + * 根据key获取Set中的所有值 + * @param key 键 + * @return + */ + public Set sGet(String key){ + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key,Object value){ + try { + return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value)); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将数据放入set缓存 + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object...values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 将set数据放入缓存 + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key,long time,Object...values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if(time>0) + {expire(key, time);} + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 获取set缓存的长度 + * @param key 键 + * @return + */ + public long sGetSetSize(String key){ + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 移除值为value的 + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public long setRemove(String key, Object ...values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + //===============================list================================= + + /** + * 获取list缓存的内容 + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end){ + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * @param key 键 + * @return + */ + public long lGetListSize(String key){ + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key,long index){ + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) + {expire(key, time);} + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index,Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key,long count,Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } +} + diff --git a/src/main/java/com/xkrs/common/config/RestConfiguration.java b/src/main/java/com/xkrs/common/config/RestConfiguration.java new file mode 100644 index 0000000..ce45f96 --- /dev/null +++ b/src/main/java/com/xkrs/common/config/RestConfiguration.java @@ -0,0 +1,24 @@ +package com.xkrs.common.config; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.Resource; + +/** + * @author XinYi Song + */ +@Configuration +public class RestConfiguration { + + @Resource + private RestTemplateBuilder restTemplateBuilder; + + @Bean + public RestTemplate restTemplate(){ + return restTemplateBuilder.build(); + } + +} diff --git a/src/main/java/com/xkrs/common/config/RestTemplateConfig.java b/src/main/java/com/xkrs/common/config/RestTemplateConfig.java new file mode 100644 index 0000000..93eb92b --- /dev/null +++ b/src/main/java/com/xkrs/common/config/RestTemplateConfig.java @@ -0,0 +1,91 @@ +package com.xkrs.common.config; + +/** + * @author xkrs + */ +import org.apache.http.client.HttpClient; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.ssl.TrustStrategy; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.RestTemplate; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * @Author: HongZhi Wang + * @Date: 2020/8/17 16:45 + * + * 创建RestTemplate配置类,设置连接池大小、超时时间、重试机制等。 + */ +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate(){ + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setRequestFactory(clientHttpRequestFactory()); + restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); + return restTemplate; + } + + @Bean + public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() { + try { + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { + @Override + public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { + return true; + } + }).build(); + httpClientBuilder.setSSLContext(sslContext); + HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE; + SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier); + Registry socketFactoryRegistry = RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + //注册http和https请求 + .register("https", sslConnectionSocketFactory).build(); + //开始设置连接池 + //创建连接池 + PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + // 最大连接数500 + poolingHttpClientConnectionManager.setMaxTotal(500); + // 同路由并发数100 + poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100); + httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager); + // 重试次数 + httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)); + HttpClient httpClient = httpClientBuilder.build(); + // httpClient连接配置 + HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); + // 连接超时 + clientHttpRequestFactory.setConnectTimeout(20000); + // 数据读取超时时间 + clientHttpRequestFactory.setReadTimeout(30000); + // 连接不够用的等待时间 + clientHttpRequestFactory.setConnectionRequestTimeout(20000); + return clientHttpRequestFactory; + } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) { + System.out.println("初始化HTTP连接池出错"+ e); + } + return null; + } +} diff --git a/src/main/java/com/xkrs/common/config/WebSecurityConfig.java b/src/main/java/com/xkrs/common/config/WebSecurityConfig.java new file mode 100644 index 0000000..2e38446 --- /dev/null +++ b/src/main/java/com/xkrs/common/config/WebSecurityConfig.java @@ -0,0 +1,83 @@ +package com.xkrs.common.config; + +import com.xkrs.common.account.CustomAuthenticationProvider; +import com.xkrs.common.account.JwtAuthenticationFilter; +import com.xkrs.common.account.JwtLoginFilter; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled=true) +class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + /** + * 设置 HTTP 验证规则 + * @param http + * @throws Exception + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + // 关闭csrf验证 + http.csrf().disable() + // 对请求进行认证 + .authorizeRequests() + // 所有 / 的所有请求 都放行 + //.antMatchers("/").permitAll() + // 所有OPTIONS请求都放行 + .antMatchers(HttpMethod.OPTIONS).permitAll() + // 所有 /user/add 用户注册 的POST请求 都放行 + .antMatchers(HttpMethod.POST, "/api/user/add").permitAll() + // 所有 /user/check/duplicate 检查用户名是否重复 的POST请求 都放行 + .antMatchers(HttpMethod.POST, "/api/user/check/duplicate").permitAll() + // 所有 /login 用户登录 的POST请求 都放行 + .antMatchers(HttpMethod.POST, "/api/login").permitAll() + // 所有 app 用户注册 的POST请求 都放行 + .antMatchers(HttpMethod.POST, "/api/person-investigator/add").permitAll() + .antMatchers("/ws/asset").permitAll() + .antMatchers(HttpMethod.GET,"/api/user/booleanUserName").permitAll() + .antMatchers(HttpMethod.POST,"/insertFirePoint").permitAll() + .antMatchers(HttpMethod.GET,"/api/ws/sendAll").permitAll() + .antMatchers(HttpMethod.GET,"/api/ws/sendOne").permitAll() + .antMatchers(HttpMethod.POST,"/insertAppTask").permitAll() + .antMatchers(HttpMethod.GET,"/selectAppTask").permitAll() + .antMatchers(HttpMethod.GET,"/selectFirePointBetweenSeven").permitAll() + .antMatchers(HttpMethod.GET,"/selectFirePointNum").permitAll() + .antMatchers(HttpMethod.GET,"/api/user/booleanUserName").permitAll() + .antMatchers(HttpMethod.GET,"/websocketTest").permitAll() + .antMatchers(HttpMethod.GET,"/selectCityName").permitAll() + .antMatchers(HttpMethod.GET,"/weather/cityName").permitAll() + .antMatchers(HttpMethod.GET,"/weather/cityId").permitAll() + .antMatchers(HttpMethod.GET,"/selectFirePoint").permitAll() + .antMatchers(HttpMethod.POST,"/updateTypeByFireCode").permitAll() + .antMatchers(HttpMethod.GET,"/api/user/verificationCode").permitAll() + .antMatchers(HttpMethod.POST,"/uploadFileMore").permitAll() + .antMatchers(HttpMethod.POST,"/uploadFile").permitAll() + .antMatchers(HttpMethod.POST,"/insertFireTest").permitAll() + .antMatchers(HttpMethod.POST,"/importCityExcel").permitAll() + .antMatchers(HttpMethod.POST,"/deleteShuiTi").permitAll() + .antMatchers(HttpMethod.POST,"/insertBeijing").permitAll() + // 所有其它请求需要身份认证 + .anyRequest().authenticated() + .and() + // 添加一个过滤器 所有访问 /login 的请求交给 JWTLoginFilter 来处理 这个类处理所有的JWT相关内容 + .addFilterBefore(new JwtLoginFilter("/api/login", authenticationManager()), + UsernamePasswordAuthenticationFilter.class) + // 添加一个过滤器验证其他请求的Token是否合法 + .addFilterBefore(new JwtAuthenticationFilter(), + UsernamePasswordAuthenticationFilter.class); + ;} + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + // 使用自定义身份验证组件 + auth.authenticationProvider(new CustomAuthenticationProvider()); + } +} + diff --git a/src/main/java/com/xkrs/common/config/WebSocketSecurityConfig.java b/src/main/java/com/xkrs/common/config/WebSocketSecurityConfig.java new file mode 100644 index 0000000..5ea9f85 --- /dev/null +++ b/src/main/java/com/xkrs/common/config/WebSocketSecurityConfig.java @@ -0,0 +1,25 @@ +package com.xkrs.common.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry; +import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer; + +import static org.springframework.messaging.simp.SimpMessageType.MESSAGE; +import static org.springframework.messaging.simp.SimpMessageType.SUBSCRIBE; + + +/** + * @author xkrs + */ +@Configuration +public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { + @Override + protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { + messages + .nullDestMatcher().authenticated() + .simpSubscribeDestMatchers("/user/queue/errors").permitAll() + .simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll() + .anyMessage().denyAll(); + + } +} \ No newline at end of file diff --git a/src/main/java/com/xkrs/common/encapsulation/EncapsulationObejct.java b/src/main/java/com/xkrs/common/encapsulation/EncapsulationObejct.java new file mode 100644 index 0000000..e11fea7 --- /dev/null +++ b/src/main/java/com/xkrs/common/encapsulation/EncapsulationObejct.java @@ -0,0 +1,59 @@ +package com.xkrs.common.encapsulation; + +import java.io.Serializable; + +/** + * 输出信息对象 + * @author tajochen + * @param + */ +public class EncapsulationObejct implements Serializable { + + /** + * 状态码 + */ + int status; + + /** + * 提示信息 + */ + String msg; + + /** + * 数据 + */ + T data; + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + @Override + public String toString() { + return "EncapsulationObejct{" + + "status=" + status + + ", msg='" + msg + '\'' + + ", data=" + data + + '}'; + } +} diff --git a/src/main/java/com/xkrs/common/encapsulation/OutputEncapsulation.java b/src/main/java/com/xkrs/common/encapsulation/OutputEncapsulation.java new file mode 100644 index 0000000..9bee083 --- /dev/null +++ b/src/main/java/com/xkrs/common/encapsulation/OutputEncapsulation.java @@ -0,0 +1,96 @@ +package com.xkrs.common.encapsulation; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.MessageSource; +import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.stereotype.Component; +import org.springframework.validation.FieldError; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Properties; + +/** + * 输出信息封装 + * @author tajochen + */ +@Component +public class OutputEncapsulation { + + private static final Logger logger = LoggerFactory.getLogger(OutputEncapsulation.class); + + /** + * 读取多国语言文件 + * @return + */ + public static MessageSource messageSource() { + Properties properties = new Properties(); + // 使用ClassLoader加载properties配置文件生成对应的输入流 + InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties"); + // 使用properties对象加载输入流 + try { + properties.load(in); + } catch (IOException e) { + e.printStackTrace(); + } + ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("i18n/messages"); + messageSource.setDefaultEncoding("UTF-8"); + return messageSource; + } + + /** + * 封装输出数据 + * @param promptMessageEnum + * @param obj + * @return + */ + public static String outputEncapsulationObject(PromptMessageEnum promptMessageEnum, Object obj, Locale locale) { + + EncapsulationObejct encapsulationObejct = new EncapsulationObejct(); + encapsulationObejct.setStatus(promptMessageEnum.getCode()); + encapsulationObejct.setMsg(messageSource().getMessage(promptMessageEnum.getText(),null,locale)); + encapsulationObejct.setData(obj); + + ObjectMapper objectMapper = new ObjectMapper(); + // 忽略无法转换的对象 + objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false); + // 忽略json字符串中不识别的属性 + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + // 解决jackson无法反序列化LocalDateTime的问题,引入jsr310标准 + JavaTimeModule javaTimeModule = new JavaTimeModule(); + objectMapper.registerModule(javaTimeModule); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + String strByEo = ""; + try { + strByEo = objectMapper.writeValueAsString(encapsulationObejct); + } catch (JsonProcessingException e) { + e.printStackTrace(); + logger.warn(e.toString()); + } + return strByEo; + } + + /** + * 输出请求值检验错误信息 + * @param fieldErrors + * @return + */ + public static String outputEncapsulationErrorList(List fieldErrors, Locale locale){ + List errorMsg = new ArrayList<>(); + for (FieldError fieldError : fieldErrors) { + String errMessage = fieldError.getDefaultMessage().subSequence(1,fieldError.getDefaultMessage().length()-1).toString(); + errorMsg.add(messageSource().getMessage(errMessage,null,locale)); + } + return outputEncapsulationObject(PromptMessageEnum.PARAM_ILLEGAL,errorMsg,locale); + } +} diff --git a/src/main/java/com/xkrs/common/encapsulation/PromptMessageEnum.java b/src/main/java/com/xkrs/common/encapsulation/PromptMessageEnum.java new file mode 100644 index 0000000..74d5bdb --- /dev/null +++ b/src/main/java/com/xkrs/common/encapsulation/PromptMessageEnum.java @@ -0,0 +1,65 @@ +package com.xkrs.common.encapsulation; + +/** + * 提示信息枚举 + * @author tajochen + */ +public enum PromptMessageEnum{ + + // 执行成功 + SUCCESS(0, "sys.message.success"), + + + // 用户权限错误或非法操作: 1001-1999 + USER_NOT_LOGGED(1001, "sys.message.user.not_logged_in"), + USER_LOGIN_ERROR(1002, "sys.message.user.login_error"), + USER_ACCOUNT_FORBIDDEN(1003, "sys.message.user.account_forbidden"), + USER_ACCOUNT_NOT_ACTIVATED(1004, "sys.message.user.account_not_activated"), + USER_HAS_OVERTIME(1005, "sys.message.user.overtime"), + USER_NO_PERMISSION(1006,"sys.message.user.no_permission"), + USER_ALREADY_LOGGED(1007, "sys.message.user.already_logged"), + + // 请求参数错误或非法:2001-2999 + PARAM_NULL(2001, "sys.message.param.null"), + PARAM_ILLEGAL(2002, "sys.message.param.illegal"), + + // 数据返回错误:3001-3999 + DATA_NONE(3001, "sys.message.data.none"), + + DATA_WRONG(3002, "sys.message.data.wrong"), + DATA_EXIT(3003,"sys.message.exit"), + + // 操作失败:4001-4999 + PROCESS_FAIL(4001,"sys.message.process.fail"), + PROCESS_OVERTIME(4002,"sys.message.process.overtime"), + FILE_EXISTS(4003,"sys.message.file.exists"), + FILE_WRITE_ERROR(4004,"sys.message.file.write.error"), + FILE_READ_ERROR(4005,"sys.message.file.read.error"), + + // 系统内部错误或异常:5001-5999 + SYSTEM_INNER_ERROR(5001,"sys.message.system.inner_error"), + SYSTEM_ABNORMAL(5002,"sys.message.system.abnormal"), + SYSTEM_BUSY(5003,"sys.message.system.busy"), + SYSTEM_MAINTAIN(5004,"sys.message.system.maintain"), + + // 数据库错误:6001-6999 + DATABASE_ERROR(6001,"sys.message.database.error"); + + private int code; + + private String text; + + private PromptMessageEnum(int code,String text) { + this.code = code; + this.text = text; + } + + public String getText() { + return this.text; + } + + public int getCode() { + return this.code; + } + +} diff --git a/src/main/java/com/xkrs/common/tool/CompareVersion.java b/src/main/java/com/xkrs/common/tool/CompareVersion.java new file mode 100644 index 0000000..7d2d6e7 --- /dev/null +++ b/src/main/java/com/xkrs/common/tool/CompareVersion.java @@ -0,0 +1,33 @@ +package com.xkrs.common.tool; + +/** + * CompareVersion 比较版本号 + * @author tajochen + */ +public class CompareVersion { + + /** + * 比较三位版本号 ,若 版本1>版本2 返回 1,若版本1<版本2 返回 -1,否则返回0 + * @param version1 版本1 + * @param version2 版本2 + * @return + */ + public static int compareVersion(String version1, String version2) { + String[] v1 = version1.split("\\."); + String[] v2 = version2.split("\\."); + int n = Math.max(v1.length, v2.length); + for (int i = 0; i < n; i++) { + int v1Int = i < v1.length ? Integer.parseInt(v1[i]) : 0; + int v2Int = i < v2.length ? Integer.parseInt(v2[i]) : 0; + if (v1Int == v2Int) { + continue; + } + if (v1Int > v2Int){ + return 1; + } else { + return -1; + } + } + return 0; + } +} diff --git a/src/main/java/com/xkrs/common/tool/EntityUtil.java b/src/main/java/com/xkrs/common/tool/EntityUtil.java new file mode 100644 index 0000000..70c54b6 --- /dev/null +++ b/src/main/java/com/xkrs/common/tool/EntityUtil.java @@ -0,0 +1,98 @@ +package com.xkrs.common.tool; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * dao接口类处理工具 + * @author tajochen + */ +public class EntityUtil { + private static final Logger logger = LoggerFactory.getLogger(EntityUtil.class); + + /** + * 将数组数据转换为实体类 + * 此处数组元素的顺序必须与实体类构造函数中的属性顺序一致 + * @param list 数组对象集合 + * @param clazz 实体类 + * @param 实体类 + * @param model 实例化的实体类 + * @return 实体类集合 + */ + public static List castEntity(List list, Class clazz, Object model) { + List returnList = new ArrayList(); + if (list.isEmpty()) { + return returnList; + } + //获取每个数组集合的元素个数 + Object[] co = list.get(0); + + //获取当前实体类的属性名、属性值、属性类别 + List attributeInfoList = getFiledsInfo(model); + //创建属性类别数组 + Class[] c2 = new Class[attributeInfoList.size()]; + //如果数组集合元素个数与实体类属性个数不一致则发生错误 + if (attributeInfoList.size() != co.length) { + return returnList; + } + //确定构造方法 + for (int i = 0; i < attributeInfoList.size(); i++) { + c2[i] = (Class) attributeInfoList.get(i).get("type"); + } + try { + for (Object[] o : list) { + Constructor constructor = clazz.getConstructor(c2); + returnList.add(constructor.newInstance(o)); + } + } catch (Exception ex) { + logger.error("实体数据转化为实体类发生异常:异常信息:{}", ex.getMessage()); + return returnList; + } + return returnList; + } + + /** + * 根据属性名获取属性值 + * @param fieldName 属性名 + * @param modle 实体类 + * @return 属性值 + */ + private static Object getFieldValueByName(String fieldName, Object modle) { + try { + String firstLetter = fieldName.substring(0, 1).toUpperCase(); + String getter = "get" + firstLetter + fieldName.substring(1); + Method method = modle.getClass().getMethod(getter, new Class[]{}); + Object value = method.invoke(modle, new Object[]{}); + return value; + } catch (Exception e) { + return null; + } + } + + /** + * 获取属性类型(type),属性名(name),属性值(value)的map组成的list + * @param model 实体类 + * @return list集合 + */ + private static List getFiledsInfo(Object model) { + Field[] fields = model.getClass().getDeclaredFields(); + List list = new ArrayList(fields.length); + Map infoMap = null; + for (int i = 0; i < fields.length; i++) { + infoMap = new HashMap(3); + infoMap.put("type", fields[i].getType()); + infoMap.put("name", fields[i].getName()); + infoMap.put("value", getFieldValueByName(fields[i].getName(), model)); + list.add(infoMap); + } + return list; + } +} diff --git a/src/main/java/com/xkrs/common/tool/TokenUtil.java b/src/main/java/com/xkrs/common/tool/TokenUtil.java new file mode 100644 index 0000000..0c4a642 --- /dev/null +++ b/src/main/java/com/xkrs/common/tool/TokenUtil.java @@ -0,0 +1,51 @@ +package com.xkrs.common.tool; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; + +import javax.crypto.SecretKey; +import java.util.List; + +/** + * token工具 + * @author tajochen + */ +public class TokenUtil { + /** + * Token前缀 + */ + static public final String TOKEN_PREFIX = "Bearer"; + + static public final String SECRETKEY = "0Y9H364Q9Y908262F25LMXGIKIN5N858XM3674GWL2DD8X1DS4W6I722IRY8PS4XPNB6U30345" + + "HBVCUL94STG8C3Z53T7A09JJ100I56YE9894CI11PX9J71HIZ8L5Y2O504C4E2K8276425UA8734833F45K36878FXAG799QV9LXUJ" + + "OI3XA2046UPG8TB2OT84R5T6ZB127N9ZPJ7AJMC41JVHB2WK2B6H8NL45LZNAZ666KHZH3QUT65UX6F8"; + + static SecretKey key = Keys.hmacShaKeyFor(SECRETKEY.getBytes()); + + public static String getTokenUserName(String token) { + String userName = ""; + if (token != null) { + try { + // 解析 Token + Claims claims = Jwts.parserBuilder() + .setSigningKey(key).build() + // 去掉 Bearer + .parseClaimsJws(token.replace(TOKEN_PREFIX, "")) + .getBody(); + // 获取用户名 + userName = claims.getSubject(); + // 获取权限 + List authorities = AuthorityUtils.commaSeparatedStringToAuthorityList((String) claims.get("auths")); + } catch(Exception e) { + // the sub field was missing or did not have a 'jsmith' value + return null; + } + } else { + return null; + } + return userName; + } +} diff --git a/src/main/java/com/xkrs/controller/FileController.java b/src/main/java/com/xkrs/controller/FileController.java new file mode 100644 index 0000000..e1b7cba --- /dev/null +++ b/src/main/java/com/xkrs/controller/FileController.java @@ -0,0 +1,118 @@ +package com.xkrs.controller; + +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.dao.FilePathDao; +import com.xkrs.model.entity.FilePath; +import com.xkrs.utils.FileFastDfs; +import com.xkrs.utils.FileUtil; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject; +import static com.xkrs.utils.FileUtil.getUploadInfo; + +/** + * @author XinYi Song + * 文件上传 + */ +@RestController +public class FileController { + + @Resource + private FileFastDfs fileFastDfs; + + @Resource + private FilePathDao filePathDao; + + /** + * 上传多张图片 + * @param files + * @return + */ + @PostMapping("/uploadFileMore") + public String uploadFileMore(MultipartFile[] files) throws Exception { + Locale locale = LocaleContextHolder.getLocale(); + if (null == files || files.length == 0){ + return outputEncapsulationObject(PromptMessageEnum.PARAM_NULL, "result or fileType is null", locale); + } + List list = new ArrayList(); + for (MultipartFile file : + files) { + boolean m = FileUtil.checkFileSize(file.getSize(), 100, "M"); + if(m == false){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG, "图片大小不能超过100M", locale); + } + File file1 = fileFastDfs.multipartFileToFile(file); + String dir = "fire_point"; + String info = fileFastDfs.uploadFile(file1, dir); + Map map = getUploadInfo(info); + file1.delete(); + FilePath filePath = new FilePath(); + filePath.setFilePath(map.get("path")); + filePath.setFileName(map.get("fileName")); + filePath.setSize(map.get("size")); + filePath.setMtime(map.get("mtime")); + filePath.setUrl(map.get("url")); + filePath.setMd5(map.get("md5")); + filePath.setScene(map.get("scene")); + filePathDao.save(filePath); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS, "上传成功!", locale); + } + + /** + * 上传单张图片 + * @param file + * @return + */ + @PostMapping("/uploadFile") + public String uploadFile(MultipartFile file) throws Exception { + Locale locale = LocaleContextHolder.getLocale(); + if (null == file){ + return outputEncapsulationObject(PromptMessageEnum.PARAM_NULL, "result or fileType is null", locale); + } + boolean m = FileUtil.checkFileSize(file.getSize(), 100, "M"); + if(m == false){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG, "图片大小不能超过100M", locale); + } + File file1 = fileFastDfs.multipartFileToFile(file); + String dir = "fire_point"; + String info = fileFastDfs.uploadFile(file1, dir); + Map map = getUploadInfo(info); + file1.delete(); + FilePath filePath = new FilePath(); + filePath.setFilePath(map.get("path")); + filePath.setFileName(map.get("fileName")); + filePath.setSize(map.get("size")); + filePath.setMtime(map.get("mtime")); + filePath.setUrl(map.get("url")); + filePath.setMd5(map.get("md5")); + filePath.setScene(map.get("scene")); + filePathDao.save(filePath); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS, "上传成功!", locale); + } + + /** + * 查询火点图片路径 + * @return + */ + @GetMapping("/findPath") + public String findPath(){ + Locale locale = LocaleContextHolder.getLocale(); + List> path = filePathDao.findPath(); + if(path == null || path.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE, "还未上传任何图片信息!", locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS, path, locale); + } +} diff --git a/src/main/java/com/xkrs/controller/FireAndRangerController.java b/src/main/java/com/xkrs/controller/FireAndRangerController.java new file mode 100644 index 0000000..d0949c6 --- /dev/null +++ b/src/main/java/com/xkrs/controller/FireAndRangerController.java @@ -0,0 +1,58 @@ +package com.xkrs.controller; + +import com.xkrs.service.FireAndRangerService; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.io.UnsupportedEncodingException; +import java.util.Map; + +/** + * @author xkrs + */ +@RestController +public class FireAndRangerController { + + @Resource + private FireAndRangerService fireAndRangerService; + + /** + * 将火点分配给某个人 + * @param map + * @param token + * @return + */ + @PreAuthorize("hasAnyAuthority('auth_general_user')") + @PostMapping("/addFireAndRanger") + public String addFireAndRanger(@RequestBody Map map, @RequestHeader(value="Authorization") String token) throws UnsupportedEncodingException { + String rangerName = (String) map.get("rangerName"); + String fireCode = (String) map.get("fireCode"); + String handler = (String) map.get("handler"); + String verifier = (String) map.get("verifier"); + return fireAndRangerService.addFireAndRanger(rangerName,fireCode,handler,verifier,token); + } + + /** + * 护林员查看自己的火点任务 + * @param token + * @return + */ + @PreAuthorize("hasAnyAuthority('auth_rangers')") + @GetMapping("/selectFireInformation") + public String selectFireInformation(@RequestHeader(value="Authorization") String token){ + return fireAndRangerService.selectFireInformation(token); + } + + /** + * 根据火点编码查询核查信息 + * @param map + * @return + */ + @PreAuthorize("hasAnyAuthority('auth_general_user')") + @PostMapping("/findFireAndRanger") + public String findFireAndRangerByFireCode(@RequestBody Map map, @RequestHeader(value="Authorization") String token) throws Exception { + String fireCode = (String) map.get("fireCode"); + return fireAndRangerService.findFireAndRangerByFireCode(fireCode,token); + } +} diff --git a/src/main/java/com/xkrs/controller/FirePointController.java b/src/main/java/com/xkrs/controller/FirePointController.java new file mode 100644 index 0000000..32001dc --- /dev/null +++ b/src/main/java/com/xkrs/controller/FirePointController.java @@ -0,0 +1,386 @@ +package com.xkrs.controller; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.common.tool.TokenUtil; +import com.xkrs.dao.FirePointDao; +import com.xkrs.dao.SysUserDao; +import com.xkrs.model.entity.FirePoint; +import com.xkrs.model.entity.FirePointEntity; +import com.xkrs.model.entity.SysUserEntity; +import com.xkrs.model.qo.FirePointQo; +import com.xkrs.model.vo.AppTaskBodyVo; +import com.xkrs.service.FirePointService; +import com.xkrs.utils.RequestUtil; +import com.xkrs.utils.RestTemplateUtil; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.transaction.Transactional; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject; + +/** + * @author XinYi Song + */ +@RestController +public class FirePointController { + + @Resource + private FirePointService firePointService; + + @Resource + private SysUserDao sysUserDao; + + @Resource + private FirePointDao firePointDao; + + @Resource + private RestTemplateUtil restTemplateUtil; + + + /** + * 添加火点数据 + * @param firePointQo + * @return + */ + @PostMapping("/insertFirePoint") + public String insertFirePoint(@RequestBody FirePointQo firePointQo) throws IOException { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + FirePointEntity firePointEntity = firePointService.insertFirePoint(firePointQo); + if(firePointEntity == null){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"添加数据失败",locale); + }else { + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"添加成功",locale); + } + } + + /** + * 根据时间段查询火点信息 + * @param startTime + * @param endTime + * @return + */ + @GetMapping("/findByTime") + public String findByAddTime(@RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime){ + return firePointService.findByAddTime(startTime, endTime); + } + + /** + * 测试 + * @param token + * @return + */ + @GetMapping("/selectUserName") + @PreAuthorize("hasAnyAuthority('auth_general_user')") + public String selectUserName(@RequestHeader(value="Authorization") String token){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 验证token + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + if(sysUserEntity == null){ + return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR,"您还没有注册登录,请先注册登录",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,sysUserEntity.getUserName(),locale); + } + + /** + * 查询今天的火点信息 + * @param token + * @return + */ + @GetMapping("/selectTodayFirePoint") + @PreAuthorize("hasAnyAuthority('auth_general_user')") + public String selectTodayFirePoint(@RequestParam("countyCode") String countyCode,@RequestHeader(value="Authorization") String token){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + List firePointEntities = firePointService.selectTodayFirePoint(countyCode); + if(firePointEntities == null || firePointEntities.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有火点数据",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,firePointEntities,locale); + } + + /** + * 动态多条件查询火点信息 + * @param map + * @param token + * @return + */ + @PostMapping("/selectFirePoint") + @PreAuthorize("hasAnyAuthority('auth_general_user')") + public String selectFirePoint(@RequestBody Map map, @RequestHeader(value="Authorization") String token){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 区县编码 + String cityCode = (String) map.get("cityCode"); + // 卫星类型 + String satelliteType = (String) map.get("satelliteType"); + // 植被类型 + String landType = (String) map.get("landType"); + // 开始时间 + String startTime = (String) map.get("startTime"); + // 结束时间 + String endTime = (String) map.get("endTime"); + // 验证token + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + // 查询省 + if(sysUserEntity.getCountyCode().substring(2).equals("0000")){ + List firePointEntities = firePointService.selectFirePoint(sysUserEntity.getCountyCode(),cityCode, satelliteType, landType, startTime, endTime); + if(firePointEntities == null || firePointEntities.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有火点数据",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,firePointEntities,locale); + // 查询市 + }else if(sysUserEntity.getCountyCode().substring(4).equals("00") && !sysUserEntity.getCountyCode().substring(2).equals("0000")){ + List firePointEntities = firePointService.selectFirePointByCity(sysUserEntity.getCountyCode(), cityCode, satelliteType, landType, startTime, endTime); + if(firePointEntities == null || firePointEntities.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有火点数据",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,firePointEntities,locale); + // 查询县 + }else { + List firePointEntities = firePointService.selectFirePointByCounty(sysUserEntity.getCountyCode(), satelliteType, landType, startTime, endTime); + if(firePointEntities == null || firePointEntities.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有火点数据",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,firePointEntities,locale); + } + } + + /** + * 根据火点编码修改火点状态 + * @param map + * @param token + * @return + */ + @PostMapping("/updateTypeByFireCode") + public String updateTypeByFireCode(@RequestBody Map map, @RequestHeader(value="Authorization") String token){ + String fireCode = (String) map.get("fireCode"); + String fireType = (String) map.get("fireType"); + return firePointService.updateTypeByFireCode(fireCode,fireType,token); + } + + /** + * 提交核查任务 + * @param files + * @param appTaskBodyVo + * @return + */ + @PostMapping("/insertAppTask") + public String insertAppTask(@RequestParam("files") MultipartFile[] files, AppTaskBodyVo appTaskBodyVo) throws IOException { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + if("".equals(appTaskBodyVo.getFireCode()) || appTaskBodyVo.getFireCode() == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"火点编码不能为空",locale); + } + if("".equals(appTaskBodyVo.getTaskInformation()) || appTaskBodyVo.getTaskInformation() == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"任务描述不能为空",locale); + } + if(files == null || files.length == 0 ){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"图片不能为空",locale); + } + return firePointService.insertAppTask(files,appTaskBodyVo); + } + + /** + * 查询核查的任务信息 + * @param fireCode + * @return + */ + @GetMapping("/selectAppTask") + public String selectAppTask(@RequestParam("fireCode") String fireCode) throws Exception { + return firePointService.selectAppTask(fireCode); + } + + /** + * 查询近一周的火点信息 + * @return + */ + @GetMapping("/selectFirePointBetweenSeven") + public String selectFirePointBetweenSeven(){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + List firePointEntities = firePointService.selectFirePointBetweenSeven(); + if(firePointEntities == null || firePointEntities.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时没有火点数据",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,firePointEntities,locale); + } + + /** + * 查询近一个月的火点信息 + * @return + */ + @GetMapping("/selectFirePointByMonth") + @PreAuthorize("hasAnyAuthority('auth_general_user')") + public String selectFirePointByMonth(@RequestHeader(value="Authorization") String token) { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 验证token + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + List firePointEntities = firePointService.selectFirePointByMonth(sysUserEntity.getCountyCode()); + if(firePointEntities == null || firePointEntities.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时没有火点数据",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,firePointEntities,locale); + } + + /** + * 查询火点数量 + * @return + */ + @GetMapping("/selectFirePointNum") + public String selectFirePointNum(@RequestParam("keepType") String keepType){ + // keepType为1时,查询近一天的火点数量 + if("1".equals(keepType)){ + return firePointService.selectFirePointNumDay(); + // keepType为2时,查询近一周的火点数量 + }else if("2".equals(keepType)){ + return firePointService.selectFirePointNumWeek(); + }else { + return firePointService.selectFirePointNumMonth(); + } + } + + /*@GetMapping("/websocketTest") + public void websocketTest(@RequestParam("message") String message){ + + WebSocketServer.broadInfo(message); + }*/ + + /** + * 查询该省所有的市 + * @return + */ + @GetMapping("/selectCityName") + public String selectCityName(@RequestParam("code") String code){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + if(code.substring(2).equals("0000")){ + List> maps = firePointService.selectCityName(code); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,maps,locale); + }else { + List> maps = firePointService.selectCountyName(code); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,maps,locale); + } + } + + /** + * 根据火点编码查询火点信息 + * @param fireCode + * @return + */ + @GetMapping("/selectFirePoint") + public String selectFirePoint(@RequestParam("fireCode") String fireCode){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + FirePointEntity byFireCode = firePointDao.findByFireCode(fireCode); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,byFireCode,locale); + } + + /** + * 测试添加火点信息 + * @param firePointQo + * @return + */ + @PostMapping("/insertFireTest") + public String insertFireTest(@RequestBody FirePointQo firePointQo){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + FirePoint firePoint = firePointService.insertFireTest(firePointQo); + if(firePoint == null){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"添加数据失败",locale); + }else { + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"添加成功",locale); + } + } + + /** + * 导入全国省市区 + * @param file + * @return + * @throws Exception + */ + @PostMapping("/importCityExcel") + public String importCityExcel(MultipartFile file) throws Exception { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + firePointService.importCityExcel(file); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"导入成功",locale); + } + + /** + * 查询今天的火点信息(测试) + * @param token + * @return + */ + @GetMapping("/selectTodayFire") + @PreAuthorize("hasAnyAuthority('auth_general_user')") + public String selectTodayFire(@RequestParam("countyCode") String countyCode,@RequestHeader(value="Authorization") String token){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + List firePointEntities = firePointService.selectTodayFire(countyCode); + if(firePointEntities == null || firePointEntities.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有火点数据",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,firePointEntities,locale); + } + + /** + * 删除水体类型的火点信息 + * @return + */ + @Transactional(rollbackOn = Exception.class) + @PostMapping("/deleteShuiTi") + public String deleteShuiTi(){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + List integers = firePointDao.selectId(); + firePointDao.deleteByIdIn(integers); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"删除成功",locale); + } + + @PostMapping("/insertBeijing") + public String insertBeijing(){ + Locale locale = LocaleContextHolder.getLocale(); + //JSONObject jsonObject = restTemplateUtil.doGetForEntity("http://192.168.2.139:6801/selectBeijing"); + Map map = new HashMap(3); + String s = RequestUtil.doGet("http://localhost:6801/selectBeijing", null); + JSONObject jsonObject = JSON.parseObject(s); + List data = (List) jsonObject.get("data"); + for(Map obj : data){ + FirePointEntity firePointEntity = new FirePointEntity(); + firePointEntity.setFireImage(null); + firePointEntity.setSatelliteImage(null); + firePointEntity.setFirePointAddress(obj.get("firePointAddress").toString()); + firePointEntity.setFireCode(obj.get("fireCode").toString()); + firePointEntity.setFireType(obj.get("fireType").toString()); + firePointEntity.setAddTime(obj.get("addTime").toString()); + firePointEntity.setConfidence(obj.get("confidence").toString()); + firePointEntity.setCountyCode(obj.get("countyCode").toString()); + firePointEntity.setCountyName(obj.get("countyName").toString()); + firePointEntity.setLandType(obj.get("landType").toString()); + firePointEntity.setLatitude(Double.parseDouble(obj.get("latitude").toString())); + firePointEntity.setLongitude(Double.parseDouble(obj.get("longitude").toString())); + firePointEntity.setSatelliteTime(obj.get("satelliteTime").toString()); + firePointEntity.setSatelliteType(obj.get("satelliteType").toString()); + firePointDao.save(firePointEntity); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"插入成功",locale); + } +} diff --git a/src/main/java/com/xkrs/controller/ForestRangerController.java b/src/main/java/com/xkrs/controller/ForestRangerController.java new file mode 100644 index 0000000..945859a --- /dev/null +++ b/src/main/java/com/xkrs/controller/ForestRangerController.java @@ -0,0 +1,57 @@ +package com.xkrs.controller; + +import com.xkrs.service.ForestRangerService; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.Map; + +/** + * @author xkrs + */ +@RestController +public class ForestRangerController { + + @Resource + private ForestRangerService forestRangerService; + + /** + * 根据区县编码查询相关护林员的信息 + * @param rangerCountyCode + * @return + */ + @GetMapping("/findByRangerCountyCode") + @PreAuthorize("hasAnyAuthority('auth_general_user')") + public String findByRangerCountyCode(@RequestParam("rangerCountyCode") String rangerCountyCode, @RequestHeader(value="Authorization") String token){ + return forestRangerService.findByRangerCountyCode(rangerCountyCode); + } + + /** + * 根据区县编码查询该区县所有护林员的信息 + * @param countyCode + * @param token + * @return + */ + @GetMapping("/findAllByRangerCountyCode") + @PreAuthorize("hasAnyAuthority('auth_general_user')") + public String findAllByRangerCountyCode(@RequestParam("countyCode") String countyCode, @RequestHeader(value="Authorization") String token){ + return forestRangerService.findAllByRangerCountyCode(countyCode,token); + } + + /** + * 根据手机号修改护林员的位置 + * @param map + * @return + */ + @PostMapping("/updateLatAndLonByPhone") + @PreAuthorize("hasAnyAuthority('auth_general_user')") + public String updateLatAndLonByPhone(@RequestBody Map map, @RequestHeader(value="Authorization") String token){ + String rangerLatitude = (String) map.get("rangerLatitude"); + String rangerLongitude = (String) map.get("rangerLongitude"); + String rangerPhone = (String) map.get("rangerPhone"); + return forestRangerService.updateLatAndLonByPhone(rangerLatitude,rangerLongitude,rangerPhone); + } + + +} diff --git a/src/main/java/com/xkrs/controller/SysUserController.java b/src/main/java/com/xkrs/controller/SysUserController.java new file mode 100644 index 0000000..b2a7e52 --- /dev/null +++ b/src/main/java/com/xkrs/controller/SysUserController.java @@ -0,0 +1,292 @@ +package com.xkrs.controller; + +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; +import com.aliyuncs.exceptions.ClientException; +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.common.tool.TokenUtil; +import com.xkrs.dao.SysUserDao; +import com.xkrs.model.entity.SysUserEntity; +import com.xkrs.model.qo.SysUserQo; +import com.xkrs.model.validation.SysUserQoInsert; +import com.xkrs.model.validation.SysUserQoUpdate; +import com.xkrs.model.vo.SysUserVo; +import com.xkrs.service.RedisService; +import com.xkrs.service.SysUserService; +import com.xkrs.utils.RandomUtil; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationErrorList; +import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject; +import static com.xkrs.utils.AliYunSmsUtils.sendSms; + +/** + * 系统用户Controller + * @author tajocehn + */ +@RestController +@RequestMapping(value = "/api/user") +public class SysUserController { + + @Resource + private SysUserService sysUserService; + + @Resource + private SysUserDao sysUserDao; + + @Resource + private RedisService redisService; + + /** + * 登录用户Token验证 + * @return + */ + @RequestMapping(value = "/logged/check",method = RequestMethod.POST) + public String loginUserTokenCheck(){ + Locale locale = LocaleContextHolder.getLocale(); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"",locale); + } + + @RequestMapping(value = "/check/duplicate", method = RequestMethod.POST) + public String checkDuplicate(@RequestParam(value="userName", required=false) String userName){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 验证用户名是否重复 + if(!sysUserService.checkUserName(userName)){ + return outputEncapsulationObject(PromptMessageEnum.PARAM_ILLEGAL,"",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"OK",locale); + } + + + @RequestMapping(value = "/add", method = RequestMethod.POST) + public String addUser(@Validated({SysUserQoInsert.class}) @RequestBody SysUserQo userQo, + BindingResult bindingResult){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 验证数据合法性 + if(bindingResult.hasErrors()){ + return outputEncapsulationErrorList(bindingResult.getFieldErrors(),locale); + } + // 验证用户名是否重复 + if(!sysUserService.checkUserName(userQo.getUserName())){ + return outputEncapsulationObject(PromptMessageEnum.PARAM_ILLEGAL,"该账号已经注册,请勿重复注册",locale); + } + // 添加新用户 + return sysUserService.addUser(userQo); + } + + /** + * 软删除指定id的普通用户 + * @param id + * @return + */ + @RequestMapping(value = "/general/delete", method = RequestMethod.DELETE) + @PreAuthorize("hasAnyAuthority('auth_system_manager','auth_general_user')") + public String deleteCustomUser(@RequestParam(value="userId", required=false) int id){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 验证数据合法性 + int res = sysUserService.softDeleteGeneralUser(id); + if(res==1){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"",locale); + } else { + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"",locale); + } + } + + @RequestMapping(value = "/update", method = RequestMethod.POST) + @PreAuthorize("hasAnyAuthority('auth_system_manager','auth_administor')") + public String updateUser(@Validated({SysUserQoUpdate.class}) @RequestBody SysUserQo userQo, + BindingResult bindingResult){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 验证数据合法性 + if(bindingResult.hasErrors()){ + return outputEncapsulationErrorList(bindingResult.getFieldErrors(),locale); + } + // 修改用户 + sysUserService.updateSysUser(userQo); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"OK",locale); + } + + /** + * 判断用户名是否存在 + * @param userName + * @return + */ + @GetMapping("/booleanUserName") + public String booleanUserName(@RequestParam("userName") String userName){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + Map map = new HashMap(3); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(userName); + if(sysUserEntity == null){ + map.put("status",0); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale); + }else { + map.put("status",1); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale); + } + } + + /** + * 查看用户信息 + * @return + */ + @GetMapping("/selectAllUser") + @PreAuthorize("hasAnyAuthority('auth_administor')") + public String selectAllUser(@RequestHeader(value="Authorization") String token){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 验证token + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + if(sysUserEntity == null){ + return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR,"您还没有注册登录,请先注册登录",locale); + } + List sysUserVos = sysUserService.selectAllUser(); + if(sysUserVos == null || sysUserVos.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有任何用户数据",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,sysUserVos,locale); + } + + /** + * 管理员进行启用禁用的操作 + * @param map + * @param token + * @return + */ + @PostMapping("/operateActiveFlag") + @PreAuthorize("hasAnyAuthority('auth_administor')") + public String operateActiveFlag(@RequestBody Map map,@RequestHeader(value="Authorization") String token){ + Integer userId = (Integer) map.get("userId"); + String keepType = (String) map.get("keepType"); + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 验证token + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + if(sysUserEntity == null){ + return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR,"您还没有注册登录,请先注册登录",locale); + } + // 如果keepType等于1进行启用操作 + if("1".equals(keepType)){ + sysUserService.updateEnable(userId); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"启用成功",locale); + }else { + sysUserService.updateDisable(userId); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"禁用成功",locale); + } + } + + /** + * 用户修改密码 + * @param map + * @param token + * @return + */ + @PostMapping("/updatePassword") + @PreAuthorize("hasAnyAuthority('auth_administor','auth_general_user')") + public String updatePassword(@RequestBody Map map,@RequestHeader(value="Authorization") String token){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + String oldPassword = (String) map.get("oldPassword"); + String newPassword = (String) map.get("newPassword"); + String confirmPassword = (String) map.get("confirmPassword"); + // 验证token + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + if(sysUserEntity == null){ + return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR,"您还没有注册登录,请先注册登录",locale); + } + return sysUserService.updatePassword(oldPassword,newPassword,confirmPassword,sysUserEntity); + } + + /** + * 管理员修改用户的密码 + * @param map + * @param token + * @return + */ + @PostMapping("/adminUpdatePassword") + @PreAuthorize("hasAnyAuthority('auth_administor')") + public String adminUpdatePassword(@RequestBody Map map,@RequestHeader(value="Authorization") String token){ + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + // 要修改的用户的id + Integer userId = (Integer) map.get("userId"); + String newPassword = (String) map.get("newPassword"); + String confirmPassword = (String) map.get("confirmPassword"); + // 验证token + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + if(sysUserEntity == null){ + return outputEncapsulationObject(PromptMessageEnum.USER_LOGIN_ERROR,"您还没有注册登录,请先注册登录",locale); + } + return sysUserService.adminUpdatePassword(userId,newPassword,confirmPassword); + } + + /** + * 发送手机号 + * @param phone + * @return + * @throws ClientException + */ + @GetMapping("/verificationCode") + public String verificationCode(@RequestParam("phone") String phone) throws ClientException { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + String optCode = String.valueOf(RandomUtil.returnCode()); + redisService.set(phone,optCode,10, TimeUnit.MINUTES); + SendSmsResponse response =sendSms(phone,optCode); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"",locale); + } + + /** + * 更改账号过期时间 + * @return + */ + @PostMapping("/updateExpireDate") + @PreAuthorize("hasAnyAuthority('auth_administor')") + public String updateExpireDate(@RequestBody Map map,@RequestHeader(value="Authorization") String token){ + Integer userId = (Integer) map.get("userId"); + Integer timeNum = (Integer) map.get("timeNum"); + String keepType = (String) map.get("keepType"); + if("1".equals(keepType)){ + return sysUserService.updateExpireDateDay(userId, timeNum); + }else if("2".equals(keepType)){ + return sysUserService.updateExpireDateMonth(userId,timeNum); + }else if("3".equals(keepType)){ + return sysUserService.updateExpireDateYear(userId,timeNum); + }else { + return sysUserService.updatePermanent(userId); + } + } + + /** + * 修改账号到期时间 + * @param map + * @param token + * @return + */ + @PostMapping("/updateOverTime") + @PreAuthorize("hasAnyAuthority('auth_administor')") + public String updateOverTime(@RequestBody Map map,@RequestHeader(value="Authorization") String token){ + Integer userId = (Integer) map.get("userId"); + String overTime = (String) map.get("overTime"); + return sysUserService.updateOverTime(userId,overTime); + } + +} diff --git a/src/main/java/com/xkrs/dao/CityDao.java b/src/main/java/com/xkrs/dao/CityDao.java new file mode 100644 index 0000000..bbca4e5 --- /dev/null +++ b/src/main/java/com/xkrs/dao/CityDao.java @@ -0,0 +1,63 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.CityEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * @author xkrs + */ +@Component +public interface CityDao extends JpaRepository, JpaSpecificationExecutor { + + /** + * 根据省编码查询城市有关信息 + * @param proCode + * @return + */ + @Query(value = "select city_name,city_code,city_latitude,city_longitude from city where pro_code = ?",nativeQuery = true) + List selectCityNameAndLatAndLog(String proCode); + + /** + * 查询所有市和对应的编码 + * @param code + * @return + */ + @Query(value = "select city_name cityname,city_code citycode from city where pro_code = :code",nativeQuery = true) + List> selectCityName(String code); + + /** + * 根据市编码查询信息 + * @param cityCode + * @return + */ + List findByCityCode(String cityCode); + + /** + * 根据省编码查询信息 + * @param proCode + * @return + */ + List findByProCode(String proCode); + + /** + * 根据市名称查询信息 + * @param cityName + * @return + */ + List findByCityName(String cityName); + + /** + * 根据省名称查询信息 + * @param proName + * @return + */ + List findByProName(String proName); + + +} diff --git a/src/main/java/com/xkrs/dao/CountyDao.java b/src/main/java/com/xkrs/dao/CountyDao.java new file mode 100644 index 0000000..5c79431 --- /dev/null +++ b/src/main/java/com/xkrs/dao/CountyDao.java @@ -0,0 +1,44 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.CountyEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * @author XinYi Song + */ +@Component +public interface CountyDao extends JpaRepository { + /** + * 查询市包含的区县和编码 + * @param code + * @return + */ + @Query(value = "select county_name cityname,county_code citycode from county where city_code = :code",nativeQuery = true) + List> selectCountyName(String code); + + /** + * 根据市编码查询信息 + * @param cityCode + * @return + */ + List findByCityCode(String cityCode); + + /** + * 根据countyCode查询信息 + * @param countyCode + * @return + */ + CountyEntity findByCountyCode(String countyCode); + + /** + * 根据县名称查询信息 + * @param countyName + * @return + */ + CountyEntity findByCountyName(String countyName); +} diff --git a/src/main/java/com/xkrs/dao/FilePathDao.java b/src/main/java/com/xkrs/dao/FilePathDao.java new file mode 100644 index 0000000..f4412f4 --- /dev/null +++ b/src/main/java/com/xkrs/dao/FilePathDao.java @@ -0,0 +1,21 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.FilePath; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; +import java.util.Map; + +/** + * @author XinYi Song + */ +public interface FilePathDao extends JpaRepository { + + /** + * 查询全部路径 + * @return + */ + @Query(value = "select file_path filepath from file_path",nativeQuery = true) + List> findPath(); +} diff --git a/src/main/java/com/xkrs/dao/FireAndRangerDao.java b/src/main/java/com/xkrs/dao/FireAndRangerDao.java new file mode 100644 index 0000000..e8f1ed1 --- /dev/null +++ b/src/main/java/com/xkrs/dao/FireAndRangerDao.java @@ -0,0 +1,55 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.FireAndRanger; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Component; + +/** + * @author xkrs + */ +@Component +public interface FireAndRangerDao extends JpaRepository, JpaSpecificationExecutor { + + /** + * 根据火点编码查询信息 + * @param fireCode + * @return + */ + FireAndRanger findByFireCode(String fireCode); + + /** + * 根据护林员手机号查询 + * @param rangerName + * @param progressType + * @return + */ + FireAndRanger findByRangerNameAndProgressType(String rangerName, String progressType); + + /** + * 根据火点编码删除火点信息 + * @param fireCode + * @return + */ + FireAndRanger deleteByFireCode(String fireCode); + + /** + * 根据火点编码修改结束时间 + * @param fireCode + * @param endTime + */ + @Modifying(clearAutomatically=true) + @Query(value = "update fire_and_ranger set end_time = ?2 where fire_code = ?1",nativeQuery = true) + void updateEndTimeByFireCode(String fireCode, String endTime); + + /** + * 根据火点编码修改进程状态 + * @param fireCode + * @param endTime + */ + @Modifying(clearAutomatically=true) + @Query(value = "update fire_and_ranger set progress_type = ?2 where fire_code = ?1",nativeQuery = true) + void updateProgressTypeByFireCode(String fireCode, String endTime); +} diff --git a/src/main/java/com/xkrs/dao/FireDao.java b/src/main/java/com/xkrs/dao/FireDao.java new file mode 100644 index 0000000..e09c7b5 --- /dev/null +++ b/src/main/java/com/xkrs/dao/FireDao.java @@ -0,0 +1,34 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.FirePoint; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author XinYi Song + */ +@Component +public interface FireDao extends JpaRepository { + + /** + * 查询今天的火点信息 + * @param addTime + * @param address + * @return + */ + @Query(value = "select * from fire where add_time like CONCAT('%',:addTime,'%') and fire_point_address like CONCAT('%',:address,'%')",nativeQuery = true) + List selectTodayFire(String addTime, String address); + + /** + * 区县条件查询今天火点信息 + * @param addTime + * @param countyCode + * @return + */ + @Query(value = "select * from fire_point where add_time like CONCAT('%',:addTime,'%') and county_code = :countyCode",nativeQuery = true) + List selectTodayFireOne(String addTime,String countyCode); + +} diff --git a/src/main/java/com/xkrs/dao/FirePointDao.java b/src/main/java/com/xkrs/dao/FirePointDao.java new file mode 100644 index 0000000..b0b5062 --- /dev/null +++ b/src/main/java/com/xkrs/dao/FirePointDao.java @@ -0,0 +1,97 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.FirePointEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * @author XinYi Song + */ +@Component +public interface FirePointDao extends JpaRepository, JpaSpecificationExecutor { + + /** + * 查询今天的火点信息 + * @param addTime + * @param address + * @return + */ + @Query(value = "select * from fire_point where add_time like CONCAT('%',:addTime,'%') and fire_point_address like CONCAT('%',:address,'%')",nativeQuery = true) + List selectTodayFirePoint(String addTime,String address); + + /** + * 区县条件查询今天火点信息 + * @param addTime + * @param countyCode + * @return + */ + @Query(value = "select * from fire_point where add_time like CONCAT('%',:addTime,'%') and county_code = :countyCode",nativeQuery = true) + List selectTodayFirePointOne(String addTime,String countyCode); + + /** + * 根据火点编码查询火点信息 + * @param fireCode + * @return + */ + FirePointEntity findByFireCode(String fireCode); + + /** + * 根据火点编码修改火点状态 + * @param fireCode + * @param fireType + */ + @Modifying(clearAutomatically=true) + @Query(value = "update fire_point set fire_type = ?2 where fire_code = ?1",nativeQuery = true) + void updateFireTypeByFireCode(String fireCode,String fireType); + + /** + * 查询时间段内各植被类型的火点数量 + * @param startTime + * @param endTime + * @return + */ + @Query(value = "select la.land_name landname,count(fp.id) as num from land la left join fire_point fp " + + "on fp.land_type = la.land_name AND fp.add_time BETWEEN ?1 AND ?2 " + + "group by la.land_name",nativeQuery = true) + List> selectNumByLandType(String startTime,String endTime); + + /** + * 查询时间段内各地区的火点数量 + * @param startTime + * @param endTime + * @return + */ + @Query(value = "select ci.city_name cityname,count(fp.id) from city ci left join fire_point fp " + + "on fp.county_code like concat('%',ci.city_code,'%') AND fp.add_time BETWEEN ?1 AND ?2 " + + "group by ci.city_name",nativeQuery = true) + List> selectNumByArea(String startTime,String endTime); + + /** + * 查询水体类型的id + * @return + */ + @Query(value = "select id from fire_point where land_type = '水体'",nativeQuery = true) + List selectId(); + + /** + * 批量删除水体 + * @param id + */ + @Modifying(clearAutomatically=true) + void deleteByIdIn(List id); + + /** + * 时间段查询火点信息 + * @param startTime + * @param endTime + * @return + */ + @Query(value = "select fire_code firecode,county_code countycode,county_name countyname,satellite_time satellitetime,latitude,longitude,land_type landtype,confidence,satellite_type satellitetype,fire_point_address address from fire_point fp where county_code = '371328' and fp.satellite_time between ?1 and ?2",nativeQuery = true) + List> selectByAddTime(String startTime,String endTime); +} diff --git a/src/main/java/com/xkrs/dao/FireTaskDao.java b/src/main/java/com/xkrs/dao/FireTaskDao.java new file mode 100644 index 0000000..964f4ca --- /dev/null +++ b/src/main/java/com/xkrs/dao/FireTaskDao.java @@ -0,0 +1,18 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.FireTask; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +/** + * @author xkrs + */ +public interface FireTaskDao extends JpaRepository, JpaSpecificationExecutor { + + /** + * 根据火点编码查询该条任务 + * @param fireCode + * @return + */ + FireTask findByTaskFireCode(String fireCode); +} diff --git a/src/main/java/com/xkrs/dao/FireTaskPhotoDao.java b/src/main/java/com/xkrs/dao/FireTaskPhotoDao.java new file mode 100644 index 0000000..141e4ed --- /dev/null +++ b/src/main/java/com/xkrs/dao/FireTaskPhotoDao.java @@ -0,0 +1,29 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.FireTaskPhoto; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +/** + * @author xkrs + */ +public interface FireTaskPhotoDao extends JpaRepository, JpaSpecificationExecutor { + + /** + * 根据火点编码查询图片 + * @param fireCode + * @return + */ + @Query(value = "select task_photo from fire_task_photo where photo_fire_code = :fireCode",nativeQuery = true) + List findPhotoPath(String fireCode); + + /** + * 通过火点编码查询图片的信息 + * @param fireCode + * @return + */ + List findAllByPhotoFireCode(String fireCode); +} diff --git a/src/main/java/com/xkrs/dao/ForestRangerDao.java b/src/main/java/com/xkrs/dao/ForestRangerDao.java new file mode 100644 index 0000000..174a473 --- /dev/null +++ b/src/main/java/com/xkrs/dao/ForestRangerDao.java @@ -0,0 +1,63 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.ForestRanger; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +/** + * @author xkrs + */ +public interface ForestRangerDao extends JpaRepository, JpaSpecificationExecutor { + + /** + * 根据市区县编码查询护林员的信息 + * @param rangerCountyCode + * @return + */ + ForestRanger findByRangerCountyCode(String rangerCountyCode); + + /** + * 根据手机号对护林员的位置进行修改 + * @param rangerLatitude + * @param rangerLongitude + * @param rangerPhone + */ + @Modifying(clearAutomatically=true) + @Query(value = "update forest_ranger set ranger_latitude = ?1,ranger_longitude = ?2 where ranger_phone = ?3",nativeQuery = true) + void updateLatAndLonByPhone(String rangerLatitude,String rangerLongitude,String rangerPhone); + + /** + * 根据手机号修改护林员的状态值 + * @param rangerPhone + * @param rangerType + */ + @Modifying(clearAutomatically=true) + @Query(value = "update forest_ranger set ranger_type = ?2 where ranger_phone = ?1",nativeQuery = true) + void updateRangerTypeByPhone(String rangerPhone,String rangerType); + + /** + * 根据手机号查询护林员的信息 + * @param rangerPhone + * @return + */ + ForestRanger findByRangerPhone(String rangerPhone); + + /** + * 根据区县编码查询该区县护林员的信息 + * @param rangerCountyCode + * @return + */ + List findAllByRangerCountyCode(String rangerCountyCode); + + /** + * 根据区县编码模糊查询护林员的信息 + * @param rangerCountyCode + * @return + */ + @Query(value = "select * from forest_ranger where ranger_county_code like CONCAT('%',:rangerCountyCode,'%')",nativeQuery = true) + List findAllsByRangerCountyCode(String rangerCountyCode); +} diff --git a/src/main/java/com/xkrs/dao/NationwideDao.java b/src/main/java/com/xkrs/dao/NationwideDao.java new file mode 100644 index 0000000..f429328 --- /dev/null +++ b/src/main/java/com/xkrs/dao/NationwideDao.java @@ -0,0 +1,40 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.Nationwide; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * @author XinYi Song + */ +@Component +public interface NationwideDao extends JpaRepository { + + /** + * 通过省编码查询市名称和编码 + * @param proCode + * @return + */ + @Query(value = "select DISTINCT city_name,city_code from nationwide where pro_code = ?",nativeQuery = true) + List> findCityByProCode(String proCode); + + /** + * 通过省编码查询县名称和编码 + * @param proCode + * @return + */ + @Query(value = "select county_name,county_code from nationwide where pro_code = ?",nativeQuery = true) + List> findCountyByProCode(String proCode); + + /** + * 通过市编码查询区县名称和编码 + * @param cityCode + * @return + */ + @Query(value = "select county_name,county_code from nationwide where city_code = ?",nativeQuery = true) + List> findCountyByCityCode(String cityCode); +} diff --git a/src/main/java/com/xkrs/dao/RelRoleAuthorityDao.java b/src/main/java/com/xkrs/dao/RelRoleAuthorityDao.java new file mode 100644 index 0000000..087c926 --- /dev/null +++ b/src/main/java/com/xkrs/dao/RelRoleAuthorityDao.java @@ -0,0 +1,22 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.RelRoleAuthorityEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * @author XinYi Song + */ +public interface RelRoleAuthorityDao extends JpaRepository { + + /** + * 根据userId查询出权限的id + * @param userId + * @return + */ + @Query(value = "select authority_id from rel_role_authority where user_id = ?",nativeQuery = true) + List selectAuthorityByUserId(@Param("userId") Integer userId); +} diff --git a/src/main/java/com/xkrs/dao/RelUserRoleDao.java b/src/main/java/com/xkrs/dao/RelUserRoleDao.java new file mode 100644 index 0000000..ebd8e96 --- /dev/null +++ b/src/main/java/com/xkrs/dao/RelUserRoleDao.java @@ -0,0 +1,10 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.RelUserRoleEntity; +import org.springframework.data.jpa.repository.JpaRepository; + +/** + * @author XinYi Song + */ +public interface RelUserRoleDao extends JpaRepository { +} diff --git a/src/main/java/com/xkrs/dao/SysAuthorityDao.java b/src/main/java/com/xkrs/dao/SysAuthorityDao.java new file mode 100644 index 0000000..34bcc6d --- /dev/null +++ b/src/main/java/com/xkrs/dao/SysAuthorityDao.java @@ -0,0 +1,32 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.SysAuthorityEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * SysAuthorityDao + * @author tajochen + */ +public interface SysAuthorityDao extends JpaRepository { + /** + * 查询权限实体列表根据用户名 Object[] + * @param userName 用户名 + * @return 用户实体 + */ + @Query(value = "SELECT a.id, a.authority_name, a.authority_name_zh, a.authority_desc " + + "FROM sys_authority a,rel_role_authority ra,sys_role r WHERE r.id = ra.role_id AND ra.authority_id = a.id AND r.id " + + "IN (SELECT r.id FROM sys_user u,sys_role r,rel_user_role ur " + + " WHERE u.user_name = :userName AND u.id = ur.user_id AND ur.role_id = r.id)", nativeQuery = true) + List selectByUserName(@Param("userName") String userName); + + /** + * 根据id批量查询权限信息 + * @param id + * @return + */ + List findAllByIdIn(List id); +} diff --git a/src/main/java/com/xkrs/dao/SysRoleDao.java b/src/main/java/com/xkrs/dao/SysRoleDao.java new file mode 100644 index 0000000..04e704d --- /dev/null +++ b/src/main/java/com/xkrs/dao/SysRoleDao.java @@ -0,0 +1,60 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.SysRoleEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * SysRoleDao + * @author tajochen + */ +public interface SysRoleDao extends JpaRepository { + + /** + * 查询用户角色列表根据用户id + * @param id + * @return + */ + @Query(value = "SELECT sys_role.id,sys_role.role_name,sys_role.role_name_zh,sys_role.role_desc " + + "FROM sys_role,rel_user_role " + + "WHERE sys_role.id = rel_user_role.role_id " + + "AND rel_user_role.user_id = :id ", nativeQuery = true) + List selectByUserId(@Param("id") Integer id); + + /** + * 查询用户角色列表根据用户名 + * @param userName + * @return + */ + @Query(value = "SELECT sys_role.id,sys_role.role_name,sys_role.role_name_zh,sys_role.role_desc " + + "FROM sys_role.ID = rel_user_role.role_id " + + "WHERE rel_user_role.user_id = sys_user.id " + + "AND rel_user_role.user_id = sys_user.id " + + "AND sys_user.user_name = :userName ", nativeQuery = true) + List selectByUserName(@Param("userName") String userName); + + +// /** +// * 根据用户名修改用户角色 +// */ +// @Modifying +// @Query(value = "UPDATE sys_user SET last_entry_time = now(), last_entry_ip = :ipAddress " + +// "WHERE user_name = :userName ;", nativeQuery = true) +// int updateUserRoleByUserName(@Param("userName") String userName); + + /** + * 添加用户角色根据用户名和角色名 + * @param userName + * @param roleName + * @return + */ + @Modifying + @Query(value = "INSERT INTO rel_user_role (id,role_id, user_id) " + + "SELECT nextval('rel_user_role_seq'),sys_role.ID,sys_user.ID FROM sys_role,sys_user " + + "WHERE sys_role.role_name = :roleName AND sys_user.user_name = :userName ", nativeQuery = true) + int insertRelUserRole(@Param("userName") String userName, @Param("roleName") String roleName); +} diff --git a/src/main/java/com/xkrs/dao/SysUserDao.java b/src/main/java/com/xkrs/dao/SysUserDao.java new file mode 100644 index 0000000..d4452a8 --- /dev/null +++ b/src/main/java/com/xkrs/dao/SysUserDao.java @@ -0,0 +1,165 @@ +package com.xkrs.dao; + +import com.xkrs.model.entity.SysUserEntity; +import com.xkrs.model.vo.SysUserVo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +/** + * SysUserDao + * @author tajochen + */ +public interface SysUserDao extends JpaRepository { + + /** + * 检查系统用户名是否存在 + * @param userName + * @return + */ + @Query(value = "SELECT COUNT(*) FROM sys_user WHERE user_name = :userName", nativeQuery = true) + int checkUserName(@Param("userName") String userName); + + /** + * 查找用户实体根据用户名 + * @param userName + * @return + */ + @Query(value = "SELECT * FROM sys_user WHERE user_name = :userName", nativeQuery = true) + SysUserEntity selectByUserName(@Param("userName") String userName); + + /** + * 根据用户名查询用户信息 + * @param userName + * @return + */ + SysUserEntity findByUserName(String userName); + + /** + * 更新用户登录信息 + * @param userName + * @param ipAddress + * @return + */ + @Modifying + @Query(value = "UPDATE sys_user SET last_entry_time = now(), last_entry_ip = :ipAddress " + + "WHERE user_name = :userName ;", nativeQuery = true) + int updateSysUserLogin(@Param("userName") String userName, @Param("ipAddress") String ipAddress); + + /** + * 软删除系统用户根据用户名 + * @param userName + * @return + */ + @Modifying + @Query(value = "UPDATE sys_user SET delete_flag = 1 " + + "WHERE user_name = :userName ;", nativeQuery = true) + int softDeleteSysUserByUserName(@Param("userName") String userName); + + /** + * 软删除系统用户根据id + * @param id + * @return + */ + @Modifying + @Query(value = "UPDATE sys_user SET delete_flag = 1 " + + "WHERE id = :id ;", nativeQuery = true) + int softDeleteGeneralUserById(@Param("id") Integer id); + + /** + * 删除系统用户(危险操作!) + * @param userName + * @return + */ + @Modifying + @Query(value = "DELETE FROM sys_user WHERE user_name = :userName ;", nativeQuery = true) + int deleteSysUser(@Param("userName") String userName); + + /** + * 查询用户信息 + * @return + */ + @Query(value = "select new com.xkrs.model.vo.SysUserVo (id,reallyName,telephone,countyCode,activeFlag,addTime,overTime,dayNum,accountType,countyName,lastEntryIp,loginNum,loginLastTime) " + + "from SysUserEntity") + List selectAll(); + + /** + * 根据用户名查询实体信息 + * @param userName + * @return + */ + @Query(value = "select new com.xkrs.model.vo.SysUserVo (id,reallyName,telephone,countyCode,activeFlag,addTime,overTime,dayNum,accountType,countyName,lastEntryIp,loginNum,loginLastTime) " + + "from SysUserEntity where userName = :userName") + SysUserVo selectUserByUserName(String userName); + + /** + * 启用 + * @param userId + */ + @Query(value = "update sys_user set active_flag = 0 where id = ?",nativeQuery = true) + @Modifying(clearAutomatically=true) + void updateEnable(Integer userId); + + /** + * 禁用 + * @param userId + */ + @Query(value = "update sys_user set active_flag = 1 where id = ?",nativeQuery = true) + @Modifying(clearAutomatically=true) + void updateDisable(Integer userId); + + /** + * 用户修改密码 + * @param userId + * @param newPassword + */ + @Query(value = "update sys_user set password = ?2 where id = ?1",nativeQuery = true) + @Modifying(clearAutomatically=true) + void updatePassword(Integer userId,String newPassword); + + /** + * 根据id查询用户的信息 + * @param userId + * @return + */ + @Query(value = "select * from sys_user where id = ?",nativeQuery = true) + SysUserEntity selectByUserId(Integer userId); + + /** + * 根据id修改账户的到期时间 + * @param userId + * @param overTime + */ + @Query(value = "update sys_user set over_time = ?2 where id = ?1",nativeQuery = true) + @Modifying(clearAutomatically=true) + void updateOverTime(Integer userId,String overTime); + + /** + * 将账户的期限修改为永久有效 + * @param userId + */ + @Query(value = "update sys_user set over_time = '永久' and day_num = 1 where id = ?",nativeQuery = true) + @Modifying(clearAutomatically=true) + void updateDayNum(Integer userId); + + /** + * 记录用户登录次数 + * @param userId + * @param loginNum + */ + @Query(value = "update sys_user set login_num = ?2 where id = ?1",nativeQuery = true) + @Modifying(clearAutomatically=true) + void updateLoginNum(Integer userId,Integer loginNum); + + /** + * 修改登陆时间 + * @param userId + * @param loginLastTime + */ + @Query(value = "update sys_user set login_last_time = ?2 where id = ?1",nativeQuery = true) + @Modifying(clearAutomatically=true) + void updateLoginLastTime(Integer userId,String loginLastTime); +} diff --git a/src/main/java/com/xkrs/model/entity/CityEntity.java b/src/main/java/com/xkrs/model/entity/CityEntity.java new file mode 100644 index 0000000..8739fc3 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/CityEntity.java @@ -0,0 +1,137 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * @author xkrs + */ +@Entity +@Table(name = "city") +public class CityEntity implements Serializable { + /** + * 主键id + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "city_seq_gen") + @SequenceGenerator(name = "city_seq_gen", sequenceName = "city_id_seq",allocationSize = 1) + private Integer id; + + /** + * 省名称 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String proName; + + /** + * 省编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String proCode; + + /** + * 市名称 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String cityName; + + /** + * 市编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String cityCode; + + /** + * 市纬度 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String cityLatitude; + + /** + * 市经度 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String cityLongitude; + + public CityEntity() { + } + + public CityEntity(Integer id, String proName, String proCode, String cityName, String cityCode, String cityLatitude, String cityLongitude) { + this.id = id; + this.proName = proName; + this.proCode = proCode; + this.cityName = cityName; + this.cityCode = cityCode; + this.cityLatitude = cityLatitude; + this.cityLongitude = cityLongitude; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getProName() { + return proName; + } + + public void setProName(String proName) { + this.proName = proName; + } + + public String getProCode() { + return proCode; + } + + public void setProCode(String proCode) { + this.proCode = proCode; + } + + public String getCityName() { + return cityName; + } + + public void setCityName(String cityName) { + this.cityName = cityName; + } + + public String getCityCode() { + return cityCode; + } + + public void setCityCode(String cityCode) { + this.cityCode = cityCode; + } + + public String getCityLatitude() { + return cityLatitude; + } + + public void setCityLatitude(String cityLatitude) { + this.cityLatitude = cityLatitude; + } + + public String getCityLongitude() { + return cityLongitude; + } + + public void setCityLongitude(String cityLongitude) { + this.cityLongitude = cityLongitude; + } + + @Override + public String toString() { + return "City{" + + "id=" + id + + ", proName='" + proName + '\'' + + ", proCode='" + proCode + '\'' + + ", cityName='" + cityName + '\'' + + ", cityCode='" + cityCode + '\'' + + ", cityLatitude='" + cityLatitude + '\'' + + ", cityLongitude='" + cityLongitude + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/CountyEntity.java b/src/main/java/com/xkrs/model/entity/CountyEntity.java new file mode 100644 index 0000000..a7a3c79 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/CountyEntity.java @@ -0,0 +1,104 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; + +/** + * @author XinYi Song + */ +@Entity +@Table(name = "county") +public class CountyEntity { + /** + * 主键id + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "county_seq_gen") + @SequenceGenerator(name = "county_seq_gen", sequenceName = "county_id_seq",allocationSize = 1) + private Integer id; + + /** + * 区县编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String countyCode; + + /** + * 区县名称 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String countyName; + + /** + * 城市编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String cityCode; + + /** + * 城市名称 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String cityName; + + public CountyEntity() { + } + + public CountyEntity(Integer id, String countyCode, String countyName, String cityCode, String cityName) { + this.id = id; + this.countyCode = countyCode; + this.countyName = countyName; + this.cityCode = cityCode; + this.cityName = cityName; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getCountyCode() { + return countyCode; + } + + public void setCountyCode(String countyCode) { + this.countyCode = countyCode; + } + + public String getCountyName() { + return countyName; + } + + public void setCountyName(String countyName) { + this.countyName = countyName; + } + + public String getCityCode() { + return cityCode; + } + + public void setCityCode(String cityCode) { + this.cityCode = cityCode; + } + + public String getCityName() { + return cityName; + } + + public void setCityName(String cityName) { + this.cityName = cityName; + } + + @Override + public String toString() { + return "CountyEntity{" + + "id=" + id + + ", countyCode='" + countyCode + '\'' + + ", countyName='" + countyName + '\'' + + ", cityCode='" + cityCode + '\'' + + ", cityName='" + cityName + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/FilePath.java b/src/main/java/com/xkrs/model/entity/FilePath.java new file mode 100644 index 0000000..6581133 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/FilePath.java @@ -0,0 +1,135 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; + +/** + * @author XinYi Song + */ +@Entity +@Table(name = "file_path") +public class FilePath { + + /** + * 主键id + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "file_path_seq_gen") + @SequenceGenerator(name = "file_path_seq_gen", sequenceName = "file_path_id_seq",allocationSize = 1) + private Integer id; + + /** + * 图片路径 + */ + @Column(length = 500,columnDefinition = "varchar(500)") + private String filePath; + + @Column(length = 88,columnDefinition = "varchar(88)") + private String fileName; + + @Column(length = 65,columnDefinition = "varchar(65)") + private String size; + + @Column(length = 85,columnDefinition = "varchar(85)") + private String mtime; + + @Column(length = 88,columnDefinition = "varchar(88)") + private String url; + + @Column(length = 85,columnDefinition = "varchar(85)") + private String md5; + + @Column(length = 65,columnDefinition = "varchar(65)") + private String scene; + + public FilePath() { + } + + public FilePath(Integer id, String filePath, String fileName, String size, String mtime, String url, String md5, String scene) { + this.id = id; + this.filePath = filePath; + this.fileName = fileName; + this.size = size; + this.mtime = mtime; + this.url = url; + this.md5 = md5; + this.scene = scene; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + public String getMtime() { + return mtime; + } + + public void setMtime(String mtime) { + this.mtime = mtime; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getMd5() { + return md5; + } + + public void setMd5(String md5) { + this.md5 = md5; + } + + public String getScene() { + return scene; + } + + public void setScene(String scene) { + this.scene = scene; + } + + @Override + public String toString() { + return "FilePath{" + + "id=" + id + + ", filePath='" + filePath + '\'' + + ", fileName='" + fileName + '\'' + + ", size='" + size + '\'' + + ", mtime='" + mtime + '\'' + + ", url='" + url + '\'' + + ", md5='" + md5 + '\'' + + ", scene='" + scene + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/FireAndRanger.java b/src/main/java/com/xkrs/model/entity/FireAndRanger.java new file mode 100644 index 0000000..ea549bf --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/FireAndRanger.java @@ -0,0 +1,151 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; + +/** + * 护林员和火点中间表 + * @author xkrs + */ +@Entity +@Table(name="fire_and_ranger") +public class FireAndRanger { + + /** + * 主键id + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fire_and_ranger_seq_gen") + @SequenceGenerator(name = "fire_and_ranger_seq_gen", sequenceName = "fire_and_ranger_id_seq",allocationSize = 1) + private Integer id; + + /** + * 护林员的账号(手机号作为和火点的标识) + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String rangerName; + + /** + * 火点编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String fireCode; + + /** + * 处理人 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String handler; + + /** + * 核查人 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String verifier; + + /** + * 处理时间(核查时间) + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String handlerTime; + + /** + * 结束时间 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String endTime; + + @Column(length = 32, columnDefinition = "varchar(32)") + private String progressType; + + public FireAndRanger() { + } + + public FireAndRanger(Integer id, String rangerName, String fireCode, String handler, String verifier, String handlerTime, String endTime, String progressType) { + this.id = id; + this.rangerName = rangerName; + this.fireCode = fireCode; + this.handler = handler; + this.verifier = verifier; + this.handlerTime = handlerTime; + this.endTime = endTime; + this.progressType = progressType; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getRangerName() { + return rangerName; + } + + public void setRangerName(String rangerName) { + this.rangerName = rangerName; + } + + public String getFireCode() { + return fireCode; + } + + public void setFireCode(String fireCode) { + this.fireCode = fireCode; + } + + public String getHandler() { + return handler; + } + + public void setHandler(String handler) { + this.handler = handler; + } + + public String getVerifier() { + return verifier; + } + + public void setVerifier(String verifier) { + this.verifier = verifier; + } + + public String getHandlerTime() { + return handlerTime; + } + + public void setHandlerTime(String handlerTime) { + this.handlerTime = handlerTime; + } + + public String getEndTime() { + return endTime; + } + + public void setEndTime(String endTime) { + this.endTime = endTime; + } + + public String getProgressType() { + return progressType; + } + + public void setProgressType(String progressType) { + this.progressType = progressType; + } + + @Override + public String toString() { + return "FireAndRanger{" + + "id=" + id + + ", rangerName='" + rangerName + '\'' + + ", fireCode='" + fireCode + '\'' + + ", handler='" + handler + '\'' + + ", verifier='" + verifier + '\'' + + ", handlerTime='" + handlerTime + '\'' + + ", endTime='" + endTime + '\'' + + ", progressType='" + progressType + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/FirePoint.java b/src/main/java/com/xkrs/model/entity/FirePoint.java new file mode 100644 index 0000000..77df8bf --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/FirePoint.java @@ -0,0 +1,258 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; + +/** + * @author XinYi Song + */ +@Entity +@Table(name="fire") +public class FirePoint { + /** + * 指定主键,建立自增序列,主键值取自序列 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fire_seq_gen") + @SequenceGenerator(name = "fire_seq_gen", sequenceName = "fire_id_seq",allocationSize = 1) + private Integer id; + + /** + * 火点编码 + */ + @Column( length = 32,unique = true,columnDefinition = "varchar(32)") + private String fireCode; + + /** + * 经度 + */ + private double longitude; + + /** + * 纬度 + */ + private double latitude; + + /** + * 省市区的编码 + */ + @Column(length = 32, columnDefinition = "varchar(32)") + private String countyCode; + + /** + * 省市区的名称 + */ + @Column( columnDefinition = "varchar(64)") + private String countyName; + + /** + * 卫星监测的时间 + */ + private String satelliteTime; + + /** + * 卫星的类型 + */ + @Column( columnDefinition = "varchar(64)") + private String satelliteType; + + /** + * 植被类型 + */ + @Column( columnDefinition = "varchar(64)") + private String landType; + + /** + * 添加的时间 + */ + private String addTime; + + /** + * 置信度 + */ + @Column(length = 32, columnDefinition = "varchar(32)") + private String confidence; + + /** + * 详细地址 + */ + private String firePointAddress; + + /** + * 火点状态 0 发现 1预警 2核查 -1,3结案 + */ + @Column(length = 32, columnDefinition = "varchar(32)") + private String fireType; + + /** + * 当前火点的图片 + */ + private String fireImage; + + /** + * 卫星影像图片 + */ + private String satelliteImage; + + + public FirePoint() { + } + + public FirePoint(Integer id, String fireCode, double longitude, double latitude, String countyCode, String countyName, String satelliteTime, String satelliteType, String landType, String addTime, String confidence, String firePointAddress, String fireType, String fireImage, String satelliteImage) { + this.id = id; + this.fireCode = fireCode; + this.longitude = longitude; + this.latitude = latitude; + this.countyCode = countyCode; + this.countyName = countyName; + this.satelliteTime = satelliteTime; + this.satelliteType = satelliteType; + this.landType = landType; + this.addTime = addTime; + this.confidence = confidence; + this.firePointAddress = firePointAddress; + this.fireType = fireType; + this.fireImage = fireImage; + this.satelliteImage = satelliteImage; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getFireCode() { + return fireCode; + } + + public void setFireCode(String fireCode) { + this.fireCode = fireCode; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public String getCountyCode() { + return countyCode; + } + + public void setCountyCode(String countyCode) { + this.countyCode = countyCode; + } + + public String getCountyName() { + return countyName; + } + + public void setCountyName(String countyName) { + this.countyName = countyName; + } + + public String getSatelliteTime() { + return satelliteTime; + } + + public void setSatelliteTime(String satelliteTime) { + this.satelliteTime = satelliteTime; + } + + public String getSatelliteType() { + return satelliteType; + } + + public void setSatelliteType(String satelliteType) { + this.satelliteType = satelliteType; + } + + public String getLandType() { + return landType; + } + + public void setLandType(String landType) { + this.landType = landType; + } + + public String getAddTime() { + return addTime; + } + + public void setAddTime(String addTime) { + this.addTime = addTime; + } + + public String getConfidence() { + return confidence; + } + + public void setConfidence(String confidence) { + this.confidence = confidence; + } + + public String getFirePointAddress() { + return firePointAddress; + } + + public void setFirePointAddress(String firePointAddress) { + this.firePointAddress = firePointAddress; + } + + public String getFireType() { + return fireType; + } + + public void setFireType(String fireType) { + this.fireType = fireType; + } + + public String getFireImage() { + return fireImage; + } + + public void setFireImage(String fireImage) { + this.fireImage = fireImage; + } + + public String getSatelliteImage() { + return satelliteImage; + } + + public void setSatelliteImage(String satelliteImage) { + this.satelliteImage = satelliteImage; + } + + @Override + public String toString() { + return "FirePointEntity{" + + "id=" + id + + ", fireCode='" + fireCode + '\'' + + ", longitude=" + longitude + + ", latitude=" + latitude + + ", countyCode='" + countyCode + '\'' + + ", countyName='" + countyName + '\'' + + ", satelliteTime='" + satelliteTime + '\'' + + ", satelliteType='" + satelliteType + '\'' + + ", landType='" + landType + '\'' + + ", addTime='" + addTime + '\'' + + ", confidence='" + confidence + '\'' + + ", firePointAddress='" + firePointAddress + '\'' + + ", fireType='" + fireType + '\'' + + ", fireImage='" + fireImage + '\'' + + ", satelliteImage='" + satelliteImage + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/FirePointEntity.java b/src/main/java/com/xkrs/model/entity/FirePointEntity.java new file mode 100644 index 0000000..f5f8fd7 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/FirePointEntity.java @@ -0,0 +1,261 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * @author XinYi Song + */ +@Entity +@Table(name="fire_point") +public class FirePointEntity implements Serializable { + + /** + * 指定主键,建立自增序列,主键值取自序列 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fire_point_seq_gen") + @SequenceGenerator(name = "fire_point_seq_gen", sequenceName = "fire_point_id_seq",allocationSize = 1) + private Integer id; + + /** + * 火点编码 + */ + @Column( length = 32,unique = true,columnDefinition = "varchar(32)") + private String fireCode; + + /** + * 经度 + */ + private double longitude; + + /** + * 纬度 + */ + private double latitude; + + /** + * 省市区的编码 + */ + @Column(length = 32, columnDefinition = "varchar(32)") + private String countyCode; + + /** + * 省市区的名称 + */ + @Column( columnDefinition = "varchar(64)") + private String countyName; + + /** + * 卫星监测的时间 + */ + private String satelliteTime; + + /** + * 卫星的类型 + */ + @Column( columnDefinition = "varchar(64)") + private String satelliteType; + + /** + * 植被类型 + */ + @Column( columnDefinition = "varchar(64)") + private String landType; + + /** + * 添加的时间 + */ + private String addTime; + + /** + * 置信度 + */ + @Column(length = 32, columnDefinition = "varchar(32)") + private String confidence; + + /** + * 详细地址 + */ + private String firePointAddress; + + /** + * 火点状态 0 发现 1预警 2核查 -1,3结案 + */ + @Column(length = 32, columnDefinition = "varchar(32)") + private String fireType; + + /** + * 当前火点的图片 + */ + private String fireImage; + + /** + * 卫星影像图片 + */ + private String satelliteImage; + + + + public FirePointEntity() { + } + + public FirePointEntity(Integer id, String fireCode, double longitude, double latitude, String countyCode, String countyName, String satelliteTime, String satelliteType, String landType, String addTime, String confidence, String firePointAddress, String fireType, String fireImage, String satelliteImage) { + this.id = id; + this.fireCode = fireCode; + this.longitude = longitude; + this.latitude = latitude; + this.countyCode = countyCode; + this.countyName = countyName; + this.satelliteTime = satelliteTime; + this.satelliteType = satelliteType; + this.landType = landType; + this.addTime = addTime; + this.confidence = confidence; + this.firePointAddress = firePointAddress; + this.fireType = fireType; + this.fireImage = fireImage; + this.satelliteImage = satelliteImage; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getFireCode() { + return fireCode; + } + + public void setFireCode(String fireCode) { + this.fireCode = fireCode; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public String getCountyCode() { + return countyCode; + } + + public void setCountyCode(String countyCode) { + this.countyCode = countyCode; + } + + public String getCountyName() { + return countyName; + } + + public void setCountyName(String countyName) { + this.countyName = countyName; + } + + public String getSatelliteTime() { + return satelliteTime; + } + + public void setSatelliteTime(String satelliteTime) { + this.satelliteTime = satelliteTime; + } + + public String getSatelliteType() { + return satelliteType; + } + + public void setSatelliteType(String satelliteType) { + this.satelliteType = satelliteType; + } + + public String getLandType() { + return landType; + } + + public void setLandType(String landType) { + this.landType = landType; + } + + public String getAddTime() { + return addTime; + } + + public void setAddTime(String addTime) { + this.addTime = addTime; + } + + public String getConfidence() { + return confidence; + } + + public void setConfidence(String confidence) { + this.confidence = confidence; + } + + public String getFirePointAddress() { + return firePointAddress; + } + + public void setFirePointAddress(String firePointAddress) { + this.firePointAddress = firePointAddress; + } + + public String getFireType() { + return fireType; + } + + public void setFireType(String fireType) { + this.fireType = fireType; + } + + public String getFireImage() { + return fireImage; + } + + public void setFireImage(String fireImage) { + this.fireImage = fireImage; + } + + public String getSatelliteImage() { + return satelliteImage; + } + + public void setSatelliteImage(String satelliteImage) { + this.satelliteImage = satelliteImage; + } + + @Override + public String toString() { + return "FirePointEntity{" + + "id=" + id + + ", fireCode='" + fireCode + '\'' + + ", longitude=" + longitude + + ", latitude=" + latitude + + ", countyCode='" + countyCode + '\'' + + ", countyName='" + countyName + '\'' + + ", satelliteTime='" + satelliteTime + '\'' + + ", satelliteType='" + satelliteType + '\'' + + ", landType='" + landType + '\'' + + ", addTime='" + addTime + '\'' + + ", confidence='" + confidence + '\'' + + ", firePointAddress='" + firePointAddress + '\'' + + ", fireType='" + fireType + '\'' + + ", fireImage='" + fireImage + '\'' + + ", satelliteImage='" + satelliteImage + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/FireTask.java b/src/main/java/com/xkrs/model/entity/FireTask.java new file mode 100644 index 0000000..e588755 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/FireTask.java @@ -0,0 +1,91 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * @author xkrs + * 任务表 + */ +@Entity +@Table(name = "fire_task") +public class FireTask implements Serializable { + + /** + * id 主键 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fire_task_seq_gen") + @SequenceGenerator(name = "fire_task_seq_gen", sequenceName = "fire_task_id_seq",allocationSize = 1) + private Integer id; + + /** + * 火点编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String taskFireCode; + + /** + * 任务描述 + */ + @Column(length = 2000, columnDefinition = "varchar(2000)") + private String taskInformation; + + /** + * 提交任务的时间 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String taskTime; + + public FireTask() { + } + + public FireTask(Integer id, String taskFireCode, String taskInformation, String taskTime) { + this.id = id; + this.taskFireCode = taskFireCode; + this.taskInformation = taskInformation; + this.taskTime = taskTime; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getTaskFireCode() { + return taskFireCode; + } + + public void setTaskFireCode(String taskFireCode) { + this.taskFireCode = taskFireCode; + } + + public String getTaskInformation() { + return taskInformation; + } + + public void setTaskInformation(String taskInformation) { + this.taskInformation = taskInformation; + } + + public String getTaskTime() { + return taskTime; + } + + public void setTaskTime(String taskTime) { + this.taskTime = taskTime; + } + + @Override + public String toString() { + return "FireTask{" + + "id=" + id + + ", taskFireCode='" + taskFireCode + '\'' + + ", taskInformation='" + taskInformation + '\'' + + ", taskTime='" + taskTime + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/FireTaskPhoto.java b/src/main/java/com/xkrs/model/entity/FireTaskPhoto.java new file mode 100644 index 0000000..d22cc6e --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/FireTaskPhoto.java @@ -0,0 +1,74 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * @author xkrs + * 任务和图片中间表 + */ +@Entity +@Table(name = "fire_task_photo") +public class FireTaskPhoto implements Serializable { + /** + * id 主键 + */ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "fire_task_photo_seq_gen") + @SequenceGenerator(name = "fire_task_photo_seq_gen", sequenceName = "fire_task_photo_id_seq",allocationSize = 1) + private Integer id; + + /** + * 火点编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String photoFireCode; + + /** + * 任务图片链接 + */ + @Column(length = 85, columnDefinition = "varchar(85)") + private String taskPhoto; + + public FireTaskPhoto() { + } + + public FireTaskPhoto(Integer id, String photoFireCode, String taskPhoto) { + this.id = id; + this.photoFireCode = photoFireCode; + this.taskPhoto = taskPhoto; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getPhotoFireCode() { + return photoFireCode; + } + + public void setPhotoFireCode(String photoFireCode) { + this.photoFireCode = photoFireCode; + } + + public String getTaskPhoto() { + return taskPhoto; + } + + public void setTaskPhoto(String taskPhoto) { + this.taskPhoto = taskPhoto; + } + + @Override + public String toString() { + return "FireTaskPhoto{" + + "id=" + id + + ", photoFireCode='" + photoFireCode + '\'' + + ", taskPhoto='" + taskPhoto + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/ForestRanger.java b/src/main/java/com/xkrs/model/entity/ForestRanger.java new file mode 100644 index 0000000..7ebfb2b --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/ForestRanger.java @@ -0,0 +1,155 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * @author xkrs + * 护林员信息 + */ +@Entity +@Table(name = "forest_ranger") +public class ForestRanger implements Serializable { + + /** + * 主键 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "forest_ranger_seq_gen") + @SequenceGenerator(name = "forest_ranger_seq_gen", sequenceName = "forest_ranger_id_seq",allocationSize = 1) + private Integer id; + + /** + * 护林员的姓名 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String rangerName; + + /** + * 护林员的电话 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String rangerPhone; + + /** + * 纬度 + */ + @Column(length = 85, columnDefinition = "varchar(85)") + private String rangerLatitude; + + /** + * 经度 + */ + @Column(length = 85, columnDefinition = "varchar(85)") + private String rangerLongitude; + + /** + * 护林员所在市区县 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String rangerCountyName; + + /** + * 市区县的编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String rangerCountyCode; + + /** + * 护林员的状态(0空闲 1正在执行任务) + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String rangerType; + + public ForestRanger() { + } + + public ForestRanger(Integer id, String rangerName, String rangerPhone, String rangerLatitude, String rangerLongitude, String rangerCountyName, String rangerCountyCode, String rangerType) { + this.id = id; + this.rangerName = rangerName; + this.rangerPhone = rangerPhone; + this.rangerLatitude = rangerLatitude; + this.rangerLongitude = rangerLongitude; + this.rangerCountyName = rangerCountyName; + this.rangerCountyCode = rangerCountyCode; + this.rangerType = rangerType; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getRangerName() { + return rangerName; + } + + public void setRangerName(String rangerName) { + this.rangerName = rangerName; + } + + public String getRangerPhone() { + return rangerPhone; + } + + public void setRangerPhone(String rangerPhone) { + this.rangerPhone = rangerPhone; + } + + public String getRangerLatitude() { + return rangerLatitude; + } + + public void setRangerLatitude(String rangerLatitude) { + this.rangerLatitude = rangerLatitude; + } + + public String getRangerLongitude() { + return rangerLongitude; + } + + public void setRangerLongitude(String rangerLongitude) { + this.rangerLongitude = rangerLongitude; + } + + public String getRangerCountyName() { + return rangerCountyName; + } + + public void setRangerCountyName(String rangerCountyName) { + this.rangerCountyName = rangerCountyName; + } + + public String getRangerCountyCode() { + return rangerCountyCode; + } + + public void setRangerCountyCode(String rangerCountyCode) { + this.rangerCountyCode = rangerCountyCode; + } + + public String getRangerType() { + return rangerType; + } + + public void setRangerType(String rangerType) { + this.rangerType = rangerType; + } + + @Override + public String toString() { + return "XkRsForestRanger{" + + "id=" + id + + ", rangerName='" + rangerName + '\'' + + ", rangerPhone='" + rangerPhone + '\'' + + ", rangerLatitude='" + rangerLatitude + '\'' + + ", rangerLongitude='" + rangerLongitude + '\'' + + ", rangerCountyName='" + rangerCountyName + '\'' + + ", rangerCountyCode='" + rangerCountyCode + '\'' + + ", rangerType='" + rangerType + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/LandEntity.java b/src/main/java/com/xkrs/model/entity/LandEntity.java new file mode 100644 index 0000000..3ca5d5b --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/LandEntity.java @@ -0,0 +1,56 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; + +/** + * @author HP + */ +@Entity +@Table(name = "land") +public class LandEntity { + /** + * 主键id + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "city_seq_gen") + @SequenceGenerator(name = "city_seq_gen", sequenceName = "city_id_seq",allocationSize = 1) + private Integer id; + + /** + * 植被名称 + */ + @Column(length = 32, columnDefinition = "varchar(32)") + private String landName; + + public LandEntity() { + } + + public LandEntity(Integer id, String landName) { + this.id = id; + this.landName = landName; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getLandName() { + return landName; + } + + public void setLandName(String landName) { + this.landName = landName; + } + + @Override + public String toString() { + return "LandEntity{" + + "id=" + id + + ", landName='" + landName + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/Nationwide.java b/src/main/java/com/xkrs/model/entity/Nationwide.java new file mode 100644 index 0000000..802c6bc --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/Nationwide.java @@ -0,0 +1,137 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; + +/** + * @author XinYi Song + * 全国省市区 + */ +@Entity +@Table(name = "nationwide") +public class Nationwide { + /** + * 主键id + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "nationwide_seq_gen") + @SequenceGenerator(name = "nationwide_seq_gen", sequenceName = "nationwide_id_seq",allocationSize = 1) + private Integer id; + + /** + * 省名称 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String proName; + + /** + * 省编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String proCode; + + /** + * 市名称 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String cityName; + + /** + * 市编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String cityCode; + + /** + * 区县名称 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String countyName; + + /** + * 区县编码 + */ + @Column(length = 65, columnDefinition = "varchar(65)") + private String countyCode; + + public Nationwide() { + } + + public Nationwide(Integer id, String proName, String proCode, String cityName, String cityCode, String countyName, String countyCode) { + this.id = id; + this.proName = proName; + this.proCode = proCode; + this.cityName = cityName; + this.cityCode = cityCode; + this.countyName = countyName; + this.countyCode = countyCode; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getProName() { + return proName; + } + + public void setProName(String proName) { + this.proName = proName; + } + + public String getProCode() { + return proCode; + } + + public void setProCode(String proCode) { + this.proCode = proCode; + } + + public String getCityName() { + return cityName; + } + + public void setCityName(String cityName) { + this.cityName = cityName; + } + + public String getCityCode() { + return cityCode; + } + + public void setCityCode(String cityCode) { + this.cityCode = cityCode; + } + + public String getCountyName() { + return countyName; + } + + public void setCountyName(String countyName) { + this.countyName = countyName; + } + + public String getCountyCode() { + return countyCode; + } + + public void setCountyCode(String countyCode) { + this.countyCode = countyCode; + } + + @Override + public String toString() { + return "Nationwide{" + + "id=" + id + + ", proName='" + proName + '\'' + + ", proCode='" + proCode + '\'' + + ", cityName='" + cityName + '\'' + + ", cityCode='" + cityCode + '\'' + + ", countyName='" + countyName + '\'' + + ", countyCode='" + countyCode + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/RelRoleAuthorityEntity.java b/src/main/java/com/xkrs/model/entity/RelRoleAuthorityEntity.java new file mode 100644 index 0000000..24121c1 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/RelRoleAuthorityEntity.java @@ -0,0 +1,71 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * RelRoleAuthority 表实体类 + * @author tajochen + */ +@Entity +@Table(name="rel_role_authority") +public class RelRoleAuthorityEntity implements Serializable { + + /** + * 指定主键,建立自增序列,主键值取自序列 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "rel_role_authority_seq_gen") + @SequenceGenerator(name = "rel_role_authority_seq_gen", sequenceName = "rel_role_authority_id_seq",allocationSize = 1) + private Integer id; + + @Column(nullable = false) + private Integer roleId; + + @Column(nullable = false) + private Integer authorityId; + + private Integer userId; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + + public Integer getAuthorityId() { + return authorityId; + } + + public void setAuthorityId(Integer authorityId) { + this.authorityId = authorityId; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + @Override + public String toString() { + return "RelRoleAuthorityEntity{" + + "id=" + id + + ", roleId=" + roleId + + ", authorityId=" + authorityId + + ", userId=" + userId + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/RelUserRoleEntity.java b/src/main/java/com/xkrs/model/entity/RelUserRoleEntity.java new file mode 100644 index 0000000..2f77c81 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/RelUserRoleEntity.java @@ -0,0 +1,60 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * RelUserRole 表实体类 + * @author tajochen + */ +@Entity +@Table(name="rel_user_role") +public class RelUserRoleEntity implements Serializable { + + /** + * 指定主键,建立自增序列,主键值取自序列 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "rel_user_role_seq_gen") + @SequenceGenerator(name = "rel_user_role_seq_gen", sequenceName = "rel_user_role_id_seq",allocationSize = 1) + private Integer id; + + @Column(nullable = false) + private Long userId; + + @Column(nullable = false) + private Integer roleId; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + + @Override + public String toString() { + return "RelUserRoleEntity{" + + "id=" + id + + ", userId=" + userId + + ", roleId=" + roleId + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/SysAuthorityEntity.java b/src/main/java/com/xkrs/model/entity/SysAuthorityEntity.java new file mode 100644 index 0000000..080d0f6 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/SysAuthorityEntity.java @@ -0,0 +1,72 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * SysAuthority 表实体类 + * @author tajochen + */ +@Entity +@Table(name="sys_authority") +public class SysAuthorityEntity implements Serializable { + + /** + * 指定主键,建立自增序列,主键值取自序列 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sys_authority_seq_gen") + @SequenceGenerator(name = "sys_authority_seq_gen", sequenceName = "sys_authority_id_seq",allocationSize = 1) + private Integer id; + + @Column(length = 64, nullable = false, unique = true,columnDefinition = "varchar(64)") + private String authorityName; + + @Column(length = 64, columnDefinition = "varchar(64)") + private String authorityNameZh; + + @Column(length = 128, columnDefinition = "varchar(128)") + private String authorityDesc; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getAuthorityName() { + return authorityName; + } + + public void setAuthorityName(String authorityName) { + this.authorityName = authorityName == null ? null : authorityName.trim(); + } + + public String getAuthorityNameZh() { + return authorityNameZh; + } + + public void setAuthorityNameZh(String authorityNameZh) { + this.authorityNameZh = authorityNameZh == null ? null : authorityNameZh.trim(); + } + + public String getAuthorityDesc() { + return authorityDesc; + } + + public void setAuthorityDesc(String authorityDesc) { + this.authorityDesc = authorityDesc == null ? null : authorityDesc.trim(); + } + + @Override + public String toString() { + return "SysAuthorityEntity{" + + "id=" + id + + ", authorityName='" + authorityName + '\'' + + ", authorityDesc='" + authorityDesc + '\'' + + ", authorityNameZh='" + authorityNameZh + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/SysRoleEntity.java b/src/main/java/com/xkrs/model/entity/SysRoleEntity.java new file mode 100644 index 0000000..32bd4c5 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/SysRoleEntity.java @@ -0,0 +1,72 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; + +/** + * SysRole 表实体类 + * @author tajochen + */ +@Entity +@Table(name="sys_role") +public class SysRoleEntity implements Serializable { + + /** + * 指定主键,建立自增序列,主键值取自序列 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sys_role_seq_gen") + @SequenceGenerator(name = "sys_role_seq_gen", sequenceName = "sys_role_id_seq",allocationSize = 1) + private Integer id; + + @Column(length = 32, nullable = false, unique = true,columnDefinition = "varchar(32)") + private String roleName; + + @Column(length = 32, columnDefinition = "varchar(32)") + private String roleNameZh; + + @Column(length = 64, columnDefinition = "varchar(64)") + private String roleDesc; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getRoleName() { + return roleName; + } + + public void setRoleName(String roleName) { + this.roleName = roleName == null ? null : roleName.trim(); + } + + public String getRoleDesc() { + return roleDesc; + } + + public void setRoleDesc(String roleDesc) { + this.roleDesc = roleDesc == null ? null : roleDesc.trim(); + } + + public String getRoleNameZh() { + return roleNameZh; + } + + public void setRoleNameZh(String roleNameZh) { + this.roleNameZh = roleNameZh == null ? null : roleNameZh.trim(); + } + + @Override + public String toString() { + return "SysRoleEntity{" + + "id=" + id + + ", roleName='" + roleName + '\'' + + ", roleNameZh='" + roleNameZh + '\'' + + ", roleDesc='" + roleDesc + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/entity/SysUserEntity.java b/src/main/java/com/xkrs/model/entity/SysUserEntity.java new file mode 100644 index 0000000..f2b7386 --- /dev/null +++ b/src/main/java/com/xkrs/model/entity/SysUserEntity.java @@ -0,0 +1,285 @@ +package com.xkrs.model.entity; + +import javax.persistence.*; +import java.io.Serializable; +import java.time.LocalDateTime; + + +/** + * SysUser 表实体类 + * @author tajochen + */ +@Entity +@Table(name="sys_user") +public class SysUserEntity implements Serializable { + + /** + * 指定主键,建立自增序列,主键值取自序列 + */ + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sys_user_seq_gen") + @SequenceGenerator(name = "sys_user_seq_gen", sequenceName = "sys_user_id_seq",allocationSize = 1) + private Integer id; + + /** + * 用户名 + */ + @Column(length = 16, nullable = false, unique = true, columnDefinition = "varchar(16)") + private String userName; + + /** + * 用户真实姓名 + */ + @Column(length = 32, columnDefinition = "varchar(32)") + private String reallyName; + + /** + * 密码 + */ + @Column(length = 64, nullable = false, columnDefinition = "varchar(64)") + private String password; + + @Column(length = 32, nullable = false, columnDefinition = "varchar(32)") + private String salt; + + @Column(length = 16, unique = true, columnDefinition = "varchar(16)") + private String telephone; + + @Column(length = 32, columnDefinition = "varchar(32)") + private String countyCode; + + @Column(columnDefinition = "varchar(192)") + private String signature; + + @Column(nullable = false) + private Integer activeFlag; + + @Column(nullable = false,columnDefinition = "smallint") + private Integer statusCode; + + @Column(nullable = false) + private String addTime; + + private LocalDateTime lastEntryTime; + + @Column(nullable = false) + private Integer deleteFlag; + + @Column(columnDefinition = "varchar(64)") + private String lastEntryIp; + + /** + * 账号的使用天数 + */ + private Integer dayNum; + + /** + * 账号到期的时间 + */ + private String overTime; + + /** + * 账号类别 + */ + @Column(length = 64,columnDefinition = "varchar(64)") + private String accountType; + + @Column(length = 64,columnDefinition = "varchar(64)") + private String countyName; + + /** + * 登录次数 + */ + private Integer loginNum; + + /** + * 用户最新登录时间 + */ + private String loginLastTime; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getReallyName() { + return reallyName; + } + + public void setReallyName(String reallyName) { + this.reallyName = reallyName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getSalt() { + return salt; + } + + public void setSalt(String salt) { + this.salt = salt; + } + + public String getTelephone() { + return telephone; + } + + public void setTelephone(String telephone) { + this.telephone = telephone; + } + + public String getCountyCode() { + return countyCode; + } + + public void setCountyCode(String countyCode) { + this.countyCode = countyCode; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public Integer getActiveFlag() { + return activeFlag; + } + + public void setActiveFlag(Integer activeFlag) { + this.activeFlag = activeFlag; + } + + public Integer getStatusCode() { + return statusCode; + } + + public void setStatusCode(Integer statusCode) { + this.statusCode = statusCode; + } + + public String getAddTime() { + return addTime; + } + + public void setAddTime(String addTime) { + this.addTime = addTime; + } + + public LocalDateTime getLastEntryTime() { + return lastEntryTime; + } + + public void setLastEntryTime(LocalDateTime lastEntryTime) { + this.lastEntryTime = lastEntryTime; + } + + public Integer getDeleteFlag() { + return deleteFlag; + } + + public void setDeleteFlag(Integer deleteFlag) { + this.deleteFlag = deleteFlag; + } + + public String getLastEntryIp() { + return lastEntryIp; + } + + public void setLastEntryIp(String lastEntryIp) { + this.lastEntryIp = lastEntryIp; + } + + public Integer getDayNum() { + return dayNum; + } + + public void setDayNum(Integer dayNum) { + this.dayNum = dayNum; + } + + public String getOverTime() { + return overTime; + } + + public void setOverTime(String overTime) { + this.overTime = overTime; + } + + public String getAccountType() { + return accountType; + } + + public void setAccountType(String accountType) { + this.accountType = accountType; + } + + public String getCountyName() { + return countyName; + } + + public void setCountyName(String countyName) { + this.countyName = countyName; + } + + public Integer getLoginNum() { + return loginNum; + } + + public void setLoginNum(Integer loginNum) { + this.loginNum = loginNum; + } + + public String getLoginLastTime() { + return loginLastTime; + } + + public void setLoginLastTime(String loginLastTime) { + this.loginLastTime = loginLastTime; + } + + @Override + public String toString() { + return "SysUserEntity{" + + "id=" + id + + ", userName='" + userName + '\'' + + ", reallyName='" + reallyName + '\'' + + ", password='" + password + '\'' + + ", salt='" + salt + '\'' + + ", telephone='" + telephone + '\'' + + ", countyCode='" + countyCode + '\'' + + ", signature='" + signature + '\'' + + ", activeFlag=" + activeFlag + + ", statusCode=" + statusCode + + ", addTime='" + addTime + '\'' + + ", lastEntryTime=" + lastEntryTime + + ", deleteFlag=" + deleteFlag + + ", lastEntryIp='" + lastEntryIp + '\'' + + ", dayNum=" + dayNum + + ", overTime='" + overTime + '\'' + + ", accountType='" + accountType + '\'' + + ", countyName='" + countyName + '\'' + + ", loginNum=" + loginNum + + ", loginLastTime='" + loginLastTime + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/qo/FirePointQo.java b/src/main/java/com/xkrs/model/qo/FirePointQo.java new file mode 100644 index 0000000..0117900 --- /dev/null +++ b/src/main/java/com/xkrs/model/qo/FirePointQo.java @@ -0,0 +1,185 @@ +package com.xkrs.model.qo; + +/** + * @author XinYi Song + * 火点参数类 + */ +public class FirePointQo { + + /** + * 火点编码 + */ + private String fireCode; + + /** + * 省市区的编码 + */ + private Integer countyCode; + + /** + * 省市区的名称 + */ + private String countyName; + + /** + * 卫星监测的时间戳 + */ + private Integer satelliteTimeTs; + + /** + * 经度 + */ + private Double longitude; + + /** + * 纬度 + */ + private Double latitude; + + /** + * 卫星类型 + */ + private String satelliteType; + + /** + * 植被类型 + */ + private String landtype; + + /** + * 置信度 + */ + private String confidence; + + /** + * 当前火点的图片 + */ + private String fireImage; + + /** + * 卫星影像图片 + */ + private String satelliteImage; + + public FirePointQo() { + } + + public FirePointQo(String fireCode, Integer countyCode, String countyName, Integer satelliteTimeTs, Double longitude, Double latitude, String satelliteType, String landtype, String confidence, String fireImage, String satelliteImage) { + this.fireCode = fireCode; + this.countyCode = countyCode; + this.countyName = countyName; + this.satelliteTimeTs = satelliteTimeTs; + this.longitude = longitude; + this.latitude = latitude; + this.satelliteType = satelliteType; + this.landtype = landtype; + this.confidence = confidence; + this.fireImage = fireImage; + this.satelliteImage = satelliteImage; + } + + public String getFireCode() { + return fireCode; + } + + public void setFireCode(String fireCode) { + this.fireCode = fireCode; + } + + public Integer getCountyCode() { + return countyCode; + } + + public void setCountyCode(Integer countyCode) { + this.countyCode = countyCode; + } + + public String getCountyName() { + return countyName; + } + + public void setCountyName(String countyName) { + this.countyName = countyName; + } + + public Integer getSatelliteTimeTs() { + return satelliteTimeTs; + } + + public void setSatelliteTimeTs(Integer satelliteTimeTs) { + this.satelliteTimeTs = satelliteTimeTs; + } + + public Double getLongitude() { + return longitude; + } + + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + public Double getLatitude() { + return latitude; + } + + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + public String getSatelliteType() { + return satelliteType; + } + + public void setSatelliteType(String satelliteType) { + this.satelliteType = satelliteType; + } + + public String getLandtype() { + return landtype; + } + + public void setLandtype(String landtype) { + this.landtype = landtype; + } + + public String getConfidence() { + return confidence; + } + + public void setConfidence(String confidence) { + this.confidence = confidence; + } + + public String getFireImage() { + return fireImage; + } + + public void setFireImage(String fireImage) { + this.fireImage = fireImage; + } + + public String getSatelliteImage() { + return satelliteImage; + } + + public void setSatelliteImage(String satelliteImage) { + this.satelliteImage = satelliteImage; + } + + @Override + public String toString() { + return "FirePointQo{" + + "fireCode='" + fireCode + '\'' + + ", countyCode=" + countyCode + + ", countyName='" + countyName + '\'' + + ", satelliteTimeTs=" + satelliteTimeTs + + ", longitude=" + longitude + + ", latitude=" + latitude + + ", satelliteType='" + satelliteType + '\'' + + ", landtype='" + landtype + '\'' + + ", confidence='" + confidence + '\'' + + ", fireImage='" + fireImage + '\'' + + ", satelliteImage='" + satelliteImage + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/qo/SysUserQo.java b/src/main/java/com/xkrs/model/qo/SysUserQo.java new file mode 100644 index 0000000..3128103 --- /dev/null +++ b/src/main/java/com/xkrs/model/qo/SysUserQo.java @@ -0,0 +1,168 @@ +package com.xkrs.model.qo; + +import com.xkrs.model.validation.SysUserQoInsert; +import com.xkrs.model.validation.SysUserQoUpdate; +import org.hibernate.validator.constraints.Range; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +/** + * SysUserQo + * @author tajochen + */ +public class SysUserQo { + + @NotNull( message = "{SysUser.id.blank}",groups={SysUserQoUpdate.class}) + private Integer id; + + @NotBlank(message = "{SysUser.userName.blank}",groups={SysUserQoInsert.class}) + @Size(min = 4,max = 16, message = "{SysUser.userName.length.illegal}",groups = {SysUserQoInsert.class, + SysUserQoUpdate.class}) + /** + * regexp = "^([A-Za-z0-9_]+)$" + */ + @Pattern(regexp = "^(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])\\d{8}$",message = "{SysUser.userName.format.illegal}",groups = {SysUserQoInsert.class, + SysUserQoUpdate.class}) + private String userName; + + @Size(max = 32, message = "{SysUser.nickName.length.illegal}",groups = {SysUserQoInsert.class, + SysUserQoUpdate.class}) + private String reallyName; + + @NotBlank(message = "{SysUser.password.blank}",groups = {SysUserQoInsert.class}) + @Size(min = 6,max = 16, message = "{SysUser.password.length.illegal}",groups = {SysUserQoInsert.class, + SysUserQoUpdate.class}) + @Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$",message = "{SysUser.password.format.illegal}", + groups = {SysUserQoInsert.class,SysUserQoUpdate.class}) + private String password; + + @Pattern(regexp = "^(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])\\d{8}$", + message = "{SysUser.telephone.format.illegal}",groups = {SysUserQoInsert.class,SysUserQoUpdate.class}) + private String telephone; + + @NotNull(message = "{SysUser.statusCode.illegal}",groups={SysUserQoUpdate.class}) + @Range(min=0,max=2,message = "{SysUser.statusCode.illegal}",groups = {SysUserQoInsert.class, SysUserQoUpdate.class}) + private Integer statusCode; + + private String countyCode; + + @NotNull(message = "{SysUser.deleteFlag.null}",groups={SysUserQoUpdate.class}) + private Integer deleteFlag; + + private Integer roleId; + + private Integer authorityId; + + private String verificationCode; + + private String accountType; + + private String countyName; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getReallyName() { + return reallyName; + } + + public void setReallyName(String reallyName) { + this.reallyName = reallyName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getTelephone() { + return telephone; + } + + public void setTelephone(String telephone) { + this.telephone = telephone; + } + + public Integer getStatusCode() { + return statusCode; + } + + public void setStatusCode(Integer statusCode) { + this.statusCode = statusCode; + } + + public String getCountyCode() { + return countyCode; + } + + public void setCountyCode(String countyCode) { + this.countyCode = countyCode; + } + + public Integer getDeleteFlag() { + return deleteFlag; + } + + public void setDeleteFlag(Integer deleteFlag) { + this.deleteFlag = deleteFlag; + } + + public Integer getRoleId() { + return roleId; + } + + public void setRoleId(Integer roleId) { + this.roleId = roleId; + } + + public Integer getAuthorityId() { + return authorityId; + } + + public void setAuthorityId(Integer authorityId) { + this.authorityId = authorityId; + } + + public String getVerificationCode() { + return verificationCode; + } + + public void setVerificationCode(String verificationCode) { + this.verificationCode = verificationCode; + } + + public String getAccountType() { + return accountType; + } + + public void setAccountType(String accountType) { + this.accountType = accountType; + } + + public String getCountyName() { + return countyName; + } + + public void setCountyName(String countyName) { + this.countyName = countyName; + } +} diff --git a/src/main/java/com/xkrs/model/validation/SysUserQoInsert.java b/src/main/java/com/xkrs/model/validation/SysUserQoInsert.java new file mode 100644 index 0000000..b7ce804 --- /dev/null +++ b/src/main/java/com/xkrs/model/validation/SysUserQoInsert.java @@ -0,0 +1,8 @@ +package com.xkrs.model.validation; + +/** + * SysUserQoInsert + * @author tajochen + */ +public interface SysUserQoInsert { +} diff --git a/src/main/java/com/xkrs/model/validation/SysUserQoUpdate.java b/src/main/java/com/xkrs/model/validation/SysUserQoUpdate.java new file mode 100644 index 0000000..2c1d87d --- /dev/null +++ b/src/main/java/com/xkrs/model/validation/SysUserQoUpdate.java @@ -0,0 +1,8 @@ +package com.xkrs.model.validation; + +/** + * SysUserQoUpdate + * @author tajochen + */ +public interface SysUserQoUpdate { +} diff --git a/src/main/java/com/xkrs/model/vo/AppPhotoVo.java b/src/main/java/com/xkrs/model/vo/AppPhotoVo.java new file mode 100644 index 0000000..3bd4dd2 --- /dev/null +++ b/src/main/java/com/xkrs/model/vo/AppPhotoVo.java @@ -0,0 +1,33 @@ +package com.xkrs.model.vo; + +import java.io.Serializable; + +/** + * @author xkrs + */ +public class AppPhotoVo implements Serializable { + + private String taskPhoto; + + public AppPhotoVo() { + } + + public AppPhotoVo(String taskPhoto) { + this.taskPhoto = taskPhoto; + } + + public String getTaskPhoto() { + return taskPhoto; + } + + public void setTaskPhoto(String taskPhoto) { + this.taskPhoto = taskPhoto; + } + + @Override + public String toString() { + return "AppPhotoVo{" + + "taskPhoto='" + taskPhoto + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/vo/AppTaskBodyVo.java b/src/main/java/com/xkrs/model/vo/AppTaskBodyVo.java new file mode 100644 index 0000000..bf7eb64 --- /dev/null +++ b/src/main/java/com/xkrs/model/vo/AppTaskBodyVo.java @@ -0,0 +1,70 @@ +package com.xkrs.model.vo; + +import java.io.Serializable; +import java.util.List; + +/** + * @author xkrs + */ +public class AppTaskBodyVo implements Serializable { + + private String fireCode; + + private String taskInformation; + + private String taskTime; + + private List taskFirePhoto; + + public AppTaskBodyVo() { + } + + public AppTaskBodyVo(String fireCode, String taskInformation, String taskTime, List taskFirePhoto) { + this.fireCode = fireCode; + this.taskInformation = taskInformation; + this.taskTime = taskTime; + this.taskFirePhoto = taskFirePhoto; + } + + public String getFireCode() { + return fireCode; + } + + public void setFireCode(String fireCode) { + this.fireCode = fireCode; + } + + public String getTaskInformation() { + return taskInformation; + } + + public void setTaskInformation(String taskInformation) { + this.taskInformation = taskInformation; + } + + public String getTaskTime() { + return taskTime; + } + + public void setTaskTime(String taskTime) { + this.taskTime = taskTime; + } + + public List getTaskFirePhoto() { + return taskFirePhoto; + } + + public void setTaskFirePhoto(List taskFirePhoto) { + this.taskFirePhoto = taskFirePhoto; + } + + @Override + public String toString() { + return "AppTaskBodyVo{" + + "fireCode='" + fireCode + '\'' + + ", taskInformation='" + taskInformation + '\'' + + ", taskTime='" + taskTime + '\'' + + ", taskFirePhoto=" + taskFirePhoto + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/vo/FileServerResultVo.java b/src/main/java/com/xkrs/model/vo/FileServerResultVo.java new file mode 100644 index 0000000..77fb534 --- /dev/null +++ b/src/main/java/com/xkrs/model/vo/FileServerResultVo.java @@ -0,0 +1,67 @@ +package com.xkrs.model.vo; + +import java.io.Serializable; + +/** + * FileServerResultVo 文件服务器查询结果 + * @author tajochen + */ +public class FileServerResultVo implements Serializable { + + /** + * 状态信息 + */ + String status; + + /** + * 提示信息 + */ + String message; + + /** + * 数据 + */ + T data; + + public FileServerResultVo() { + } + + public FileServerResultVo(String status, String msg, T data) { + this.status = status; + this.message = msg; + this.data = data; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + @Override + public String toString() { + return "FileServerResultVo{" + + "status='" + status + '\'' + + ", message='" + message + '\'' + + ", data=" + data + + '}'; + } +} diff --git a/src/main/java/com/xkrs/model/vo/SysUserVo.java b/src/main/java/com/xkrs/model/vo/SysUserVo.java new file mode 100644 index 0000000..763edb7 --- /dev/null +++ b/src/main/java/com/xkrs/model/vo/SysUserVo.java @@ -0,0 +1,156 @@ +package com.xkrs.model.vo; + +import java.io.Serializable; + +/** + * SysUserVo + * @Author tajochen + */ +public class SysUserVo implements Serializable { + private Integer id; + + private String reallyName; + + private String telephone; + + private String countyCode; + + private Integer activeFlag; + + private String addTime; + + private String overTime; + + private Integer dayNum; + + private String accountType; + + private String countyName; + + private String lastEntryIp; + + private Integer loginNum; + + private String loginLastTime; + + public SysUserVo(Integer id, String reallyName, String telephone, String countyCode, Integer activeFlag, String addTime, String overTime, Integer dayNum, String accountType, String countyName, String lastEntryIp, Integer loginNum, String loginLastTime) { + this.id = id; + this.reallyName = reallyName; + this.telephone = telephone; + this.countyCode = countyCode; + this.activeFlag = activeFlag; + this.addTime = addTime; + this.overTime = overTime; + this.dayNum = dayNum; + this.accountType = accountType; + this.countyName = countyName; + this.lastEntryIp = lastEntryIp; + this.loginNum = loginNum; + this.loginLastTime = loginLastTime; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getReallyName() { + return reallyName; + } + + public void setReallyName(String reallyName) { + this.reallyName = reallyName; + } + + public String getTelephone() { + return telephone; + } + + public void setTelephone(String telephone) { + this.telephone = telephone; + } + + public String getCountyCode() { + return countyCode; + } + + public void setCountyCode(String countyCode) { + this.countyCode = countyCode; + } + + public Integer getActiveFlag() { + return activeFlag; + } + + public void setActiveFlag(Integer activeFlag) { + this.activeFlag = activeFlag; + } + + public String getAddTime() { + return addTime; + } + + public void setAddTime(String addTime) { + this.addTime = addTime; + } + + public String getOverTime() { + return overTime; + } + + public void setOverTime(String overTime) { + this.overTime = overTime; + } + + public Integer getDayNum() { + return dayNum; + } + + public void setDayNum(Integer dayNum) { + this.dayNum = dayNum; + } + + public String getAccountType() { + return accountType; + } + + public void setAccountType(String accountType) { + this.accountType = accountType; + } + + public String getCountyName() { + return countyName; + } + + public void setCountyName(String countyName) { + this.countyName = countyName; + } + + public String getLastEntryIp() { + return lastEntryIp; + } + + public void setLastEntryIp(String lastEntryIp) { + this.lastEntryIp = lastEntryIp; + } + + public Integer getLoginNum() { + return loginNum; + } + + public void setLoginNum(Integer loginNum) { + this.loginNum = loginNum; + } + + public String getLoginLastTime() { + return loginLastTime; + } + + public void setLoginLastTime(String loginLastTime) { + this.loginLastTime = loginLastTime; + } +} + diff --git a/src/main/java/com/xkrs/service/FireAndRangerService.java b/src/main/java/com/xkrs/service/FireAndRangerService.java new file mode 100644 index 0000000..9edd104 --- /dev/null +++ b/src/main/java/com/xkrs/service/FireAndRangerService.java @@ -0,0 +1,34 @@ +package com.xkrs.service; + +import java.io.UnsupportedEncodingException; + +/** + * @author xkrs + */ +public interface FireAndRangerService { + + /** + * 将火点分配给护林员 + * @param token + * @param rangerName + * @param fireCode + * @param handler + * @param verifier + * @return + */ + String addFireAndRanger(String rangerName, String fireCode, String handler, String verifier, String token) throws UnsupportedEncodingException; + + /** + * 护林员查看自己的火点任务 + * @param token + * @return + */ + String selectFireInformation(String token); + + /** + * 根据火点编码查询处理的信息 + * @param fireCode + * @return + */ + String findFireAndRangerByFireCode(String fireCode, String token) throws Exception; +} diff --git a/src/main/java/com/xkrs/service/FirePointService.java b/src/main/java/com/xkrs/service/FirePointService.java new file mode 100644 index 0000000..d9e95cc --- /dev/null +++ b/src/main/java/com/xkrs/service/FirePointService.java @@ -0,0 +1,167 @@ +package com.xkrs.service; + +import com.xkrs.model.entity.FirePoint; +import com.xkrs.model.entity.FirePointEntity; +import com.xkrs.model.qo.FirePointQo; +import com.xkrs.model.vo.AppTaskBodyVo; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * @author XinYi Song + */ +public interface FirePointService { + + /** + * 添加火点信息 + * @param firePointQo + * @return + */ + FirePointEntity insertFirePoint(FirePointQo firePointQo) throws IOException; + + /** + * 根据时间段查询火点信息 + * @param startAddTime + * @param endTime + * @return + */ + String findByAddTime(String startAddTime, String endTime); + + /** + * 查询今天的火点信息 + * @param + * @return + */ + List selectTodayFirePoint(String countyCode); + + /** + * 动态多条件查询火点信息(省) + * @param proCode + * @param cityCode + * @param satelliteType + * @param landType + * @param startTime + * @param endTime + * @return + */ + List selectFirePoint(String proCode,String cityCode,String satelliteType,String landType,String startTime,String endTime); + + + /** + * 动态多条件查询火点信息(市) + * @param cityCodeOne 市编码 + * @param cityCode 县编码 + * @param satelliteType + * @param landType + * @param startTime + * @param endTime + * @return + */ + List selectFirePointByCity(String cityCodeOne,String cityCode,String satelliteType,String landType,String startTime,String endTime); + + /** + * 动态多条件查询火点信息(县) + * @param cityCode 县编码 + * @param satelliteType + * @param landType + * @param startTime + * @param endTime + * @return + */ + List selectFirePointByCounty(String cityCode,String satelliteType,String landType,String startTime,String endTime); + + /** + * 根据火点编码修改火点的状态(预警) + * @param fireCode + * @param fireType + * @param token + * @return + */ + String updateTypeByFireCode(String fireCode,String fireType,String token); + + /** + * 提交核查任务信息 + * @param files + * @param appTaskBodyVo + * @return + * @throws IOException + */ + String insertAppTask(MultipartFile[] files, AppTaskBodyVo appTaskBodyVo) throws IOException; + + /** + * 根据火点编码查询任务信息 + * @param fireCode + * @param + * @return + * @throws Exception + */ + String selectAppTask(String fireCode) throws Exception; + + /** + * 查询近一周天的火点信息 + * @return + */ + List selectFirePointBetweenSeven(); + + /** + * 查询近一个月的火点信息 + * @return + */ + List selectFirePointByMonth(String countyCode); + + /** + * 查询近一个月的火点数量 + * @return + */ + String selectFirePointNumMonth(); + + /** + * 查询近一天的火点数量 + * @return + */ + String selectFirePointNumDay(); + + /** + * 查询 + * @return + */ + String selectFirePointNumWeek(); + + /** + * 查询该省所有的市 + * @param code + * @return + */ + List> selectCityName(String code); + + /** + * 查询市包含的区县和编码 + * @param code + * @return + */ + List> selectCountyName(String code); + + /** + * 测试插入火点信息 + * @param firePointQo + * @return + */ + FirePoint insertFireTest(FirePointQo firePointQo); + + /** + * 导入全国省市区 + * @param file + * @throws Exception + */ + void importCityExcel(MultipartFile file) throws Exception; + + /** + * 查询今日火点信息(测试) + * @param countyCode + * @return + */ + List selectTodayFire(String countyCode); +} diff --git a/src/main/java/com/xkrs/service/ForestRangerService.java b/src/main/java/com/xkrs/service/ForestRangerService.java new file mode 100644 index 0000000..fef04be --- /dev/null +++ b/src/main/java/com/xkrs/service/ForestRangerService.java @@ -0,0 +1,31 @@ +package com.xkrs.service; + +/** + * @author xkrs + */ +public interface ForestRangerService { + + /** + * 根据区县编码查询护林员的信息 + * @param rangerCountyCode + * @return + */ + String findByRangerCountyCode(String rangerCountyCode); + + /** + * 根据区县编码查询该区县所有护林员的信息 + * @param countyCode + * @param token + * @return + */ + String findAllByRangerCountyCode(String countyCode, String token); + + /** + * 根据手机号修改用户位置 + * @param rangerLatitude + * @param rangerLongitude + * @param rangerPhone + * @return + */ + String updateLatAndLonByPhone(String rangerLatitude,String rangerLongitude,String rangerPhone); +} diff --git a/src/main/java/com/xkrs/service/RedisService.java b/src/main/java/com/xkrs/service/RedisService.java new file mode 100644 index 0000000..e0a14c9 --- /dev/null +++ b/src/main/java/com/xkrs/service/RedisService.java @@ -0,0 +1,992 @@ +package com.xkrs.service; + +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * @ClassName: RedisService + */ +@Service +public class RedisService { + + @Resource + private RedisTemplate redisTemplate; + /** -------------------key相关操作--------------------- */ + + /** + * 是否存在key + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.Boolean + * @throws + */ + public Boolean hasKey(String key) { + if (null==key){ + return false; + } + return redisTemplate.hasKey(key); + } + + /** + * 删除key + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return Boolean 成功返回true 失败返回false + * @throws + */ + public Boolean delete(String key) { + if (null==key){ + return false; + } + return redisTemplate.delete(key); + } + + /** + * 批量删除key + * @Author: 小霍 + * @CreateDate: 2019/8/27 20:27 + * @UpdateUser: + * @UpdateDate: 2019/8/27 20:27 + * @Version: 0.0.1 + * @param keys + * @return Long 返回成功删除key的数量 + * @throws + */ + public Long delete(Collection keys) { + return redisTemplate.delete(keys); + } + + + /** + * 设置过期时间 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param timeout +  * @param unit + * @return java.lang.Boolean + * @throws + */ + public Boolean expire(String key, long timeout, TimeUnit unit) { + if (null==key||null==unit){ + return false; + } + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 查找匹配的key + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param pattern + * @return java.util.Set + * @throws + */ + public Set keys(String pattern) { + if (null==pattern){ + return null; + } + return redisTemplate.keys(pattern); + } + + + /** + * 移除 key 的过期时间,key 将持久保持 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.Boolean + * @throws + */ + public Boolean persist(String key) { + if (null==key){ + return false; + } + return redisTemplate.persist(key); + } + + /** + * 返回 key 的剩余的过期时间 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param unit + * @return java.lang.Long 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以秒为单位,返回 key的剩余生存时间 + * @throws + */ + public Long getExpire(String key, TimeUnit unit) { + if(null==key||null==unit){ +// throw new BusinessException(4001004,"key or TomeUnit 不能为空"); + } + return redisTemplate.getExpire(key, unit); + } + + //*************String相关数据类型*************************** + /** + * 设置指定 key 的值 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param value + * @return void + * @throws + */ + public void set(String key, Object value) { + + if(null==key||null==value){ + return; + } + redisTemplate.opsForValue().set(key, value); + } + /** + * 设置key 的值 并设置过期时间 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param value +  * @param time +  * @param unit + * @return void + * @throws + */ + public void set(String key,Object value,long time,TimeUnit unit){ + + if(null==key||null==value||null==unit){ + return; + } + redisTemplate.opsForValue().set(key,value,time,unit); + } + /** + * 设置key 的值 并设置过期时间 + * key存在 不做操作返回false + * key不存在设置值返回true + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param value +  * @param time +  * @param unit + * @return java.lang.Boolean + * @throws + */ + public Boolean setifAbsen(String key,Object value,long time,TimeUnit unit){ + + if(null==key||null==value||null==unit){ +// throw new BusinessException(4001004,"kkey、value、unit都不能为空"); + } + return redisTemplate.opsForValue().setIfAbsent(key,value,time,unit); + } + /** + * 获取指定Key的Value。如果与该Key关联的Value不是string类型,Redis将抛出异常, + * 因为GET命令只能用于获取string Value,如果该Key不存在,返回null + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.Object + * @throws + */ + public Object get(String key){ + + if(null==key){ + return null; + } + return redisTemplate.opsForValue().get(key); + } + /** + * 很明显先get再set就说先获取key值对应的value然后再set 新的value 值。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param value + * @return java.lang.Object + * @throws + */ + public Object getSet(String key,Object value){ + + if(null==key){ + return null; + } + return redisTemplate.opsForValue().getAndSet(key,value); + } + /** + * 通过批量的key获取批量的value + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param keys + * @return java.util.List + * @throws + */ + public List mget(Collection keys){ + + if(null==keys){ + return Collections.emptyList(); + } + return redisTemplate.opsForValue().multiGet(keys); + } + /** + * 将指定Key的Value原子性的增加increment。如果该Key不存在,其初始值为0,在incrby之后其值为increment。 + * 如果Value的值不能转换为整型值,如Hi,该操作将执行失败并抛出相应异常。操作成功则返回增加后的value值。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param increment + * @return long + * @throws + */ + public long incrby(String key,long increment){ + if(null==key){ +// throw new BusinessException(4001004,"key不能为空"); + } + return redisTemplate.opsForValue().increment(key,increment); + } + /** + * + * 将指定Key的Value原子性的减少decrement。如果该Key不存在,其初始值为0, + * 在decrby之后其值为-decrement。如果Value的值不能转换为整型值, + * 如Hi,该操作将执行失败并抛出相应的异常。操作成功则返回减少后的value值。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param decrement + * @return java.lang.Long + * @throws + */ + public Long decrby(String key,long decrement){ + if(null==key){ +// throw new BusinessException(4001004,"key不能为空"); + } + return redisTemplate.opsForValue().decrement(key,decrement); + } + /** + * 如果该Key已经存在,APPEND命令将参数Value的数据追加到已存在Value的末尾。如果该Key不存在, + * APPEND命令将会创建一个新的Key/Value。返回追加后Value的字符串长度。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param value + * @return java.lang.Integer + * @throws + */ + public Integer append(String key,String value){ + if(key==null){ +// throw new BusinessException(4001004,"key不能为空"); + } + return redisTemplate.opsForValue().append(key,value); + } +//******************hash数据类型********************* + /** + * 通过key 和 field 获取指定的 value + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param field + * @return java.lang.Object + * @throws + */ + public Object hget(String key, Object field) { + if(null==key||null==field){ + return null; + } + return redisTemplate.opsForHash().get(key,field); + } + + /** + * 为指定的Key设定Field/Value对,如果Key不存在,该命令将创建新Key以用于存储参数中的Field/Value对, + * 如果参数中的Field在该Key中已经存在,则用新值覆盖其原有值。 + * 返回1表示新的Field被设置了新值,0表示Field已经存在,用新值覆盖原有值。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param field + * @param value + * @return + * @throws + */ + public void hset(String key, Object field, Object value) { + if(null==key||null==field){ + return; + } + redisTemplate.opsForHash().put(key,field,value); + } + + /** + * 判断指定Key中的指定Field是否存在,返回true表示存在,false表示参数中的Field或Key不存在。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param field + * @return java.lang.Boolean + * @throws + */ + public Boolean hexists(String key, Object field) { + if(null==key||null==field){ + return false; + } + return redisTemplate.opsForHash().hasKey(key,field); + } + + /** + * 从指定Key的Hashes Value中删除参数中指定的多个字段,如果不存在的字段将被忽略, + * 返回实际删除的Field数量。如果Key不存在,则将其视为空Hashes,并返回0。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param fields + * @return java.lang.Long + * @throws + */ + public Long hdel(String key, Object... fields) { + if(null==key||null==fields||fields.length==0){ + return 0L; + } + return redisTemplate.opsForHash().delete(key,fields); + } + + + /** + * 通过key获取所有的field和value + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.util.Map + * @throws + */ + public Map hgetall(String key) { + if(key==null){ + return null; + } + return redisTemplate.opsForHash().entries(key); + } + + /** + * 逐对依次设置参数中给出的Field/Value对。如果其中某个Field已经存在,则用新值覆盖原有值。 + * 如果Key不存在,则创建新Key,同时设定参数中的Field/Value。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param hash + * @return + * @throws + */ + public void hmset(String key, Map hash) { + + if(null==key||null==hash){ + return; + } + redisTemplate.opsForHash().putAll(key,hash); + } + + /** + * 获取和参数中指定Fields关联的一组Values,其返回顺序等同于Fields的请求顺序。 + * 如果请求的Field不存在,其值对应的value为null。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param fields + * @return java.util.List + * @throws + */ + public List hmget(String key, Collection fields) { + + if(null==key||null==fields){ + return null; + } + + return redisTemplate.opsForHash().multiGet(key,fields); + } + + /** + * 对应key的字段自增相应的值 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param field +  * @param increment + * @return java.lang.Long + * @throws + */ + public Long hIncrBy(String key,Object field,long increment){ + if (null==key||null==field){ +// throw new BusinessException(4001004,"key or field 不能为空"); + } + return redisTemplate.opsForHash().increment(key,field,increment); + + } + //***************List数据类型*************** + /** + * 向列表左边添加元素。如果该Key不存在,该命令将在插入之前创建一个与该Key关联的空链表,之后再将数据从链表的头部插入。 + * 如果该键的Value不是链表类型,该命令将将会抛出相关异常。操作成功则返回插入后链表中元素的数量。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param strs 可以使一个string 也可以使string数组 + * @return java.lang.Long 返回操作的value个数 + * @throws + */ + public Long lpush(String key, Object... strs) { + if(null==key){ + return 0L; + } + return redisTemplate.opsForList().leftPushAll(key,strs); + } + + /** + * 向列表右边添加元素。如果该Key不存在,该命令将在插入之前创建一个与该Key关联的空链表,之后再将数据从链表的尾部插入。 + * 如果该键的Value不是链表类型,该命令将将会抛出相关异常。操作成功则返回插入后链表中元素的数量。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param strs 可以使一个string 也可以使string数组 + * @return java.lang.Long 返回操作的value个数 + * @throws + */ + public Long rpush(String key, Object... strs) { + if(null==key){ + return 0L; + } + return redisTemplate.opsForList().rightPushAll(key,strs); + } + /** + * 返回并弹出指定Key关联的链表中的第一个元素,即头部元素。如果该Key不存在, + * 返回nil。LPOP命令执行两步操作:第一步是将列表左边的元素从列表中移除,第二步是返回被移除的元素值。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.Object + * @throws + */ + public Object lpop(String key) { + if(null==key){ + return null; + } + return redisTemplate.opsForList().leftPop(key); + } + + /** + * 返回并弹出指定Key关联的链表中的最后一个元素,即头部元素。如果该Key不存在,返回nil。 + * RPOP命令执行两步操作:第一步是将列表右边的元素从列表中移除,第二步是返回被移除的元素值。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.Object + * @throws + */ + public Object rpop(String key) { + if(null==key){ + return null; + } + return redisTemplate.opsForList().rightPop(key); + } + + /** + *该命令的参数start和end都是0-based。即0表示链表头部(leftmost)的第一个元素。 + * 其中start的值也可以为负值,-1将表示链表中的最后一个元素,即尾部元素,-2表示倒数第二个并以此类推。 + * 该命令在获取元素时,start和end位置上的元素也会被取出。如果start的值大于链表中元素的数量, + * 空链表将会被返回。如果end的值大于元素的数量,该命令则获取从start(包括start)开始,链表中剩余的所有元素。 + * 注:Redis的列表起始索引为0。显然,LRANGE numbers 0 -1 可以获取列表中的所有元素。返回指定范围内元素的列表。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param start + * @param end + * @return java.util.List + * @throws + */ + public List lrange(String key, long start, long end) { + if(null==key){ + return null; + } + return redisTemplate.opsForList().range(key,start,end); + } + + /** + * 让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。 + * 下标 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。 + * 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param start + * @param end + * @return + * @throws + */ + public void ltrim(String key, long start, long end) { + if(null==key){ + return; + } + redisTemplate.opsForList().trim(key,start,end); + } + + /** + * 该命令将返回链表中指定位置(index)的元素,index是0-based,表示从头部位置开始第index的元素, + * 如果index为-1,表示尾部元素。如果与该Key关联的不是链表,该命令将返回相关的错误信息。 如果超出index返回这返回nil。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @param index + * @return java.lang.Object + * @throws + */ + public Object lindex(String key, long index) { + if(null==key){ + return null; + } + return redisTemplate.opsForList().index(key,index); + } + + /** + * 返回指定Key关联的链表中元素的数量,如果该Key不存在,则返回0。如果与该Key关联的Value的类型不是链表,则抛出相关的异常。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.Long + * @throws + */ + public Long llen(String key) { + + if(null==key){ + return 0L; + } + return redisTemplate.opsForList().size(key); + } + //***************Set数据类型************* + /** + * 如果在插入的过程用,参数中有的成员在Set中已经存在,该成员将被忽略,而其它成员仍将会被正常插入。 + * 如果执行该命令之前,该Key并不存在,该命令将会创建一个新的Set,此后再将参数中的成员陆续插入。返回实际插入的成员数量。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param members 可以是一个String 也可以是一个String数组 + * @return java.lang.Long 添加成功的个数 + * @throws + */ + public Long sadd(String key, Object... members) { + if (null==key){ + return 0L; + } + return redisTemplate.opsForSet().add(key, members); + + } + + /** + * 返回Set中成员的数量,如果该Key并不存在,返回0。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.Long + * @throws + */ + public Long scard(String key) { + if (null==key){ + return 0L; + } + return redisTemplate.opsForSet().size(key); + + } + + /** + * 判断参数中指定成员是否已经存在于与Key相关联的Set集合中。返回true表示已经存在,false表示不存在,或该Key本身并不存在。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param member + * @return java.lang.Boolean + * @throws + */ + public Boolean sismember(String key, Object member) { + if (null==key){ + return false; + } + return redisTemplate.opsForSet().isMember(key,member); + + } + + /** + * 和SPOP一样,随机的返回Set中的一个成员,不同的是该命令并不会删除返回的成员。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.String + * @throws + */ + public Object srandmember(String key) { + if (null==key){ + return null; + } + return redisTemplate.opsForSet().randomMember(key); + + } + /** + * 和SPOP一样,随机的返回Set中的一个成员,不同的是该命令并不会删除返回的成员。 + * 还可以传递count参数来一次随机获得多个元素,根据count的正负不同,具体表现也不同。 + * 当count 为正数时,SRANDMEMBER 会随机从集合里获得count个不重复的元素。 + * 如果count的值大于集合中的元素个数,则SRANDMEMBER 会返回集合中的全部元素。 + * 当count为负数时,SRANDMEMBER 会随机从集合里获得|count|个的元素,如果|count|大与集合中的元素, + * 就会返回全部元素不够的以重复元素补齐,如果key不存在则返回nil。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param count + * @return java.util.List + * @throws + */ + public List srandmember(String key,int count) { + if(null==key){ + return null; + } + return redisTemplate.opsForSet().randomMembers(key,count); + + } + + /** + * 通过key随机删除一个set中的value并返回该值 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.String + * @throws + */ + public Object spop(String key) { + if (null==key){ + return null; + } + return redisTemplate.opsForSet().pop(key); + + } + + /** + * 通过key获取set中所有的value + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.util.Set + * @throws + */ + public Set smembers(String key) { + if (null==key){ + return null; + } + return redisTemplate.opsForSet().members(key); + + } + /** + * 从与Key关联的Set中删除参数中指定的成员,不存在的参数成员将被忽略, + * 如果该Key并不存在,将视为空Set处理。返回从Set中实际移除的成员数量,如果没有则返回0。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param members + * @return java.lang.Long + * @throws + */ + public Long srem(String key, Object... members) { + if (null==key){ + return 0L; + } + return redisTemplate.opsForSet().remove(key,members); + + } + + /** + * 将元素value从一个集合移到另一个集合 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param srckey +  * @param dstkey +  * @param member + * @return java.lang.Long + * @throws + */ + public Boolean smove(String srckey, String dstkey, Object member) { + if (null==srckey||null==dstkey){ + return false; + } + return redisTemplate.opsForSet().move(srckey,member,dstkey); + + } + + + /** + * 获取两个集合的并集 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param otherKeys + * @return java.util.Set 返回两个集合合并值 + * @throws + */ + public Set sUnion(String key, String otherKeys) { + if (null==key||otherKeys==null){ + return null; + } + return redisTemplate.opsForSet().union(key, otherKeys); + } + //**********Sorted Set 数据类型******************** + /** + *添加参数中指定的所有成员及其分数到指定key的Sorted Set中,在该命令中我们可以指定多组score/member作为参数。 + * 如果在添加时参数中的某一成员已经存在,该命令将更新此成员的分数为新值,同时再将该成员基于新值重新排序。 + * 如果键不存在,该命令将为该键创建一个新的Sorted Set Value,并将score/member对插入其中。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param score +  * @param member + * @return java.lang.Long + * @throws + */ + public Boolean zadd(String key, double score, Object member) { + if (null==key){ + return false; + } + return redisTemplate.opsForZSet().add(key,member,score); + + } + + + /** + * 该命令将移除参数中指定的成员,其中不存在的成员将被忽略。 + * 如果与该Key关联的Value不是Sorted Set,相应的错误信息将被返回。 如果操作成功则返回实际被删除的成员数量。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param members 可以使一个string 也可以是一个string数组 + * @return java.lang.Long + * @throws + */ + public Long zrem(String key, Object... members) { + if(null==key||null==members){ + return 0L; + } + return redisTemplate.opsForZSet().remove(key,members); + + } + + /** + * 返回Sorted Set中的成员数量,如果该Key不存在,返回0。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key + * @return java.lang.Long + * @throws + */ + public Long zcard(String key) { + if (null==key){ + return 0L; + } + return redisTemplate.opsForZSet().size(key); + } + + /** + * 该命令将为指定Key中的指定成员增加指定的分数。如果成员不存在,该命令将添加该成员并假设其初始分数为0, + * 此后再将其分数加上increment。如果Key不存在,该命令将创建该Key及其关联的Sorted Set, + * 并包含参数指定的成员,其分数为increment参数。如果与该Key关联的不是Sorted Set类型, + * 相关的错误信息将被返回。如果不报错则以串形式表示的新分数。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param score +  * @param member + * @return java.lang.Double + * @throws + */ + public Double zincrby(String key, double score, Object member) { + if (null==key){ +// throw new BusinessException(4001004,"key 不能为空"); + } + return redisTemplate.opsForZSet().incrementScore(key,member,score); + } + + /** + * 该命令用于获取分数(score)在min和max之间的成员数量。 + * (min= stop,此时一个空集合将被返回。如果stop大于最大索引值, + * 该命令将返回从start到集合的最后一个成员。如果命令中带有可选参数WITHSCORES选项, + * 该命令在返回的结果中将包含每个成员的分数值,如value1,score1,value2,score2...。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param min +  * @param max + * @return java.util.Set 指定区间内的有序集成员的列表。 + * @throws + */ + public Set zrange(String key, long min, long max) { + if (null==key){ + return null; + } + return redisTemplate.opsForZSet().range(key, min, max); + + } + /** + * 该命令的功能和ZRANGE基本相同,唯一的差别在于该命令是通过反向排序获取指定位置的成员, + * 即从高到低的顺序。如果成员具有相同的分数,则按降序字典顺序排序。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param start +  * @param end + * @return java.util.Set + * @throws + */ + public Set zReverseRange(String key, long start, long end) { + if (null==key){ + return null; + } + return redisTemplate.opsForZSet().reverseRange(key, start, end); + + } + + /** + * 该命令将返回分数在min和max之间的所有成员,即满足表达式min <= score <= max的成员, + * 其中返回的成员是按照其分数从低到高的顺序返回,如果成员具有相同的分数, + * 则按成员的字典顺序返回。可选参数LIMIT用于限制返回成员的数量范围。 + * 可选参数offset表示从符合条件的第offset个成员开始返回,同时返回count个成员。 + * 可选参数WITHSCORES的含义参照ZRANGE中该选项的说明。*最后需要说明的是参数中min和max的规则可参照命令ZCOUNT。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param max +  * @param min + * @return java.util.Set + * @throws + */ + public Set zrangebyscore(String key, double min, double max) { + if (null==key){ + return null; + } + return redisTemplate.opsForZSet().rangeByScore(key, min, max); + + } + + + + /** + * 该命令除了排序方式是基于从高到低的分数排序之外,其它功能和参数含义均与ZRANGEBYSCORE相同。 + * 需要注意的是该命令中的min和max参数的顺序和ZRANGEBYSCORE命令是相反的。 + * @Author: 小霍 + * @UpdateUser: + * @Version: 0.0.1 + * @param key +  * @param max +  * @param min + * @return java.util.Set + * @throws + */ + public Set zrevrangeByScore(String key, double min, double max) { + if (null==key){ + return null; + } + return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max); + } +} diff --git a/src/main/java/com/xkrs/service/SysAuthorityService.java b/src/main/java/com/xkrs/service/SysAuthorityService.java new file mode 100644 index 0000000..643abbf --- /dev/null +++ b/src/main/java/com/xkrs/service/SysAuthorityService.java @@ -0,0 +1,23 @@ +package com.xkrs.service; + +import com.xkrs.model.entity.SysAuthorityEntity; + +import java.util.List; + +/** + * 系统权限服务接口 + * @author tajochen + */ +public interface SysAuthorityService { + + /** + * 获取权限实体列表根据用户名 + * @param userName + * @return + */ + List getSysAuthorityListByUserName(String userName); + + List findAllByIdIn(List id); + + List selectAuthorityByUserId(Integer userId); +} diff --git a/src/main/java/com/xkrs/service/SysRoleService.java b/src/main/java/com/xkrs/service/SysRoleService.java new file mode 100644 index 0000000..b3149eb --- /dev/null +++ b/src/main/java/com/xkrs/service/SysRoleService.java @@ -0,0 +1,19 @@ +package com.xkrs.service; + +import com.xkrs.model.entity.SysRoleEntity; + +import java.util.List; + +/** + * 系统角色服务接口 + * @author tajochen + */ +public interface SysRoleService { + + /** + * 获取角色实体列表根据用户名 + * @param userName + * @return + */ + List getSysRoleListByUserName(String userName); +} diff --git a/src/main/java/com/xkrs/service/SysUserService.java b/src/main/java/com/xkrs/service/SysUserService.java new file mode 100644 index 0000000..54e09e9 --- /dev/null +++ b/src/main/java/com/xkrs/service/SysUserService.java @@ -0,0 +1,178 @@ +package com.xkrs.service; + +import com.xkrs.model.entity.SysUserEntity; +import com.xkrs.model.qo.SysUserQo; +import com.xkrs.model.vo.SysUserVo; + +import java.util.List; +import java.util.Map; + +/** + * 系统用户服务接口 + * @author tajochen + */ +public interface SysUserService { + + /** + * 检查用户名 + * @param userName + * @return + */ + boolean checkUserName(String userName); + + /** + * 获取所有用户 + * @return + */ + //Iterable getAllSysUser(); + + /** + * 保存用户 + * @param sysUserQo + * @return + */ + String addUser(SysUserQo sysUserQo); + + /** + * 获取系统用户实体根据用户名 + * @param userName + * @return + */ + SysUserEntity getSysUserByUserName(String userName); + + /** + * 用户登录更新 + * @param userName + * @param ipAddress + * @return + */ + int updateSysUserLogin(String userName, String ipAddress); + + /** + * 系统用户更新 + * @param sysUserQo + * @return + */ + int updateSysUser(SysUserQo sysUserQo); + + /** + * 软删除系统用户 + * @param id + * @return + */ + int softDeleteGeneralUser(Integer id); + + /** + * 查询用户的信息 + * @return + */ + List selectAllUser(); + + /** + * 启用 + * @param userId + */ + void updateEnable(Integer userId); + + /** + * 禁用 + * @param userId + */ + void updateDisable(Integer userId); + + /** + * 用户修改密码 + * @param oldPassword + * @param newPassword + * @param confirmPassword + * @param sysUserEntity + * @return + */ + String updatePassword(String oldPassword,String newPassword,String confirmPassword,SysUserEntity sysUserEntity); + + /** + * 管理员修改用户的密码 + * @param userId + * @param newPassword + * @param confirmPassword + * @return + */ + String adminUpdatePassword(Integer userId,String newPassword,String confirmPassword); + + /** + * 获取系统用户实体根据用户名 + * @param userName + * @return + */ + SysUserVo getUserByUserName(String userName); + + /** + * 按天数修改账号到期时间 + * @param userId + * @param dayNum + * @return + */ + String updateExpireDateDay(Integer userId, Integer dayNum); + + /** + * 按月份修改账号到期时间 + * @param userId + * @param dayNum + * @return + */ + String updateExpireDateMonth(Integer userId, Integer dayNum); + + /** + * 按年份修改账号到期时间 + * @param userId + * @param dayNum + * @return + */ + String updateExpireDateYear(Integer userId, Integer dayNum); + + /** + * 设置账号时间永久有效 + * @param userId + * @return + */ + String updatePermanent(Integer userId); + + /** + * 修改账号到期时间 + * @param userId + * @param overTime + * @return + */ + String updateOverTime(Integer userId,String overTime); + + /** + * 记录用户登录次数 + * @param userId + * @param loginNum + */ + void updateLoginNum(Integer userId,Integer loginNum); + + /** + * 记录用户登录时间 + * @param userId + * @param loginLastTime + */ + void updateLoginLastTime(Integer userId,String loginLastTime); + + + List> findCityByProCode(String proCode); + + /** + * 通过省编码查询县名称和编码 + * @param proCode + * @return + */ + List> findCountyByProCode(String proCode); + + /** + * 通过市编码查询区县名称和编码 + * @param cityCode + * @return + */ + List> findCountyByCityCode(String cityCode); +} diff --git a/src/main/java/com/xkrs/service/impl/FireAndRangerServiceImpl.java b/src/main/java/com/xkrs/service/impl/FireAndRangerServiceImpl.java new file mode 100644 index 0000000..787b85f --- /dev/null +++ b/src/main/java/com/xkrs/service/impl/FireAndRangerServiceImpl.java @@ -0,0 +1,174 @@ +package com.xkrs.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.common.tool.TokenUtil; +import com.xkrs.dao.*; +import com.xkrs.model.entity.*; +import com.xkrs.model.vo.AppPhotoVo; +import com.xkrs.model.vo.AppTaskBodyVo; +import com.xkrs.service.FireAndRangerService; +import com.xkrs.utils.DateTimeUtil; +import com.xkrs.utils.ObjectToBeanUtils; +import com.xkrs.utils.RestTemplateUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cglib.beans.BeanCopier; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.transaction.Transactional; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject; + +/** + * @author xkrs + */ +@Service +public class FireAndRangerServiceImpl implements FireAndRangerService { + + public static Logger log = LoggerFactory.getLogger(FireAndRangerServiceImpl.class); + + @Resource + private FireAndRangerDao fireAndRangerDao; + + @Resource + private SysUserDao sysUserDao; + + @Resource + private FirePointDao firePointDao; + + @Resource + private ForestRangerDao forestRangerDao; + + @Resource + private RestTemplateUtil restTemplateUtil; + + @Resource + private FireTaskDao fireTaskDao; + + @Resource + private FireTaskPhotoDao fireTaskPhotoDao; + + /** + * 将火点分配给护林员 + * @param rangerName + * @param fireCode + * @return + */ + @Transactional(rollbackOn = Exception.class) + @Override + public String addFireAndRanger(String rangerName, String fireCode, String handler, String verifier, String token) throws UnsupportedEncodingException { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + String tokenUserName = TokenUtil.getTokenUserName(token); + FireAndRanger byFireCode = fireAndRangerDao.findByFireCode(fireCode); + if(byFireCode != null){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"该火点已经分配,请勿重复操作",locale); + } + FirePointEntity byFireCode1 = firePointDao.findByFireCode(fireCode); + // 给app端推送的消息内容 + + Map map = new HashMap(3); + map.put("latitude",byFireCode1.getLatitude()); + map.put("longitude",byFireCode1.getLongitude()); + map.put("detailedAddress",byFireCode1.getFirePointAddress()); + String content = JSON.toJSONString(map); + String ss = URLEncoder.encode(content,"utf-8"); + + String url = "https://api.xmpush.xiaomi.com/v3/message/alias?title=收到消息&description=请"+verifier+"去核查该火点信息&payload="+ss+"&restricted_package_name=com.xkrs.fieldverification¬ify_id=2&extra.notify_effect=2&extra.intent_uri=fieldverify://xkrs.com&alias="+rangerName+"&extra.notify_foreground=0&extra.channel_id=mipush"; + + String time = DateTimeUtil.dateTimeToString(LocalDateTime.now()); + FireAndRanger fireAndRanger = new FireAndRanger(); + fireAndRanger.setRangerName(rangerName); + fireAndRanger.setFireCode(fireCode); + fireAndRanger.setHandlerTime(time); + fireAndRanger.setHandler(handler); + fireAndRanger.setVerifier(verifier); + fireAndRanger.setProgressType("1"); + + // 将火点分配给该护林员后,将护林员状态修改为1 表示正在执行火点任务 + forestRangerDao.updateRangerTypeByPhone(rangerName,"1"); + + JSONObject jsonObject = new JSONObject(); + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add("Authorization","key=QW+6vVbWptJHscqD7zuM5w=="); + log.info("-----------已向app发送消息"); + restTemplateUtil.doPostMessageToApp(url, httpHeaders, jsonObject); + + FireAndRanger save = fireAndRangerDao.save(fireAndRanger); + if(save == null){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"操作失败",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"操作成功",locale); + } + + /** + * 护林员查看自己的火点任务 + * @param token + * @return + */ + @Override + public String selectFireInformation(String token) { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + ForestRanger byRangerPhone = forestRangerDao.findByRangerPhone(sysUserEntity.getUserName()); + if(byRangerPhone.getRangerType().equals("1")){ + FireAndRanger byRangerName = fireAndRangerDao.findByRangerNameAndProgressType(sysUserEntity.getUserName(),"1"); + if(byRangerName == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有任何任务",locale); + } + FirePointEntity byFireCode = firePointDao.findByFireCode(byRangerName.getFireCode()); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,byFireCode,locale); + }else { + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有任何任务",locale); + } + + } + + /** + * 根据火点编码查询核查的信息 + * @param fireCode + * @return + */ + @Override + public String findFireAndRangerByFireCode(String fireCode, String token) throws Exception { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + String tokenUserName = TokenUtil.getTokenUserName(token); + FireAndRanger byFireCode = fireAndRangerDao.findByFireCode(fireCode); + if(byFireCode == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有该火点的核查信息",locale); + } + Map map = new HashMap(3); + map.put("fire",byFireCode); + FireTask byTaskFireCode = fireTaskDao.findByTaskFireCode(fireCode); + if(byTaskFireCode == null){ + map.put("task",null); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale); + }else { + AppTaskBodyVo appTaskBodyVo = new AppTaskBodyVo(); + // 做映射,返回vo类对象 + BeanCopier beanCopier = BeanCopier.create(FireTask.class, AppTaskBodyVo.class, false); + beanCopier.copy(byTaskFireCode,appTaskBodyVo,null); + + List photoPath = fireTaskPhotoDao.findPhotoPath(fireCode); + List appPhotoVos = ObjectToBeanUtils.objectToBean(photoPath, AppPhotoVo.class); + appTaskBodyVo.setTaskFirePhoto(appPhotoVos); + map.put("task",appTaskBodyVo); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale); + } + } +} diff --git a/src/main/java/com/xkrs/service/impl/FirePointServiceImpl.java b/src/main/java/com/xkrs/service/impl/FirePointServiceImpl.java new file mode 100644 index 0000000..9a917df --- /dev/null +++ b/src/main/java/com/xkrs/service/impl/FirePointServiceImpl.java @@ -0,0 +1,572 @@ +package com.xkrs.service.impl; + +import com.alibaba.fastjson.JSON; +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.common.tool.TokenUtil; +import com.xkrs.dao.*; +import com.xkrs.model.entity.*; +import com.xkrs.model.qo.FirePointQo; +import com.xkrs.model.vo.AppPhotoVo; +import com.xkrs.model.vo.AppTaskBodyVo; +import com.xkrs.service.FirePointService; +import com.xkrs.utils.*; +import com.xkrs.websocket.server.WebSocketServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cglib.beans.BeanCopier; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.jdbc.support.JdbcUtils; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.transaction.Transactional; +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.*; +import java.util.stream.Collectors; + +import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject; + +/** + * @author XinYi Song + */ +@Service +@CacheConfig(cacheNames = "FirePointServiceCache") +public class FirePointServiceImpl implements FirePointService { + + public static Logger log = LoggerFactory.getLogger(FirePointServiceImpl.class); + + @Resource + private FirePointDao firePointDao; + + @Resource + private Query query; + + @Resource + private SysUserDao sysUserDao; + + @Resource + private FireAndRangerDao fireAndRangerDao; + + @Resource + private ForestRangerDao forestRangerDao; + + @Resource + private FireTaskDao fireTaskDao; + + @Resource + private FireTaskPhotoDao fireTaskPhotoDao; + + @Resource + private CityDao cityDao; + + @Resource + private CountyDao countyDao; + + @Resource + private FireDao fireDao; + + @Resource + private NationwideDao nationwideDao; + + /** + * 添加火点信息 + * @param firePointQo + * @return + */ + @CacheEvict(value = "FirePointServiceCache",allEntries = true) + @Override + public FirePointEntity insertFirePoint(FirePointQo firePointQo) throws IOException { + FirePointEntity firePointEntity = new FirePointEntity(); + if("水体".equals(firePointQo.getLandtype())){ + return null; + }else if("L".equals(firePointQo.getConfidence())){ + return null; + }else if("Himawari 8".equals(firePointQo.getSatelliteType()) && "L".equals(firePointQo.getConfidence())){ + return null; + }else if("Himawari 8".equals(firePointQo.getSatelliteType()) && "N".equals(firePointQo.getConfidence())){ + return null; + }else { + if(firePointQo.getCountyCode().toString().equals("371328")){ + firePointEntity.setFireCode(firePointQo.getFireCode()); + firePointEntity.setCountyCode(firePointQo.getCountyCode().toString()); + firePointEntity.setCountyName(firePointQo.getCountyName()); + String satelliteTime = DateTimeUtil.timeMillisToString(firePointQo.getSatelliteTimeTs().longValue()); + firePointEntity.setSatelliteTime(satelliteTime); + firePointEntity.setLongitude(firePointQo.getLongitude()); + firePointEntity.setLatitude(firePointQo.getLatitude()); + String local = AddressUtils.getLocal(firePointQo.getLatitude().toString(), firePointQo.getLongitude().toString()); + firePointEntity.setFirePointAddress(local); + firePointEntity.setSatelliteType(firePointQo.getSatelliteType()); + firePointEntity.setLandType(firePointQo.getLandtype()); + firePointEntity.setConfidence(firePointQo.getConfidence()); + firePointEntity.setAddTime(DateTimeUtil.dateTimeToString(LocalDateTime.now())); + firePointEntity.setFireType("0"); + firePointEntity.setFireImage(firePointQo.getFireImage()); + firePointEntity.setSatelliteImage(firePointQo.getSatelliteImage()); + log.info("-------发现新火点"); + log.info("---------------开始进行实时通讯,将检测到的火点传给前端"); + Map map = new HashMap(3); + map.put("firecode",firePointQo.getFireCode()); + map.put("countycode",firePointQo.getCountyCode()); + map.put("countyname",firePointQo.getCountyName()); + map.put("satellitetime",satelliteTime); + map.put("latitude",firePointQo.getLatitude()); + map.put("longitude",firePointQo.getLongitude()); + map.put("satellitetype",firePointQo.getSatelliteType()); + map.put("landtype",firePointQo.getLandtype()); + map.put("confidence",firePointQo.getConfidence()); + map.put("address",local); + String websocket = JSON.toJSONString(map); + // 将监测到的火点信息返给前端 + WebSocketServer.BroadCastInfo(websocket); + return firePointDao.save(firePointEntity); + }else { + firePointEntity.setFireCode(firePointQo.getFireCode()); + firePointEntity.setCountyCode(firePointQo.getCountyCode().toString()); + firePointEntity.setCountyName(firePointQo.getCountyName()); + String satelliteTime = DateTimeUtil.timeMillisToString(firePointQo.getSatelliteTimeTs().longValue()); + firePointEntity.setSatelliteTime(satelliteTime); + firePointEntity.setLongitude(firePointQo.getLongitude()); + firePointEntity.setLatitude(firePointQo.getLatitude()); + String local = AddressUtils.getLocal(firePointQo.getLatitude().toString(), firePointQo.getLongitude().toString()); + firePointEntity.setFirePointAddress(local); + firePointEntity.setSatelliteType(firePointQo.getSatelliteType()); + firePointEntity.setLandType(firePointQo.getLandtype()); + firePointEntity.setConfidence(firePointQo.getConfidence()); + firePointEntity.setAddTime(DateTimeUtil.dateTimeToString(LocalDateTime.now())); + firePointEntity.setFireType("0"); + firePointEntity.setFireImage(firePointQo.getFireImage()); + firePointEntity.setSatelliteImage(firePointQo.getSatelliteImage()); + log.info("-------发现新火点"); + return firePointDao.save(firePointEntity); + } + + } + } + + /** + * 根据时间段查询火点信息 + * @param startAddTime + * @param endTime + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public String findByAddTime(String startAddTime, String endTime) { + Locale locale = LocaleContextHolder.getLocale(); + List> firePointEntities = firePointDao.selectByAddTime(startAddTime, endTime); + if(firePointEntities == null || firePointEntities.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时没有火点信息",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,firePointEntities,locale); + } + + /** + * 查询今天的火点信息 + * @param + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public List selectTodayFirePoint(String countyCode) { + String addTime = DateTimeUtil.dateToString(LocalDate.now()); + if("0000".equals(countyCode.substring(2))){ + List byProCode = cityDao.findByProCode(countyCode); + String proName = byProCode.get(0).getProName(); + return firePointDao.selectTodayFirePoint(addTime,proName); + }else if("00".equals(countyCode.substring(4)) && !"0000".equals(countyCode.substring(2))){ + List byCityCode = countyDao.findByCityCode(countyCode); + String cityName = byCityCode.get(0).getCityName(); + return firePointDao.selectTodayFirePoint(addTime,cityName); + }else { + return firePointDao.selectTodayFirePointOne(addTime,countyCode); + } + } + + /** + * 动态多条件查询火点信息(省) + * @param cityCode + * @param satelliteType + * @param landType + * @param startTime + * @param endTime + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public List selectFirePoint(String proCode,String cityCode, String satelliteType, String landType, String startTime, String endTime) { + List byProCode = cityDao.findByProCode(proCode); + String proName = byProCode.get(0).getProName(); + return query.selectFirePointByPro(proName,cityCode, satelliteType, landType, startTime, endTime); + } + + /** + * 动态多条件查询火点信息(市) + * @param cityCodeOne 市编码 + * @param cityCode 县编码 + * @param satelliteType + * @param landType + * @param startTime + * @param endTime + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public List selectFirePointByCity(String cityCodeOne, String cityCode, String satelliteType, String landType, String startTime, String endTime) { + //List byCityCode = cityDao.findByCityCode(cityCodeOne.substring(0,3)); + List byCityCode = countyDao.findByCityCode(cityCodeOne); + String cityName = byCityCode.get(0).getCityName(); + return query.selectFirePointByCity(cityName,cityCode,satelliteType,landType,startTime,endTime); + } + + /** + * 动态多条件查询火点信息(县) + * @param cityCode 县编码 + * @param satelliteType + * @param landType + * @param startTime + * @param endTime + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public List selectFirePointByCounty(String cityCode, String satelliteType, String landType, String startTime, String endTime) { + return query.selectFirePointByCounty(cityCode,satelliteType,landType,startTime,endTime); + } + + /** + * 根据火点编码修改火点的状态(预警) + * @param fireCode + * @param fireType + * @param token + * @return + */ + @Transactional(rollbackOn = Exception.class) + @Override + public String updateTypeByFireCode(String fireCode, String fireType, String token) { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + String tokenUserName = TokenUtil.getTokenUserName(token); + SysUserEntity sysUserEntity = sysUserDao.selectByUserName(tokenUserName); + FirePointEntity byFireCode = firePointDao.findByFireCode(fireCode); + if ("3".equals(byFireCode.getFireType()) || "-1".equals(byFireCode.getFireType())) { + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"该火点已经结案,请勿进行有关状态操作",locale); + } + if (fireType.equals(byFireCode.getFireType())) { + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"您正处于当前的状态,请勿进行该操作",locale); + } + firePointDao.updateFireTypeByFireCode(fireCode, fireType); + if ("1".equals(fireType)) { + FirePointEntity byFireCode1 = firePointDao.findByFireCode(fireCode); + // 预警 + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,byFireCode1,locale); + } else if ("2".equals(fireType)){ + FirePointEntity byFireCode3 = firePointDao.findByFireCode(fireCode); + // 核查 + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,byFireCode3,locale); + } else { + String rangerType = "0"; + FireAndRanger byFireCode1 = fireAndRangerDao.findByFireCode(fireCode); + if (byFireCode1 == null) { + FirePointEntity byFireCode4 = firePointDao.findByFireCode(fireCode); + String time = DateTimeUtil.dateTimeToString(LocalDateTime.now()); + FireAndRanger fireAndRanger = new FireAndRanger(); + fireAndRanger.setFireCode(fireCode); + // 由于测试阶段先用用户账号代替,后期换成getReallyName(用户真实姓名) + fireAndRanger.setHandler(sysUserEntity.getReallyName()); + fireAndRanger.setEndTime(time); + fireAndRangerDao.save(fireAndRanger); + // 结案 + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,byFireCode4,locale); + } + // 火点结案,将护林员的状态修改为0 表示该护林员没有在执行任务,处于空闲状态 + forestRangerDao.updateRangerTypeByPhone(byFireCode1.getRangerName(), rangerType); + String time = DateTimeUtil.dateTimeToString(LocalDateTime.now()); + fireAndRangerDao.updateEndTimeByFireCode(fireCode, time); + fireAndRangerDao.updateProgressTypeByFireCode(fireCode, "0"); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"结案",locale); + } + } + + /** + * 提交核查任务 + * @param files + * @param appTaskBodyVo + * @return + */ + @Transactional(rollbackOn = Exception.class) + @Override + public String insertAppTask(MultipartFile[] files, AppTaskBodyVo appTaskBodyVo) throws IOException { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + FirePointEntity byFireCode = firePointDao.findByFireCode(appTaskBodyVo.getFireCode()); + if(byFireCode == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"火点编码错误,请重新输入",locale); + } + FireTask byTaskFireCode = fireTaskDao.findByTaskFireCode(appTaskBodyVo.getFireCode()); + if(byTaskFireCode != null){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"该火点的任务已经提交,请勿重复提交",locale); + } + String s = DateTimeUtil.dateTimeToString(LocalDateTime.now()); + FireTask fireTask = new FireTask(); + fireTask.setTaskFireCode(appTaskBodyVo.getFireCode()); + fireTask.setTaskInformation(appTaskBodyVo.getTaskInformation()); + fireTask.setTaskTime(s); + FireTask save = fireTaskDao.save(fireTask); + if(save == null){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"任务提交失败",locale); + } + List fireTaskPhotos = PhotoUtil.uploadImage(files, appTaskBodyVo.getFireCode()); + List fireTaskPhotos1 = fireTaskPhotoDao.saveAll(fireTaskPhotos); + if(fireTaskPhotos1 == null || fireTaskPhotos1.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"图片上传失败,任务提交失败",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"任务提交成功",locale); + } + + /** + * 根据火点编码查询任务信息 + * @param fireCode + * @return + * @throws Exception + */ + @Override + public String selectAppTask(String fireCode) throws Exception { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + FireTask byTaskFireCode = fireTaskDao.findByTaskFireCode(fireCode); + if(byTaskFireCode == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没有该火点的任务信息",locale); + } + AppTaskBodyVo appTaskBodyVo = new AppTaskBodyVo(); + // 做映射,返回vo类对象 + BeanCopier beanCopier = BeanCopier.create(FireTask.class, AppTaskBodyVo.class, false); + beanCopier.copy(byTaskFireCode,appTaskBodyVo,null); + + List photoPath = fireTaskPhotoDao.findPhotoPath(fireCode); + List appPhotoVos = ObjectToBeanUtils.objectToBean(photoPath, AppPhotoVo.class); + appTaskBodyVo.setTaskFirePhoto(appPhotoVos); + + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,appTaskBodyVo,locale); + } + + /** + * 查询近一周的火点信息 + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public List selectFirePointBetweenSeven() { + LocalDateTime localDateTime = LocalDateTime.now(); + String endTime = DateTimeUtil.dateTimeToString(localDateTime); + + // 当前时间减7 + LocalDateTime localDateTime1 = localDateTime.minusDays(7); + String startTime = DateTimeUtil.dateTimeToString(localDateTime1); + return query.selectFirePointBetweenThree(startTime, endTime); + } + + /** + * 查询近一个月的火点信息 + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public List selectFirePointByMonth(String countyCode) { + LocalDateTime localDateTime = LocalDateTime.now(); + String endTime = DateTimeUtil.dateTimeToString(localDateTime); + // 当前时间减7 + LocalDateTime localDateTime1 = localDateTime.minusDays(31); + String startTime = DateTimeUtil.dateTimeToString(localDateTime1); + if("0000".equals(countyCode.substring(2))){ + List byProCode = cityDao.findByProCode(countyCode); + String proName = byProCode.get(0).getProName(); + return query.selectFirePointByMonth(proName,startTime,endTime); + }else if("00".equals(countyCode.substring(4)) && !"0000".equals(countyCode.substring(2))){ + List byCityCode = countyDao.findByCityCode(countyCode); + String cityName = byCityCode.get(0).getCityName(); + return query.selectFirePointByMonthCity(cityName,startTime,endTime); + }else { + return query.selectFirePointByMonthCounty(countyCode,startTime,endTime); + } + + } + + /** + * 查询近一个月的火点数量 + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public String selectFirePointNumMonth() { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + Map map = new HashMap(3); + LocalDateTime localDateTime = LocalDateTime.now(); + LocalDateTime localDateTime2 = localDateTime.plusDays(1); + String endTime = DateTimeUtil.dateTimeToString(localDateTime2); + // 当前时间减30 + LocalDateTime localDateTime1 = localDateTime.minusDays(30); + String startTime = DateTimeUtil.dateTimeToString(localDateTime1); + // 查询近一个月各植被类型的火点数量 + List> maps = firePointDao.selectNumByLandType(startTime, endTime); + map.put("land",maps); + // 查询近一个月各地区火点数量 + List> maps1 = firePointDao.selectNumByArea(startTime, endTime); + map.put("area",maps1); + + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale); + } + + /** + * 查询近一天的火点数量 + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public String selectFirePointNumDay() { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + Map map = new HashMap(3); + LocalDateTime localDateTime = LocalDateTime.now(); + LocalDateTime localDateTime2 = localDateTime.plusDays(1); + String endTime = DateTimeUtil.dateTimeToString(localDateTime2); + // 当前时间减1 + LocalDateTime localDateTime1 = localDateTime.minusDays(1); + String startTime = DateTimeUtil.dateTimeToString(localDateTime1); + // 查询近一个月各植被类型的火点数量 + List> maps = firePointDao.selectNumByLandType(startTime, endTime); + map.put("land",maps); + // 查询近一个月各地区火点数量 + List> maps1 = firePointDao.selectNumByArea(startTime, endTime); + map.put("area",maps1); + + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale); + } + + /** + * 查询近一周的火点数量 + * @return + */ + @Cacheable(keyGenerator = "keyGenerator", unless="#result == null") + @Override + public String selectFirePointNumWeek() { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + Map map = new HashMap(3); + LocalDateTime localDateTime = LocalDateTime.now(); + LocalDateTime localDateTime2 = localDateTime.plusDays(1); + String endTime = DateTimeUtil.dateTimeToString(localDateTime2); + // 当前时间减7 + LocalDateTime localDateTime1 = localDateTime.minusDays(7); + String startTime = DateTimeUtil.dateTimeToString(localDateTime1); + // 查询近一个月各植被类型的火点数量 + List> maps = firePointDao.selectNumByLandType(startTime, endTime); + map.put("land",maps); + // 查询近一个月各地区火点数量 + List> maps1 = firePointDao.selectNumByArea(startTime, endTime); + map.put("area",maps1); + + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,map,locale); + } + + /** + * 查询该省所有的市 + * @param code + * @return + */ + @Override + public List> selectCityName(String code) { + return cityDao.selectCityName(code); + } + + /** + * 查询市包含的区县和编码 + * @param code + * @return + */ + @Override + public List> selectCountyName(String code) { + return countyDao.selectCountyName(code); + } + + /** + * 测试插入火点信息 + * @param firePointQo + * @return + */ + @Override + public FirePoint insertFireTest(FirePointQo firePointQo) { + FirePoint firePoint = new FirePoint(); + firePoint.setFireCode(firePointQo.getFireCode()); + firePoint.setCountyCode(firePointQo.getCountyCode().toString()); + firePoint.setCountyName(firePointQo.getCountyName()); + firePoint.setSatelliteTime(DateTimeUtil.timeMillisToString(firePointQo.getSatelliteTimeTs().longValue())); + firePoint.setLongitude(firePointQo.getLongitude()); + firePoint.setLatitude(firePointQo.getLatitude()); + firePoint.setFirePointAddress(AddressUtils.getLocal(firePointQo.getLatitude().toString(),firePointQo.getLongitude().toString())); + firePoint.setSatelliteType(firePointQo.getSatelliteType()); + firePoint.setLandType(firePointQo.getLandtype()); + firePoint.setConfidence(firePointQo.getConfidence()); + firePoint.setAddTime(DateTimeUtil.dateTimeToString(LocalDateTime.now())); + firePoint.setFireType("0"); + firePoint.setFireImage(firePointQo.getFireImage()); + firePoint.setSatelliteImage(firePointQo.getSatelliteImage()); + log.info("-------发现新火点"); + return fireDao.save(firePoint); + } + + /** + * 导入全国省市区 + * @param file + * @throws Exception + */ + @Transactional(rollbackOn = Exception.class) + @Override + public void importCityExcel(MultipartFile file) throws Exception { + //调用封装好的工具 + ExcelImportUtil importUtil = new ExcelImportUtil(file); + //调用导入的方法,获取sheet表的内容 + List> maps = importUtil.readExcelContent(); + //导入订单详情表 + List orderDetails = maps.stream().filter(Objects::nonNull).map(map -> { + Nationwide nationwide = new Nationwide(); + nationwide.setProName(map.get("pro_name")); + nationwide.setProCode(map.get("pro_code")); + nationwide.setCityName(map.get("city_name")); + nationwide.setCityCode(map.get("city_code")); + nationwide.setCountyName(map.get("town_name")); + nationwide.setCountyCode(map.get("town_code")); + return nationwide; + }).collect(Collectors.toList()); + //批量添加到订单详情 + nationwideDao.saveAll(orderDetails); + } + + /** + * 查询今日的火点信息(测试) + * @param countyCode + * @return + */ + @Override + public List selectTodayFire(String countyCode) { + String addTime = DateTimeUtil.dateToString(LocalDate.now()); + if("0000".equals(countyCode.substring(2))){ + List byProCode = cityDao.findByProCode(countyCode); + String proName = byProCode.get(0).getProName(); + return fireDao.selectTodayFire(addTime,proName); + }else if("00".equals(countyCode.substring(4)) && !"0000".equals(countyCode.substring(2))){ + List byCityCode = countyDao.findByCityCode(countyCode); + String cityName = byCityCode.get(0).getCityName(); + return fireDao.selectTodayFire(addTime,cityName); + }else { + return fireDao.selectTodayFireOne(addTime,countyCode); + } + } +} diff --git a/src/main/java/com/xkrs/service/impl/ForestRangerServiceImpl.java b/src/main/java/com/xkrs/service/impl/ForestRangerServiceImpl.java new file mode 100644 index 0000000..b71b70d --- /dev/null +++ b/src/main/java/com/xkrs/service/impl/ForestRangerServiceImpl.java @@ -0,0 +1,83 @@ +package com.xkrs.service.impl; + +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.common.tool.TokenUtil; +import com.xkrs.dao.ForestRangerDao; +import com.xkrs.model.entity.ForestRanger; +import com.xkrs.service.ForestRangerService; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.transaction.Transactional; +import java.util.List; +import java.util.Locale; + +import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject; + +/** + * @author xkrs + */ +@Service +public class ForestRangerServiceImpl implements ForestRangerService { + + @Resource + private ForestRangerDao forestRangerDao; + + /** + * 根据曲线编码查询护林员的信息 + * @param rangerCountyCode + * @return + */ + @Override + public String findByRangerCountyCode(String rangerCountyCode) { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + ForestRanger byRangerCountyCode = forestRangerDao.findByRangerCountyCode(rangerCountyCode); + if(byRangerCountyCode == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"该区县暂时还没有相关护林员的信息",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,byRangerCountyCode,locale); + } + + /** + * 根据区县编码查询该区县所有护林员的信息 + * @param countyCode + * @return + */ + @Override + public String findAllByRangerCountyCode(String countyCode, String token) { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + String tokenUserName = TokenUtil.getTokenUserName(token); + if("0000".equals(countyCode.substring(2))){ + List allsByRangerCountyCode = forestRangerDao.findAllsByRangerCountyCode(countyCode.substring(0,2)); + if(allsByRangerCountyCode == null || allsByRangerCountyCode.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没该省护林员的信息",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,allsByRangerCountyCode,locale); + }else { + List allByRangerCountyCode = forestRangerDao.findAllsByRangerCountyCode(countyCode.substring(0,4)); + if(allByRangerCountyCode == null || allByRangerCountyCode.size() == 0){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"暂时还没该市护林员的信息",locale); + } + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,allByRangerCountyCode,locale); + } + } + + /** + * 根据手机号修改护林员的位置信息 + * @param rangerLatitude + * @param rangerLongitude + * @param rangerPhone + * @return + */ + @Transactional(rollbackOn = Exception.class) + @Override + public String updateLatAndLonByPhone(String rangerLatitude, String rangerLongitude, String rangerPhone) { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + forestRangerDao.updateLatAndLonByPhone(rangerLatitude,rangerLongitude,rangerPhone); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"操作成功",locale); + } +} diff --git a/src/main/java/com/xkrs/service/impl/SysAuthorityServiceImpl.java b/src/main/java/com/xkrs/service/impl/SysAuthorityServiceImpl.java new file mode 100644 index 0000000..459a58f --- /dev/null +++ b/src/main/java/com/xkrs/service/impl/SysAuthorityServiceImpl.java @@ -0,0 +1,39 @@ +package com.xkrs.service.impl; + +import com.xkrs.dao.RelRoleAuthorityDao; +import com.xkrs.dao.SysAuthorityDao; +import com.xkrs.model.entity.SysAuthorityEntity; +import com.xkrs.service.SysAuthorityService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 系统权限服务实现 + * @author tajochen + */ +@Service +public class SysAuthorityServiceImpl implements SysAuthorityService { + + @Resource + private SysAuthorityDao sysAuthorityDao; + + @Resource + private RelRoleAuthorityDao relRoleAuthorityDao; + + @Override + public List getSysAuthorityListByUserName(String userName) { + return sysAuthorityDao.selectByUserName(userName); + } + + @Override + public List findAllByIdIn(List id) { + return sysAuthorityDao.findAllByIdIn(id); + } + + @Override + public List selectAuthorityByUserId(Integer userId) { + return relRoleAuthorityDao.selectAuthorityByUserId(userId); + } +} diff --git a/src/main/java/com/xkrs/service/impl/SysRoleServiceImpl.java b/src/main/java/com/xkrs/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..5b5828f --- /dev/null +++ b/src/main/java/com/xkrs/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,25 @@ +package com.xkrs.service.impl; + +import com.xkrs.dao.SysRoleDao; +import com.xkrs.model.entity.SysRoleEntity; +import com.xkrs.service.SysRoleService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 系统角色服务实现 + * @author tajochen + */ +@Service +public class SysRoleServiceImpl implements SysRoleService { + + @Resource + private SysRoleDao sysRoleDao; + + @Override + public List getSysRoleListByUserName(String userName) { + return sysRoleDao.selectByUserName(userName); + } +} diff --git a/src/main/java/com/xkrs/service/impl/SysUserServiceImpl.java b/src/main/java/com/xkrs/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..20588c1 --- /dev/null +++ b/src/main/java/com/xkrs/service/impl/SysUserServiceImpl.java @@ -0,0 +1,437 @@ +package com.xkrs.service.impl; + +import com.xkrs.common.encapsulation.PromptMessageEnum; +import com.xkrs.dao.*; +import com.xkrs.model.entity.*; +import com.xkrs.model.qo.SysUserQo; +import com.xkrs.model.vo.SysUserVo; +import com.xkrs.service.RedisService; +import com.xkrs.service.SysUserService; +import com.xkrs.utils.DateTimeUtil; +import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.security.crypto.keygen.KeyGenerators; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject; +import static com.xkrs.utils.DateTimeUtil.dateTimeToString; +import static com.xkrs.utils.EncryptDecryptUtil.encry256; + +/** + * 系统用户服务实现 + * @author tajochen + */ +@Service +public class SysUserServiceImpl implements SysUserService { + + @Resource + private SysUserDao sysUserDao; + + @Resource + private SysRoleDao sysRoleDao; + + @Resource + private RelUserRoleDao relUserRoleDao; + + @Resource + private RelRoleAuthorityDao relRoleAuthorityDao; + + @Resource + private RedisService redisService; + + @Resource + private NationwideDao nationwideDao; + + @Resource + private CountyDao countyDao; + + @Resource + private CityDao cityDao; + + /** + * 检查用户名是否存在 + * @param userName + * @return + */ + @Override + public boolean checkUserName(String userName) { + int num = sysUserDao.checkUserName(userName); + return (num == 0); + }; + + /** + * 新增用户 + * @param sysUserQo + */ + @Transactional(rollbackFor=Exception.class) + @Override + public String addUser(SysUserQo sysUserQo) { + // 获取区域信息 + Locale locale = LocaleContextHolder.getLocale(); + String salt = KeyGenerators.string().generateKey(); + SysUserEntity sysUserEntity = new SysUserEntity(); + sysUserEntity.setUserName(sysUserQo.getUserName()); + String o = (String) redisService.get(sysUserQo.getUserName()); + if("".equals(o) || o == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"请先发送验证码!",locale); + } + if(!redisService.get(sysUserQo.getUserName()).equals(sysUserQo.getVerificationCode())){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"验证码错误,请重新输入!",locale); + } + if("".equals(sysUserQo.getReallyName()) || sysUserQo.getReallyName() == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_NONE,"真实姓名不能为空!",locale); + } + sysUserEntity.setReallyName(sysUserQo.getReallyName()); + sysUserEntity.setSalt(salt); + sysUserEntity.setPassword(encry256(sysUserQo.getPassword() + salt)); + sysUserEntity.setTelephone(sysUserQo.getUserName()); + + sysUserEntity.setCountyCode(sysUserQo.getCountyCode()); + if("".equals(sysUserQo.getCountyName()) || sysUserQo.getCountyName() == null){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"省市区名称不能为空!",locale); + } + + if("0000".equals(sysUserQo.getCountyCode().substring(2))){ + if(!"110000".equals(sysUserQo.getCountyCode())){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"编码错误,不属于北京市!",locale); + } + if(!"北京市".equals(sysUserQo.getCountyName())){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"名称错误,不属于北京市!",locale); + } + sysUserEntity.setActiveFlag(0); + sysUserEntity.setAccountType("省级"); + }else if("00".equals(sysUserQo.getCountyCode().substring(4)) && !"0000".equals(sysUserQo.getCountyCode().substring(2))){ + if(!"110100".equals(sysUserQo.getCountyCode())){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"编码错误,不属于北京市!",locale); + } + if(!"北京城区".equals(sysUserQo.getCountyName())){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"名称错误,不属于北京市!",locale); + } + sysUserEntity.setActiveFlag(0); + sysUserEntity.setAccountType("市级"); + }else { + CountyEntity byCountyCode = countyDao.findByCountyCode(sysUserQo.getCountyCode()); + if(!"110100".equals(byCountyCode.getCityCode())){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"编码错误,不属于北京市!",locale); + } + CountyEntity byCountyName = countyDao.findByCountyName(sysUserQo.getCountyName()); + if(!"110100".equals(byCountyName.getCityCode())){ + return outputEncapsulationObject(PromptMessageEnum.DATA_WRONG,"名称错误,不属于北京市!",locale); + } + sysUserEntity.setActiveFlag(0); + sysUserEntity.setAccountType("县级"); + } + sysUserEntity.setStatusCode(0); + sysUserEntity.setAddTime(dateTimeToString(LocalDateTime.now())); + sysUserEntity.setDeleteFlag(0); + sysUserEntity.setDayNum(7); + String string = dateTimeToString(LocalDateTime.now().plusDays(3L)); + sysUserEntity.setOverTime(string); + sysUserEntity.setLoginNum(0); + sysUserEntity.setCountyName(sysUserQo.getCountyName()); + + sysUserDao.save(sysUserEntity); + + RelUserRoleEntity relUserRoleEntity = new RelUserRoleEntity(); + relUserRoleEntity.setUserId(sysUserEntity.getId().longValue()); + relUserRoleEntity.setRoleId(2); + + RelRoleAuthorityEntity relRoleAuthorityEntity = new RelRoleAuthorityEntity(); + relRoleAuthorityEntity.setRoleId(2); + relRoleAuthorityEntity.setAuthorityId(2); + relRoleAuthorityEntity.setUserId(sysUserEntity.getId()); + relUserRoleDao.save(relUserRoleEntity); + + relRoleAuthorityDao.save(relRoleAuthorityEntity); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"注册成功!",locale); + } + + /** + * 查询所有用户Vo + * @return + */ + /*@Transactional(rollbackFor=Exception.class) + @Override + public Iterable getAllSysUser() { + Iterable ls = sysUserDao.selectAllSysUser(); + return ls; + }*/ + + @Transactional(rollbackFor=Exception.class) + @Override + public SysUserEntity getSysUserByUserName(String userName) { + return sysUserDao.selectByUserName(userName); + } + + @Transactional(rollbackFor=Exception.class) + @Override + public int updateSysUserLogin(String userName,String ipAddress) { + return sysUserDao.updateSysUserLogin(userName,ipAddress); + } + + /** + * 更新用户 + * @param sysUserQo + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public int updateSysUser(SysUserQo sysUserQo) { + SysUserEntity sysUserEntity = new SysUserEntity(); + sysUserEntity.setReallyName(sysUserQo.getReallyName()); + sysUserDao.save(sysUserEntity); + return 1; + } + + /** + * 软删除普通用户 + * @param id + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public int softDeleteGeneralUser(Integer id) { + String adminRole = "role_administor"; + String sysRole ="role_system_manager"; + + List list = sysRoleDao.selectByUserId(id); + if(list.size()>0){ + SysRoleEntity sysRoleEntity = list.get(1); + if(sysRole.equals(sysRoleEntity.getRoleName())||adminRole.equals(sysRoleEntity.getRoleName())){ + sysUserDao.softDeleteGeneralUserById(id); + return 0; + } + } + return 1; + } + + /** + * 查询用户的信息 + * @return + */ + @Override + public List selectAllUser() { + return sysUserDao.selectAll(); + } + + /** + * 启用 + * @param userId + */ + @Transactional(rollbackFor=Exception.class) + @Override + public void updateEnable(Integer userId) { + sysUserDao.updateEnable(userId); + } + + /** + * 禁用 + * @param userId + */ + @Transactional(rollbackFor=Exception.class) + @Override + public void updateDisable(Integer userId) { + sysUserDao.updateDisable(userId); + } + + /** + * 用户修改密码 + * @param oldPassword + * @param newPassword + * @param confirmPassword + * @param sysUserEntity + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public String updatePassword(String oldPassword, String newPassword, String confirmPassword, SysUserEntity sysUserEntity) { + Locale locale = LocaleContextHolder.getLocale(); + String oldFrontPassword = encry256(oldPassword + sysUserEntity.getSalt()); + if(!oldFrontPassword.equals(sysUserEntity.getPassword())){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"旧密码输入错误",locale); + } + if(!newPassword.equals(confirmPassword)){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"两次密码输入不一致",locale); + } + String newAfterPassword = encry256(newPassword + sysUserEntity.getSalt()); + sysUserDao.updatePassword(sysUserEntity.getId(),newAfterPassword); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"密码修改成功",locale); + } + + /** + * 管理员修改用户的密码 + * @param userId + * @param newPassword + * @param confirmPassword + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public String adminUpdatePassword(Integer userId, String newPassword, String confirmPassword) { + Locale locale = LocaleContextHolder.getLocale(); + if(!newPassword.equals(confirmPassword)){ + return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"两次密码输入不一致",locale); + } + SysUserEntity sysUserEntity = sysUserDao.selectByUserId(userId); + String newAfterPassword = encry256(newPassword + sysUserEntity.getSalt()); + sysUserDao.updatePassword(userId,newAfterPassword); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"密码修改成功",locale); + } + + @Override + public SysUserVo getUserByUserName(String userName) { + return sysUserDao.selectUserByUserName(userName); + } + + /** + * 按天数修改账号到期时间 + * @param userId + * @param dayNum + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public String updateExpireDateDay(Integer userId, Integer dayNum) { + Locale locale = LocaleContextHolder.getLocale(); + long l = dayNum.longValue(); + LocalDateTime now = LocalDateTime.now(); + SysUserEntity sysUserEntity = sysUserDao.selectByUserId(userId); + if(DateTimeUtil.dateTimeToString(now).compareTo(sysUserEntity.getOverTime()) > 0){ + LocalDateTime localDateTime = now.plusDays(l); + String time = dateTimeToString(localDateTime); + sysUserDao.updateOverTime(userId,time); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"修改成功",locale); + }else { + LocalDateTime localDateTime = DateTimeUtil.stringToDateTime(sysUserEntity.getOverTime()); + LocalDateTime localDateTime1 = localDateTime.plusDays(l); + String time = dateTimeToString(localDateTime1); + sysUserDao.updateOverTime(userId,time); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"修改成功",locale); + } + } + + /** + * 按月份修改账号过期时间 + * @param userId + * @param dayNum + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public String updateExpireDateMonth(Integer userId, Integer dayNum) { + Locale locale = LocaleContextHolder.getLocale(); + long l = dayNum.longValue(); + LocalDateTime now = LocalDateTime.now(); + SysUserEntity sysUserEntity = sysUserDao.selectByUserId(userId); + if(DateTimeUtil.dateTimeToString(now).compareTo(sysUserEntity.getOverTime()) > 0){ + LocalDateTime localDateTime = now.plusMonths(l); + String time = dateTimeToString(localDateTime); + sysUserDao.updateOverTime(userId,time); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"修改成功",locale); + }else { + LocalDateTime localDateTime = DateTimeUtil.stringToDateTime(sysUserEntity.getOverTime()); + LocalDateTime localDateTime1 = localDateTime.plusMonths(l); + String time = dateTimeToString(localDateTime1); + sysUserDao.updateOverTime(userId,time); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"修改成功",locale); + } + } + + /** + * 按年份修改账号到期时间 + * @param userId + * @param dayNum + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public String updateExpireDateYear(Integer userId, Integer dayNum) { + Locale locale = LocaleContextHolder.getLocale(); + long l = dayNum.longValue(); + LocalDateTime now = LocalDateTime.now(); + SysUserEntity sysUserEntity = sysUserDao.selectByUserId(userId); + if(DateTimeUtil.dateTimeToString(now).compareTo(sysUserEntity.getOverTime()) > 0){ + LocalDateTime localDateTime = now.plusYears(l); + String time = dateTimeToString(localDateTime); + sysUserDao.updateOverTime(userId,time); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"修改成功",locale); + }else { + LocalDateTime localDateTime = DateTimeUtil.stringToDateTime(sysUserEntity.getOverTime()); + LocalDateTime localDateTime1 = localDateTime.plusYears(l); + String time = dateTimeToString(localDateTime1); + sysUserDao.updateOverTime(userId,time); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"修改成功",locale); + } + } + + /** + * 设置账号永久有效 + * @param userId + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public String updatePermanent(Integer userId) { + Locale locale = LocaleContextHolder.getLocale(); + sysUserDao.updateDayNum(userId); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"修改成功",locale); + } + + /** + * 修改账号到期时间 + * @param userId + * @param overTime + * @return + */ + @Transactional(rollbackFor=Exception.class) + @Override + public String updateOverTime(Integer userId, String overTime) { + Locale locale = LocaleContextHolder.getLocale(); + sysUserDao.updateOverTime(userId,overTime); + return outputEncapsulationObject(PromptMessageEnum.SUCCESS,"修改成功",locale); + } + + /** + * 记录用户登录次数 + * @param userId + * @param loginNum + */ + @Transactional(rollbackFor=Exception.class) + @Override + public void updateLoginNum(Integer userId, Integer loginNum) { + sysUserDao.updateLoginNum(userId,loginNum); + } + + /** + * 记录用户登录时间 + * @param userId + * @param loginLastTime + */ + @Transactional(rollbackFor=Exception.class) + @Override + public void updateLoginLastTime(Integer userId, String loginLastTime) { + sysUserDao.updateLoginLastTime(userId,loginLastTime); + } + + @Override + public List> findCityByProCode(String proCode) { + return nationwideDao.findCityByProCode(proCode); + } + + @Override + public List> findCountyByProCode(String proCode) { + return nationwideDao.findCountyByProCode(proCode); + } + + @Override + public List> findCountyByCityCode(String cityCode) { + return nationwideDao.findCountyByCityCode(cityCode); + } + +} diff --git a/src/main/java/com/xkrs/utils/AddressUtils.java b/src/main/java/com/xkrs/utils/AddressUtils.java new file mode 100644 index 0000000..1ec5bf4 --- /dev/null +++ b/src/main/java/com/xkrs/utils/AddressUtils.java @@ -0,0 +1,293 @@ +package com.xkrs.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.http.HttpEntity; +import org.apache.http.HttpStatus; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * 根据经纬度获取地址:省 市 区 位置名称 + * @author XinYi Song + */ +public class AddressUtils { + + /*public static String getLatAndLng(String lat, String lng) { + String key = "O7QBZ-ZYDKI-EMKGN-53UHG-5XSJF-AAFBP"; + try { + String hsUrl = "https://apis.map.qq.com/ws/geocoder/v1/?location=" + lat + "," + lng + "&key=" + key + "&get_poi=1"; + + URL url; + + url = new URL(hsUrl); + HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); + // 提交模式 + con.setRequestMethod("GET"); + X509TrustManager xtm = new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + // TODO Auto-generated method stub + } + + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + // TODO Auto-generated method stub + } + }; + + TrustManager[] tm = {xtm}; + + SSLContext ctx = SSLContext.getInstance("TLS"); + ctx.init(null, tm, null); + + con.setSSLSocketFactory(ctx.getSocketFactory()); + con.setHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String arg0, SSLSession arg1) { + return true; + } + }); + + + InputStream inStream = con.getInputStream(); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = 0; + while ((len = inStream.read(buffer)) != -1) { + outStream.write(buffer, 0, len); + } + //网页的二进制数据 + byte[] b = outStream.toByteArray(); + outStream.close(); + inStream.close(); + String rtn = new String(b, "utf-8"); + if (StringUtils.isNotBlank(rtn)) { + JSONObject object = JSONObject.fromObject(rtn); + if (object != null) { + if (object.has("status") && object.getInt("status") == 0) { + JSONObject result = JSONObject.fromObject(object.get("result")); + if (result != null) { + JSONObject addressComponent = JSONObject.fromObject(result.get("address_component")); + if (addressComponent != null) { + String province = (String) addressComponent.get("province"); + String city = (String) addressComponent.get("city"); + String district = (String) addressComponent.get("district"); + String street = (String) addressComponent.get("street"); + String street_number = (String) addressComponent.get("street_number"); + String address = province + city + district + street + street_number; + return address; + } + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + }*/ + + private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); + private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36"; + + /** + * 获取指定经纬度的地理位置 + * @param latitude 纬度 + * @param longitude 经度 + * @return + */ + public static String getLocal(String latitude, String longitude) { + String ok = "ok"; + String msg = "msg"; + String info = getAdd(latitude, longitude); + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = null; + try { + node = mapper.readTree(info); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + assert node != null; + String province = null; + String city = null; + String county = null; + String road = null; + String address = null; + if (ok.equals(node.path(msg).asText())) { + province = node.path("result").path("addressComponent").path("province").asText(); + city = node.path("result").path("addressComponent").path("city").asText(); + county = node.path("result").path("addressComponent").path("county").asText(); + road = node.path("result").path("addressComponent").path("road").asText(); + address = node.path("result").path("addressComponent").path("address").asText(); + } + String fireAddress = province + city + county + road + address; + return fireAddress; + } + /** + * 根据经纬度获取位置信息 + * @param latitude 纬度 + * @param longitude 经度 + * @return + */ + public static String getAdd(String latitude, String longitude) { + // 读取成功标志 + boolean isSuccess = false; + // 重复次数 + int count = 10; + ObjectMapper mapper = new ObjectMapper(); + Map paramMap = new HashMap<>(3); + paramMap.put("lon", longitude); + paramMap.put("lat", latitude); + paramMap.put("ver", "1"); + String paramStr = null; + try { + paramStr = mapper.writeValueAsString(paramMap); + } catch (JsonProcessingException e) { + log.error("转json失败,{}", (Object) e.getStackTrace()); + } + String url = String.format("http://api.tianditu.gov.cn/geocoder?type=geocode&tk=5a1d34815475f88e6d8802da6be832ae&postStr=%s", + paramStr); + // 创建http对象 + RequestConfig defaultRequestConfig = RequestConfig.custom() + .setSocketTimeout(60000).setConnectTimeout(60000) + .setConnectionRequestTimeout(60000) + .build(); + CloseableHttpClient client = HttpClients.custom() + .setDefaultRequestConfig(defaultRequestConfig).build(); + + // 创建并设置URI + URIBuilder uri = null; + // 创建Get请求 + HttpGet get = null; + + try { + URL url1 = new URL(url); + URI uri1 = new URI(url1.getProtocol(), url1.getHost(), url1.getPath(), url1.getQuery(), null); + uri = new URIBuilder(uri1); + get = new HttpGet(uri.build()); + // 设置请求头 + setGet(get); + } catch (URISyntaxException | MalformedURLException e) { + log.info("错误{}", (Object) e.getStackTrace()); + } + //发送请求 + HttpEntity entity = null; + InputStream is = null; + BufferedReader br = null; + // 创建响应对象 + CloseableHttpResponse response = null; + String line; + String sLine = null; + + String json = null; + while (!isSuccess && count > 0) { + try { + response = client.execute(get); + // 获取请求结果 + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + log.info("实时定位数据未请求成功"); + count--; + //close(is, br, response, client); + continue; + } + entity = response.getEntity(); + is = entity.getContent(); + br = new BufferedReader( + new InputStreamReader(is, StandardCharsets.UTF_8) + ); + StringBuilder sb = new StringBuilder(); + while ((line = br.readLine()) != null) { + sb.append(line); + } + sLine = sb.toString(); + sLine = sLine.substring(sLine.indexOf("{")); + //使用ObjectMapper对象对 User对象进行转换 + try { + json = mapper.writeValueAsString(sLine); + } catch (JsonProcessingException e) { + log.info("json字符串转化异常{}", (Object) e.getStackTrace()); + } + isSuccess = true; + + } catch (ClientProtocolException e) { + log.info("请求超时等问题:{}", (Object) e.getStackTrace()); + } catch (IOException e) { + log.info("I/O问题:{}", (Object) e.getStackTrace()); + } finally { + close(is, br, response, client); + } + } + return sLine; + } + + private static void close(InputStream is, BufferedReader br, CloseableHttpResponse response, CloseableHttpClient client){ + try { + if (null != is){ + is.close(); + } + if (null != br){ + br.close(); + } + if (null != response){ + response.close(); + } + if (null != client){ + client.close(); + } + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + } + } + + private static HttpGet setGet(HttpGet get) { + get.setHeader("Accept" + , "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); + get.setHeader("Accept-Encoding" + , "gzip, deflate"); + get.setHeader("Accept-Language" + , "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6"); + get.setHeader("Connection" + , "keep-alive"); + get.setHeader("Cache-Control" + , "no-cache"); + get.setHeader("Upgrade-Insecure-Requests" + , "1"); + get.setHeader("User-Agent", USER_AGENT); + return get; + } + + public static void main(String[] args) { + String latAndLng = getLocal("36.89", "115.90"); + System.out.println(latAndLng); + } +} diff --git a/src/main/java/com/xkrs/utils/AliYunSmsUtils.java b/src/main/java/com/xkrs/utils/AliYunSmsUtils.java new file mode 100644 index 0000000..7d91942 --- /dev/null +++ b/src/main/java/com/xkrs/utils/AliYunSmsUtils.java @@ -0,0 +1,67 @@ +package com.xkrs.utils; + +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.profile.DefaultProfile; +import com.aliyuncs.profile.IClientProfile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Xin + */ +public class AliYunSmsUtils { + public static Logger log = LoggerFactory.getLogger(AliYunSmsUtils.class); + /** + * 产品名称:云通信短信API产品,开发者无需替换 + */ + static final String product = "Dysmsapi"; + /** + * 产品域名,开发者无需替换 + */ + static final String domain = "dysmsapi.aliyuncs.com"; + /** + * TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找) + * TODO 修改成自己的 + */ + static final String accessKeyId = "LTAI5tMSjLfu8Xu2w6WeguFF"; + /** + * TODO 修改成自己的 + */ + static final String accessKeySecret = "hvqM5zpi72hvX4VXM71wq6AE0XYtDI"; + + public static SendSmsResponse sendSms(String telephone, String code) throws ClientException { + //可自助调整超时时间 + System.setProperty("sun.net.client.defaultConnectTimeout", "10000"); + System.setProperty("sun.net.client.defaultReadTimeout", "10000"); + //初始化acsClient,暂不支持region化 + IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret); + DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain); + IAcsClient acsClient = new DefaultAcsClient(profile); + //组装请求对象-具体描述见控制台-文档部分内容 + SendSmsRequest request = new SendSmsRequest(); + //必填:待发送手机号 + request.setPhoneNumbers(telephone); + //必填:短信签名-可在短信控制台中找到 + request.setSignName("青岛星科瑞升"); + //必填:短信模板-可在短信控制台中找到 + request.setTemplateCode("SMS_221082764"); + //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为 + //如果为发送验证码 无需修改 + request.setTemplateParam("{\"code\":\"" + code + "\"}"); + //选填-上行短信扩展码(无特殊需求用户请忽略此字段) + //request.setSmsUpExtendCode("90997"); + //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者 + //hint 此处可能会抛出异常,注意catch + SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); + if(sendSmsResponse.getCode()!= null && sendSmsResponse.getCode().equals("OK")){ + log.info("------------>短信发送成功!"); + }else { + log.info("------------>短信发送失败!"); + } + return sendSmsResponse; + } +} diff --git a/src/main/java/com/xkrs/utils/BeanUtils.java b/src/main/java/com/xkrs/utils/BeanUtils.java new file mode 100644 index 0000000..67c5ba2 --- /dev/null +++ b/src/main/java/com/xkrs/utils/BeanUtils.java @@ -0,0 +1,73 @@ +package com.xkrs.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; + +/** + * @author xkrs + */ +public class BeanUtils { + + /** + * 缓存BeanCopier 对象 提升性能 + */ + private static final ConcurrentHashMap BEAN_COPIER_MAP = new ConcurrentHashMap<>(); + + + /** + * Bean属性复制工具方法。 + * @param sources 原始集合 + * @param supplier: 目标类::new(eg: UserVO::new) + */ + public static List cgLibCopyList(List sources, Supplier supplier) { + List list = new ArrayList<>(sources.size()); + org.springframework.cglib.beans.BeanCopier beanCopier = null; + for (S source : sources) { + T t = supplier.get(); + if (beanCopier == null) { + beanCopier = getBeanCopier(source.getClass(), t.getClass()); + } + beanCopier.copy(source, t, null); + list.add(t); + } + return list; + } + + /** + * Bean属性复制工具方法。 + * @param source 目标对象 + * @param supplier: 目标类::new(eg: UserVO::new) + */ + public static T cgLibCopyBean(Object source, Supplier supplier) { + T t = supplier.get(); + getBeanCopier(source.getClass(), t.getClass()).copy(source, t, null); + return t; + } + + + /** + * 获取BeanCopier对象 如果缓存中有从缓存中获取 如果没有则新创建对象并加入缓存 + * @param sourceClass + * @param targetClass + * @return + */ + private static org.springframework.cglib.beans.BeanCopier getBeanCopier(Class sourceClass, Class targetClass) { + String key = getKey(sourceClass.getName(), targetClass.getName()); + org.springframework.cglib.beans.BeanCopier beanCopier; + beanCopier = BEAN_COPIER_MAP.get(key); + if (beanCopier == null) { + beanCopier = org.springframework.cglib.beans.BeanCopier.create(sourceClass, targetClass, false); + BEAN_COPIER_MAP.put(key, beanCopier); + } + return beanCopier; + } + + /** + * 生成缓存key + */ + private static String getKey(String sourceClassName, String targetClassName) { + return sourceClassName + targetClassName; + } +} diff --git a/src/main/java/com/xkrs/utils/CopyPropertiesUtil.java b/src/main/java/com/xkrs/utils/CopyPropertiesUtil.java new file mode 100644 index 0000000..03155f8 --- /dev/null +++ b/src/main/java/com/xkrs/utils/CopyPropertiesUtil.java @@ -0,0 +1,54 @@ +package com.xkrs.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * 复制源对象的属性值 + * @Author tajochen + */ +public class CopyPropertiesUtil { + + /** + * 复制源对象和目标对象的属性值 + * @param source 源对象 + * @param target 目标对象 + * @throws SecurityException + * @throws IllegalArgumentException + */ + public static void copy(Object source, Object target) { + //得到对象的Class + Class sourceClass = source.getClass(); + Class targetClass = target.getClass(); + //得到Class对象的所有属性 + Field[] sourceFields = sourceClass.getDeclaredFields(); + Field[] targetFields = targetClass.getDeclaredFields(); + + for(Field sourceField : sourceFields){ + //属性名 + String name = sourceField.getName(); + //属性类型 + Class type = sourceField.getType(); + String methodName = name.substring(0, 1).toUpperCase() + name.substring(1); + try{ + //得到属性对应get方法 + Method getMethod = sourceClass.getMethod("get" + methodName); + //执行源对象的get方法得到属性值 + Object value = getMethod.invoke(source); + //目标对象的属性名 + for(Field targetField : targetFields){ + String targetName = targetField.getName(); + if(targetName.equals(name)){ + //属性对应的set方法 + Method setMethod = targetClass.getMethod("set" + methodName, type); + //执行目标对象的set方法 + setMethod.invoke(target, value); + } + } + } + catch (Exception e){ + e.printStackTrace(); + } + } + } +} diff --git a/src/main/java/com/xkrs/utils/DateTimeUtil.java b/src/main/java/com/xkrs/utils/DateTimeUtil.java new file mode 100644 index 0000000..2cd1f8b --- /dev/null +++ b/src/main/java/com/xkrs/utils/DateTimeUtil.java @@ -0,0 +1,228 @@ +package com.xkrs.utils; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 日期时间工具 + * @author tajochen + */ +public class DateTimeUtil { + + private final static String COMMON_PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss"; + private final static String COMMON_PATTERN_DATE = "yyyy-MM-dd"; + private final static DateTimeFormatter COMMON_FORMATTER_DATETIME = DateTimeFormatter.ofPattern(COMMON_PATTERN_DATETIME); + private final static DateTimeFormatter COMMON_FORMATTER_DATE = DateTimeFormatter.ofPattern(COMMON_PATTERN_DATE); + private final static ZoneOffset DEFAULT_ZONE_OFFSET = ZoneOffset.of("+8"); + + /** + * 字符串转LocalDate + * @param date + * @return + */ + public static LocalDate stringToDate(String date) { + assert date != null; + return LocalDate.parse(date, COMMON_FORMATTER_DATE); + } + + /** + * LocalDate转字符串 + * @param date + * @return + */ + public static String dateToString(LocalDate date) { + assert date != null; + return COMMON_FORMATTER_DATE.format(date); + } + + /** + * LocalDateTime转字符串 + * @param dateTime + * @return + */ + public static String dateTimeToString(LocalDateTime dateTime) { + assert dateTime != null; + return COMMON_FORMATTER_DATETIME.format(dateTime); + } + + /** + * 字符串转LocalDateTime + * @param dateStr + * @return + */ + public static LocalDateTime stringToDateTime(String dateStr) { + assert dateStr != null; + return LocalDateTime.parse(dateStr, COMMON_FORMATTER_DATETIME); + } + + /** + * 字符串转Instant时间戳 + * @param str + * @return + */ + public static Instant stringToInstant(String str) { + assert str != null; + return stringToDateTime(str).toInstant(DEFAULT_ZONE_OFFSET); + } + + /** + * LocalDateTime转字符串(格式化) + * @param dateTime + * @param formatter + * @return + */ + public static String dateToStringFormatter(LocalDateTime dateTime, DateTimeFormatter formatter) { + assert dateTime != null; + return formatter.format(dateTime); + } + + /** + * 字符串转LocalDateTime(格式化) + * @param dateStr + * @param formatter + * @return + */ + public static LocalDateTime stringToDateTimeFormatter(String dateStr, DateTimeFormatter formatter) { + assert dateStr != null; + return LocalDateTime.parse(dateStr, formatter); + } + + /** + * 字符串转 local date + * @param dateStr + * @return + */ + public static LocalDate stringToDateFormatter(String dateStr){ + LocalDate date = LocalDate.parse(dateStr, COMMON_FORMATTER_DATE); + return date; + } + + + /** + * 日期转时间戳 + * @param dateTime + * @return + */ + public static long dateToTimeMillis(LocalDateTime dateTime) { + assert dateTime != null; + return dateTime.toInstant(DEFAULT_ZONE_OFFSET).toEpochMilli(); + } + + /** + * 时间戳转日期 + * @param timeMillis + * @return + */ + public static LocalDateTime timeMillisToDate(long timeMillis) { + Instant instant = Instant.ofEpochMilli(timeMillis); + return LocalDateTime.ofInstant(instant, DEFAULT_ZONE_OFFSET); + } + + /** + * 时间戳转时间 + * @param timeMillis + * @return + */ + public static LocalDateTime timeMillisToTime(long timeMillis) { + LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timeMillis, 0, ZoneOffset.ofHours(8)); + return localDateTime; + } + + /** + * 时间戳转时间再转字符串 + * @param timeMillis + * @return + */ + public static String timeMillisToString(long timeMillis){ + LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(timeMillis, 0, ZoneOffset.ofHours(8)); + return COMMON_FORMATTER_DATETIME.format(localDateTime); + } + + /** + * 获取当前时间 hh:mm:ss:nnn + * @return + */ + public static LocalDateTime getNowTime() { + LocalDateTime now = LocalDateTime.now(); + return now; + } + + /** + * 获取当前日期 yyyy-MM-dd + * @return + */ + public static LocalDate getToday() { + LocalDate now = LocalDate.now(); + return now; + } + + /** + * 获取当前 Instant 时间戳 + * @return + */ + public static Instant getInstant() { + Instant timeStamp = Instant.now(); + return timeStamp; + } + + /** + * 获取当前时间 yyyy-MM-ss hh:mm:ss + * @return + */ + public static String getNowTimeStr(){ + return COMMON_FORMATTER_DATETIME.format(getNowTime()); + } + + /** + * 判断日期格式是否合法 "yyyy-MM-dd" + * @param strDate + * @return + */ + public static boolean isValidDate(String strDate) { + final int minLen = 10; + if(strDate == null || strDate.length() < minLen) { + return false; + } + //正则表达式校验日期格式 yyyy-MM-dd + String eL = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-" + + "(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})" + + "(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)(([0-9]{3}[1-9]|[0-9]{2}[1-9]" + + "[0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-" + + "(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|" + + "((0[48]|[2468][048]|[3579][26])00))-02-29)"; + Pattern pat = Pattern.compile(eL); + Matcher matcher = pat.matcher(strDate); + return matcher.matches(); + } + + /** + * 判断时间格式 格式必须为 "YYYY-MM-DD HH:mm:ss" + * @param sDateTime + * @return + */ + public static boolean isValidDateTime(String sDateTime) { + final int minLen = 19; + if ((sDateTime == null) || (sDateTime.length() < minLen)) { + return false; + } + String eL = "(((01[0-9]{2}|0[2-9][0-9]{2}|[1-9][0-9]{3})-(0?[13578]|1[02])-" + + "(0?[1-9]|[12]\\\\d|3[01]))|((01[0-9]{2}|0[2-9][0-9]{2}|[1-9][0-9]{3})-" + + "(0?[13456789]|1[012])-(0?[1-9]|[12]\\\\d|30))|((01[0-9]{2}|0[2-9][0-9]{2}|[1-9][0-9]{3})-0?2-" + + "(0?[1-9]|1\\\\d|2[0-8]))|(((1[6-9]|[2-9]\\\\d)(0[48]|[2468][048]|[13579][26])|((04|08|12|16|[2468][048]|" + + "[3579][26])00))-0?2-29)) (20|21|22|23|[0-1]?\\\\d):[0-5]?\\\\d:[0-5]?\\\\d"; + Pattern pat = Pattern.compile(eL); + Matcher matcher = pat.matcher(sDateTime); + return matcher.matches(); + } + + public static void main(String[] args) { + long l = dateToTimeMillis(LocalDateTime.now()); + System.out.println("------"+l); + } + +} diff --git a/src/main/java/com/xkrs/utils/EncryptDecryptUtil.java b/src/main/java/com/xkrs/utils/EncryptDecryptUtil.java new file mode 100644 index 0000000..7ef363e --- /dev/null +++ b/src/main/java/com/xkrs/utils/EncryptDecryptUtil.java @@ -0,0 +1,66 @@ +package com.xkrs.utils; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * SHA加密解密工具 + * @author tajochen + */ +public class EncryptDecryptUtil { + + /** + * SHA-256加密 + * @param strText + * @return + */ + public static String encry256(final String strText){ + return encrySha(strText,"SHA-256"); + } + + /** + * SHA-512加密 + * @param strText + * @return + */ + public static String encry512(final String strText){ + return encrySha(strText,"SHA-512"); + } + + /** + * 基础SHA加密 + * @param strText + * @param strType + * @return + */ + private static String encrySha(final String strText, final String strType){ + // 返回值 + String strResult=null; + // 是否是有效的字符串 + if (strText != null && strText.length()>0){ + // 加密开始,创建加密对象,并传入加密类型 + try { + MessageDigest messageDigest = MessageDigest.getInstance(strType); + // 传入加密的字符串 + messageDigest.update(strText.getBytes()); + // 得到bytes类型结果 + byte[] byteBuffer = messageDigest.digest(); + StringBuilder strHexString = new StringBuilder(); + for (byte b : byteBuffer) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + strHexString.append('0'); + } + strHexString.append(hex); + } + // 得到返回的结果 + strResult = strHexString.toString(); + } + catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + } + return strResult; + } +} + diff --git a/src/main/java/com/xkrs/utils/EntityManagerUtil.java b/src/main/java/com/xkrs/utils/EntityManagerUtil.java new file mode 100644 index 0000000..ac1ede1 --- /dev/null +++ b/src/main/java/com/xkrs/utils/EntityManagerUtil.java @@ -0,0 +1,36 @@ +package com.xkrs.utils; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; + +/** + * @author XinYi Song + */ +public class EntityManagerUtil { + /** + * 把List转换成List + */ + public static List objectToBean(List objList, Class clz) throws Exception{ + if (objList==null || objList.size()==0) { + return null; + } + + Class[] cz = null; + Constructor[] cons = clz.getConstructors(); + for (Constructor ct : cons) { + Class[] clazz = ct.getParameterTypes(); + if (objList.get(0).length == clazz.length) { + cz = clazz; + break; + } + } + + List list = new ArrayList(); + for (Object[] obj : objList) { + Constructor cr = clz.getConstructor(cz); + list.add(cr.newInstance(obj)); + } + return list; + } +} diff --git a/src/main/java/com/xkrs/utils/ExcelImportUtil.java b/src/main/java/com/xkrs/utils/ExcelImportUtil.java new file mode 100644 index 0000000..8788901 --- /dev/null +++ b/src/main/java/com/xkrs/utils/ExcelImportUtil.java @@ -0,0 +1,193 @@ +package com.xkrs.utils; + +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.web.multipart.MultipartFile; + +import java.io.InputStream; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * @author ZHY + * @date 2020/6/17 15:56 + */ +public class ExcelImportUtil { + private Workbook wb; + private Sheet sheet; + private Row row; + + String xls = ".xls"; + String xlsx = ".xlsx"; + + /** + * 读取Excel + * + * @author ZHY + */ + public ExcelImportUtil(MultipartFile file) throws Exception { + String filename = file.getOriginalFilename(); + String ext = filename.substring(filename.lastIndexOf(".")); + InputStream is = file.getInputStream(); + if (xls.equals(ext)) { + wb = new HSSFWorkbook(is); + } else if (xlsx.equals(ext)) { + wb = new XSSFWorkbook(is); + } else { + wb = null; + } + } + + /** + * 读取Excel表格表头的内容输出 + * + */ + public List> readExcelTitleOut() { + List> list = new ArrayList>(); + if (wb != null) { + sheet = wb.getSheetAt(0); + row = sheet.getRow(0); + // 标题总列数 + int colNum = row.getPhysicalNumberOfCells(); + + System.out.println("colNum:" + colNum); + + Map map = new LinkedHashMap(); + + for (int i = 0; i < colNum; i++) { + String stringCellValue = row.getCell(i).getStringCellValue(); + map.put(stringCellValue, null); + } + list.add(map); + return list; + } + return list; + } + + /** + * 读取Excel表格表头 + * + */ + public String[] readExcelTitle() { + String[] title = {}; + if (wb != null) { + sheet = wb.getSheetAt(0); + row = sheet.getRow(0); + // 标题总列数 + int colNum = row.getPhysicalNumberOfCells(); + + System.out.println("colNum:" + colNum); + + title = new String[colNum]; + + for (int i = 0; i < colNum; i++) { + Cell cell = row.getCell(i); + title[i] = cell.getStringCellValue().replaceAll("\\s+", ""); + } + } + return title; + } + + /** + * 读取Excel表格的某一个数值 + * @return + */ + public Map readExcelSomeTitle(){ + Map map = new LinkedHashMap<>(); + if (wb != null) { + sheet = wb.getSheetAt(0); + String title = parseExcel(sheet.getRow(2).getCell(1)); + String remark = parseExcel(sheet.getRow(3).getCell(1)); + map.put("date",title); + map.put("remark",remark); + } + return map; + } + + /** + * 读取Excel数据内容 + * + */ + public List> readExcelContent() { + List> list = new ArrayList<>(); + if (wb != null) { + //获取sheet表 + sheet = wb.getSheetAt(0); + // 得到总行数 + int rowNum = sheet.getLastRowNum(); + //获取表头的标题 + String[] readExcelTitle = readExcelTitle(); + // 正文内容应该从第二行开始,第一行为表头的标题 + for (int i = 1; i <= rowNum; i++) { + row = sheet.getRow(i); + if (row == null) { + continue; + } + Map map = new LinkedHashMap<>(); + for (int j = 0; j < readExcelTitle.length; j++) { + //获取每一列的数据值 + String str = parseExcel(row.getCell(j)); + //判断对应行的列值是否为空 + if (str != null || "".equals(str)) { + //表头的标题为键值,列值为值 + map.put(readExcelTitle[j], str); + } + } + //判段添加的对象是否为空 + if (!map.isEmpty()){ + list.add(map); + } + } + } + return list; + } + + /** + * + * 根据Cell类型设置数据 + * + */ + int ss = 20; + int xx = 58; + private String parseExcel(Cell cell) { + String result = ""; + if (cell != null) { + SimpleDateFormat sdf = null; + switch (cell.getCellType()) { + // 数字类型 + case NUMERIC: + // 处理日期格式、时间格式 + if (DateUtil.isCellDateFormatted(cell)) { + if (cell.getCellStyle().getDataFormat() == ss) { + sdf = new SimpleDateFormat("HH:mm"); + } else {// 日期 + sdf = new SimpleDateFormat("yyyy-MM-dd"); + } + String dateFormat = sdf.format(cell.getDateCellValue()); + result = dateFormat; + } else if (cell.getCellStyle().getDataFormat() == xx) { + // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58) + sdf = new SimpleDateFormat("yyyy-MM-dd"); + double value = cell.getNumericCellValue(); + Date date = DateUtil.getJavaDate(value); + result = sdf.format(date); + } else { + double value = cell.getNumericCellValue(); + DecimalFormat format = new DecimalFormat("#.###########"); + String strVal = format.format(value); + result = strVal; + } + break; + // String类型 + case STRING: + result = cell.getRichStringCellValue().toString(); + break; + default: + break; + } + } + return result; + } +} diff --git a/src/main/java/com/xkrs/utils/FileFastDfs.java b/src/main/java/com/xkrs/utils/FileFastDfs.java new file mode 100644 index 0000000..2ec28d9 --- /dev/null +++ b/src/main/java/com/xkrs/utils/FileFastDfs.java @@ -0,0 +1,477 @@ +package com.xkrs.utils; + +import cn.hutool.core.io.resource.InputStreamResource; +import cn.hutool.core.thread.ThreadUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.tus.java.client.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.HashMap; +import java.util.Objects; + +/** + * @author dong + * @date 2020/12/31 + */ +@Component +public class FileFastDfs { + + @Value("${dfs.ip}") + public String ip; + @Value("${dfs.port}") + public String port; + +// @Value("${dfs.upload}") +// public String upload; +// +// @Value("${dfs.delete}") +// public String delete; + + @Resource + private KafkaTemplate kafkaTemplate; + private static final Logger log = LoggerFactory.getLogger(FileFastDfs.class); + private static final String STATUS = "status"; + private static final String UPLOAD_BIG_PATH = "http://192.168.2.166:2001/group1/big/upload"; + private static final String UPLOAD_PATH = "http://192.168.2.166:2001/group1/upload"; + + /** + * 文件上传到dfs服务器 + * @param file + * @param dir + * @return + */ + public String uploadFile(MultipartFile file, String dir) { + File file1 = null; + InputStreamResource isr = null; + try { + file1 = multipartFileToFile(file); + isr=new InputStreamResource(file.getInputStream(), + file.getOriginalFilename()); + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + } catch (Exception e) { + e.printStackTrace(); + } + //文件地址 + //声明参数集合 + HashMap paramMap = new HashMap<>(7); + //文件 + paramMap.put("file", isr); + //输出 + paramMap.put("output", "json"); + //自定义路径 + paramMap.put("path", dir); + //场景 文件分类 + if (null == file1) { + return null; + } + String name = file1.getName(); + System.err.println("file:" + file1.getName()); + paramMap.put("scene", name.substring(name.lastIndexOf(".") + 1)); + paramMap.put("fileName", System.currentTimeMillis() + "" + + Objects.requireNonNull(file.getOriginalFilename()) + .substring(file.getOriginalFilename().lastIndexOf("."))); + System.err.println(paramMap); + // + String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/upload", paramMap); + System.err.println(result); + + // 拿出状态码,判断上传状态 + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = null; + try { + node = mapper.readTree(result); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + final String fail = "fail"; + if (null != node) { + if (fail.equals(node.path(STATUS).asText())) { + return null; + } + } + return result; + } + + /** + * @description: 文件上传到dfs服务器 + * @params [file:File 文件, dir 文件存放路径] + * @author: wd + * @time: 2020/3/31 2020/3/31 + */ + public String uploadFile(File file, String dir) { + //文件地址 + //声明参数集合 + HashMap paramMap = new HashMap<>(7); + //文件 + paramMap.put("file", file); + //输出 + paramMap.put("output", "json"); + //自定义路径 + paramMap.put("path", dir); + //场景 +// System.err.println(file.getName()); + + // paramMap.put("fileName", System.currentTimeMillis() + "" + file.getName().substring(file.getName().lastIndexOf("."))); + paramMap.put("fileName", file.getName()); + System.err.println(paramMap); + //上传 + String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/upload", paramMap); + System.err.println(result); + // 拿出状态码,判断上传状态 + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = null; + try { + node = mapper.readTree(result); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + final String status = "status"; + final String statusFail = "fail"; + if (null != node) { + if (statusFail.equals(node.path(status).asText())) { + return null; + } + } + return result; + } + + /** + * @description: 文件上传到dfs服务器 + * @params [file:File 文件, dir 文件存放路径] + * @author: wd + * @time: 2020/3/31 2020/3/31 + */ + public String uploadFile(File file, String dir, String fileType) { + //文件地址 + //声明参数集合 + HashMap paramMap = new HashMap<>(7); + //文件 + paramMap.put("file", file); + //输出 + paramMap.put("output", "json"); + //自定义路径 + paramMap.put("path", dir); + //场景 + System.err.println(file.getName()); + + // paramMap.put("fileName", System.currentTimeMillis() + "" + file.getName().substring(file.getName().lastIndexOf("."))); + paramMap.put("fileName", file.getName()); + paramMap.put("scene", fileType); + System.err.println(paramMap); + //上传 + String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/upload", paramMap); + System.err.println(result); + // 拿出状态码,判断上传状态 + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = null; + try { + node = mapper.readTree(result); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + final String status = "status"; + final String statusFail = "fail"; + if (null != node) { + if (statusFail.equals(node.path(status).asText())) { + return null; + } + } + return result; + } + + public String uploadBigFile(File file, String dir, String fileType) { + // 下面这个一定要注意,如果不设置为true,将会直接返回301 + System.setProperty("http.strictPostRedirect", Boolean.toString(true)); + TusClient tusClient = new TusClient(); + try { + tusClient.setUploadCreationURL(new URL(UPLOAD_BIG_PATH)); + +// tusClient.enableResuming(new TusRedisUrlStrore()); + tusClient.enableResuming(new TusURLMemoryStore()); + + final TusUpload upload = new TusUpload(file); + System.out.println("start upload......"); + TusExecutor executor = new TusExecutor() { + @Override + protected void makeAttempt() throws ProtocolException, IOException { + TusUploader uploader = tusClient.resumeOrCreateUpload(upload); + uploader.setChunkSize(1024 * 1024); + + long start = System.currentTimeMillis(); + do { + long totalBytes = upload.getSize(); + long bytesUploaded = uploader.getOffset(); + double progress = (double) bytesUploaded / totalBytes * 100; + + System.out.printf("Upload at %06.2f%%.\n", progress); + } while (uploader.uploadChunk() > -1); + + uploader.finish(); + + String uploadUrl = uploader.getUploadURL().toString(); + System.out.println("Upload finished."); + System.out.format("Upload available at: %s\n", uploadUrl); + + long end = System.currentTimeMillis(); + + System.out.println((end - start) + "ms"); + // 使用hutool进行秒传置换url + String fileId = StrUtil.subAfter(uploadUrl, UPLOAD_BIG_PATH + "/", true); + System.out.println("fileId: " + fileId); + String url = StrUtil.format("{}?md5={}&output=json", UPLOAD_PATH, fileId); + System.out.println("url: " + url); + // 上传大文件的时候(1.xG)需要sleep一下,要不然会有问题 + ThreadUtil.sleep(5000); + String result = HttpUtil.get(url); + } + }; + executor.makeAttempts(); + } catch (IOException | ProtocolException e) { + e.printStackTrace(); + } + return null; + } + + /** + * @description: 文件base64流获取 + * @params [fileName : 文件路径] + * @return: java.lang.String + * @author: chqf + * @time: 2020/3/31 2020/3/31 + */ + public String getBase64(String fileName) { + if (fileName == null || "".equals(fileName)) { + return null; + } + InputStream fis = null; + URL url = null; + try { + url = new URL("http://" + ip + ":" + port + "/" + URLEncoder.encode(fileName, StandardCharsets.UTF_8)); + System.err.println(url); + fis = url.openStream(); + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + } + final ByteArrayOutputStream data = new ByteArrayOutputStream(); + String imgStr = ""; + try { + if (fis == null) { + return null; + } + int len = -1; + byte[] buf = new byte[2048]; + while (-1 != (len = fis.read(buf, 0, buf.length))) { + data.write(buf, 0, len); + } + Base64.Encoder encoder = Base64.getEncoder(); + imgStr = encoder.encodeToString(data.toByteArray()); + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + }finally { + try { + if (null != fis) { + fis.close(); + } + data.close(); + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + } + } + + return "data:image/jpeg;base64," + imgStr; + } + + /** + * @description: 文件格式转换multipartFil 转为 File 格式 + * @params [file] + * @return: java.io.File + * @author: dong + * @time: 2020/3/31 2020/3/31 + */ + public File multipartFileToFile(MultipartFile file) throws Exception { + + File toFile = null; + if ("".equals(file) || file.getSize() <= 0) { + file = null; + } else { + InputStream ins; + ins = file.getInputStream(); + toFile = new File(Objects.requireNonNull(file.getOriginalFilename())); + inputStreamToFile(ins, toFile); + ins.close(); + } + return toFile; + } + + private static void inputStreamToFile(InputStream ins, File file) { + OutputStream os = null; + try { + os = new FileOutputStream(file); + int bytesRead = 0; + byte[] buffer = new byte[8192]; + while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { + os.write(buffer, 0, bytesRead); + } + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + }finally { + try { + if (null != os) { + os.close(); + } + if (null != ins) { + ins.close(); + } + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + } + } + } + + /** + * @description: 文件base64流获取 + * @params [fileName : 文件路径] + * @return: java.lang.String + * @author: dong + * @time: 2020/3/31 2020/3/31 + */ + public Boolean getFile(String fileName, HttpServletResponse response) { + if (fileName == null || "".equals(fileName)) { + return null; + } + InputStream fis = null; + URL url = null; + try { + url = new URL("http://" + ip + ":" + port + "/" + URLEncoder.encode(fileName, StandardCharsets.UTF_8)); + System.err.println(url); + fis = url.openStream(); + response.reset(); + response.setContentType("bin"); + response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + } + // + byte[] b = new byte[256]; + int len; + try { + assert fis != null; + while ((len = fis.read(b)) > 0){ + response.getOutputStream().write(b, 0, len); + } + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + }finally { + try { + if (null != fis) { + fis.close(); + } + } catch (IOException e) { + log.info("IO错误{}", (Object) e.getStackTrace()); + } + } + return true; + } + + /** + * 删除文件 path + * @param filePath 文件路径 上传返回的path + * @return + */ + public Boolean deleteFileByPath(String filePath) { + if (filePath == null || "".equals(filePath)) { + return false; + } + HashMap paramMap = new HashMap<>(1); + // 参数 + paramMap.put("path", filePath); + + String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/delete", paramMap); + System.out.println(result); + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = null; + try { + node = mapper.readTree(result); + } catch (JsonProcessingException e) { + + e.printStackTrace(); + } + + final String statusOk = "ok"; + + if (null == node) { + log.error("返回结果为空"); + return false; + } + if (!statusOk.equals(node.path(STATUS).asText())) { + log.error("未删除成功"); + return false; + } + return true; + } + + /** + * 删除文件 path + * @param md5 上传返回的md5 + * @return + */ + public Boolean deleteFileByMd5(String md5) { + if (md5 == null || "".equals(md5)) { + return false; + } + HashMap paramMap = new HashMap<>(1); + // 参数 + paramMap.put("md5", md5); + + String result = HttpUtil.post("http://" + ip + ":" + port + "/group1/delete", paramMap); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode node = null; + try { + node = mapper.readTree(result); + } catch (JsonProcessingException e) { + + e.printStackTrace(); + } + final String status = "status"; + final String statusOk = "ok"; + + if (null == node) { + log.error("返回结果为空"); + return false; + } + if (!statusOk.equals(node.path(status).asText())) { + log.error("未删除成功"); + return false; + } + return true; + } + + + + + + public static void main(String[] args) { + File file = new File("C:\\Users\\dong\\Desktop\\遥感影像\\遥感影像\\GF1\\GF1_PMS1_E116.8_N36.6_20190528_L1A0004026837-MSS1_ORTHO_MS.tif"); + FileFastDfs fileFastDfs = new FileFastDfs(); + } +} + + diff --git a/src/main/java/com/xkrs/utils/FileUtil.java b/src/main/java/com/xkrs/utils/FileUtil.java new file mode 100644 index 0000000..6a2d201 --- /dev/null +++ b/src/main/java/com/xkrs/utils/FileUtil.java @@ -0,0 +1,250 @@ +package com.xkrs.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.xkrs.utils.DateTimeUtil.getNowTimeStr; + +public class FileUtil { + private static final Logger log = LoggerFactory.getLogger(FileUtil.class); + + /** + * 判断目录是否存在, 不存在创建 + * @param path 路径,目录最后带 File.separator + * @return + */ + public static boolean isFileExit(String path){ + path = path.replace("/",File.separator); + File file = new File(path); + if (file.exists()) { + log.info("文件已存在"); + return true; + } + if(path.endsWith(File.separator)) { + log.info("创建单个文件" + path + "失败,目标不能是目录!"); + return false; + } + if(!file.getParentFile().exists()) { + log.info("目标文件所在路径不存在,准备创建。。。"); + if (file.getParentFile().mkdirs()) { + if (file.mkdir()) { + log.info("创建目录文件成功!"); + } + } + } else { + log.info("目标文件所在路径存在"); + if (file.mkdir()) { + log.info("创建目录文件成功!"); + } + } + return true; + } + + /** + * 获取目录下的所有文件 + * @param filePath 目录 + * @return + * @throws Exception + */ + public static List showListFile(String filePath) { + File dir = new File(filePath); + List list = new ArrayList<>(); + // 查找参数文件是否存在,只检查第一个入参 + if(!dir.exists()) { + log.error("找不到文件"); + } + // 如果是目录那么进行递归调用 + if(dir.isDirectory()) { + // 获取目录下的所有文件 + File[] f = dir.listFiles(); + // 进行递归调用,最后总会返回一个list + assert f != null; + for (File file : f) { + list.addAll(showListFile(file.getPath())); + } + }else { + // 不是目录直接添加进去,判断是否为xml文件 + list.add(dir.getPath()); + } + return list; + } + + /** + * 移动文件到目标目录 + * @param path 文件路径 + * @return + */ + /*public static FileEntity mvFile(String path){ + String savePath = "D:" + File.separator + "dms" + File.separator + "data" ; + + File file = new File(path); + if (!file.isFile()) { + log.info("{}不是文件。",path); + return null; + } + // 从文件名获取到入库信息 暂时不知道 + String[] infos = path.split("/"); + String fileNameUnHandler = infos[infos.length - 1]; + String[] fileNameUnHandlerSplitWithPoint = fileNameUnHandler.split("."); + String fileName = fileNameUnHandlerSplitWithPoint[0]; + String scene = fileNameUnHandlerSplitWithPoint[1]; + String[] fileNames = fileNameUnHandler.split("_"); + long length = file.length(); + String filePath = File.separator + scene + File.separator + fileName; +// savePath = savePath + File.separator + dir + File.separator + fileName; + if (isFileExit(savePath + File.separator + scene)) { + if (file.renameTo(new File(filePath))) { + log.info("移动文件{}到{}目录",file.getName(), savePath + filePath); + } else { + log.info("文件{}移动失败",file.getName()); + return null; + } + } + return null; + }*/ + + /** + * 读取txt文件内容 + * @param file + * @return + */ + public static String txt2String(File file){ + StringBuilder result = new StringBuilder(); + try{ + //构造一个BufferedReader类来读取文件 + BufferedReader br = new BufferedReader(new FileReader(file)); + String s = null; + //使用readLine方法,一次读一行 + while((s = br.readLine())!=null){ + result.append(System.lineSeparator()).append(s); + } + br.close(); + }catch(Exception e){ + e.printStackTrace(); + } + return result.toString(); + } + + /** + * 确定上传文件路径遥感数据 栅格 + * @param file 文件 + * @return + */ + public static String fileRsSaveType(File file) { + String name = file.getName(); + String suffix = name.substring(name.indexOf(".")); + // 判断是否为栅格数据 + if (!suffix.contains("tif")) { + return null; + } + // GF1_PMS1_E116.8_N36.6_20190528_L1A0004026837-MSS1_ORTHO_MS.tif + String[] s = name.split("_"); + // 卫星种类 + String satelliteType = s[0]; + // 传感器种类 + String sensorType = s[1]; + // 中心点经度 + String lat = s[2]; + // 中心点纬度 + String lon = s[3]; + // 时间 + String time = s[4]; + String year = time.substring(0, 4); + String month = time.substring(4, 6); + String day = time.substring(6); + // 产品号 + String product = s[5]; + String productLevel = product.substring(0, 3); + String productCode = product.substring(3); + // 种类 + String type = s[6]; + // 文件路径 + String filePath = "/" + satelliteType + "/" + sensorType + "/" + productLevel + "/" + year + "/" + month + "/" + + day + "/" + productCode + "/"; + + return filePath; + } + + /** + * 矢量数据路径 + * C:\Users\dong\Desktop\2018年山东省矢量数据\2018年山东省矢量数据\2018年动态\分县动态\山东.gdb\sa.gdb + * @param file + * @return + */ + public static String fileShpSavePath(File file) { + if (file.exists()) { + if (file.isFile()) { + String path = file.getPath(); + String[] dirNames = path.split("\\\\"); + StringBuffer sb = new StringBuffer(); + int length = dirNames.length; + final int minLength = 5; + if (length >= minLength) { + for (int i = 5; i > 1; i--) { + sb.append("/").append(dirNames[length - i]); + } + return sb.toString(); + } + } + } + return null; + } + + public static Map getUploadInfo(String info) { + final String statusFail = "fail"; + final String status = "status"; + ObjectMapper mapper = new ObjectMapper(); + JsonNode resultNode = null; + Map map = new HashMap<>(); + try { + resultNode = mapper.readTree(info); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + if (!statusFail.equals(resultNode.path(status).asText())) { + String path = resultNode.path("path").asText(); + String fileName = path.substring(path.lastIndexOf("/") + 1); + map.put("md5", resultNode.path("md5").asText()); + map.put("mtime", getNowTimeStr()); + map.put("path", path); + map.put("scene", resultNode.path("scene").asText()); + map.put("size", resultNode.path("size").asText()); + map.put("url", resultNode.path("url").asText()); + map.put("fileName", fileName); + } + return map; + } + + public static boolean checkFileSize(Long len, int size, String unit) { + double fileSize = 0; + if ("B".equals(unit.toUpperCase())) { + fileSize = (double) len; + } else if ("K".equals(unit.toUpperCase())) { + fileSize = (double) len / 1024; + } else if ("M".equals(unit.toUpperCase())) { + fileSize = (double) len / 1048576; + } else if ("G".equals(unit.toUpperCase())) { + fileSize = (double) len / 1073741824; + } + if (fileSize > size) { + return false; + } + return true; + } + + public static void main(String[] args) { + String s = "C:/Users/dong/Desktop/2018年山东省矢量数据/2018年山东省矢量数据/2018年动态/分县动态/山东.gdb/a0000000a.gdbindexes"; + fileShpSavePath(new File(s)); + } +} diff --git a/src/main/java/com/xkrs/utils/HashUtil.java b/src/main/java/com/xkrs/utils/HashUtil.java new file mode 100644 index 0000000..2aa3a99 --- /dev/null +++ b/src/main/java/com/xkrs/utils/HashUtil.java @@ -0,0 +1,40 @@ +package com.xkrs.utils; + +import java.security.MessageDigest; + +/** + * md5加密解密工具 + * @author tajochen + */ +public class HashUtil { + + /** + * MD5加密 + * + * @param password + * @return + */ + public static String md5Encode(String password) { + MessageDigest md5 = null; + try { + md5 = MessageDigest.getInstance("MD5"); + } catch (Exception e) { + throw new RuntimeException(e); + } + char[] charArray = password.toCharArray(); + byte[] byteArray = new byte[charArray.length]; + for (int i = 0; i < charArray.length; i++){ + byteArray[i] = (byte) charArray[i]; + } + byte[] md5Bytes = md5.digest(byteArray); + StringBuilder hexValue = new StringBuilder(); + for (byte md5Byte : md5Bytes) { + int val = ((int) md5Byte) & 0xff; + if (val < 16) { + hexValue.append("0"); + } + hexValue.append(Integer.toHexString(val)); + } + return hexValue.toString(); + } +} diff --git a/src/main/java/com/xkrs/utils/IpUtil.java b/src/main/java/com/xkrs/utils/IpUtil.java new file mode 100644 index 0000000..ae88933 --- /dev/null +++ b/src/main/java/com/xkrs/utils/IpUtil.java @@ -0,0 +1,42 @@ +package com.xkrs.utils; + +import javax.servlet.http.HttpServletRequest; + +/** + * IP地址处理工具 + * @author tajochen + */ +public class IpUtil { + + public static String getIpAddr(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + final String unkonwMsg = "unknown"; + final char splitChar = ','; + if (ip != null && ip.length() != 0 && !unkonwMsg.equalsIgnoreCase(ip)) { + // 多次反向代理后会有多个ip值,第一个ip才是真实ip + if( ip.indexOf(splitChar)!=-1 ){ + ip = ip.split(",")[0]; + } + } + if (ip == null || ip.length() == 0 || unkonwMsg.equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || unkonwMsg.equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || unkonwMsg.equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || unkonwMsg.equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || unkonwMsg.equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + if (ip == null || ip.length() == 0 || unkonwMsg.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + System.out.println("获取客户端ip: " + ip); + return ip; + } +} diff --git a/src/main/java/com/xkrs/utils/NumberUtil.java b/src/main/java/com/xkrs/utils/NumberUtil.java new file mode 100644 index 0000000..2ead0c3 --- /dev/null +++ b/src/main/java/com/xkrs/utils/NumberUtil.java @@ -0,0 +1,21 @@ +package com.xkrs.utils; + +/** + * 数字工具 + * @author tajochen + */ +public class NumberUtil { + + public static boolean isStrNumeric(String str) { + if(str==null||str.length()==0){ + return false; + } + for (int i = 0; i < str.length(); i++) { + System.out.println(str.charAt(i)); + if (!Character.isDigit(str.charAt(i))) { + return false; + } + } + return true; + } +} diff --git a/src/main/java/com/xkrs/utils/ObjectToBeanUtils.java b/src/main/java/com/xkrs/utils/ObjectToBeanUtils.java new file mode 100644 index 0000000..1caf481 --- /dev/null +++ b/src/main/java/com/xkrs/utils/ObjectToBeanUtils.java @@ -0,0 +1,152 @@ +package com.xkrs.utils; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author XinYi Song + */ +public class ObjectToBeanUtils { + + public static Logger log = LoggerFactory.getLogger(ObjectToBeanUtils.class); + + /** + * 把List转换成List + */ + public static List objectToBean(List objList, Class clz) throws Exception{ + if (objList==null || objList.size()==0) { + return null; + } + + Class[] cz = null; + Constructor[] cons = clz.getConstructors(); + for (Constructor ct : cons) { + Class[] clazz = ct.getParameterTypes(); + if (objList.get(0).length == clazz.length) { + cz = clazz; + break; + } + } + + List list = new ArrayList(); + for (Object[] obj : objList) { + Constructor cr = clz.getConstructor(cz); + list.add(cr.newInstance(obj)); + } + return list; + } + + + + + + + public static List objectToBeans(List objList, Class clz) throws Exception{ + if (objList==null || objList.size()==0) { + return null; + } + + int length = objList.get(0).length; + log.info("*************>"+length); + + Class[] cz = null; + Constructor[] cons = clz.getConstructors(); + for (Constructor ct : cons) { + Class[] clazz = ct.getParameterTypes(); + if (objList.get(0).length == clazz.length) { + cz = clazz; + break; + } + } + + List list = new ArrayList(); + log.info("---------->"+objList.get(0)); + Constructor cr = clz.getConstructor(cz); + T newInstance = cr.newInstance((Object) objList.get(0)); + list.add(newInstance); + return list; + } + + + public static List castEntity(List list, Class clazz, Object model) { + List returnList = new ArrayList(); + if (list.isEmpty()) { + return returnList; + } + //获取每个数组集合的元素个数 + Object[] co = list.get(0); + + //获取当前实体类的属性名、属性值、属性类别 + List attributeInfoList = getFiledsInfo(model); + //创建属性类别数组 + Class[] c2 = new Class[attributeInfoList.size()]; + //如果数组集合元素个数与实体类属性个数不一致则发生错误 + if (attributeInfoList.size() != co.length) { + return returnList; + } + //确定构造方法 + for (int i = 0; i < attributeInfoList.size(); i++) { + c2[i] = (Class) attributeInfoList.get(i).get("type"); + } + try { + for (Object[] o : list) { + Constructor constructor = clazz.getConstructor(c2); + returnList.add(constructor.newInstance(o)); + } + } catch (Exception ex) { + log.info("实体数据转化为实体类发生异常:异常信息:{}", ex.getMessage()); + return returnList; + } + return returnList; + } + + /** + * 根据属性名获取属性值 + * + * @param fieldName 属性名 + * @param modle 实体类 + * @return 属性值 + */ + private static Object getFieldValueByName(String fieldName, Object modle) { + try { + String firstLetter = fieldName.substring(0, 1).toUpperCase(); + String getter = "get" + firstLetter + fieldName.substring(1); + Method method = modle.getClass().getMethod(getter, new Class[]{}); + Object value = method.invoke(modle, new Object[]{}); + return value; + } catch (Exception e) { + return null; + } + } + + /** + * 获取属性类型(type),属性名(name),属性值(value)的map组成的list + * + * @param model 实体类 + * @return list集合 + */ + private static List getFiledsInfo(Object model) { + Field[] fields = model.getClass().getDeclaredFields(); + List list = new ArrayList(fields.length); + Map infoMap = null; + for (int i = 0; i < fields.length; i++) { + infoMap = new HashMap(3); + infoMap.put("type", fields[i].getType()); + infoMap.put("name", fields[i].getName()); + infoMap.put("value", getFieldValueByName(fields[i].getName(), model)); + list.add(infoMap); + } + return list; + } + + +} diff --git a/src/main/java/com/xkrs/utils/OpenGeoUtil.java b/src/main/java/com/xkrs/utils/OpenGeoUtil.java new file mode 100644 index 0000000..cc1b03a --- /dev/null +++ b/src/main/java/com/xkrs/utils/OpenGeoUtil.java @@ -0,0 +1,37 @@ +package com.xkrs.utils; + +import org.geolatte.geom.Geometry; +import org.geolatte.geom.Point; +import org.geolatte.geom.codec.Wkt; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 开源Gis工具集 + * @author tajochen + */ +public class OpenGeoUtil { + + Logger logger = LoggerFactory.getLogger(OpenGeoUtil.class); + + /** + * wkt文本转为点数据 + * @param wkt + * @return + */ + public static Point wktStrToPoint(String wkt) { + Point point = (Point) Wkt.fromWkt(wkt); + return point; + } + + /** + * wkt文本转geometry + * @param wkt + * @return + */ + public static Geometry wktStrToGeom(String wkt) { + Geometry geom = Wkt.fromWkt(wkt); + return geom; + } + +} diff --git a/src/main/java/com/xkrs/utils/PhotoUtil.java b/src/main/java/com/xkrs/utils/PhotoUtil.java new file mode 100644 index 0000000..10ff940 --- /dev/null +++ b/src/main/java/com/xkrs/utils/PhotoUtil.java @@ -0,0 +1,190 @@ +package com.xkrs.utils; + +import com.xkrs.model.entity.FireTaskPhoto; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +/** + * @author XinYi Song + */ +public class PhotoUtil { + + public static Logger log = LoggerFactory.getLogger(PhotoUtil.class); + + /** + * 上传单张图片 + * @param imgFile + * @return + * @throws IOException + */ + public static String memoryPhoto(MultipartFile imgFile,String distributedTime,String distributedType) throws IOException { + //String uploadPath = "http://139.199.98.175:2088/wfTaskImage/"; + String uploadPath = "http://192.168.2.172/"; + //获取原始文件名 + String originalFilename = imgFile.getOriginalFilename(); + if (originalFilename != null && !"".equals(originalFilename)) { + //找到 . 的位置 + int index = originalFilename.lastIndexOf("."); + //根据 . 的位置进行分割,拿到文件后缀名 + String suffix = originalFilename.substring(index); + //uuid生成新的文件名 + String newName = UUID.randomUUID().toString() + suffix; + + //将图片保存到本地/usr/etc/images/Folder + File file = new File("E:/img/"); + if (!file.exists()) { + file.mkdirs(); + } + String path = "E:/img/" + newName; + String uploadsImage = uploadPath + newName; + //实现上传 + imgFile.transferTo(new File(path)); + + + return "video/"+newName; + } + return null; + } + + /** + * 以文件形式,批量上传图片 + * @param files + * @return + * @throws IOException + */ + public static List uploadImage(MultipartFile[] files, String fireCode) throws IOException { + //String uploadPath = "http://139.199.98.175:2099/forestTaskImage/"; + String uploadPath = "http://118.24.27.47:2088/"; + String newName = ""; + String oldName = ""; + List fireTaskPhotos = new ArrayList<>(); + for(MultipartFile file : files){ + //获取file图片名称 + oldName = file.getOriginalFilename(); + //找到 . 的位置 + int index = oldName.lastIndexOf("."); + //根据 . 的位置进行分割,拿到文件后缀名 + String suffix = oldName.substring(index); + //uuid生成新的文件名 + newName = UUID.randomUUID().toString() + suffix; + //将图片保存到本地/usr/etc/images/Folder + File file1 = new File("/home/sxy/server/fire_point/firePointImage/"); + //File file1 = new File("E:/file/work/image/"); + if (!file1.exists()) { + file1.mkdirs(); + } + String path = "/home/sxy/server/fire_point/firePointImage/" + newName; + //String path = "E:/file/work/image/" + newName; + String uploadPaths = "/firePointImage/" + newName; + //实现上传 + file.transferTo(new File(path)); + FireTaskPhoto fireTaskPhoto = new FireTaskPhoto(); + fireTaskPhoto.setPhotoFireCode(fireCode); + fireTaskPhoto.setTaskPhoto(uploadPaths); + + fireTaskPhotos.add(fireTaskPhoto); + } + return fireTaskPhotos; + } + + + + /** + * 删除本地或服务器储存的图片 + * @param path + * @return + */ + public static String delFile(String path){ + String resultInfo = null; + int lastIndexOf = path.lastIndexOf("/"); + String imgPath = path.substring(lastIndexOf + 1,path.length()); + System.out.println(imgPath); + imgPath = "/usr/local/etc/images/" + imgPath; +// img_path = "/usr/etc/images/Folder/" + img_path; + File file = new File(imgPath); + if(file.exists()){ + if(file.delete()){ + resultInfo = "删除成功!"; + }else { + resultInfo = "删除失败!"; + } + }else { + resultInfo = "文件不存在"; + } + return resultInfo; + } + + /** + * 通过图片路径解析 ,上传保存 + * @param listImgSrc + * @return + */ + public static List downloadImage(List listImgSrc) { + try { + List list = new ArrayList(); + //开始时间 + Date beginDate = new Date(); + for (String url : listImgSrc) { + //开始时间 + Date beginDate2 = new Date(); + String imageName = url.substring(url.lastIndexOf("/") + 1, url.length()); + URL uri = new URL(url); + InputStream in = uri.openStream(); + //String pathUpload = "E:/img/" + imageName; + String pathUpload = "/home/web/wf-fire-service/wfimage/" + imageName; + FileOutputStream fo = new FileOutputStream(new File(pathUpload)); + byte[] buf = new byte[1024]; + int length = 0; + log.info("-------开始下载:" + url); + while ((length = in.read(buf, 0, buf.length)) != -1) { + fo.write(buf, 0, length); + } + in.close(); + fo.close(); + list.add(imageName); + log.info(imageName + "------下载完成"); + //结束时间 + Date overDate2 = new Date(); + double time = overDate2.getTime() - beginDate2.getTime(); + log.info("-----耗时:" + time / 1000 + "s"); + } + Date overDate = new Date(); + double time = overDate.getTime() - beginDate.getTime(); + log.info("======总耗时:" + time / 1000 + "s"); + return list; + } catch (Exception e) { + log.info("++++++下载失败"); + } + return null; + } + + /** + * 删除本地文件夹图片 + * @param url + */ + public static void deleteImage(String url){ + File file=new File(url); + //判断file是否是文件目录 若是返回TRUE + if (file.isDirectory()){ + //name存储file文件夹中的文件名 + String[] name =file.list(); + for (int i=0; i selectFirePointByPro(String address, String cityCode, String satelliteType, String landType, String startTime, String endTime) { + Specification specification = new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List list = new ArrayList<>(); + if(address != null && !"".equals(address)){ + list.add(criteriaBuilder.like(root.get("firePointAddress").as(String.class), "%" + address + "%")); + } + if (cityCode != null && !"".equals(cityCode)) { + list.add(criteriaBuilder.like(root.get("countyCode").as(String.class), "%" + cityCode + "%")); + } + if (satelliteType != null && !"".equals(satelliteType)) { + list.add(criteriaBuilder.equal(root.get("satelliteType").as(String.class), satelliteType)); + } + if (landType != null && !"".equals(landType)) { + list.add(criteriaBuilder.equal(root.get("landType").as(String.class), landType)); + } + if(startTime != null && !"".equals(startTime)){ + list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("addTime").as(String.class), startTime)); + } + if(endTime != null && !"".equals(endTime)){ + list.add(criteriaBuilder.lessThanOrEqualTo(root.get("addTime").as(String.class), endTime)); + } + Predicate[] predicates = new Predicate[list.size()]; + return criteriaBuilder.and(list.toArray(predicates)); + } + }; + return firePointDao.findAll(specification); + } + + /** + * 动态多条件查询项目信息(市) + * @param + * @return + */ + public List selectFirePointByCity(String address, String cityCode,String satelliteType,String landType,String startTime,String endTime) { + Specification specification = new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List list = new ArrayList<>(); + if(address != null && !"".equals(address)){ + list.add(criteriaBuilder.like(root.get("firePointAddress").as(String.class), "%" + address + "%")); + } + if (cityCode != null && !"".equals(cityCode)) { + list.add(criteriaBuilder.equal(root.get("countyCode").as(String.class),cityCode)); + } + if (satelliteType != null && !"".equals(satelliteType)) { + list.add(criteriaBuilder.equal(root.get("satelliteType").as(String.class), satelliteType)); + } + if (landType != null && !"".equals(landType)) { + list.add(criteriaBuilder.equal(root.get("landType").as(String.class), landType)); + } + if(startTime != null && !"".equals(startTime)){ + list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("addTime").as(String.class), startTime)); + } + if(endTime != null && !"".equals(endTime)){ + list.add(criteriaBuilder.lessThanOrEqualTo(root.get("addTime").as(String.class), endTime)); + } + Predicate[] predicates = new Predicate[list.size()]; + return criteriaBuilder.and(list.toArray(predicates)); + } + }; + return firePointDao.findAll(specification); + } + + /** + * 动态多条件查询项目信息(县) + * @param + * @return + */ + public List selectFirePointByCounty(String cityCode,String satelliteType,String landType,String startTime,String endTime) { + Specification specification = new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List list = new ArrayList<>(); + if (cityCode != null && !"".equals(cityCode)) { + list.add(criteriaBuilder.equal(root.get("countyCode").as(String.class),cityCode)); + } + if (satelliteType != null && !"".equals(satelliteType)) { + list.add(criteriaBuilder.equal(root.get("satelliteType").as(String.class), satelliteType)); + } + if (landType != null && !"".equals(landType)) { + list.add(criteriaBuilder.equal(root.get("landType").as(String.class), landType)); + } + if(startTime != null && !"".equals(startTime)){ + list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("addTime").as(String.class), startTime)); + } + if(endTime != null && !"".equals(endTime)){ + list.add(criteriaBuilder.lessThanOrEqualTo(root.get("addTime").as(String.class), endTime)); + } + Predicate[] predicates = new Predicate[list.size()]; + return criteriaBuilder.and(list.toArray(predicates)); + } + }; + return firePointDao.findAll(specification); + } + + /** + * 查询近一周的火点 + * @param startTime + * @param endTime + * @return + */ + public List selectFirePointBetweenThree(String startTime,String endTime) { + Specification specification = new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List list = new ArrayList<>(); + if(startTime != null && !"".equals(startTime)){ + list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("addTime").as(String.class), startTime)); + } + if(endTime != null && !"".equals(endTime)){ + list.add(criteriaBuilder.lessThanOrEqualTo(root.get("addTime").as(String.class), endTime)); + } + Predicate[] predicates = new Predicate[list.size()]; + return criteriaBuilder.and(list.toArray(predicates)); + } + }; + return firePointDao.findAll(specification); + } + + /** + * 查询近一个月的火点 + * @param startTime + * @param endTime + * @return + */ + public List selectFirePointByMonth(String address,String startTime,String endTime) { + Specification specification = new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List list = new ArrayList<>(); + if(address != null && !"".equals(address)){ + list.add(criteriaBuilder.like(root.get("firePointAddress").as(String.class), "%" + address + "%")); + } + if(startTime != null && !"".equals(startTime)){ + list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("addTime").as(String.class), startTime)); + } + if(endTime != null && !"".equals(endTime)){ + list.add(criteriaBuilder.lessThanOrEqualTo(root.get("addTime").as(String.class), endTime)); + } + Predicate[] predicates = new Predicate[list.size()]; + return criteriaBuilder.and(list.toArray(predicates)); + } + }; + return firePointDao.findAll(specification); + } + + /** + * 查询近一个月的火点信息(市) + * @param address + * @param startTime + * @param endTime + * @return + */ + public List selectFirePointByMonthCity(String address,String startTime,String endTime) { + Specification specification = new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List list = new ArrayList<>(); + if(address != null && !"".equals(address)){ + list.add(criteriaBuilder.like(root.get("firePointAddress").as(String.class), "%" + address + "%")); + } + if(startTime != null && !"".equals(startTime)){ + list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("addTime").as(String.class), startTime)); + } + if(endTime != null && !"".equals(endTime)){ + list.add(criteriaBuilder.lessThanOrEqualTo(root.get("addTime").as(String.class), endTime)); + } + Predicate[] predicates = new Predicate[list.size()]; + return criteriaBuilder.and(list.toArray(predicates)); + } + }; + return firePointDao.findAll(specification); + } + + /** + * 查询近一个月的火点信息(县) + * @param countyCode + * @param startTime + * @param endTime + * @return + */ + public List selectFirePointByMonthCounty(String countyCode,String startTime,String endTime) { + Specification specification = new Specification() { + @Override + public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + List list = new ArrayList<>(); + if(countyCode != null && !"".equals(countyCode)){ + list.add(criteriaBuilder.like(root.get("countyCode").as(String.class), countyCode)); + } + if(startTime != null && !"".equals(startTime)){ + list.add(criteriaBuilder.greaterThanOrEqualTo(root.get("addTime").as(String.class), startTime)); + } + if(endTime != null && !"".equals(endTime)){ + list.add(criteriaBuilder.lessThanOrEqualTo(root.get("addTime").as(String.class), endTime)); + } + Predicate[] predicates = new Predicate[list.size()]; + return criteriaBuilder.and(list.toArray(predicates)); + } + }; + return firePointDao.findAll(specification); + } + + +} \ No newline at end of file diff --git a/src/main/java/com/xkrs/utils/RandomUtil.java b/src/main/java/com/xkrs/utils/RandomUtil.java new file mode 100644 index 0000000..c546877 --- /dev/null +++ b/src/main/java/com/xkrs/utils/RandomUtil.java @@ -0,0 +1,71 @@ +package com.xkrs.utils; + +import java.util.Random; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 随机字符串产生工具 + * @author tajochen + */ +public class RandomUtil { + /** + * 获取随机字母数字组合 + * @param length + * 字符串长度 + * @return + */ + public static String getRandomCharAndNumr(Integer length) { + String str = ""; + StringBuilder strBuffer = new StringBuilder(); + Random random = new Random(); + for (int i = 0; i < length; i++) { + boolean b = random.nextBoolean(); + // 字符串 + if (b) { + //取得65大写字母还是97小写字母 + int choice = random.nextBoolean() ? 65 : 97; + strBuffer.append((char) (choice + random.nextInt(26))); + } else { + // 数字 + strBuffer.append(random.nextInt(10)); + } + } + str = strBuffer.toString(); + return str; + } + + /** + * 验证随机字母数字组合是否纯数字与纯字母 + * @param str + * @return true 是 , false 否 + */ + public static boolean isRandomUsable(String str) { + // String regExp = + // "^[A-Za-z]+(([0-9]+[A-Za-z0-9]+)|([A-Za-z0-9]+[0-9]+))|[0-9]+(([A-Za-z]+[A-Za-z0-9]+)|([A-Za-z0-9]+[A-Za-z]+))$"; + String regExp = "^([0-9]+)|([A-Za-z]+)$"; + Pattern pat = Pattern.compile(regExp); + Matcher mat = pat.matcher(str); + return mat.matches(); + } + + /** + * 生成UUID + * @return + */ + public static String getUuid32(){ + String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase(); + return uuid; +//  return UUID.randomUUID().toString().replace("-", "").toLowerCase(); + } + + /** + * 随机生成六位数 + * @return + */ + public static int returnCode() { + Random rand = new Random(); + return rand.nextInt(899999) + 100000; + } +} diff --git a/src/main/java/com/xkrs/utils/RequestUtil.java b/src/main/java/com/xkrs/utils/RequestUtil.java new file mode 100644 index 0000000..b2321f5 --- /dev/null +++ b/src/main/java/com/xkrs/utils/RequestUtil.java @@ -0,0 +1,300 @@ +package com.xkrs.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.xkrs.model.vo.FileServerResultVo; +import org.apache.http.Consts; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.StringBody; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * 上传工具 + * @author tajochen + **/ +public class RequestUtil { + + /** + * 发送管理命令到文件服务器 + * @param url + * @param map + * @return + */ + public static FileServerResultVo postFileManage(String url, Map map){ + Logger log = LoggerFactory.getLogger(RequestUtil.class); + String body = ""; + // 创建httpclient对象 + CloseableHttpClient client = HttpClients.createDefault(); + // 创建post方式请求对象 + HttpPost httpPost = new HttpPost(url); + // 装填参数 + List nvps = new ArrayList(); + if(map!=null){ + for (Map.Entry entry : map.entrySet()) { + nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); + } + } + try { + // 设置参数到请求对象中 + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8")); + // 设置header报文头信息 + httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); + httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0"); + httpPost.setHeader("Accept", "application"); + httpPost.setHeader("Accept-Encoding", "gzip, deflate"); + // 执行请求操作,并拿到结果(同步阻塞) + CloseableHttpResponse response = client.execute(httpPost); + // 获取结果实体 + HttpEntity entity = response.getEntity(); + if (entity != null) { + // 按指定编码转换结果实体为String类型 + body = EntityUtils.toString(entity, "UTF-8"); + } + EntityUtils.consume(entity); + // 释放链接 + response.close(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + client.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + FileServerResultVo fileServerResultVo = new FileServerResultVo(); + ObjectMapper mapper = new ObjectMapper(); + try { + fileServerResultVo = mapper.readValue(body, FileServerResultVo.class); + } catch (JsonProcessingException e) { + e.printStackTrace(); + log.warn(e.toString()); + + } + return fileServerResultVo; + } + + /** + * 模拟 get请求 + * @param url 链接 + * @param map 参数列表 + */ + public static String getStandard(String url, Map map) { + // 1.拿到一个httpclient的对象 + CloseableHttpClient httpClient = HttpClients.createDefault(); + // 2.设置请求方式和请求信息 + HttpPost httpPost = new HttpPost(url); + //2.1 提交header头信息 + httpPost.addHeader("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"); + //2.1 提交请求体 + ArrayList parameters = new ArrayList(); + // 装填参数 + if(map!=null){ + for (Map.Entry entry : map.entrySet()) { + parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); + } + } + + try { + httpPost.setEntity(new UrlEncodedFormEntity(parameters)); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + // 3.执行请求 + CloseableHttpResponse response = null; + try { + response = httpClient.execute(httpPost); + } catch (IOException e) { + e.printStackTrace(); + } + // 4.获取返回值 + String html = null; + try { + assert response != null; + html = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); + } catch (IOException e) { + e.printStackTrace(); + } + // 5.打印 + System.out.println(html); + return html; + } + + + public static String doGet(String url, Map param) { + + String result = null; + CloseableHttpClient httpclient = HttpClients.createDefault(); + CloseableHttpResponse response = null; + try { + URIBuilder builder = new URIBuilder(url); + if (param != null) { + for (String key : param.keySet()) { + builder.addParameter(key, param.get(key)); + } + } + URI uri = builder.build(); + HttpGet httpGet = new HttpGet(uri); + httpGet.addHeader("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"); + //httpGet.addHeader("Authorization",token); + response = httpclient.execute(httpGet); + if (response.getStatusLine().getStatusCode() == 200) { + result = EntityUtils.toString(response.getEntity(), "UTF-8"); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (response != null) { + response.close(); + } + httpclient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return result; + } + + /** + * 模拟Post请求 application/x-www-form-urlencoded + * @param url 资源地址 + * @param map 参数列表 + * @return + */ + public static String postStandard(String url, Map map) { + String body = ""; + // 创建httpclient对象 + CloseableHttpClient client = HttpClients.createDefault(); + // 创建post方式请求对象 + HttpPost httpPost = new HttpPost(url); + // 装填参数 + List nvps = new ArrayList(); + if(map!=null){ + for (Map.Entry entry : map.entrySet()) { + nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); + } + } + try { + // 设置参数到请求对象中 + httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8")); + // 设置header报文头信息 + httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); + httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0"); + httpPost.setHeader("Accept", "application"); + httpPost.setHeader("Accept-Encoding", "gzip, deflate"); + // 执行请求操作,并拿到结果(同步阻塞) + CloseableHttpResponse response = client.execute(httpPost); + // 获取结果实体 + HttpEntity entity = response.getEntity(); + if (entity != null) { + // 按指定编码转换结果实体为String类型 + body = EntityUtils.toString(entity, "UTF-8"); + } + EntityUtils.consume(entity); + // 释放链接 + response.close(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + client.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return body; + } + + /** + * 模拟Post请求 multipart/form-data + * @param postFile + * @param postUrl + * @param postParam + * @return + */ + public static Map postFile(File postFile,String postUrl,Map postParam) { + + Logger log = LoggerFactory.getLogger(RequestUtil.class); + Map resultMap = new HashMap(16); + CloseableHttpClient httpClient = HttpClients.createDefault(); + try{ + // 把一个普通参数和文件上传给下面这个地址 + HttpPost httpPost = new HttpPost(postUrl); + + // 设置传输参数 + MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create(); + // 解决乱码问题 + multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + multipartEntity.setCharset(StandardCharsets.UTF_8); + + // 设置文件参数 ,获取文件名postFile.getName() + // 把文件转换成流对象FileBody + multipartEntity.addBinaryBody("file",postFile, ContentType.create("multipart/form-data", Consts.UTF_8),postFile.getName()); + // 设计文件以外的参数 + Set keySet = postParam.keySet(); + for (String key : keySet) { + // 相当于 + multipartEntity.addPart(key, new StringBody(postParam.get(key), ContentType.create("multipart/form-data", Consts.UTF_8))); + } + HttpEntity reqEntity = multipartEntity.build(); + httpPost.setEntity(reqEntity); + // 设置header报文头信息 + httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0"); + httpPost.setHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); + httpPost.setHeader("Accept-Encoding","gzip, deflate"); + + // 发起请求,返回请求的响应 + CloseableHttpResponse response = httpClient.execute(httpPost); + try { + resultMap.put("statusCode", response.getStatusLine().getStatusCode()); + // 获取响应对象 + HttpEntity resEntity = response.getEntity(); + if (resEntity != null) { + // 打印响应内容 + resultMap.put("data", EntityUtils.toString(resEntity, StandardCharsets.UTF_8)); + resultMap.put("message", EntityUtils.toString(resEntity, StandardCharsets.UTF_8)); + resultMap.put("status", EntityUtils.toString(resEntity, StandardCharsets.UTF_8)); + } + // 销毁 + EntityUtils.consume(resEntity); + } catch (Exception e) { + e.printStackTrace(); + } finally { + response.close(); + } + } catch (IOException e1) { + e1.printStackTrace(); + } finally{ + try { + httpClient.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + log.info("上传结果:" + resultMap); + return resultMap; + } +} diff --git a/src/main/java/com/xkrs/utils/RestTemplateUtil.java b/src/main/java/com/xkrs/utils/RestTemplateUtil.java new file mode 100644 index 0000000..dfb4384 --- /dev/null +++ b/src/main/java/com/xkrs/utils/RestTemplateUtil.java @@ -0,0 +1,94 @@ +package com.xkrs.utils; + +import com.alibaba.fastjson.JSONObject; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.Resource; + +/** + * @author xkrs + */ +@Service +public class RestTemplateUtil { + + @Resource + private RestTemplate restTemplate; + + /** + * 以get方式请求第三方http接口 getForEntity + * @param url + * @return + */ + public JSONObject doGetForEntity(String url) { + ResponseEntity responseEntity = restTemplate.getForEntity(url, JSONObject.class); + return responseEntity.getBody(); + } + + /** + * 以get方式请求第三方http接口 getForObject + * 返回值返回的是响应体 + * @param url + * @return + */ + public JSONObject doGetForObject(String url) { + JSONObject result = restTemplate.getForObject(url, JSONObject.class); + return result; + } + + /** + * 以post方式请求第三方http接口 postForEntity + * @param url + * @return + */ + public JSONObject doPostForEntity(String url) { + //可设置请求参数 + JSONObject param = new JSONObject(); + param.put("userName","admin"); + param.put("ipAddress",""); + param.put("clientType","WINPC"); + ResponseEntity responseEntity = restTemplate.postForEntity(url, param, JSONObject.class); + return responseEntity.getBody(); + } + + /** + * 以post方式请求第三方http接口 postForObject + * @param url + * @return + */ + public JSONObject doPostForObject(String url,JSONObject param) { + JSONObject result = restTemplate.postForObject(url, param, JSONObject.class); + return result; + } + + + /** + * exchange方法请求第三方http接口 + * + */ + public JSONObject doExchange(String url, HttpHeaders httpHeaders, JSONObject param) { + //创建请求对象 + HttpEntity request = new HttpEntity<>(param,httpHeaders); + //执行请求(请求路径,请求方式,请求体,响应体) + ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.POST, request, JSONObject.class); + return responseEntity.getBody(); + } + + /** + * 发送第三方小米推送请求,向app端推送消息 + * @param url + * @param httpHeaders + * @param param + */ + public void doPostMessageToApp(String url,HttpHeaders httpHeaders,JSONObject param) { + //创建请求对象 + HttpEntity request = new HttpEntity<>(param,httpHeaders); + //执行请求(请求路径,请求方式,请求体,响应体) + restTemplate.exchange(url, HttpMethod.POST, request, JSONObject.class); + } + +} diff --git a/src/main/java/com/xkrs/utils/SnowFlakeUtil.java b/src/main/java/com/xkrs/utils/SnowFlakeUtil.java new file mode 100644 index 0000000..a5ba62d --- /dev/null +++ b/src/main/java/com/xkrs/utils/SnowFlakeUtil.java @@ -0,0 +1,124 @@ +package com.xkrs.utils; + +/** + * 基于Twitter开源的分布式ID生成算法snowflake + * @author tajochen + **/ +public class SnowFlakeUtil { + + /** + * 起始时间戳 + * 2018-01-01 00:00:00 + */ + private final static long START_STMP = 1514736000L; + /** + * 序列在id中占用的位数 + */ + private final static long SEQUENCE_BIT = 12L; + /** + * 机器标识占用的位数 + */ + private final static long MACHINE_BIT = 5L; + /** + * 数据中心占用的位数 + */ + private final static long DATACENTER_BIT = 5L; + /** + * 每一部分的最大值 + */ + private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); + private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); + private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); + + /** + * 每一部分向左的位移 + */ + private final static long MACHINE_LEFT = SEQUENCE_BIT; + private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; + private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; + + /** + * 数据中心 + */ + private long datacenterId; + /** + * 机器标识 + */ + private long machineId; + /** + * 序列号 + */ + private long sequence = 0L; + /** + * 上一次时间戳 + */ + private long lastStmp = -1L; + + public SnowFlakeUtil(long datacenterId, long machineId) { + if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) { + throw new IllegalArgumentException("data center id can't be greater than MAX_DATACENTER_NUM or less than 0"); + } + if (machineId > MAX_MACHINE_NUM || machineId < 0) { + throw new IllegalArgumentException("machine id can't be greater than MAX_MACHINE_NUM or less than 0"); + } + this.datacenterId = datacenterId; + this.machineId = machineId; + } + + /** + * 产生下一个ID + * @return + */ + public synchronized long nextId() { + long currStmp = getNewstmp(); + if (currStmp < lastStmp) { + throw new RuntimeException("Clock moved backwards. Refusing to generate id"); + } + + if (currStmp == lastStmp) { + //相同毫秒内,序列号自增 + sequence = (sequence + 1) & MAX_SEQUENCE; + //同一毫秒的序列数已经达到最大 + if (sequence == 0L) { + currStmp = getNextMill(); + } + } else { + //不同毫秒内,序列号置为0 + sequence = 0L; + } + + lastStmp = currStmp; + //时间戳部分 + return (currStmp - START_STMP) << TIMESTMP_LEFT + //数据中心部分 + | datacenterId << DATACENTER_LEFT + //机器标识部分 + | machineId << MACHINE_LEFT + //序列号部分 + | sequence; + } + + private long getNextMill() { + long mill = getNewstmp(); + while (mill <= lastStmp) { + mill = getNewstmp(); + } + return mill; + } + + private long getNewstmp() { + return System.currentTimeMillis(); + } + + public static void main(String[] args) { + SnowFlakeUtil snowFlake = new SnowFlakeUtil(5, 5); + //测试次数 + int testTimes = 10000; + long start = System.currentTimeMillis(); + for (int i = 0; i < testTimes; i++) { + System.out.println(snowFlake.nextId()); + } + + System.out.println(System.currentTimeMillis() - start); + } +} diff --git a/src/main/java/com/xkrs/weather/controller/WeatherController.java b/src/main/java/com/xkrs/weather/controller/WeatherController.java new file mode 100644 index 0000000..9b7869e --- /dev/null +++ b/src/main/java/com/xkrs/weather/controller/WeatherController.java @@ -0,0 +1,31 @@ +package com.xkrs.weather.controller; + +import com.xkrs.weather.entity.WeatherResponse; +import com.xkrs.weather.service.WeatherDataService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author XinYi Song + */ +@RestController +@RequestMapping(value = "/weather") +public class WeatherController { + + @Autowired + private WeatherDataService weatherDataService; + + @GetMapping("/cityId") + public WeatherResponse getWeatherByCityId(@RequestParam("cityId") String cityId){ + return weatherDataService.getDataByCityId(cityId); + } + + @GetMapping("/cityName") + public WeatherResponse getWeatherByCityName(@RequestParam("cityName") String cityName){ + return weatherDataService.getDataByCityName(cityName); + } + +} diff --git a/src/main/java/com/xkrs/weather/entity/Forecast.java b/src/main/java/com/xkrs/weather/entity/Forecast.java new file mode 100644 index 0000000..6587ea0 --- /dev/null +++ b/src/main/java/com/xkrs/weather/entity/Forecast.java @@ -0,0 +1,78 @@ +package com.xkrs.weather.entity; + +import java.io.Serializable; + +/** + * 未来天气 + * @author XinYi Song + */ +public class Forecast implements Serializable { + + /* "forecast":[{ + "date":"23日星期天", "high":"高温 24℃", "fengli":"", "low":"低温 12℃", "fengxiang":"北风", "type":"晴" + },{ + "date":"24日星期一", "high":"高温 23℃", "fengli":"", "low":"低温 11℃", "fengxiang":"无持续风向", "type": + "晴" + },{ + "date":"25日星期二", "high":"高温 23℃", "fengli":"", "low":"低温 13℃", "fengxiang":"南风", "type":"多云" + },{ + "date":"26日星期三", "high":"高温 22℃", "fengli":"", "low":"低温 14℃", "fengxiang":"南风", "type":"多云" + },{ + "date":"27日星期四", "high":"高温 22℃", "fengli":"", "low":"低温 14℃", "fengxiang":"南风", "type":"阴" + }]*/ + + private String date; + private String high; + private String fengli; + private String low; + private String fengxiang; + private String type; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getHigh() { + return high; + } + + public void setHigh(String high) { + this.high = high; + } + + public String getFengli() { + return fengli; + } + + public void setFengli(String fengli) { + this.fengli = fengli; + } + + public String getLow() { + return low; + } + + public void setLow(String low) { + this.low = low; + } + + public String getFengxiang() { + return fengxiang; + } + + public void setFengxiang(String fengxiang) { + this.fengxiang = fengxiang; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/src/main/java/com/xkrs/weather/entity/Weather.java b/src/main/java/com/xkrs/weather/entity/Weather.java new file mode 100644 index 0000000..55923ef --- /dev/null +++ b/src/main/java/com/xkrs/weather/entity/Weather.java @@ -0,0 +1,87 @@ +package com.xkrs.weather.entity; + +import java.io.Serializable; +import java.util.List; + +/** + * 天气信息 + * @author XinYi Song + */ +public class Weather implements Serializable { + +/* + http://wthrcdn.etouch.cn/weather_mini?city=北京 + { + "data":{ + "yesterday":{ + "date":"22日星期六", "high":"高温 24℃", "fx":"西北风", "low":"低温 13℃", "fl":"", "type":"晴" + },"city":"北京", "aqi":"35", "forecast":[{ + "date":"23日星期天", "high":"高温 24℃", "fengli":"", "low":"低温 12℃", "fengxiang":"北风", "type":"晴" + },{ + "date":"24日星期一", "high":"高温 23℃", "fengli":"", "low":"低温 11℃", "fengxiang":"无持续风向", "type": + "晴" + },{ + "date":"25日星期二", "high":"高温 23℃", "fengli":"", "low":"低温 13℃", "fengxiang":"南风", "type":"多云" + },{ + "date":"26日星期三", "high":"高温 22℃", "fengli":"", "low":"低温 14℃", "fengxiang":"南风", "type":"多云" + },{ + "date":"27日星期四", "high":"高温 22℃", "fengli":"", "low":"低温 14℃", "fengxiang":"南风", "type":"阴" + }],"ganmao":"各项气象条件适宜,无明显降温过程,发生感冒机率较低。", "wendu":"14" + },"status":1000, "desc":"OK" + }*/ + + private String city; + private Yesterday yesterday; + private String aqi; + private String ganmao; + private String wendu; + private List forecast; + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public Yesterday getYesterday() { + return yesterday; + } + + public void setYesterday(Yesterday yesterday) { + this.yesterday = yesterday; + } + + public String getAqi() { + return aqi; + } + + public void setAqi(String aqi) { + this.aqi = aqi; + } + + public String getGanmao() { + return ganmao; + } + + public void setGanmao(String ganmao) { + this.ganmao = ganmao; + } + + public String getWendu() { + return wendu; + } + + public void setWendu(String wendu) { + this.wendu = wendu; + } + + public List getForecast() { + return forecast; + } + + public void setForecast(List forecast) { + this.forecast = forecast; + } +} diff --git a/src/main/java/com/xkrs/weather/entity/WeatherResponse.java b/src/main/java/com/xkrs/weather/entity/WeatherResponse.java new file mode 100644 index 0000000..84a16ad --- /dev/null +++ b/src/main/java/com/xkrs/weather/entity/WeatherResponse.java @@ -0,0 +1,55 @@ +package com.xkrs.weather.entity; + +import java.io.Serializable; + +/** + * @author XinYi Song + */ +public class WeatherResponse implements Serializable { + private static final long serialVersionUID = -8483256225271502962L; + private Weather data; + private Integer status; + private String desc; + + public WeatherResponse() { + } + + public WeatherResponse(Weather data, Integer status, String desc) { + this.data = data; + this.status = status; + this.desc = desc; + } + + public Weather getData() { + return data; + } + + public void setData(Weather data) { + this.data = data; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + @Override + public String toString() { + return "WeatherResponse{" + + "data=" + data + + ", status=" + status + + ", desc='" + desc + '\'' + + '}'; + } +} diff --git a/src/main/java/com/xkrs/weather/entity/Yesterday.java b/src/main/java/com/xkrs/weather/entity/Yesterday.java new file mode 100644 index 0000000..472ba98 --- /dev/null +++ b/src/main/java/com/xkrs/weather/entity/Yesterday.java @@ -0,0 +1,68 @@ +package com.xkrs.weather.entity; + +import java.io.Serializable; + +/** + * 昨日天气 + * @author XinYi Song + */ +public class Yesterday implements Serializable { + /* "yesterday":{ + "date":"22日星期六", "high":"高温 24℃", "fx":"西北风", "low":"低温 13℃", "fl":"", "type":"晴" + },*/ + + private String date; + private String high; + private String fx; + private String low; + private String fl; + private String type; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getHigh() { + return high; + } + + public void setHigh(String high) { + this.high = high; + } + + public String getFx() { + return fx; + } + + public void setFx(String fx) { + this.fx = fx; + } + + public String getLow() { + return low; + } + + public void setLow(String low) { + this.low = low; + } + + public String getFl() { + return fl; + } + + public void setFl(String fl) { + this.fl = fl; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } +} diff --git a/src/main/java/com/xkrs/weather/service/WeatherDataService.java b/src/main/java/com/xkrs/weather/service/WeatherDataService.java new file mode 100644 index 0000000..8c382dd --- /dev/null +++ b/src/main/java/com/xkrs/weather/service/WeatherDataService.java @@ -0,0 +1,24 @@ +package com.xkrs.weather.service; + +import com.xkrs.weather.entity.WeatherResponse; + +/** + * @author XinYi Song + */ +public interface WeatherDataService { + + /** + * 根据城市ID查询天气数据 + * @param CityId + * @return + */ + WeatherResponse getDataByCityId(String CityId); + + /** + * 根据城市名称查询天气数据 + * @param cityName + * @return + */ + WeatherResponse getDataByCityName(String cityName); + +} diff --git a/src/main/java/com/xkrs/weather/service/impl/WeatherDataServiceImpl.java b/src/main/java/com/xkrs/weather/service/impl/WeatherDataServiceImpl.java new file mode 100644 index 0000000..40ee22e --- /dev/null +++ b/src/main/java/com/xkrs/weather/service/impl/WeatherDataServiceImpl.java @@ -0,0 +1,53 @@ +package com.xkrs.weather.service.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.xkrs.weather.entity.WeatherResponse; +import com.xkrs.weather.service.WeatherDataService; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.Resource; + +/** + * @author XinYi Song + */ +@Service +public class WeatherDataServiceImpl implements WeatherDataService { + + private static final String WEATHER_URI = "http://wthrcdn.etouch.cn/weather_mini?"; + + @Resource + private RestTemplate restTemplate; + + @Override + public WeatherResponse getDataByCityId(String cityId) { + String uri = WEATHER_URI + "citykey=" + cityId; + return this.getWeatherResponse(uri); + } + + + @Override + public WeatherResponse getDataByCityName(String cityName) { + String uri = WEATHER_URI + "city=" + cityName; + return this.getWeatherResponse(uri); + } + + + private WeatherResponse getWeatherResponse(String uri) { + ResponseEntity respString = restTemplate.getForEntity(uri, String.class); + ObjectMapper objectMapper = new ObjectMapper(); + WeatherResponse resp = null; + String strBody = null; + if (respString.getStatusCodeValue() == 200) { + strBody = respString.getBody(); + } + try { + resp = objectMapper.readValue(strBody, WeatherResponse.class); + } catch (Exception e) { + e.printStackTrace(); + } + return resp; + } + +} diff --git a/src/main/java/com/xkrs/websocket/config/WebSocketBrokerConfig.java b/src/main/java/com/xkrs/websocket/config/WebSocketBrokerConfig.java new file mode 100644 index 0000000..bb8d377 --- /dev/null +++ b/src/main/java/com/xkrs/websocket/config/WebSocketBrokerConfig.java @@ -0,0 +1,25 @@ +package com.xkrs.websocket.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; + +/** + * websocket广播配置 + * @author xkrs + */ +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer { + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/endPointClientServer").withSockJS(); + } + + @Override + public void configureMessageBroker(MessageBrokerRegistry registry) { + registry.enableSimpleBroker("/ws"); + } +} diff --git a/src/main/java/com/xkrs/websocket/config/WebSocketConfig.java b/src/main/java/com/xkrs/websocket/config/WebSocketConfig.java new file mode 100644 index 0000000..261844d --- /dev/null +++ b/src/main/java/com/xkrs/websocket/config/WebSocketConfig.java @@ -0,0 +1,16 @@ +package com.xkrs.websocket.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +/** + * @author xkrs + */ +@Configuration +public class WebSocketConfig { + @Bean + public ServerEndpointExporter serverEndpointExporter(){ + return new ServerEndpointExporter(); + } +} diff --git a/src/main/java/com/xkrs/websocket/controller/WebSocketController.java b/src/main/java/com/xkrs/websocket/controller/WebSocketController.java new file mode 100644 index 0000000..1702069 --- /dev/null +++ b/src/main/java/com/xkrs/websocket/controller/WebSocketController.java @@ -0,0 +1,49 @@ +package com.xkrs.websocket.controller; + +import com.xkrs.websocket.server.WebSocketServer; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; + +/** + * @author XinYi Song + */ +@RestController +@RequestMapping("/api/ws") +public class WebSocketController { + + + /** + * 群发消息内容 + * @param message + * @return + */ + @RequestMapping(value="/sendAll", method= RequestMethod.GET) + public String sendAllMessage(@RequestParam(required=true) String message){ + try { + WebSocketServer.BroadCastInfo(message); + } catch (IOException e) { + e.printStackTrace(); + } + return "ok"; + } + + /** + * 指定会话ID发消息 + * @param message 消息内容 + * @param id 连接会话ID + * @return + */ + @RequestMapping(value="/sendOne", method=RequestMethod.GET) + public String sendOneMessage(@RequestParam(required=true) String message,@RequestParam(required=true) String id){ + try { + WebSocketServer.SendMessage(message,id); + } catch (IOException e) { + e.printStackTrace(); + } + return "ok"; + } +} diff --git a/src/main/java/com/xkrs/websocket/server/WebSocketServer.java b/src/main/java/com/xkrs/websocket/server/WebSocketServer.java new file mode 100644 index 0000000..60f01e5 --- /dev/null +++ b/src/main/java/com/xkrs/websocket/server/WebSocketServer.java @@ -0,0 +1,129 @@ +package com.xkrs.websocket.server; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.websocket.*; +import javax.websocket.server.ServerEndpoint; +import java.io.IOException; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author XinYi Song + */ +@ServerEndpoint(value = "/ws/asset") +@Component +public class WebSocketServer { + + public static Logger log = LoggerFactory.getLogger(WebSocketServer.class); + + @PostConstruct + public void init() { + System.out.println("websocket 加载"); + } + private static final AtomicInteger OnlineCount = new AtomicInteger(0); + /** + * concurrent包的线程安全Set,用来存放每个客户端对应的Session对象。 + */ + private static CopyOnWriteArraySet SessionSet = new CopyOnWriteArraySet(); + + + /** + * 连接建立成功调用的方法 + */ + @OnOpen + public void onOpen(Session session) { + SessionSet.add(session); + // 在线数加1 + int cnt = OnlineCount.incrementAndGet(); + log.info("有连接加入,当前连接数为:{}", cnt); + SendMessage(session, "连接成功"); + } + + /** + * 连接关闭调用的方法 + */ + @OnClose + public void onClose(Session session) { + SessionSet.remove(session); + int cnt = OnlineCount.decrementAndGet(); + log.info("有连接关闭,当前连接数为:{}", cnt); + } + + /** + * 收到客户端消息后调用的方法 + * + * @param message + * 客户端发送过来的消息 + */ + @OnMessage + public void onMessage(String message, Session session) { + log.info("来自客户端的消息:{}",message); + SendMessage(session, "收到消息,消息内容:"+message); + + } + + /** + * 出现错误 + * @param session + * @param error + */ + @OnError + public void onError(Session session, Throwable error) { + log.error("发生错误:{},Session ID: {}",error.getMessage(),session.getId()); + error.printStackTrace(); + } + + /** + * 发送消息,实践表明,每次浏览器刷新,session会发生变化。 + * @param session + * @param message + */ + public static void SendMessage(Session session, String message) { + try { + session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId())); + } catch (IOException e) { + log.error("发送消息出错:{}", e.getMessage()); + e.printStackTrace(); + } + } + + /** + * 群发消息 + * @param message + * @throws IOException + */ + public static void BroadCastInfo(String message) throws IOException { + for (Session session : SessionSet) { + if(session.isOpen()){ + SendMessage(session, message); + } + } + } + + /** + * 指定Session发送消息 + * @param sessionId + * @param message + * @throws IOException + */ + public static void SendMessage(String message,String sessionId) throws IOException { + Session session = null; + for (Session s : SessionSet) { + if(s.getId().equals(sessionId)){ + session = s; + break; + } + } + if(session!=null){ + SendMessage(session, message); + } + else{ + log.warn("没有找到你指定ID的会话:{}",sessionId); + } + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..2722759 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,81 @@ +server.port = 6805 + +## 数据源配置 +spring.datasource.url = jdbc:postgresql://118.24.27.47:5432/county_fire +spring.datasource.userName = fire_manage +spring.datasource.password = fire456 +spring.datasource.driverClassName = org.postgresql.Driver + +server.tomcat.uri-encoding=UTF-8 + +# 关闭spring data 的redis仓库 +spring.data.redis.repositories.enabled = false + +# jackson 配置 +spring.jackson.serialization.write-date-keys-as-timestamps=false + +## Hikari连接池设置 +spring.datasource.hikari.auto-commit = true +spring.datasource.hikari.maximum-pool-size = 100 +spring.datasource.hikari.idle-timeout = 10000 +spring.datasource.hikari.minimum-idle = 5 +spring.datasource.hikari.validation-timeout = 3000 + +## Spring Data JPA 配置 +spring.jpa.database = POSTGRESQL +spring.jpa.database-platform = org.hibernate.dialect.PostgreSQLDialect +spring.jpa.show-sql = true +# 指定 ddl mode (none, validate, create, create-drop, update) +spring.jpa.hibernate.ddl-auto = update +# 命名策略 +spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy +#spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQL95Dialect +#spring.jpa.properties.hibernate.dialect = org.hibernate.spatial.dialect.postgis.PostgisDialect +spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false + +## Redis配置 +spring.cache.type = redis +spring.redis.database = 8 +spring.redis.host = localhost +spring.redis.port = 6379 +spring.redis.password=sdust2020 +spring.redis.timeout = 10000 +spring.redis.lettuce.pool.max-active = 100 +spring.redis.lettuce.pool.max-wait = 10000 +spring.redis.lettuce.pool.max-idle = 100 +spring.redis.lettuce.pool.min-idle = 1 +spring.redis.lettuce.shutdown-timeout = 0 + +## Devtools配置 +spring.devtools.livereload.enabled = true + +## 多国语言配置 +spring.messages.basename = i18n/messages +spring.messages.encoding = UTF-8 + +# 上传文件配置 +spring.servlet.multipart.enabled=true +# 最大文件大小 +spring.servlet.multipart.max-file-size = 100MB +# 最大请求大小 +spring.servlet.multipart.max-request-size = 100MB + +spring.main.allow-bean-definition-overriding = true + +# Geoserver服务器地址 +my.GeoserverAdress = http://139.199.98.175:9080/geoserver/ + +# 文件服务器地址 +my.FileServerAdress = http://139.199.98.175:4096/ +my.FileServerAdminAdress = http://127.0.0.1:4096/ + +dfs.ip = 192.168.2.9 +dfs.port = 4096 + +## 自定义用户最大登录错误尝试次数 +my.MaxLoginErrorCount = 5 + +## 自定义用户登录错误间隔时间(分钟) +my.LoginErrorIntervalTime = 60 + + diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties new file mode 100644 index 0000000..8cfedc5 --- /dev/null +++ b/src/main/resources/i18n/messages.properties @@ -0,0 +1,162 @@ +sys.message.success = 成功 +sys.message.null = 暂时还没有数据 +sys.message.exit = 已存在相关内容,请勿重复操作 +sys.message.user.not_logged_in = 用户未登录 +sys.message.user.login_error = 用户登陆失败 +sys.message.user.account_forbidden = 用户已被禁止 +sys.message.user.account_not_activated = 用户未激活 +sys.message.user.overtime = 用户登录超时 +sys.message.user.no_permission = 用户权限不足 +sys.message.user.already_logged = 用户已经登录 +sys.message.param.null = 参数为空 +sys.message.param.illegal = 参数非法 +sys.message.data.none = 数据为空 +sys.message.data.wrong = 数据错误 +sys.message.process.fail = 处理失败 +sys.message.process.overtime = 处理超时 +sys.message.system.inner_error = 系统内部错误 +sys.message.system.abnormal = 系统异常 +sys.message.system.busy = 系统正忙,请稍后 +sys.message.system.maintain = 系统维护中 +sys.message.database.error = 数据库错误 +sys.message.file.exists = 文件已存在 +sys.message.file.write.error = 文件写入失败 +sys.message.file.read.error = 文件读取失败 + +SysUser.id.blank = 用户id不能为空 +SysUser.userName.blank = 用户名不能为空 +SysUser.userName.length.illegal = 用户名长度不合法 +SysUser.userName.format.illegal = 用户名格式不合法 +SysUser.nickName.length.illegal = 用户昵称长度不合法 +SysUser.userCode.length.illegal = 用户编码长度不合法 +SysUser.userCode.format.illegal = 用户编码含有非法字符 +SysUser.password.blank = 用户密码不能为空 +SysUser.password.length.illegal = 用户密码长度不合法 +SysUser.password.format.illegal = 用户密码格式不合法 +SysUser.sex.num.null = 用户性别数字不能为空 +SysUser.sex.num.illegal = 用户性别数字不合法 +SysUser.telephone.format.illegal = 用户手机号码不合法 +SysUser.email.length.illegal = 用户邮箱长度不合法 +SysUser.email.format.illegal = 用户邮箱格式不合法 +SysUser.admCode.illegal = 用户行政区划代码不合法 +SysUser.address.length.illegal = 用户详细地址长度不合法 +SysUser.birthday.format.illegal = 用户出生日期必须是 yyyy-MM-dd +SysUser.personalSignature.length.illegal = 用户个性签名长度非法 +SysUser.portraitId.illegal = 用户头像id非法 +SysUser.statusCode.null = 用户当前状态编码为空 +SysUser.statusCode.illegal = 用户当前状态编码非法 +SysUser.deleteFlag.null = 用户删除标记不能是空 + +TrajectoryRecord.id.null = id 不能为空 +TrajectoryRecord.startTimeTs.null = startTimeTs 不能为空 + +SatelliteFirePoint.id.null = id 不能为空 +SatelliteFirePoint.fireCode.null = fireCode 不能为空 +SatelliteFirePoint.fireCode.length.illegal = fireCode 长度过长 +SatelliteFirePoint.countyCode.null = countyCode 不能为空 +SatelliteFirePoint.countyCode.length.illegal = countyCode 长度过长 +SatelliteFirePoint.countyName.null = countyName 不能为空 +SatelliteFirePoint.countyName.length.illegal = countyName 长度过长 +SatelliteFirePoint.satelliteType.null = satelliteType 不能为空 +SatelliteFirePoint.fireStatus.null = fireStatus 不能为空 +SatelliteFirePoint.verifyStatus.null = verifyStatus 不能为空 +SatelliteFirePoint.satelliteTimeTs.null = satelliteTimeTs 不能为空 + +PictureFirePoint.id.null = id 不能为空 +PictureFirePoint.fireCode.null = fireCode 不能为空 +PictureFirePoint.fireCode.length.illegal = fireCode 长度过长 +PictureFirePoint.pictureName.length.illegal = pictureName 长度过长 +PictureFirePoint.picturePath.null = picturePath 不能为空 +PictureFirePoint.picturePath.length.illegal = picturePath 长度过长 +PictureFirePoint.memo.length.illegal = memo 长度过长 +PictureFirePoint.size.length.illegal = size 长度过长 +PictureFirePoint.md5.null = md5 不能为空 +PictureFirePoint.md5.length.illegal = md5 长度过长 +PictureFirePoint.shootTimeTs.null = shootTimeTs 不能为空 + +PersonInvestigator.id.null = id 不能为空 +PersonInvestigator.name.null = name 不能为空 +PersonInvestigator.name.length.illegal = name 长度过长 +PersonInvestigator.code.length.illegal = code 长度过长 +PersonInvestigator.telephone.null = telephone 不能为空 +PersonInvestigator.telephone.format.illegal = telephone 格式非法 +PersonInvestigator.sex.null = sex 不能为空 +PersonInvestigator.sex.format.illegal = sex 格式非法 +PersonInvestigator.idCard.length.illegal = idCard 长度过长 +PersonInvestigator.memo.length.illegal = memo 长度过长 +PersonInvestigator.linkUserName.null = linkUserName 不能为空 +PersonInvestigator.linkUserName.format.illegal = linkUserName 格式非法 +PersonInvestigator.password.null = password 不能为空 +PersonInvestigator.password.format.illegal = password 格式非法 +InvestigateFirePoint.verifyTimeTs.null = verifyTimeTs 不能为空 + +InvestigateFirePoint.id.null = id 不能为空 +InvestigateFirePoint.fireCode.null = fireCode 不能为空 +InvestigateFirePoint.fireCode.length.illegal = fireCode 长度过长 +InvestigateFirePoint.countyCode.null = countyCode 不能为空 +InvestigateFirePoint.countyCode.length.illegal = countyCode 长度过长 +InvestigateFirePoint.countyName.null = countyName 不能为空 +InvestigateFirePoint.countyName.length.illegal = countyName 长度过长 +InvestigateFirePoint.address.null = address 不能为空 +InvestigateFirePoint.fireArea.null = fireArea 不能为空 +InvestigateFirePoint.verifyType.null = verifyType 不能为空 +InvestigateFirePoint.satelliteType.null = satelliteType 不能为空 +InvestigateFirePoint.satelliteType.length.illegal = satelliteType 长度过长 + +FileDocument.id.null = id 不能为空 +FileDocument.name.null = name 不能为空 +FileDocument.name.length.illegal = name 长度过长 +FileDocument.category.length.illegal = category 长度过长 +FileDocument.filePath.null = filePath 不能为空 +FileDocument.filePath.length.illegal = filePath 长度过长 +FileDocument.size.length.illegal = size 长度过长 +FileDocument.md5.null = md5 不能为空 +FileDocument.md5.length.illegal = md5 长度过长 +FileDocument.memo.length.illegal = memo 长度过长 +FileDocument.checkingToken.length.illegal = checkingToken 长度过长 + +AppFile.id.null = id 不能为空 +AppFile.name.null = name 不能为空 +AppFile.name.length.illegal = name 长度过长 +AppFile.appPath.null = appPath 不能为空 +AppFile.appPath.length.illegal = appPath 长度过长 +AppFile.versionNumber.null = versionNumber 不能为空 +AppFile.versionNumber.length.illegal = versionNumber 长度过长 +AppFile.versionNumber.format.illegal = versionNumber 格式不合法 +AppFile.size.null = size 不能为空 +AppFile.size.length.illegal = size 长度过长 +AppFile.md5.null = md5 不能为空 +AppFile.md5.length.illegal = md5 长度过长 +AppFile.memo.length.illegal = memo 长度过长 + +RealFirePoint.id.null = id 不能为空 +RealFirePoint.fireCode.null = fireCode 不能为空 +RealFirePoint.fireCode.length.illegal = fireCode 不合法 +RealFirePoint.countyCode.null = countyCode 不能为空 +RealFirePoint.countyCode.length.illegal = countyCode 不合法 +RealFirePoint.countyName.null = countyName 不能为空 +RealFirePoint.countyName.length.illegal = countyName 不合法 +RealFirePoint.address.null = address 不能为空 +RealFirePoint.address.length.illegal = address 不合法 +RealFirePoint.fireArea.null = fireArea 不能为空 +RealFirePoint.verifyTimeTs.null = verifyTimeTs 不能为空 +RealFirePoint.verifyType.null = verifyType 不能为空 + +InvestigationTeam.id.null = id 不能为空 +InvestigationTeam.teamName.null = teamName 不能为空 +InvestigationTeam.teamName.length.illegal = teamName 长度过长 +InvestigationTeam.memo.length.illegal = memo 长度过长 +InvestigationTeam.userName.null = userName 不能为空 +InvestigationTeam.userName.length.illegal = userName 长度过长 +InvestigationTeam.userRealName.null = userRealName 不能为空 +InvestigationTeam.userRealName.length.illegal = userRealName 长度过长 + +RelTeamInvestigator.id.null = id 不能为空 +RelTeamInvestigator.teamCode.null = teamCode 不能为空 +RelTeamInvestigator.teamCode.length.illegal = teamCode 长度过长 +RelTeamInvestigator.userName.null = userName 不能为空 +RelTeamInvestigator.userName.length.illegal = userName 长度过长 +RelTeamInvestigator.teamDeputy.null = teamDeputy 不能为空 +RelTeamInvestigator.memo.length.illegal = memo 长度过长 +RelTeamInvestigator.userRealName.null = userRealName 不能为空 +RelTeamInvestigator.userRealName.length.illegal = userRealName 长度过长 diff --git a/src/main/resources/i18n/messages_en_US.properties b/src/main/resources/i18n/messages_en_US.properties new file mode 100644 index 0000000..9b23e85 --- /dev/null +++ b/src/main/resources/i18n/messages_en_US.properties @@ -0,0 +1,162 @@ +sys.message.success = success +sys.message.null = null +sys.message.exit = data already exists +sys.message.user.not_logged_in = user not logged in +sys.message.user.login_error = user login failed +sys.message.user.account_forbidden = this account is forbidden +sys.message.user.account_not_activated = this account not activated +sys.message.user.overtime = user login timeout +sys.message.user.no_permission = user permission denied +sys.message.user.already_logged = user already logged +sys.message.param.null = parameter is null +sys.message.param.illegal = parameter is illegal +sys.message.data.none = data is none +sys.message.data.wrong = data is wrong +sys.message.process.fail = process fail +sys.message.process.overtime = process overtime +sys.message.system.inner_error = system inner error +sys.message.system.abnormal = system abnormal +sys.message.system.busy = system is busy +sys.message.system.maintain = system maintenance +sys.message.database.error = database error +sys.message.file.exists = file exists +sys.message.file.write.error = file write error +sys.message.file.read.error = file read error + +SysUser.id.blank = user id can't be blank +SysUser.userName.blank = user name can't be blank +SysUser.userName.length.illegal = user name length illegal +SysUser.userName.format.illegal = user name format illegal +SysUser.nickName.length.illegal = user nickname length illegal +SysUser.userCode.length.illegal = user code length illegal +SysUser.userCode.format.illegal = user code cantains illegal character +SysUser.password.blank = user password can't be blank +SysUser.password.length.illegal = user password length illegal +SysUser.password.format.illegal = user password format illegal +SysUser.sex.num.null = user sex num can't be blank +SysUser.sex.num.illegal = user sex num illegal +SysUser.telephone.format.illegal = user telephone format illegal +SysUser.email.length.illegal = user email length illegal +SysUser.email.format.illegal = user email format illegal +SysUser.admCode.illegal = user administrative area code illegal +SysUser.address.length.illegal = user address length illegal +SysUser.birthday.format.illegal = user birthday must be yyyy-MM-dd +SysUser.personalSignature.length.illegal = user personal signature length illegal +SysUser.portraitId.illegal = user portrait id illegal +SysUser.statusCode.null = user current status code can't be blank +SysUser.statusCode.illegal = user current status code illegal +SysUser.deleteFlag.null = user delete flag can't be null + +TrajectoryRecord.id.null = id can't be null +TrajectoryRecord.startTimeTs.null = startTimeTs can't be null + +SatelliteFirePoint.id.null = id can't be blank +SatelliteFirePoint.fireCode.null = fireCode can't be blank +SatelliteFirePoint.fireCode.length.illegal = fireCode length illegal +SatelliteFirePoint.countyCode.null = countyCode can't be blank +SatelliteFirePoint.countyCode.length.illegal = countyCode length illegal +SatelliteFirePoint.countyName.null = countyName can't be blank +SatelliteFirePoint.countyName.length.illegal = countyName length illegal +SatelliteFirePoint.satelliteType.null = satelliteType can't be blank +SatelliteFirePoint.fireStatus.null = fireStatus can't be blank +SatelliteFirePoint.verifyStatus.null = verifyStatus can't be blank +SatelliteFirePoint.satelliteTimeTs.null = satelliteTimeTs can't be blank + +PictureFirePoint.id.null = id can't be blank +PictureFirePoint.fireCode.null = fireCode can't be blank +PictureFirePoint.fireCode.length.illegal = fireCode length illegal +PictureFirePoint.pictureName.length.illegal = pictureName length illegal +PictureFirePoint.picturePath.null = picturePath can't be blank +PictureFirePoint.picturePath.length.illegal = picturePath length illegal +PictureFirePoint.memo.length.illegal = memo length illegal +PictureFirePoint.size.length.illegal = size length illegal +PictureFirePoint.md5.null = md5 can't be blank +PictureFirePoint.md5.length.illegal = md5 length illegal +PictureFirePoint.shootTimeTs.null = shootTimeTs can't be blank + +PersonInvestigator.id.null = id can't be blank +PersonInvestigator.name.null = name can't be blank +PersonInvestigator.name.length.illegal = name length illegal +PersonInvestigator.code.length.illegal = code length illegal +PersonInvestigator.telephone.null = telephone can't be blank +PersonInvestigator.telephone.format.illegal = telephone format illegal +PersonInvestigator.sex.null = sex format can't be blank +PersonInvestigator.sex.format.illegal = sex format illegal +PersonInvestigator.idCard.length.illegal = idCard length illegal +PersonInvestigator.memo.length.illegal = memo length illegal +PersonInvestigator.linkUserName.null = linkUserName can't be blank +PersonInvestigator.linkUserName.format.illegal = linkUserName format illegal +PersonInvestigator.password.null = password can't be blank +PersonInvestigator.password.format.illegal = password format +InvestigateFirePoint.verifyTimeTs.null = verifyTimeTs can't be blank + +InvestigateFirePoint.id.null = id can't be blank +InvestigateFirePoint.fireCode.null = fireCode can't be blank +InvestigateFirePoint.fireCode.length.illegal = fireCode length illegal +InvestigateFirePoint.countyCode.null = countyCode can't be blank +InvestigateFirePoint.countyCode.length.illegal = countyCode length illegal +InvestigateFirePoint.countyName.null = countyName can't be blank +InvestigateFirePoint.countyName.length.illegal = countyName length illegal +InvestigateFirePoint.address.null = address can't be blank +InvestigateFirePoint.fireArea.null = fireArea can't be blank +InvestigateFirePoint.verifyType.null = verifyType can't be blank +InvestigateFirePoint.satelliteType.null = satelliteType can't be blank +InvestigateFirePoint.satelliteType.length.illegal = satelliteType length illegal + +FileDocument.id.null = id can't be blank +FileDocument.name.null = name can't be blank +FileDocument.name.length.illegal = name length illegal +FileDocument.category.length.illegal = category length illegal +FileDocument.filePath.null = filePath can't be blank +FileDocument.filePath.length.illegal = filePath length illegal +FileDocument.size.length.illegal = size length illegal +FileDocument.md5.null = md5 can't be blank +FileDocument.md5.length.illegal = md5 length illegal +FileDocument.memo.length.illegal = memo length illegal +FileDocument.checkingToken.length.illegal = checkingToken length illegal + +AppFile.id.null = id can't be blank +AppFile.name.null = name can't be blank +AppFile.name.length.illegal = name length illegal +AppFile.appPath.null = appPath can't be blank +AppFile.appPath.length.illegal = appPath length illegal +AppFile.versionNumber.null = versionNumber can't be blank +AppFile.versionNumber.length.illegal = versionNumber length illegal +AppFile.versionNumber.format.illegal = versionNumber illegal +AppFile.size.null = size can't be blank +AppFile.size.length.illegal = size length illegal +AppFile.md5.null = md5 can't be blank +AppFile.md5.length.illegal = md5 length illegal +AppFile.memo.length.illegal = memo length illegal + +RealFirePoint.id.null = id can't be blank +RealFirePoint.fireCode.null = fireCode can't be blank +RealFirePoint.fireCode.length.illegal = fireCode illegal +RealFirePoint.countyCode.null = countyCode can't be blank +RealFirePoint.countyCode.length.illegal = countyCode +RealFirePoint.countyName.null = countyName can't be blank +RealFirePoint.countyName.length.illegal = countyName illegal +RealFirePoint.address.null = address can't be blank +RealFirePoint.address.length.illegal = address illegal +RealFirePoint.fireArea.null = fireArea can't be blank +RealFirePoint.verifyTimeTs.null = verifyTimeTs can't be blank +RealFirePoint.verifyType.null = verifyType can't be blank + +InvestigationTeam.id.null = id can't be blank +InvestigationTeam.teamName.null = teamName can't be blank +InvestigationTeam.teamName.length.illegal = teamName length illegal +InvestigationTeam.memo.length.illegal = memo length illegal +InvestigationTeam.userName.null = userName can't be blank +InvestigationTeam.userName.length.illegal = userName length illegal +InvestigationTeam.userRealName.null = userRealName can't be blank +InvestigationTeam.userRealName.length.illegal = userRealName length illegal + +RelTeamInvestigator.id.null = id can't be blank +RelTeamInvestigator.teamCode.null = teamCode can't be blank +RelTeamInvestigator.teamCode.length.illegal = teamCode length illegal +RelTeamInvestigator.userName.null = userName can't be blank +RelTeamInvestigator.userName.length.illegal = userName length illegal +RelTeamInvestigator.teamDeputy.null = teamDeputy can't be blank +RelTeamInvestigator.memo.length.illegal = memo length illegal +RelTeamInvestigator.userRealName.null = userRealName can't be blank +RelTeamInvestigator.userRealName.length.illegal = userRealName length illegal diff --git a/src/main/resources/i18n/messages_zh_CN.properties b/src/main/resources/i18n/messages_zh_CN.properties new file mode 100644 index 0000000..8cfedc5 --- /dev/null +++ b/src/main/resources/i18n/messages_zh_CN.properties @@ -0,0 +1,162 @@ +sys.message.success = 成功 +sys.message.null = 暂时还没有数据 +sys.message.exit = 已存在相关内容,请勿重复操作 +sys.message.user.not_logged_in = 用户未登录 +sys.message.user.login_error = 用户登陆失败 +sys.message.user.account_forbidden = 用户已被禁止 +sys.message.user.account_not_activated = 用户未激活 +sys.message.user.overtime = 用户登录超时 +sys.message.user.no_permission = 用户权限不足 +sys.message.user.already_logged = 用户已经登录 +sys.message.param.null = 参数为空 +sys.message.param.illegal = 参数非法 +sys.message.data.none = 数据为空 +sys.message.data.wrong = 数据错误 +sys.message.process.fail = 处理失败 +sys.message.process.overtime = 处理超时 +sys.message.system.inner_error = 系统内部错误 +sys.message.system.abnormal = 系统异常 +sys.message.system.busy = 系统正忙,请稍后 +sys.message.system.maintain = 系统维护中 +sys.message.database.error = 数据库错误 +sys.message.file.exists = 文件已存在 +sys.message.file.write.error = 文件写入失败 +sys.message.file.read.error = 文件读取失败 + +SysUser.id.blank = 用户id不能为空 +SysUser.userName.blank = 用户名不能为空 +SysUser.userName.length.illegal = 用户名长度不合法 +SysUser.userName.format.illegal = 用户名格式不合法 +SysUser.nickName.length.illegal = 用户昵称长度不合法 +SysUser.userCode.length.illegal = 用户编码长度不合法 +SysUser.userCode.format.illegal = 用户编码含有非法字符 +SysUser.password.blank = 用户密码不能为空 +SysUser.password.length.illegal = 用户密码长度不合法 +SysUser.password.format.illegal = 用户密码格式不合法 +SysUser.sex.num.null = 用户性别数字不能为空 +SysUser.sex.num.illegal = 用户性别数字不合法 +SysUser.telephone.format.illegal = 用户手机号码不合法 +SysUser.email.length.illegal = 用户邮箱长度不合法 +SysUser.email.format.illegal = 用户邮箱格式不合法 +SysUser.admCode.illegal = 用户行政区划代码不合法 +SysUser.address.length.illegal = 用户详细地址长度不合法 +SysUser.birthday.format.illegal = 用户出生日期必须是 yyyy-MM-dd +SysUser.personalSignature.length.illegal = 用户个性签名长度非法 +SysUser.portraitId.illegal = 用户头像id非法 +SysUser.statusCode.null = 用户当前状态编码为空 +SysUser.statusCode.illegal = 用户当前状态编码非法 +SysUser.deleteFlag.null = 用户删除标记不能是空 + +TrajectoryRecord.id.null = id 不能为空 +TrajectoryRecord.startTimeTs.null = startTimeTs 不能为空 + +SatelliteFirePoint.id.null = id 不能为空 +SatelliteFirePoint.fireCode.null = fireCode 不能为空 +SatelliteFirePoint.fireCode.length.illegal = fireCode 长度过长 +SatelliteFirePoint.countyCode.null = countyCode 不能为空 +SatelliteFirePoint.countyCode.length.illegal = countyCode 长度过长 +SatelliteFirePoint.countyName.null = countyName 不能为空 +SatelliteFirePoint.countyName.length.illegal = countyName 长度过长 +SatelliteFirePoint.satelliteType.null = satelliteType 不能为空 +SatelliteFirePoint.fireStatus.null = fireStatus 不能为空 +SatelliteFirePoint.verifyStatus.null = verifyStatus 不能为空 +SatelliteFirePoint.satelliteTimeTs.null = satelliteTimeTs 不能为空 + +PictureFirePoint.id.null = id 不能为空 +PictureFirePoint.fireCode.null = fireCode 不能为空 +PictureFirePoint.fireCode.length.illegal = fireCode 长度过长 +PictureFirePoint.pictureName.length.illegal = pictureName 长度过长 +PictureFirePoint.picturePath.null = picturePath 不能为空 +PictureFirePoint.picturePath.length.illegal = picturePath 长度过长 +PictureFirePoint.memo.length.illegal = memo 长度过长 +PictureFirePoint.size.length.illegal = size 长度过长 +PictureFirePoint.md5.null = md5 不能为空 +PictureFirePoint.md5.length.illegal = md5 长度过长 +PictureFirePoint.shootTimeTs.null = shootTimeTs 不能为空 + +PersonInvestigator.id.null = id 不能为空 +PersonInvestigator.name.null = name 不能为空 +PersonInvestigator.name.length.illegal = name 长度过长 +PersonInvestigator.code.length.illegal = code 长度过长 +PersonInvestigator.telephone.null = telephone 不能为空 +PersonInvestigator.telephone.format.illegal = telephone 格式非法 +PersonInvestigator.sex.null = sex 不能为空 +PersonInvestigator.sex.format.illegal = sex 格式非法 +PersonInvestigator.idCard.length.illegal = idCard 长度过长 +PersonInvestigator.memo.length.illegal = memo 长度过长 +PersonInvestigator.linkUserName.null = linkUserName 不能为空 +PersonInvestigator.linkUserName.format.illegal = linkUserName 格式非法 +PersonInvestigator.password.null = password 不能为空 +PersonInvestigator.password.format.illegal = password 格式非法 +InvestigateFirePoint.verifyTimeTs.null = verifyTimeTs 不能为空 + +InvestigateFirePoint.id.null = id 不能为空 +InvestigateFirePoint.fireCode.null = fireCode 不能为空 +InvestigateFirePoint.fireCode.length.illegal = fireCode 长度过长 +InvestigateFirePoint.countyCode.null = countyCode 不能为空 +InvestigateFirePoint.countyCode.length.illegal = countyCode 长度过长 +InvestigateFirePoint.countyName.null = countyName 不能为空 +InvestigateFirePoint.countyName.length.illegal = countyName 长度过长 +InvestigateFirePoint.address.null = address 不能为空 +InvestigateFirePoint.fireArea.null = fireArea 不能为空 +InvestigateFirePoint.verifyType.null = verifyType 不能为空 +InvestigateFirePoint.satelliteType.null = satelliteType 不能为空 +InvestigateFirePoint.satelliteType.length.illegal = satelliteType 长度过长 + +FileDocument.id.null = id 不能为空 +FileDocument.name.null = name 不能为空 +FileDocument.name.length.illegal = name 长度过长 +FileDocument.category.length.illegal = category 长度过长 +FileDocument.filePath.null = filePath 不能为空 +FileDocument.filePath.length.illegal = filePath 长度过长 +FileDocument.size.length.illegal = size 长度过长 +FileDocument.md5.null = md5 不能为空 +FileDocument.md5.length.illegal = md5 长度过长 +FileDocument.memo.length.illegal = memo 长度过长 +FileDocument.checkingToken.length.illegal = checkingToken 长度过长 + +AppFile.id.null = id 不能为空 +AppFile.name.null = name 不能为空 +AppFile.name.length.illegal = name 长度过长 +AppFile.appPath.null = appPath 不能为空 +AppFile.appPath.length.illegal = appPath 长度过长 +AppFile.versionNumber.null = versionNumber 不能为空 +AppFile.versionNumber.length.illegal = versionNumber 长度过长 +AppFile.versionNumber.format.illegal = versionNumber 格式不合法 +AppFile.size.null = size 不能为空 +AppFile.size.length.illegal = size 长度过长 +AppFile.md5.null = md5 不能为空 +AppFile.md5.length.illegal = md5 长度过长 +AppFile.memo.length.illegal = memo 长度过长 + +RealFirePoint.id.null = id 不能为空 +RealFirePoint.fireCode.null = fireCode 不能为空 +RealFirePoint.fireCode.length.illegal = fireCode 不合法 +RealFirePoint.countyCode.null = countyCode 不能为空 +RealFirePoint.countyCode.length.illegal = countyCode 不合法 +RealFirePoint.countyName.null = countyName 不能为空 +RealFirePoint.countyName.length.illegal = countyName 不合法 +RealFirePoint.address.null = address 不能为空 +RealFirePoint.address.length.illegal = address 不合法 +RealFirePoint.fireArea.null = fireArea 不能为空 +RealFirePoint.verifyTimeTs.null = verifyTimeTs 不能为空 +RealFirePoint.verifyType.null = verifyType 不能为空 + +InvestigationTeam.id.null = id 不能为空 +InvestigationTeam.teamName.null = teamName 不能为空 +InvestigationTeam.teamName.length.illegal = teamName 长度过长 +InvestigationTeam.memo.length.illegal = memo 长度过长 +InvestigationTeam.userName.null = userName 不能为空 +InvestigationTeam.userName.length.illegal = userName 长度过长 +InvestigationTeam.userRealName.null = userRealName 不能为空 +InvestigationTeam.userRealName.length.illegal = userRealName 长度过长 + +RelTeamInvestigator.id.null = id 不能为空 +RelTeamInvestigator.teamCode.null = teamCode 不能为空 +RelTeamInvestigator.teamCode.length.illegal = teamCode 长度过长 +RelTeamInvestigator.userName.null = userName 不能为空 +RelTeamInvestigator.userName.length.illegal = userName 长度过长 +RelTeamInvestigator.teamDeputy.null = teamDeputy 不能为空 +RelTeamInvestigator.memo.length.illegal = memo 长度过长 +RelTeamInvestigator.userRealName.null = userRealName 不能为空 +RelTeamInvestigator.userRealName.length.illegal = userRealName 长度过长 diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..b099c42 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file