Преглед на файлове

Merge branch 'release-1.0.0'

tags/v1.0.0^0
林万龙 преди 3 години
родител
ревизия
6d4c6a0e2f
променени са 47 файла, в които са добавени 3823 реда и са изтрити 0 реда
  1. +31
    -0
      .gitignore
  2. +12
    -0
      Dockerfile
  3. +30
    -0
      dipper_position_run.sh
  4. +159
    -0
      pom.xml
  5. +65
    -0
      setup_dev.sh
  6. +20
    -0
      setup_pro.sh
  7. +27
    -0
      setup_test.sh
  8. +39
    -0
      src/main/java/com/telpo/dipperposition/DipperPositionApplication.java
  9. +22
    -0
      src/main/java/com/telpo/dipperposition/annotation/MongoSwitch.java
  10. +35
    -0
      src/main/java/com/telpo/dipperposition/co/PositionConfigInfo.java
  11. +87
    -0
      src/main/java/com/telpo/dipperposition/common/CSVUtil.java
  12. +174
    -0
      src/main/java/com/telpo/dipperposition/common/HexConvert.java
  13. +172
    -0
      src/main/java/com/telpo/dipperposition/common/OkHttpUtil.java
  14. +672
    -0
      src/main/java/com/telpo/dipperposition/common/RedisUtil.java
  15. +88
    -0
      src/main/java/com/telpo/dipperposition/common/SocketClient.java
  16. +71
    -0
      src/main/java/com/telpo/dipperposition/config/AsyncExecutorConfig.java
  17. +31
    -0
      src/main/java/com/telpo/dipperposition/config/NettyServerConfig.java
  18. +103
    -0
      src/main/java/com/telpo/dipperposition/config/OkHttpConfig.java
  19. +26
    -0
      src/main/java/com/telpo/dipperposition/config/PositionConfig.java
  20. +53
    -0
      src/main/java/com/telpo/dipperposition/config/SchedulingExecutorConfig.java
  21. +24
    -0
      src/main/java/com/telpo/dipperposition/entity/mongo/IpProvinceEntity.java
  22. +28
    -0
      src/main/java/com/telpo/dipperposition/entity/mongo/ProvinceInfoEntity.java
  23. +53
    -0
      src/main/java/com/telpo/dipperposition/enums/DipperReturnValue.java
  24. +269
    -0
      src/main/java/com/telpo/dipperposition/handler/NettyServerHandler.java
  25. +26
    -0
      src/main/java/com/telpo/dipperposition/handler/ServerChannelInitializer.java
  26. +15
    -0
      src/main/java/com/telpo/dipperposition/mapper/IpProvinceMapper.java
  27. +15
    -0
      src/main/java/com/telpo/dipperposition/mapper/ProvinceInfoMapper.java
  28. +83
    -0
      src/main/java/com/telpo/dipperposition/server/DipperPositionServer.java
  29. +31
    -0
      src/main/java/com/telpo/dipperposition/service/IDipperAstPosAsyncTaskService.java
  30. +22
    -0
      src/main/java/com/telpo/dipperposition/service/IDipperAstTimeAsyncTaskService.java
  31. +31
    -0
      src/main/java/com/telpo/dipperposition/service/IDipperDataAsyncTaskService.java
  32. +54
    -0
      src/main/java/com/telpo/dipperposition/service/IProvinceInfoService.java
  33. +37
    -0
      src/main/java/com/telpo/dipperposition/service/IpProvinceService.java
  34. +261
    -0
      src/main/java/com/telpo/dipperposition/service/impl/DipperAstPosAsyncTaskServiceImpl.java
  35. +110
    -0
      src/main/java/com/telpo/dipperposition/service/impl/DipperAstTimeAsyncTaskServiceImpl.java
  36. +98
    -0
      src/main/java/com/telpo/dipperposition/service/impl/DipperDataAsyncTaskServiceImpl.java
  37. +69
    -0
      src/main/java/com/telpo/dipperposition/service/impl/IpProvinceServiceImpl.java
  38. +85
    -0
      src/main/java/com/telpo/dipperposition/service/impl/ProvinceInfoServiceImpl.java
  39. +43
    -0
      src/main/java/com/telpo/dipperposition/task/ScheduleService.java
  40. +20
    -0
      src/main/java/com/telpo/dipperposition/vo/IPProvinceVo.java
  41. +24
    -0
      src/main/java/com/telpo/dipperposition/vo/ProvinceInfoVo.java
  42. +61
    -0
      src/main/resources/application.properties
  43. +10
    -0
      src/main/resources/bootstrap-dev.yaml
  44. +79
    -0
      src/main/resources/bootstrap-pro.yaml
  45. +87
    -0
      src/main/resources/bootstrap-test.yaml
  46. +73
    -0
      src/main/resources/bootstrap.yaml
  47. +198
    -0
      src/main/resources/log/logback-spring.xml

+ 31
- 0
.gitignore Целия файл

@@ -0,0 +1,31 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**

### 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/

### VS Code ###
.vscode/

+ 12
- 0
Dockerfile Целия файл

@@ -0,0 +1,12 @@
FROM java:8
MAINTAINER king <1609724385@qq.com>
VOLUME /tmp
COPY target/dipperposition.jar dipperposition.jar
COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas
ENV TimeZone=Asia/Shanghai
ENV active=dev
ENV JAVA_OPTS="-Xmx256M -Xms256M"
RUN ln -snf /usr/share/zoneinfo/$TimeZone /etc/localtime && echo $TimeZone > /etc/timezone
ENTRYPOINT java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -Dio.netty.leakDetectionLevel=ADVANCED -jar /dipperposition.jar --spring.profiles.active=$active

java -Xmx256M -Xms256M -Djava.security.egd=file:/dev/./urandom -Dio.netty.leakDetectionLevel=ADVANCED -jar /dipperposition.jar --spring.profiles.active=

+ 30
- 0
dipper_position_run.sh Целия файл

@@ -0,0 +1,30 @@
#!/bin/bash
environment=$1
version=$2
echo "环境变量为${environment},版本为$version!"

#processID='ps -ef | grep dipperposition | awk '{print $2}' | awk NR==1'
ps -ef | grep dipperposition | awk '{print $2}' | xargs kill -9
#echo $processID
#if [[ "$processID" != "" ]]; then
# kill -9 $processID
#fi

if [[ ${environment} == 'pro' ]]; then
echo 'run in production environment'
cd /home/data/dipperposition
if [[ -f /home/linwl/dipperposition/dipperposition.jar ]]; then
echo 'mv /home/linwl/dipperposition/dipperposition.jar to destination'
mv /home/linwl/dipperposition/dipperposition.jar /home/data/dipperposition/dipperposition.jar
fi
nohup java -Xmx1024M -Xms1024M -Djava.security.egd=file:/dev/./urandom -Dio.netty.leakDetectionLevel=ADVANCED -jar dipperposition.jar --spring.profiles.active=pro &

fi
if [[ ${environment} == 'test' ]]; then
cd /home/data/dipperposition
if [[ -f /home/linwl/Work/DipperPosition/dipperposition.jar ]]; then
mv /home/linwl/Work/DipperPosition/dipperposition.jar /home/data/dipperposition/dipperposition.jar
fi
nohup java -Xmx128M -Xms128M -Djava.security.egd=file:/dev/./urandom -Dio.netty.leakDetectionLevel=ADVANCED -jar dipperposition.jar --spring.profiles.active=test &
fi

+ 159
- 0
pom.xml Целия файл

@@ -0,0 +1,159 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.telpo</groupId>
<artifactId>dipperposition</artifactId>
<version>1.0-SNAPSHOT</version>
<name>dipperposition</name>
<description>北斗定位服务</description>
<packaging>jar</packaging>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<spring-cloud-alibaba.version>2.2.0.RELEASE</spring-cloud-alibaba.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
<skipTests>true</skipTests>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.5.2</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>

<!-- Yaml -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.25</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.13.Final</version>
</dependency>

<!-- 开启redis缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/de.codecentric/spring-boot-admin-starter-client -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/net.sourceforge.javacsv/javacsv -->
<dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
<version>2.0</version>
</dependency>

<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

</dependencies>
</dependencyManagement>

<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--fork : 使用 devtools生效-->
<fork>true</fork>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

+ 65
- 0
setup_dev.sh Целия файл

@@ -0,0 +1,65 @@
#!/bin/bash
mvn clean
mvn package -Dmaven.test.skip=true
#image_version=$(date +%Y%m%d%H%M)
image_version=$version

#docker cp docker_jenkins:/var/jenkins_home/workspace/dipperpos_service/target/dipperposition.jar
# /usr/local/dipperposition/dipperposition.jar
docker stop dipperposition_service || true
docker rm dipperposition_service || true

# 删除镜像
docker rmi -f $(docker images | grep telpo/dipperposition_service | awk '{print $3}')

docker build . -t telpo/dipperposition_service:$image_version

#TODO:推送镜像到私有仓库
echo '=================开始推送镜像======================='
docker tag telpo/dipperposition_service:$image_version 139.224.254.18:5000/dipperposition_service:$image_version
docker push 139.224.254.18:5000/dipperposition_service:$image_version
echo '=================推送镜像完成======================='

#删除产生的None镜像
docker rmi -f $(docker images | grep none | awk '{print $3}')
# 查看镜像列表
docker images
# 启动容器
docker run -v /home/data/dipperposition/log:/var/log/dipperposition -d -e active=dev --network host --restart=always -p 9011:9011 -p 9012:9012 -p 9013:9013 --name dipperposition_service 139.224.254.18:5000/dipperposition_service:$image_version

#echo "scp ${WORKSPACE} files......begin"
#set passwd "telpo#1234"
#scp /var/jenkins_home/workspace/dipperpos_service/target/dipperposition.jar root@47.116.142.20:/home/data/dipperposition/dipperposition.jar
#expect {
# "密码:"
# {
# send "$passwd\n"
# }
# "pass"
# {
# send "$passwd\n"
# }
#
# "yes/no"
# {
# sleep 5
# send_user "send yes"
# send "yes\n"
# }
# eof
# {
# sleep 5
# send_user "eof\n"
# }
#}
#send "exit\r"
#expect eof
#echo "scp ${WORKSPACE} files......end"
# 查看日志
#docker logs dipperposition_service

#echo '=================启动NettyAPP======================='
#ps -ef |grep dipperposition |awk '{print $2}'|xargs kill -9
#java -jar -Xms256m -Xmx256m -Xss256k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
# /usr/local/dipperposition/dipperposition.jar --spring.profiles.active=dev
#echo '=================完成NettyAPP启动======================='

+ 20
- 0
setup_pro.sh Целия файл

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
mvn clean
mvn package -Dmaven.test.skip=true
image_version=$version
# 删除镜像
docker rmi -f $(
docker images | grep registry.cn-shanghai.aliyuncs.com/telpo_platform/dipperposition_service | awk '{print $3}'
)
# 构建telpo/mrp:$image_version镜像
docker build . -t telpo/dipperposition_service:$image_version
#TODO:推送镜像到阿里仓库
echo '=================开始推送镜像======================='
docker login --username=rzl_wangjx@1111649216405698 --password=telpo.123 registry.cn-shanghai.aliyuncs.com
docker tag telpo/dipperposition_service:$image_version registry.cn-shanghai.aliyuncs.com/telpo_platform/dipperposition_service:$image_version
docker push registry.cn-shanghai.aliyuncs.com/telpo_platform/dipperposition_service:$image_version
echo '=================推送镜像完成======================='
#删除产生的None镜像
docker rmi -f $(docker images | grep none | awk '{print $3}')
# 查看镜像列表
docker images

+ 27
- 0
setup_test.sh Целия файл

@@ -0,0 +1,27 @@
#!/bin/bash
mvn clean
mvn package -Dmaven.test.skip=true
#image_version=$(date +%Y%m%d%H%M)
image_version=$version
docker stop dipperposition_service || true
docker rm dipperposition_service || true

# 删除镜像
docker rmi -f $(docker images | grep telpo/dipperposition_service | awk '{print $3}')

docker build . -t telpo/dipperposition_service:$image_version

#TODO:推送镜像到私有仓库
echo '=================开始推送镜像======================='
docker tag telpo/dipperposition_service:$image_version 139.224.254.18:5000/dipperposition_service:$image_version
docker push 139.224.254.18:5000/dipperposition_service:$image_version
echo '=================推送镜像完成======================='

#删除产生的None镜像
docker rmi -f $(docker images | grep none | awk '{print $3}')
# 查看镜像列表
docker images
# 启动容器
docker run -v /home/data/dipperposition/log:/var/log/dipperposition -d -e active=test --network host --restart=always -p 9012:9012 --name dipperposition_service 139.224.254.18:5000/dipperposition_service:$image_version
# 查看日志
# docker logs dipperposition_service

+ 39
- 0
src/main/java/com/telpo/dipperposition/DipperPositionApplication.java Целия файл

@@ -0,0 +1,39 @@
package com.telpo.dipperposition;

import com.telpo.dipperposition.server.DipperPositionServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
* @program: gateway
* @description: 网关启动类
* @author: linwl
* @create: 2020-06-18 16:39
*/
@SpringBootApplication
@ConfigurationPropertiesScan
@EnableAsync
@EnableScheduling
@Slf4j
public class DipperPositionApplication {

public static void main(String[] args) {
try {
log.info("北斗定位服务开始!");
ConfigurableApplicationContext applicationContext = SpringApplication.run(DipperPositionApplication.class, args);
log.info("北斗定位服务启动!");
//启动服务端
ConfigurableEnvironment environment = applicationContext.getEnvironment();
DipperPositionServer nettyServer = new DipperPositionServer(environment);
nettyServer.start();
} catch (Exception e) {
log.error(e.getMessage());
}
}
}

+ 22
- 0
src/main/java/com/telpo/dipperposition/annotation/MongoSwitch.java Целия файл

@@ -0,0 +1,22 @@
package com.telpo.dipperposition.annotation;

import java.lang.annotation.*;

/**
* @program: DataPushServer
* @description: mongo数据源切换注解
* @author: linwl
* @create: 2020-07-11 15:06
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MongoSwitch {

/**
* mongo数据库名称
*
* @return
*/
String value() default "";
}

+ 35
- 0
src/main/java/com/telpo/dipperposition/co/PositionConfigInfo.java Целия файл

@@ -0,0 +1,35 @@
package com.telpo.dipperposition.co;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import okhttp3.*;
import okhttp3.internal.ws.RealWebSocket;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.net.SocketFactory;

/**
* @program: RzlAccount
* @description: 融智联账号配置
* @author: king
* @create: 2021-01-12 14:02
**/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "position-server")
public class PositionConfigInfo {

private String serverAddr;

private String timeAsycPort;

private String posAsycPort;

private String starsAsycPort;

}

+ 87
- 0
src/main/java/com/telpo/dipperposition/common/CSVUtil.java Целия файл

@@ -0,0 +1,87 @@
package com.telpo.dipperposition.common;

import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;

import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* @program: dipperposition
* @description: CSV文件读取单元
* @author: linwl
* @create: 2021-01-14 11:19
**/
public class CSVUtil {
/**
* 读取每行的数据
*
* @param readPath
* @return
*/
public static List<String> readCSV(String readPath) {
String filePath = readPath;
List<String> listData = new ArrayList<>();
try {
filePath = readPath;
CsvReader csvReader = new CsvReader(filePath,',',Charset.forName("UTF-8"));
// 读表头
boolean re = csvReader.readHeaders();
while (csvReader.readRecord()) {
String rawRecord = csvReader.getRawRecord();
listData.add(rawRecord);
}
return listData;
} catch (FileNotFoundException e) {
throw new RuntimeException("文件未找到");
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}

}

/**
* 写入文件头
* @param writePath
* @param header
*/
public static void writeCSV(String writePath, String[] header) {
String filePath = writePath;
try {
CsvWriter csvWriter = new CsvWriter(writePath, ',', Charset.forName("UTF-8"));
//String [] header = {"SkuId","SsuId","图片地址","大小(bit)","高度","宽度"};
csvWriter.writeRecord(header);
csvWriter.close();
} catch (Exception e) {
e.printStackTrace();
}

}

/**
* 利用输入输出流持续写
* @param fileName
* @param content
*/
public static void writeContent(String fileName, String content) {
FileWriter writer = null;
try {
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
writer = new FileWriter(fileName, true);
writer.write(content + "\r\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

+ 174
- 0
src/main/java/com/telpo/dipperposition/common/HexConvert.java Целия файл

@@ -0,0 +1,174 @@
package com.telpo.dipperposition.common;

/**
* @program: dipperposition
* @description: 16进制处理
* @author: linwl
* @create: 2021-01-14 22:05
**/
public class HexConvert {
public static String convertStringToHex(String str){

char[] chars = str.toCharArray();

StringBuffer hex = new StringBuffer();
for(int i = 0; i < chars.length; i++){
hex.append(Integer.toHexString((int)chars[i]));
}

return hex.toString();
}

public static String convertHexToString(String hex){

StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder();

for( int i=0; i<hex.length()-1; i+=2 ){

String s = hex.substring(i, (i + 2));
int decimal = Integer.parseInt(s, 16);
sb.append((char)decimal);
sb2.append(decimal);
}

return sb.toString();
}
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
// toUpperCase将字符串中的所有字符转换为大写
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
// toCharArray将此字符串转换为一个新的字符数组。
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
//返回匹配字符
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}

//将字节数组转换为short类型,即统计字符串长度
public static short bytes2Short2(byte[] b) {
short i = (short) (((b[1] & 0xff) << 8) | b[0] & 0xff);
return i;
}

//将字节数组转换为16进制字符串
public static String BinaryToHexString(byte[] bytes) {
String hexStr = "0123456789ABCDEF";
String result = "";
String hex = "";
for (byte b : bytes) {
hex = String.valueOf(hexStr.charAt((b & 0xF0) >> 4));
hex += String.valueOf(hexStr.charAt(b & 0x0F));
result += hex + " ";
}
return result;
}

//將10進制轉換為16進制
public static String encodeHEX(long numb){

String hex= Long.toHexString(numb);
return hex;

}


//將16進制字符串轉換為10進制數字
public static long decodeHEX(String hexs){
long longValue= Long.parseLong("123ABC", 16);
return longValue;
}


/**
* 生成校验码的int值
* */
public static String makeChecksum(String data) {
if (data == null || data.equals("")) {
return "";
}
int total = 0;
int len = data.length();
int num = 0;
while (num < len) {
String s = data.substring(num, num + 2);
//System.out.println(s);
total += Integer.parseInt(s, 16);
num = num + 2;
}
/**
* 用256求余最大是255,即16进制的FF
*/
int mod = total % 256;
String hex = Integer.toHexString(mod);
len = hex.length();
// 如果不够校验位的长度,补0,这里用的是两位校验
if (len < 2) {
hex = "0" + hex;
}
return hex;
}


/**
* 生成校验码的int值
* */
public static String makeChecksumForBytes(byte[] byteDatas) {
if (byteDatas == null || byteDatas.length == 0) {
return "";
}
int total = 0;
int len = byteDatas.length;

final String HEX = "0123456789abcdef";
StringBuilder sb = null;
for (byte b : byteDatas) {
sb = new StringBuilder(2);
// 取出这个字节的高4位,然后与0x0f与运算,得到一个0-15之间的数据,通过HEX.charAt(0-15)即为16进制数
sb.append(HEX.charAt((b >> 4) & 0x0f));
// 取出这个字节的低位,与0x0f与运算,得到一个0-15之间的数据,通过HEX.charAt(0-15)即为16进制数
sb.append(HEX.charAt(b & 0x0f));
total += Integer.parseInt(sb.toString(), 16);
}
/**
* 用256求余最大是255,即16进制的FF
*/
int mod = total % 256;
String hex = Integer.toHexString(mod);
len = hex.length();
// 如果不够校验位的长度,补0,这里用的是两位校验
if (len < 2) {
hex = "0" + hex;
}
return hex;
}
//
// public static void main(String[] args) {
//
//
// System.out.println("======ASCII码转换为16进制======");
// String str = "*00007VERSION\\n1$";
// System.out.println("字符串: " + str);
// String hex = HexConvert.convertStringToHex(str);
// System.out.println("====转换为16进制=====" + hex);
//
// System.out.println("======16进制转换为ASCII======");
// System.out.println("Hex : " + hex);
// System.out.println("ASCII : " + HexConvert.convertHexToString(hex));
//
// byte[] bytes = HexConvert.hexStringToBytes( hex );
//
// System.out.println(HexConvert.BinaryToHexString( bytes ));
// }

}

+ 172
- 0
src/main/java/com/telpo/dipperposition/common/OkHttpUtil.java Целия файл

@@ -0,0 +1,172 @@
package com.telpo.dipperposition.common;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

/**
* @program: DataPushServer
* @description: okhttp工具类
* @author: linwl
* @create: 2020-07-17 15:43
*/
@Slf4j
@Component
public class OkHttpUtil {

@Autowired private OkHttpClient okHttpClient;

public static OkHttpUtil okHttpUtil;

@PostConstruct
public void init() {
okHttpUtil = this;
}
/**
* 根据map获取get请求参数
*
* @param queries
* @return
*/
public StringBuffer getQueryString(String url, Map<String, String> queries) {
StringBuffer sb = new StringBuffer(url);
if (queries != null && queries.keySet().size() > 0) {
boolean firstFlag = true;
Iterator iterator = queries.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry<String, String>) iterator.next();
if (firstFlag) {
sb.append("?" + entry.getKey() + "=" + entry.getValue());
firstFlag = false;
} else {
sb.append("&" + entry.getKey() + "=" + entry.getValue());
}
}
}
return sb;
}

/**
* get
*
* @param url 请求的url
* @param queries 请求的参数,在浏览器?后面的数据,没有可以传null
* @return
*/
public String get(String url, Map<String, String> queries) {
StringBuffer sb = getQueryString(url, queries);
Request request = new Request.Builder().url(sb.toString()).build();
log.debug(MessageFormat.format("发送Get to url<{0}>,参数为:{1}", url, queries));
return execNewCall(request);
}

/**
* post
*
* @param url 请求的url
* @param params post form 提交的参数
* @return
*/
public String postFormParams(String url, Map<String, String> params) {
FormBody.Builder builder = new FormBody.Builder();
// 添加参数
if (params != null && params.keySet().size() > 0) {
for (String key : params.keySet()) {
builder.add(key, params.get(key));
}
}
log.debug(MessageFormat.format("发送post from to url<{0}>,参数为:{1}", url, params));
Request request = new Request.Builder().url(url).post(builder.build()).build();
return execNewCall(request);
}

/** Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一:请求Url 参数二:请求的JSON 参数三:请求回调 */
public String postJsonParams(String url, String jsonParams) {
RequestBody requestBody = RequestBody.create(jsonParams, MediaType.parse("application/json; charset=utf-8"));
Request request = new Request.Builder().url(url).post(requestBody).build();
log.debug(MessageFormat.format("发送post json to url<{0}>,参数为:{1}", url, jsonParams));
return execNewCall(request);
}


/** Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一:请求Url 参数二:请求的JSON 参数三:请求回调 */
public String getJsonParams(String url, String jsonParams) {
Request request = new Request.Builder().url(url).addHeader("application/json","charset=utf-8").build();
log.debug(MessageFormat.format("get json to url<{0}>", url));

return execNewCall(request);
}



/** Post请求发送xml数据.... 参数一:请求Url 参数二:请求的xmlString 参数三:请求回调 */
public String postXmlParams(String url, String xml) {
RequestBody requestBody =
RequestBody.create(xml, MediaType.parse("application/xml; charset=utf-8"));
Request request = new Request.Builder().url(url).post(requestBody).build();
log.debug(MessageFormat.format("发送post xml to url<{0}>,参数为:{1}", url, xml));
return execNewCall(request);
}

/**
* 调用okhttp的newCall方法
*
* @param request
* @return
*/
private String execNewCall(Request request) {
try (Response response = okHttpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
return Objects.requireNonNull(response.body()).string();
}
} catch (Exception e) {
log.error("okhttp3 put error >> ex = {}", ExceptionUtils.getStackTrace(e));
}
return "FAIL";
}

/**
* Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一:请求Url 参数二:请求的JSON 参数三:请求回调
*/
public String postJsonParamsWithToken(String url, String token, String jsonParams) {
RequestBody requestBody =
RequestBody.create(jsonParams, MediaType.parse("application/json; charset=utf-8"));
Request request = new Request.Builder().url(url).
addHeader("Authorization", token).post(requestBody).build();
log.debug(MessageFormat.format("发送post json to url<{0}>,参数为:{1}", url, jsonParams));
return execNewCall(request);
}

public JSONObject postRequestWithJson(String url, String accessToken, JSONObject postData) {
String postResult;
if (ObjectUtils.isNotEmpty(accessToken)) {
postResult = postJsonParamsWithToken(url, accessToken, JSONObject.toJSONString(postData));
} else {
postResult = postJsonParams(url, JSONObject.toJSONString(postData));
}

if (postResult == null) {
log.error("访问错误");
return null;
} else {
log.debug(postResult);
if(("FAIL").equals(postResult.toString())) {
JSONObject object = new JSONObject();
object.put("result", "FAIL");
return object;
} else {
return JSONObject.parseObject(postResult);
}
}
}
}

+ 672
- 0
src/main/java/com/telpo/dipperposition/common/RedisUtil.java Целия файл

@@ -0,0 +1,672 @@
package com.telpo.dipperposition.common;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
* @program: DataPushServer
* @description: redis工具类
* @author: linwl
* @create: 2020-07-11 10:26
*/
@Component
@Slf4j
public class RedisUtil {

@Resource private RedisTemplate<String, Object> redisTemplate;

// public static RedisUtil redisUtil;
// @PostConstruct
// public void init() {
// redisUtil = this;
// }
// =============================common============================
/**
* 指定缓存失效时间
*
* @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) {
log.error(key, e);
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) {
log.error(key, e);
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(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) {
log.error(key, e);
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) {
log.error(key, e);
return false;
}
}

/**
* 递增 适用场景: https://blog.csdn.net/y_y_y_k_k_k_k/article/details/79218254 高并发生成订单号,秒杀类的业务逻辑等。。
*
* @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<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}

/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(key, e);
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) {
log.error(key, e);
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) {
log.error(key, e);
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<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
log.error(key, e);
return null;
}
}

/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
log.error(key, e);
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) {
log.error(key, e);
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) {
log.error(key, e);
return 0;
}
}

/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
log.error(key, e);
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) {
log.error(key, e);
return 0;
}
}

// ============================zset=============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> zSGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
log.error(key, e);
return null;
}
}

/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean zSHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
log.error(key, e);
return false;
}
}

public Boolean zSSet(String key, Object value, double score) {
try {
return redisTemplate.opsForZSet().add(key, value, 2);
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long zSSetAndTime(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) {
log.error(key, e);
return 0;
}
}

/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long zSGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
log.error(key, e);
return 0;
}
}

/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long zSetRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
log.error(key, e);
return 0;
}
}
// ===============================list=================================

/**
* 获取list缓存的内容 取出来的元素 总数 end-start+1
*
* @param key 键
* @param start 开始 0 是第一个元素
* @param end 结束 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
log.error(key, e);
return null;
}
}

/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
log.error(key, e);
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) {
log.error(key, e);
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) {
log.error(key, e);
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) {
log.error(key, e);
return false;
}
}

/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(key, e);
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) {
log.error(key, e);
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) {
log.error(key, e);
return 0;
}
}
}

+ 88
- 0
src/main/java/com/telpo/dipperposition/common/SocketClient.java Целия файл

@@ -0,0 +1,88 @@
package com.telpo.dipperposition.common;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
* @program: dipperposition
* @description: socket连接单元
* @author: king
* @create: 2021-01-14 13:52
**/
@Slf4j
public class SocketClient {
//定义一个Socket对象
Socket socket = null;

public SocketClient(String host, int port, int timeout) {
try {
//需要服务器的IP地址和端口号,才能获得正确的Socket对象
socket = new Socket(host, port);
socket.setSoTimeout(timeout);
} catch (IOException e) {
log.error("Socket Connect Error:" + e.getMessage());
}
}

public String getOutput() {
try {
OutputStream os = socket.getOutputStream();
return os.toString();
} catch (IOException e) {
log.error("Socket getOutputStream Error:" + e.getMessage());
return null;
}
}


public byte[] sendCmd(String astCmd) {
try {
OutputStream os=socket.getOutputStream();
PrintWriter pw=new PrintWriter(os);
// TODO 发生命令
//String info="用户名:Tom,用户密码:123456";
pw.write(astCmd);
pw.flush();
socket.shutdownOutput();

//接收服务器的相应
String reply=null;
//输入流
InputStream is=socket.getInputStream();
//BufferedReader br=new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];

int rc = 0;
while ((rc = is.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] in2b = swapStream.toByteArray();

//4.关闭资源
swapStream.close();
is.close();
pw.close();
os.close();
//log.debug(ackResult);
log.debug("接收服务器的信息:"+HexConvert.BinaryToHexString(in2b));
//return HexConvert.BinaryToHexString(in2b);
return in2b;
} catch (IOException e) {
log.error("Socket sendCmd Error:" + e.getMessage());
return null;
}
}

public void closeConnection() {
try {
socket.close();
//socket.shutdownOutput();
} catch (IOException e) {
log.error("Socket getOutputStream Error:" + e.getMessage());
}
}
}

+ 71
- 0
src/main/java/com/telpo/dipperposition/config/AsyncExecutorConfig.java Целия файл

@@ -0,0 +1,71 @@
package com.telpo.dipperposition.config;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
* @program: DataPushServer
* @description:
* @author: linwl
* @create: 2020-07-11 09:17
*/
@Getter
@Setter
@Configuration
@Slf4j
public class AsyncExecutorConfig implements AsyncConfigurer {

@Value(value = "${async.pool.corePoolSize:4}")
private int corePoolSize;

@Value(value = "${async.pool.maxPoolSize:8}")
private int maxPoolSize;

@Value(value = "${async.pool.queueCapacity:5000}")
private int queueCapacity;

@Bean(name = "asyncServiceExecutor")
public Executor asyncServiceExecutor() {
log.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 配置核心线程数
executor.setCorePoolSize(corePoolSize);
// 配置最大线程数
executor.setMaxPoolSize(maxPoolSize);
// 配置队列大小
executor.setQueueCapacity(queueCapacity);
// 配置线程池中的线程的名称前缀
String threadNamePrefix = "async-pool-";
executor.setThreadNamePrefix(threadNamePrefix);

// 设置拒绝策略:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 执行初始化
executor.initialize();
return executor;
}

/**
* 异步任务中异常处理
*
* @return
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (arg0, arg1, arg2) -> {
log.error("==========================" + arg0.getMessage() + "=======================", arg0);
log.error("com.telpo.auth.exception method:" + arg1.getName());
};
}
}

+ 31
- 0
src/main/java/com/telpo/dipperposition/config/NettyServerConfig.java Целия файл

@@ -0,0 +1,31 @@
package com.telpo.dipperposition.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
* @program: NettyServerConfig
* @description: jwt设置
* @author: linwl
* @create: 2020-06-18 17:45
*/
@Getter
@Setter
@Configuration
public class NettyServerConfig {

@Value(value = "${position-server.serverAddr}")
private String serverAddr;

@Value(value = "${position-server.timeAsycPort:9011}")
private String timeAsycServerPort;

@Value(value = "${position-server.posAsycPort:9013}")
private String posAsycServerPort;

@Value(value = "${position-server.starsAsycPort:9012}")
private String starsAsycServerPort;

}

+ 103
- 0
src/main/java/com/telpo/dipperposition/config/OkHttpConfig.java Целия файл

@@ -0,0 +1,103 @@
package com.telpo.dipperposition.config;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

/**
* @program: DataPushServer
* @description: http设置
* @author: linwl
* @create: 2020-07-17 15:29
*/
@Getter
@Setter
@Configuration
@Slf4j
public class OkHttpConfig {

@Value(value = "${OkHttp-config.pool.max-conn}")
private Integer maxConn;

@Value(value = "${OkHttp-config.pool.keep-alive}")
private Integer keepAlive;

@Value(value = "${OkHttp-config.read-timeout}")
private long readTimeout;

@Value(value = "${OkHttp-config.conn-timeout}")
private long connTimeout;

@Value(value = "${OkHttp-config.write-timeout}")
private long writeTimeout;

@Bean
public X509TrustManager x509TrustManager() {
return new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
throws CertificateException {}

@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
throws CertificateException {}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
}

@Bean
public SSLSocketFactory sslSocketFactory() {
try {
// 信任任何链接
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {x509TrustManager()}, new SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
log.error("okhttp3 send https error:", e);
}
return null;
}

/**
* Create a new connection pool with tuning parameters appropriate for a single-user application.
* The tuning parameters in this pool are subject to change in future OkHttp releases. Currently
*/
@Bean
public ConnectionPool pool() {
return new ConnectionPool(maxConn, keepAlive, TimeUnit.MINUTES);
}

@Bean
public OkHttpClient okHttpClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder
.connectTimeout(connTimeout, TimeUnit.SECONDS)
.readTimeout(readTimeout, TimeUnit.SECONDS)
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
.connectionPool(pool()) // 连接池
.retryOnConnectionFailure(true)
.hostnameVerifier((s, sslSession) -> true)
.sslSocketFactory(sslSocketFactory(), x509TrustManager());
return builder.build();
}
}

+ 26
- 0
src/main/java/com/telpo/dipperposition/config/PositionConfig.java Целия файл

@@ -0,0 +1,26 @@
package com.telpo.dipperposition.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
* @program: PositionConfig
* @description: jwt设置
* @author: linwl
* @create: 2020-06-18 17:45
*/
@Getter
@Setter
@Configuration
public class PositionConfig {

@Value(value = "${pos.ipPositionRequestPath}")
private String ipPositionRequestPath;
@Value(value = "${pos.ipPositionRequestKey}")
private String ipPositionRequestKey;
@Value(value = "${pos.centerProvince}")
private String centerProvince;

}

+ 53
- 0
src/main/java/com/telpo/dipperposition/config/SchedulingExecutorConfig.java Целия файл

@@ -0,0 +1,53 @@
package com.telpo.dipperposition.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

/**
* @program: DataPushServer
* @description: 定时任务线程配置
* @author: linwl
* @create: 2020-07-24 10:53
*/
@Getter
@Setter
@Configuration
public class SchedulingExecutorConfig implements SchedulingConfigurer {

@Value(value = "${scheduler.pool.size}")
private int pollSize;

@Value(value = "${scheduler.pool.await-seconds}")
private int awaitSeconds;

@Value(value = "${pos.astServer}")
private String astServer;
@Value(value = "${pos.astPosAstPort}")
private int posAstPort;
@Value(value = "${pos.astEphAstHexPort}")
private int astEphAstHexPort;
@Value(value = "${pos.astTimeout}")
private int astTimeout;

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = taskScheduler();
taskRegistrar.setTaskScheduler(taskScheduler);
}

@Bean(destroyMethod = "shutdown", name = "taskScheduler")
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(pollSize);
scheduler.setThreadNamePrefix("task-");
scheduler.setAwaitTerminationSeconds(awaitSeconds);
scheduler.setWaitForTasksToCompleteOnShutdown(true);
return scheduler;
}
}

+ 24
- 0
src/main/java/com/telpo/dipperposition/entity/mongo/IpProvinceEntity.java Целия файл

@@ -0,0 +1,24 @@
package com.telpo.dipperposition.entity.mongo;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;

/**
* @program: IpProvinceEntity
* @description: 位置实体类
* @author: linwl
* @create: 2020-07-11 15:33
*/
@ToString
@Getter
@Setter
@Document
public class IpProvinceEntity {

/** Ip */
private String ip;
/** Ip所在省份 */
private String province;
}

+ 28
- 0
src/main/java/com/telpo/dipperposition/entity/mongo/ProvinceInfoEntity.java Целия файл

@@ -0,0 +1,28 @@
package com.telpo.dipperposition.entity.mongo;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;

/**
* @program: IpProvinceEntity
* @description: 省份位置实体类
* @author: linwl
* @create: 2020-07-11 15:33
*/
@ToString
@Getter
@Setter
@Document
public class ProvinceInfoEntity {

/** 所在省份 */
private String province;
/** lon */
private String lon;
/** alt */
private String alt;
/** centerAddress */
private String centerAddress;
}

+ 53
- 0
src/main/java/com/telpo/dipperposition/enums/DipperReturnValue.java Целия файл

@@ -0,0 +1,53 @@
package com.telpo.dipperposition.enums;

/**
* @program: DipperReturnValue
* @description: 推送类型枚举
* @author: king
* @create: 2021-01-24 11:44
*/
public enum DipperReturnValue {
ACK(0, "SDBP-PUB–ACK"),
NACK(1, "SDBP-PUB–NACK");

/** 状态值 */
private int value;
/** 描述 */
private String describe;

private DipperReturnValue(int value, String describe) {
this.value = value;
this.describe = describe;
}

/**
* 获取推送类型
*
* @param value
* @return
*/
public static DipperReturnValue getByValue(int value) {
for (DipperReturnValue enums : DipperReturnValue.values()) {
if (enums.getValue() == value) {
return enums;
}
}
return null;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}

public String getDescribe() {
return describe;
}

public void setDescribe(String describe) {
this.describe = describe;
}
}

+ 269
- 0
src/main/java/com/telpo/dipperposition/handler/NettyServerHandler.java Целия файл

@@ -0,0 +1,269 @@
package com.telpo.dipperposition.handler;

import com.telpo.dipperposition.common.HexConvert;
import com.telpo.dipperposition.config.PositionConfig;
import com.telpo.dipperposition.service.IDipperAstPosAsyncTaskService;
import com.telpo.dipperposition.service.IDipperAstTimeAsyncTaskService;
import com.telpo.dipperposition.service.IDipperDataAsyncTaskService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
* @program: dipperposition
* @description: Netty服务器处理句柄
* @author: linwl
* @create: 2021-01-13 13:56
**/
@Slf4j
@Component
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

private static String AST_TIME_CMD = "TIME";
private static String AST_POS_CMD = "POS";
private static String AST_EPH_CMD = "EPH";
private static String AST_ALL_CMD = "ALL";
private static String AST_TIME_CMD_BYTE = "54494d45";
private static String AST_POS_CMD_BYTE = "504f53";
private static String AST_EPH_CMD_BYTE = "455048";
private static String AST_ALL_CMD_BYTE = "616C6C";

@Autowired
private PositionConfig positionConfig;
@Autowired
private IDipperAstTimeAsyncTaskService dipperTimeAsyncTaskService;
@Autowired
private IDipperAstPosAsyncTaskService dipperAstPosAsyncTaskService;
@Autowired
private IDipperDataAsyncTaskService dipperDataAsyncTaskService;

private static NettyServerHandler nettyServerHandler;
public NettyServerHandler() {}
@PostConstruct
public void init() {
nettyServerHandler = this;
nettyServerHandler.positionConfig = this.positionConfig;
nettyServerHandler.dipperTimeAsyncTaskService = this.dipperTimeAsyncTaskService;
nettyServerHandler.dipperAstPosAsyncTaskService = this.dipperAstPosAsyncTaskService;
nettyServerHandler.dipperDataAsyncTaskService = this.dipperDataAsyncTaskService;
}

/**
* 客户端连接会触发
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("Channel active......");

SocketChannel channel = (SocketChannel) ctx.channel();
log.info("链接报告开始");
log.info("链接报告信息:有一客户端链接到本服务端");
log.info("链接报告IP:" + channel.localAddress().getHostString());
log.info("链接报告Port:" + channel.localAddress().getPort());
log.info("链接报告完毕");
//通知客户端链接建立成功
// 默认返回取得时间成功
// String ackAckCheckRef = "233E0101020004020A1D";
//String ackAckCheckRef = "23 3E 01 01 02 00 04 21 29 3C";
//ByteBuf buf = Unpooled.buffer(ackAckCheckRef.getBytes().length);
//buf.writeBytes(ackAckCheckRef.getBytes(CharsetUtil.UTF_8));
//ctx.writeAndFlush(buf);
}


/**
* 当客户端主动断开服务端的链接后,这个通道就是不活跃的。
* 也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("客户端断开链接,IP:{}", ctx.channel().localAddress().toString());
ctx.channel().close();
}

/**
* 客户端发消息会触发
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//接收msg消息与上一章节相比,此处已经不需要自己进行解码}
SocketChannel channel = (SocketChannel) ctx.channel();
ByteBufAllocator bba = channel.config().getAllocator();
String ipAddress = channel.remoteAddress().getHostString();
log.info("接收到消息:" + msg + ",客户端IP:" + ipAddress);
if(ipAddress.contains(":")) {
String[] ipAddressArr = ipAddress.split(":");
ipAddress = ipAddressArr[0].replace("/","");
}
log.info("新客户端IP:" + ipAddress);

String channelAns = "";
// 返回时间指令
ByteBuf buf = null;
if (AST_TIME_CMD.equals(msg)) {
// 初始时间辅助输入;
channelAns = nettyServerHandler.dipperTimeAsyncTaskService.pushAstTime();
//log.debug(channelAns);
if (channelAns != null) {
// buf = bba.buffer(channelAns.getBytes().length);
byte[] returnBytes = getReturnBytes(channelAns);
buf = bba.buffer(returnBytes.length + 4);
//Unpooled.buffer(channelAns.getBytes().length);
// buf.writeBytes(channelAns.getBytes(CharsetUtil.UTF_8));
buf.writeBytes(returnBytes);
buf.writeBytes(getCheckSumBytes(channelAns));
buf.writeBytes(getReturnBytes());
// 确保通道处于活跃状态
// 不活跃状态继续写会产生CLOSE_WAIT现象
if(ctx.channel().isActive()) {
ctx.write(buf);
ctx.flush();
}
}
}
// 发送SDBP-AST-POS获取辅助位置信息
if (AST_POS_CMD.equals(msg)) {
channelAns = nettyServerHandler.dipperAstPosAsyncTaskService.pushAstPos(ipAddress);
//log.debug(channelAns);
if (channelAns != null) {
// buf = bba.buffer(channelAns.getBytes().length);
byte[] returnBytes = getReturnBytes(channelAns);
buf = bba.buffer(returnBytes.length + 4);
//Unpooled.buffer(channelAns.getBytes().length);
// buf.writeBytes(channelAns.getBytes(CharsetUtil.UTF_8));
buf.writeBytes(returnBytes);
buf.writeBytes(getCheckSumBytes(channelAns));
buf.writeBytes(getReturnBytes());
// 确保通道处于活跃状态
// 不活跃状态继续写会产生CLOSE_WAIT现象
if(ctx.channel().isActive()) {
ctx.write(buf);
ctx.flush();
}
}
}

// 从缓存获取SDBP-AST-EPH星历数
if (AST_EPH_CMD.equals(msg)) {
//channelAns = nettyServerHandler.dipperDataAsyncTaskService.getAstEPH();
byte[] returnBytes = nettyServerHandler.dipperDataAsyncTaskService.getAstEPH();
//log.debug(channelAns);
//if (channelAns != null) {
// buf = bba.buffer(channelAns.getBytes().length);
buf = bba.buffer(returnBytes.length);
//Unpooled.buffer(channelAns.getBytes().length);
buf.writeBytes(returnBytes);
// 确保通道处于活跃状态
// 不活跃状态继续写会产生CLOSE_WAIT现象
if(ctx.channel().isActive()) {
ctx.write(buf);
ctx.flush();
}
//}
}

// 最后把SDBP-AST-TIME、SDBP-AST-POS、SDBP-AST-EPH并包一起发给设备。
// 设备采用16进制获取数据,则代理服务器也是采用16进制返回数据。
// 通知客户端链消息发送成功
if (AST_ALL_CMD.equals(msg.toString().toUpperCase())) {
channelAns = nettyServerHandler.dipperTimeAsyncTaskService.pushAstTime();

if (channelAns != null) {
byte[] returnBytes = getReturnBytes(channelAns);
buf = bba.buffer(returnBytes.length + 4);
buf.writeBytes(returnBytes);
buf.writeBytes(getCheckSumBytes(channelAns));
buf.writeBytes(getReturnBytes());

// 确保通道处于活跃状态
// 不活跃状态继续写会产生CLOSE_WAIT现象
if(ctx.channel().isActive()) {
ctx.write(buf);
ctx.flush();
}
}
channelAns = nettyServerHandler.dipperAstPosAsyncTaskService.pushAstPos(ipAddress);

if (channelAns != null) {
byte[] returnBytes = getReturnBytes(channelAns);
buf = bba.buffer(returnBytes.length + 4);
buf.writeBytes(returnBytes);
buf.writeBytes(getCheckSumBytes(channelAns));
buf.writeBytes(getReturnBytes());
// 确保通道处于活跃状态
// 不活跃状态继续写会产生CLOSE_WAIT现象
if(ctx.channel().isActive()) {
ctx.write(buf);
}
}

byte[] returnBytes = nettyServerHandler.dipperDataAsyncTaskService.getAstEPH();
//if (channelAns != null) {
log.debug("PEH Buffer Length is:" + returnBytes.length);
// 使用池化的堆内存,以减少内存碎片
//ByteBuf channelPehAnsBuf = Unpooled.buffer(channelAns.getBytes().length);
//ByteBuf channelPehAnsBuf = bba.buffer(channelAns.getBytes().length);
ByteBuf channelPehAnsBuf = bba.buffer(returnBytes.length);
//channelPehAnsBuf.writeBytes(channelAns.getBytes(CharsetUtil.UTF_8));
channelPehAnsBuf.writeBytes(returnBytes);
// compositeByteBuf.addComponent(channelPehAnsBuf);
// log.info("CompositeByteBuf Length is:" + compositeByteBuf.capacity());
// 确保通道处于活跃状态
// 不活跃状态继续写会产生CLOSE_WAIT现象
if(ctx.channel().isActive()) {
ctx.write(channelPehAnsBuf);
ctx.flush();
}
//}

// 写给下一个Handler,最后一个Handler将内容移出pipeline
// ctx.writeAndFlush(compositeByteBuf);
}

}

/**
* 发生异常触发
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}

/*
* 取得byte数组
*/
private byte[] getReturnBytes(String astCmdBuf) {
return HexConvert.hexStringToBytes(astCmdBuf);
}

private byte[] getCheckSumBytes(String astCmdBuf) {
String checkSum = HexConvert.makeChecksum(astCmdBuf).toUpperCase();
StringBuffer astCheckSumBuf = new StringBuffer();
astCheckSumBuf.append(checkSum);
while (astCheckSumBuf.length()<4) {
astCheckSumBuf.insert(0,"0");
}
return getReturnBytes(astCheckSumBuf.toString());
//log.info(checkSum);
}


private byte[] getReturnBytes() {
String returnStr = "0D0A";
return getReturnBytes(returnStr);
}


}

+ 26
- 0
src/main/java/com/telpo/dipperposition/handler/ServerChannelInitializer.java Целия файл

@@ -0,0 +1,26 @@
package com.telpo.dipperposition.handler;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
/**
* @program: dipperposition
* @description: 服务器通道初始化
* @author: king
* @create: 2021-01-13 13:54
**/
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//添加编解码
socketChannel.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
socketChannel.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
// pipeline的第一个ChannelHandler:ChannelInboundHandlerAdapter
socketChannel.pipeline().addLast(new NettyServerHandler());
// addLast后会自动创建ChannelHandlerContext
}

}

+ 15
- 0
src/main/java/com/telpo/dipperposition/mapper/IpProvinceMapper.java Целия файл

@@ -0,0 +1,15 @@
package com.telpo.dipperposition.mapper;

import com.telpo.dipperposition.entity.mongo.IpProvinceEntity;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;


/**
* @program: DataPushServer
* @description: 推送记录mapper
* @author: linwl
* @create: 2020-07-20 11:12
*/
@Repository
public interface IpProvinceMapper extends MongoRepository<IpProvinceEntity, String> {}

+ 15
- 0
src/main/java/com/telpo/dipperposition/mapper/ProvinceInfoMapper.java Целия файл

@@ -0,0 +1,15 @@
package com.telpo.dipperposition.mapper;

import com.telpo.dipperposition.entity.mongo.ProvinceInfoEntity;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

/**
* @program: ProvinceInfoMapper
* @description: 省份位置记录mapper
* @author: linwl
* @create: 2020-07-20 11:12
*/
@Repository
public interface ProvinceInfoMapper
extends MongoRepository<ProvinceInfoEntity,String> {}

+ 83
- 0
src/main/java/com/telpo/dipperposition/server/DipperPositionServer.java Целия файл

@@ -0,0 +1,83 @@
package com.telpo.dipperposition.server;

import com.telpo.dipperposition.handler.ServerChannelInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;

/**
* @program: DipperPositionServer
* @description: 北斗定位
* @author: king
* @create: 2021-01-13 14:01
*/
@Slf4j
@Component
public class DipperPositionServer {

private String serverAddr;
private Integer starsAsycPort;

public DipperPositionServer(ConfigurableEnvironment environment) {

this.serverAddr = environment.getProperty("position-server.serverAddr");

this.starsAsycPort = Integer.parseInt(environment.getProperty("position-server.starsAsycPort"));
}

/*
* 星历同步进程线程
*/
public void start() {

//new 一个主线程组
EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1);
//new 一个工作线程组
EventLoopGroup workThreadGroup = new NioEventLoopGroup(200);
InetSocketAddress socketAddress = new InetSocketAddress(serverAddr,starsAsycPort);
ServerBootstrap bootstrap = new ServerBootstrap()
.group(mainThreadGroup, workThreadGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerChannelInitializer())
.localAddress(socketAddress)
//设置队列大小, 多少合适????
.option(ChannelOption.SO_BACKLOG, 1024)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000)
// 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
.childOption(ChannelOption.SO_LINGER, 1000);
//.childOption(ChannelOption.SO_KEEPALIVE, true);


//绑定端口,开始接收进来的连接
try {

ChannelFuture channelFuture = bootstrap.bind(socketAddress).sync();
log.info("星历服务器启动开始监听端口: {}", starsAsycPort);
//log.info("服务器: {}", myServerAddr);
channelFuture.addListener(future -> {
if (future.isSuccess()){
log.info("start success");
}else{
log.info("start failed");
}
});
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//关闭主线程组
mainThreadGroup.shutdownGracefully();
//关闭工作线程组
workThreadGroup.shutdownGracefully();
}
}

}

+ 31
- 0
src/main/java/com/telpo/dipperposition/service/IDipperAstPosAsyncTaskService.java Целия файл

@@ -0,0 +1,31 @@
package com.telpo.dipperposition.service;

import org.springframework.beans.factory.annotation.Autowired;

import java.io.UnsupportedEncodingException;

/**
* @program: IDipperAstPosAsyncTaskService
* @description: 系统预先基于省份的省会城市的经纬度作为辅助信息,
* 根据设备请求的IP地址,从高德IP定位服务获取相关的省份,再匹配相应的位置信息作为辅助位置信息。
* 如果匹配不到省份,则以武汉中心作为辅助为位置信息。
* 关于IP与省份的关系保存到缓存中,用于下次使用时,先在缓存中获取匹配信息,匹配不到,再请求高德IP定位服务。
* 高德IP定位服务:https://lbs.amap.com/api/webservice/guide/api/ipconfig。
* @author: king
* @create: 2021-01-17 16:24
*/
public interface IDipperAstPosAsyncTaskService {

/**
* 同步任务
*
*/
String pushAstPos(String ipAddress);

// String pushAstPos(String ipAddress,
// String centerProvinceFilePath,
// String centerProvince,
// String ipPositionRequestPath,
// String ipPositionRequestKey) throws UnsupportedEncodingException;

}

+ 22
- 0
src/main/java/com/telpo/dipperposition/service/IDipperAstTimeAsyncTaskService.java Целия файл

@@ -0,0 +1,22 @@
package com.telpo.dipperposition.service;

import com.telpo.dipperposition.service.impl.DipperDataAsyncTaskServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;

/**
* @program: IDipperDataAsyncTaskService
* @description: 发送SDBP-AST-TIME获取时间信息
* @author: king
* @create: 2021-01-17 16:24
*/
public interface IDipperAstTimeAsyncTaskService {

// @Autowired
// void setDipperAstTimeAsyncTaskService(IDipperAstTimeAsyncTaskService dipperAstTimeAsyncTaskService);
/**
* 同步任务
*
*/
String pushAstTime();

}

+ 31
- 0
src/main/java/com/telpo/dipperposition/service/IDipperDataAsyncTaskService.java Целия файл

@@ -0,0 +1,31 @@
package com.telpo.dipperposition.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

/**
* @program: IDipperDataAsyncTaskService
* @description: 发送bds获取星历数据。
* * 每30分钟获取1次,30秒超时,
* * 如果失败,则可以等待10秒再获取1次
* @author: king
* @create: 2021-01-17 16:24
*/
public interface IDipperDataAsyncTaskService {

// @Autowired
// void setDipperDataAsyncTaskService(IDipperDataAsyncTaskService IDipperDataAsyncTaskService);
/**
* 同步任务
*
*/
void pullAstEPH(int tryTimes) throws InterruptedException;


/**
* 根据IP获取EPH
*
*/
byte[] getAstEPH();

}

+ 54
- 0
src/main/java/com/telpo/dipperposition/service/IProvinceInfoService.java Целия файл

@@ -0,0 +1,54 @@
package com.telpo.dipperposition.service;

import com.telpo.dipperposition.entity.mongo.IpProvinceEntity;
import com.telpo.dipperposition.entity.mongo.ProvinceInfoEntity;

import java.util.List;

/**
* @program: IProvinceInfoService
* @description: 省份经纬度信息
* @author: king
* @create: 2020-07-20 11:09
*/
public interface IProvinceInfoService {

// @Autowired
// void setIPProvinceService(IpProvinceService ipProvinceService);
/**
* 保存省份经纬度信息
*
* @param entity
* @return
*/
boolean saveProvinceInfo(ProvinceInfoEntity entity);

/**
* 更新省份经纬度信息
*
* @param query
* @return
*/
boolean updateProvinceInfoEntity(ProvinceInfoEntity query);

/**
* 根据ID移除IP省份记录
*
* @param id
* @return
*/
boolean romveById(String id);

/*
* @param ipAddress
* 获取省份经纬度信息
*/
ProvinceInfoEntity getProvinceInfo(String provicne);

/**
* 获取省份经纬度信息
*
* @return
*/
List<ProvinceInfoEntity> getProvinceInfoEntitys();
}

+ 37
- 0
src/main/java/com/telpo/dipperposition/service/IpProvinceService.java Целия файл

@@ -0,0 +1,37 @@
package com.telpo.dipperposition.service;

import com.telpo.dipperposition.entity.mongo.IpProvinceEntity;
import org.springframework.beans.factory.annotation.Autowired;

/**
* @program: IPProvinceService
* @description: IP省份服务接口
* @author: king
* @create: 2020-07-20 11:09
*/
public interface IpProvinceService {

// @Autowired
// void setIPProvinceService(IpProvinceService ipProvinceService);
/**
* 保存IP省份
*
* @param entity
* @return
*/
boolean saveIpProvince(IpProvinceEntity entity);

/**
* 根据ID移除IP省份记录
*
* @param id
* @return
*/
boolean romveById(String id);

/*
* @param ipAddress
* 获取IP省份
*/
IpProvinceEntity getIpProvince(String ipAddress);
}

+ 261
- 0
src/main/java/com/telpo/dipperposition/service/impl/DipperAstPosAsyncTaskServiceImpl.java Целия файл

@@ -0,0 +1,261 @@
package com.telpo.dipperposition.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.telpo.dipperposition.common.*;
import com.telpo.dipperposition.config.PositionConfig;
import com.telpo.dipperposition.entity.mongo.IpProvinceEntity;
import com.telpo.dipperposition.entity.mongo.ProvinceInfoEntity;
import com.telpo.dipperposition.service.IDipperAstPosAsyncTaskService;
import com.telpo.dipperposition.service.IProvinceInfoService;
import com.telpo.dipperposition.service.IpProvinceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
* @program: DipperAstPosAsyncTaskServiceImpl
* @description: 系统预先基于省份的省会城市的经纬度作为辅助信息,
* * 根据设备请求的IP地址,从高德IP定位服务获取相关的省份,再匹配相应的位置信息作为辅助位置信息。
* * 如果匹配不到省份,则以武汉中心作为辅助为位置信息。
* * 关于IP与省份的关系保存到缓存中,用于下次使用时,先在缓存中获取匹配信息,匹配不到,再请求高德IP定位服务。
* * 高德IP定位服务:https://lbs.amap.com/api/webservice/guide/api/ipconfig。
* @author: king
* @create: 2021-01-10 14:01
*/
@Service
@Slf4j
public class DipperAstPosAsyncTaskServiceImpl implements IDipperAstPosAsyncTaskService {

@Autowired
private OkHttpUtil okHttpUtil;
@Autowired
private PositionConfig positionConfig;
@Autowired
private IpProvinceService ipProvinceService;
@Autowired
private IProvinceInfoService provinceInfoService;

private String centerProvince;
private String ipPositionRequestPath;
private String ipPositionRequestKey;

// 根据IP获取省会信息
private String getIpPositionProvince(String ipAddress) {

// 关于IP与省份的关系保存到缓存中
// 使用时,先在缓存中获取匹配信息
// 用mongodb实现
IpProvinceEntity ipProvinceEntity = ipProvinceService.getIpProvince(ipAddress);
if (ipProvinceEntity == null) {
// 匹配不到,再请求高德IP定位服务。
//JSONObject userObj = new JSONObject();
Map<String, String> dataMap = new HashMap<String, String>();
dataMap.put("ip", ipAddress);
dataMap.put("key", ipPositionRequestKey);
StringBuffer buffer = okHttpUtil.getQueryString(ipPositionRequestPath, dataMap);
JSONObject paramObject = new JSONObject();
String result = okHttpUtil.getJsonParams(buffer.toString(), paramObject.toJSONString());
if (ObjectUtils.isNotEmpty(result)) {
if (ObjectUtils.isEmpty(result)) {
log.debug("IP省份获取错误,结果为空");
return null;
} else {
if (result.equals("FAIL")) {
log.debug("IP省份获取错误,结果为FAIL");
return null;
}
//log.debug("IP省份获取错误,结果为:" + result);
JSONObject provinceJson = JSONObject.parseObject(result);
String province = null;
try {
province = (String)provinceJson.get("province");
if (ObjectUtils.isEmpty(province)) {
log.debug("json is :" + buffer.toString());
return null;
}
} catch (Exception e) {
log.error("JSONObject分析出错,provinceJson:" + provinceJson);
}

return province;
}
} else {
// 意外错误
log.debug("ip address is null");
return null;
}
} else {
return ipProvinceEntity.getProvince();
}
}

// 将IP对应的省会保存到mongoDB
public void createIPProvince(String ipAddress, String province) {
log.debug("创建IP省份记录!");
try {
IpProvinceEntity ipProvinceEntity = ipProvinceService.getIpProvince(ipAddress);
if (ipProvinceEntity == null) {
ipProvinceEntity = new IpProvinceEntity();
ipProvinceEntity.setIp(ipAddress);
ipProvinceEntity.setProvince(province);
ipProvinceService.saveIpProvince(ipProvinceEntity);
}
} catch (Exception e) {
log.error("创建IP省份记录异常:", e);
}
}

/*
* 获取定位辅助信息
* @param ipAddress
*/
@Override
//@Async("asyncServiceExecutor")
public String pushAstPos(String ipAddress) {
this.ipPositionRequestKey = positionConfig.getIpPositionRequestKey();
this.ipPositionRequestPath = positionConfig.getIpPositionRequestPath();
this.centerProvince = positionConfig.getCenterProvince();
//this.centerProvinceFilePath = positionConfig.getCenterProvinceFilePath();
// (1) 获取省会城市信息
String centerAddress = getIpPositionProvince(ipAddress);
if (centerAddress == null || ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) {
log.warn("IP地址非法,无法获取辅助位置信息!");
// 返回武汉的定位数据
centerAddress = this.centerProvince;
} else {
// 保存到mongoDB
createIPProvince(ipAddress, centerAddress);
}

String lonValue = null;
String altValue = null;
try {
byte[] utf8 = centerAddress.getBytes("UTF-8");
String utf8CenterAddress = new String(utf8, "UTF-8");
log.debug("centerAddress is " + utf8CenterAddress);

if (utf8CenterAddress.endsWith("省") || utf8CenterAddress.endsWith("区") || utf8CenterAddress.endsWith("市")) {

ProvinceInfoEntity entity = provinceInfoService.getProvinceInfo(utf8CenterAddress);
if (entity != null) {
lonValue = entity.getLon();
altValue = entity.getAlt();
}
} else {
log.error("非法省份:" + utf8CenterAddress);
return null;
}
} catch (Exception e) {
log.error(e.getMessage());
}


// (2) 处理返回结果
if (lonValue == null) {
// null处理
log.error("系统错误,请联系系统管理员。");
return null;
}

// push to GNNS Server
return getCmdOfPos(lonValue, altValue);
}

// 组装命令发送给设备
private String getCmdOfPos(String lonStr, String altStr) {

// 时间和位置不是从服务器获取,而是本地生成
// String[] astPosArray = astPos.split(",");
// String lan = astPosArray[0].trim();
// String alt = astPosArray[1].trim();
double lanValue = Double.parseDouble(lonStr) * 10000000;
long lanLongValue = Double.doubleToLongBits(lanValue);
if (lanLongValue < 0) {
// FFFFFFFF - 439C3270 + 1= BC63CD90(补码)
lanLongValue = lanLongValue + 4294967295L + 1;
}
double altValue = Double.parseDouble(altStr) * 10000000;
long altLongValue = Double.doubleToLongBits(altValue);
if (altLongValue < 0) {
// FFFFFFFF - 439C3270 + 1= BC63CD90(补码)
altLongValue = altLongValue + 4294967295L + 1;
}

// 数值换算举例(以经度举例。纬度、高度、位置精度换算方法一致):
// (1)经度数值为 113.431,则换算方法如下:
// 113.431/比例因子 = 1134310000(十进制)
//  439C3270(十六进制)
//  经度数据填入 70 32 9C 43(小端模式)
// (2)经度数值为-113.431,则换算方法如下:
// 113.431/比例因子 = 1134310000(十进制)
//  439C3270(十六进制)
//  FFFFFFFF - 439C3270 + 1= BC63CD90(补码)
// 经度数据填入 90 CD 63 BC(小端模式)
// 指令(十六进制)
// 举例: 23 3E 04 01 10 00 70 32 9C 43 D0 B2 CE 0D 70 17 00 00 40 0D 03 00 CA 95
// 其中
// 23 3E 为同步头
// 04 01 为识别码
// 10 00 表示长度为 16
// 70 32 9C 43 表示注入的辅助经度为 113.431 度
// D0 B2 CE 0D 表示注入的辅助纬度为 23.165 度
// 70 17 00 00 表示注入的辅助高度为 60 米
// 40 0D 03 00 表示注入的位置精度为 2000 米 030d40
// A0 86 01 00 表示注入的位置精度为 1000 米 0186a0
// 00 2F 为校验和

// astPosCmd 组装
StringBuilder astPosCmdBuf = new StringBuilder();
astPosCmdBuf.append("233E0401");
astPosCmdBuf.append("1000");


// 小端模式
String lanString = HexConvert.encodeHEX(lanLongValue).toUpperCase();
String altSting = HexConvert.encodeHEX(altLongValue).toUpperCase();
//astPosCmdBuf.append(HexConvert.encodeHEX(lanLongValue).toUpperCase());
astPosCmdBuf.append(lanString.substring(6,8));
astPosCmdBuf.append(lanString.substring(4,6));
astPosCmdBuf.append(lanString.substring(2,4));
astPosCmdBuf.append(lanString.substring(0,2));

//astPosCmdBuf.append(HexConvert.encodeHEX(altLongValue).toUpperCase());

astPosCmdBuf.append(altSting.substring(6,8));
astPosCmdBuf.append(altSting.substring(4,6));
astPosCmdBuf.append(altSting.substring(2,4));
astPosCmdBuf.append(altSting.substring(0,2));
astPosCmdBuf.append("70170000");
astPosCmdBuf.append("A0860100");

//log.info(astPosCmd);
// String checkSum = HexConvert.makeChecksum(astPosCmdBuf.toString()).toUpperCase();
// StringBuffer astCheckSumBuf = new StringBuffer();
// astCheckSumBuf.append(checkSum);
// while (astCheckSumBuf.length()<4) {
// astCheckSumBuf.insert(0,"0");
// }
// checkSum = astCheckSumBuf.toString();
// //log.info(checkSum);
//
// byte[] astPosCmdBytes = HexConvert.hexStringToBytes(astPosCmdBuf.toString());
// StringBuilder astPosCmdNewBuf = new StringBuilder();
// for (byte astPosCmdByte : astPosCmdBytes) {
// String s = Integer.toHexString(astPosCmdByte & 0xff);
// if (s.length() < 2) {
// astPosCmdNewBuf.append('0');
// }
// astPosCmdNewBuf.append(s + " ");
// }
//
return astPosCmdBuf.toString();
//+ checkSum.substring(0,2) + " " + checkSum.substring(2,4);



}
}

+ 110
- 0
src/main/java/com/telpo/dipperposition/service/impl/DipperAstTimeAsyncTaskServiceImpl.java Целия файл

@@ -0,0 +1,110 @@
package com.telpo.dipperposition.service.impl;

import com.telpo.dipperposition.common.HexConvert;
import com.telpo.dipperposition.service.IDipperAstTimeAsyncTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
* @program: DipperDataAsyncTaskServiceImpl
* @description: 发送SDBP-AST-TIME获取时间信息
* @author: king
* @create: 2021-01-10 14:01
*/
@Service
@Slf4j
public class DipperAstTimeAsyncTaskServiceImpl implements IDipperAstTimeAsyncTaskService {

@Override
public String pushAstTime() {

// 创建Socket客户端实例;
// SocketClient client = new SocketClient(astServer, timeAstPort, astTimeout);

// 时间和位置不是从服务器获取,而是本地生成(其中时间误差不超过3s)
// 23 3E 04 02 10 00 20 E1 07 09 14 0C 22 38 00 00 00 00 00 28 6B EE 22 98
// 23 3E 为同步头
// 04 02 为识别码
// 10 00 表示长度为 16
// --日期--
// 20 E1 表示闰秒改正数为
// E1 07 表示年为 2017 年(十六进制 07E1 转为十进制)
// 09 表示 9 月
// 14 表示 20 日
// 0C 22 38 00 00 00 00 00 表示 UTC时间,为12时34分56.0秒(小数秒建议固定为 0)
// 00 28 6B EE 表示 4 秒的时间精度(十六进制 EE6B2800 转为十进制为 4000000000,乘以比 例因子 10-9就是 4 秒)
// 00 5E D0 B2 表示 3 秒的时间精度(十六进制 B2 D0 5E 00 转为十进制为3000000000,乘以比 例因子 10-9就是 3 秒 小端模式00 5E D0 B2)
// 00 2F 为校验和
// TODO astTimeCmd 组装
StringBuilder astTimeCmdBuf = new StringBuilder();
astTimeCmdBuf.append("233E0402");
astTimeCmdBuf.append("1000");
astTimeCmdBuf.append("20E1");
LocalDateTime now = LocalDateTime.now();
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
String hexYearString = Integer.toHexString(year);
hexYearString = "0" + hexYearString;
astTimeCmdBuf.append(hexYearString.substring(2,3).toUpperCase() + hexYearString.substring(0,1).toUpperCase());
String hexMonthString = Integer.toHexString(month);
hexMonthString = "0" + hexMonthString;
astTimeCmdBuf.append(hexMonthString.toUpperCase());

String hexDayString = Integer.toHexString(day);
if (day < 16) {
hexDayString = "0" + hexDayString;
}
astTimeCmdBuf.append(hexDayString.toUpperCase());

int hour = now.getHour();
int minitor = now.getMinute();
int second = now.getSecond();
String hexHourString = Integer.toHexString(hour);
if (hour < 16) {
hexHourString = "0" + hexHourString;
}
astTimeCmdBuf.append(hexHourString.toUpperCase());
String hexMinitorString = Integer.toHexString(minitor);
if (minitor < 16) {
hexMinitorString = "0" + hexMinitorString;
}
astTimeCmdBuf.append(hexMinitorString.toUpperCase());
String hexSecondString = Integer.toHexString(second);
if (second < 16) {
hexSecondString = "0" + hexSecondString;
}
astTimeCmdBuf.append(hexSecondString.toUpperCase());
astTimeCmdBuf.append("00000000");
astTimeCmdBuf.append("005ED0B2");

return astTimeCmdBuf.toString();

// byte[] astTimeCmdBytes = HexConvert.hexStringToBytes(astTimeCmdBuf.toString());
// StringBuilder astTimeCmdNewBuf = new StringBuilder();
// for(int i=0; i<astTimeCmdBytes.length; i++) {
// String s = Integer.toHexString(astTimeCmdBytes[i] & 0xff);
// if (s.length() < 2) {
// astTimeCmdNewBuf.append('0');
// }
// astTimeCmdNewBuf.append(s + " ");
// }
//
// //log.info(astTimeCmd);
// String checkSum = HexConvert.makeChecksum(astTimeCmdBuf.toString()).toUpperCase();
// StringBuilder astCheckSumBuf = new StringBuilder();
// astCheckSumBuf.append(checkSum);
// while (astCheckSumBuf.length()<4) {
// astCheckSumBuf.insert(0,"0");
// }
// checkSum = astCheckSumBuf.toString();
// //log.info(checkSum);
//
// return astTimeCmdNewBuf.toString() + checkSum.substring(0,2) + " " + checkSum.substring(2,4);
//String hexIn = astTimeCmd + HexConvert.makeChecksum(astTimeCmd);
//log.info("DipperAstTimeAsyncTaskServiceImpl 返回时间:" + hexIn);

}
}

+ 98
- 0
src/main/java/com/telpo/dipperposition/service/impl/DipperDataAsyncTaskServiceImpl.java Целия файл

@@ -0,0 +1,98 @@
package com.telpo.dipperposition.service.impl;

import com.telpo.dipperposition.common.HexConvert;
import com.telpo.dipperposition.common.RedisUtil;
import com.telpo.dipperposition.common.SocketClient;
import com.telpo.dipperposition.config.SchedulingExecutorConfig;
import com.telpo.dipperposition.service.IDipperDataAsyncTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import static java.lang.Thread.sleep;

/**
* @program: DipperDataAsyncTaskServiceImpl
* @description: 获取星历数据。
* @author: king
* @create: 2021-01-10 14:01
*/
@Service
@Slf4j
public class DipperDataAsyncTaskServiceImpl implements IDipperDataAsyncTaskService {


private static String DIPPER_DATA_KEY = "TaidouDipperData";
private static String DIPPER_ALL_DATA_REQ = "616C6C";

@Autowired
private RedisUtil redisUtil;
@Autowired
private SchedulingExecutorConfig schedulingExecutorConfig;

@Override
@Async("asyncServiceExecutor")
public void pullAstEPH(int tryTimes) throws InterruptedException {
tryTimes--;
// (1) 发送bds获取星历数据
byte[] dipperData = pullEPHFromDipper();

// (2) 获取星历数据
if (dipperData == null) {
log.error("获取星历数据错误,取不到星历数据。");
if (tryTimes>0) {
log.info("等待10秒再获取1次。");
sleep(10000);
pullAstEPH(tryTimes);
}
} else {
// 保存到DB或者缓存
log.info("保存到DB或者缓存");
redisUtil.set(DIPPER_DATA_KEY,dipperData);
}
}

private byte[] pullEPHFromDipper() {

// 创建Socket客户端实例;
String serverAddr = schedulingExecutorConfig.getAstServer();
int serverPort = schedulingExecutorConfig.getAstEphAstHexPort();
SocketClient client = new SocketClient(serverAddr,serverPort,schedulingExecutorConfig.getAstTimeout());

// astTimeCmd 组装
String astTimeCmd = DIPPER_ALL_DATA_REQ;
String checkSum = HexConvert.makeChecksum(astTimeCmd.toString()).toUpperCase();
StringBuilder astCheckSumBuf = new StringBuilder();
astCheckSumBuf.append(checkSum);
while (astCheckSumBuf.length()<4) {
astCheckSumBuf.insert(0,"0");
}
checkSum = astCheckSumBuf.toString();

String hexIn = astTimeCmd + checkSum.substring(0,2) + " " + checkSum.substring(2,4);

byte[] sendResult = null;
//String ackAckCheckRef = "233E010102000421293C";
sendResult = client.sendCmd(hexIn);
client.closeConnection();

return sendResult;
}

@Override
public byte[] getAstEPH(){
// String dipperData = pullEPHFromDipper();
byte[] dipperData;
if (!redisUtil.hasKey(DIPPER_DATA_KEY)) {
try {
this.pullAstEPH(1);
} catch (InterruptedException e) {
log.error("获取星历数据发生异常:", e);
}
}

dipperData = (byte[])redisUtil.get(DIPPER_DATA_KEY);
return dipperData;
}
}

+ 69
- 0
src/main/java/com/telpo/dipperposition/service/impl/IpProvinceServiceImpl.java Целия файл

@@ -0,0 +1,69 @@
package com.telpo.dipperposition.service.impl;

import com.telpo.dipperposition.entity.mongo.IpProvinceEntity;
import com.telpo.dipperposition.mapper.IpProvinceMapper;
import com.telpo.dipperposition.service.IpProvinceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
* @program: DataPushServer
* @description: 推送记录服务接口实现类
* @author: linwl
* @create: 2020-07-20 11:09
*/
@Slf4j
@Service
public class IpProvinceServiceImpl implements IpProvinceService {

@Autowired
private IpProvinceMapper ipProvinceMapper;

// private static IpProvinceService ipProvinceService;
// /**
// * spring会自动从ioc容器当中根据IPProvinceService类型找到ipProvinceService,当做参数传进来
// *
// */
// @Override
// public void setIPProvinceService(IpProvinceService ipProvinceService) {
// this.ipProvinceService = ipProvinceService;
// }
@Override
public boolean saveIpProvince(IpProvinceEntity entity) {
ipProvinceMapper.save(entity);
return true;
}

@Override
public boolean romveById(String id) {

ipProvinceMapper.deleteById(id);
return false;
}

@Override
public IpProvinceEntity getIpProvince(String ipAddress) {
try {
IpProvinceEntity query = new IpProvinceEntity();
query.setIp(ipAddress);
//忽略_class属性,不参与查询
ExampleMatcher matcher = ExampleMatcher.matching().withIgnorePaths("_class");
Example<IpProvinceEntity> example = Example.of(query, matcher);
Optional<IpProvinceEntity> data = ipProvinceMapper.findOne(example);
if (data.isPresent() == true) {
return data.get();
} else {
return null;
}
//return data.orElse(null);
} catch (Exception e) {
log.error("获取IP省份异常:", e);
return null;
}
}
}

+ 85
- 0
src/main/java/com/telpo/dipperposition/service/impl/ProvinceInfoServiceImpl.java Целия файл

@@ -0,0 +1,85 @@
package com.telpo.dipperposition.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.telpo.dipperposition.entity.mongo.ProvinceInfoEntity;
import com.telpo.dipperposition.mapper.ProvinceInfoMapper;
import com.telpo.dipperposition.service.IProvinceInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

/**
* @program: DataPushServer
* @description: 推送记录服务接口实现类
* @author: linwl
* @create: 2020-07-20 11:09
*/
@Slf4j
@Service
public class ProvinceInfoServiceImpl implements IProvinceInfoService {

@Autowired
private ProvinceInfoMapper provinceInfoMapper;


@Override
public boolean saveProvinceInfo(ProvinceInfoEntity entity) {

provinceInfoMapper.save(entity);
return false;
}

@Override
public boolean updateProvinceInfoEntity(ProvinceInfoEntity entity) {
provinceInfoMapper.save(entity);
return false;
}

@Override
public boolean romveById(String id) {

provinceInfoMapper.deleteById(id);
return false;
}

@Override
public ProvinceInfoEntity getProvinceInfo(String provicne) {
try {
ProvinceInfoEntity query = new ProvinceInfoEntity();
query.setProvince(provicne);
//忽略_class属性,不参与查询
ExampleMatcher matcher = ExampleMatcher.matching().withIgnorePaths("_class");
Example<ProvinceInfoEntity> example = Example.of(query, matcher);
Optional<ProvinceInfoEntity> data = provinceInfoMapper.findOne(example);
if (ObjectUtil.isNotEmpty(data)) {
return data.get();
} else {
return null;
}
} catch (Exception e) {
log.error("获取省份异常:", e);
return null;
}
}

@Override
public List<ProvinceInfoEntity> getProvinceInfoEntitys() {
try {
List<ProvinceInfoEntity> records = provinceInfoMapper.findAll();
if (ObjectUtils.isNotEmpty(records)) {
return records;
} else {
return null;
}
} catch (Exception e) {
log.error("获取IP省份异常:", e);
return null;
}
}
}

+ 43
- 0
src/main/java/com/telpo/dipperposition/task/ScheduleService.java Целия файл

@@ -0,0 +1,43 @@
package com.telpo.dipperposition.task;

import com.telpo.dipperposition.service.IDipperDataAsyncTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;


/**
* @program: DataPushServer
* @description: 定时执行任务服务
* @author: king
* @create: 2021-01-17 16:24
*/
@Component
@Slf4j
public class ScheduleService {

@Autowired
private IDipperDataAsyncTaskService dipperDataAsyncTaskService;

/*
* 调用9012端口的接口获取星历数据。
* 通过TCP连接服务器agnss.techtotop.com:9012,发送bds获取星历数据。
* 每30分钟获取1次,30秒超时,
* 如果失败,则可以等待10秒再获取1次。 *
*/
@Scheduled(cron = "${scheduler.task.cron}")
public void pullData() {
log.info("开始星历数据同步!");
// 获取推送失败的记录
try {
// 如果失败,则可以等待10秒再获取1次。
int tryTimes = 59;
dipperDataAsyncTaskService.pullAstEPH(tryTimes);
} catch (InterruptedException e) {
log.error("获取星历数据重试睡眠发生异常:", e);
} catch (Exception e) {
log.error("执行定时获取星历数据发生异常:", e);
}
}
}

+ 20
- 0
src/main/java/com/telpo/dipperposition/vo/IPProvinceVo.java Целия файл

@@ -0,0 +1,20 @@
package com.telpo.dipperposition.vo;

import lombok.Getter;
import lombok.Setter;

/**
* @program: DataPushServer
* @description: 基础类
* @author: linwl
* @create: 2020-07-17 16:41
*/
@Setter
@Getter
public class IPProvinceVo {

/** Ip */
private String ip;
/** Ip所在省份 */
private String province;
}

+ 24
- 0
src/main/java/com/telpo/dipperposition/vo/ProvinceInfoVo.java Целия файл

@@ -0,0 +1,24 @@
package com.telpo.dipperposition.vo;

import lombok.Getter;
import lombok.Setter;

/**
* @program: DataPushServer
* @description: 基础类
* @author: linwl
* @create: 2020-07-17 16:41
*/
@Setter
@Getter
public class ProvinceInfoVo {

/** Ip所在省份 */
private String province;
/** lon */
private String lon;
/** lon */
private String alt;
/** centerAddress */
private String centerAddress;
}

+ 61
- 0
src/main/resources/application.properties Целия файл

@@ -0,0 +1,61 @@
server.port=8105
logging.config=classpath:log/logback-spring.xml
logging.level.com.telpo.dipperposition.service.impl=DEBUG
logging.level.com.telpo.dipperposition.service.mapper=DEBUG
spring.application.name=dipperposition-service

spring.redis.database=1
spring.redis.host=127.0.0.1
#8090
spring.redis.port=6379
spring.redis.password=telpo#1234
spring.redis.timeout=3000
spring.redis.lettuce.pool.max-active=100
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-idle=100
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.min-idle=50
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.max-wait=6000
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.data.mongodb.host=172.19.42.45
spring.data.mongodb.port=27017
spring.data.mongodb.database=common
spring.data.mongodb.username=wangjx
spring.data.mongodb.password=wangjx#1234

position-server.serverAddr=172.19.42.45
position-server.timeAsycPort=9011
position-server.posAsycPort=9013
position-server.starsAsycPort=9012

#等待任务完成退出最大秒数
scheduler.pool.size=2
scheduler.pool.await-seconds=600
scheduler.task.cron=0 */30 * * * *

pos.ipPositionRequestPath=https://restapi.amap.com/v3/ip
pos.ipPositionRequestKey=46eb0eba39494a6e9a90a0dc9e76639e
pos.centerProvince=湖北省
# 测试 agnss.techtotop.com
pos.astServer=agnss.techtotop.com
pos.astPosAstPort=8012
# 占青霞说北斗的是9112端口
pos.astEphAstHexPort=9112
pos.astTimeout=30000

OkHttp-config.pool.max-conn=200
OkHttp-config.pool.keep-alive=5
OkHttp-config.read-timeout=10
OkHttp-config.conn-timeout=10
OkHttp-config.write-timeout=10

async.pool.corePoolSize=4
async.pool.maxPoolSize=8
async.pool.queueCapacity=5000

mongo.datasource.dblist.uri=mongodb://wangjx:wangjx#1234@172.19.42.45:27017/common
mongo.datasource.dblist.database=common




+ 10
- 0
src/main/resources/bootstrap-dev.yaml Целия файл

@@ -0,0 +1,10 @@
spring:
main:
allow-bean-definition-overriding: true
application:
name: dipperposition-service
cloud:
nacos:
config:
server-addr: 172.16.192.26:8848
file-extension: yaml

+ 79
- 0
src/main/resources/bootstrap-pro.yaml Целия файл

@@ -0,0 +1,79 @@
server:
port: 8105

logging:
config: classpath:log/logback-spring.xml
level:
com:
telpo:
dipperposition:
service:
impl: debug
mapper: debug
org.springframework.data.mongodb.core.MongoTemplate: DEBUG
spring:
application:
name: dipperposition-service
redis:
database: 1
host: 172.19.42.45
#8090
port: 6379
password: telpo#1234
timeout: 3000
lettuce:
pool:
max-active: 100 # 连接池最大连接数(使用负值表示没有限制)
max-idle: 100 # 连接池中的最大空闲连接
min-idle: 50 # 连接池中的最小空闲连接
max-wait: 6000 # 连接池最大阻塞等待时间(使用负值表示没有限制)
data:
mongodb:
host: 172.19.42.45
port: 27017
database: common
username: wangjx
password: wangjx#1234

mongo:
datasource:
dblist:
- uri: mongodb://wangjx:wangjx#1234@172.19.42.45:27015/common
database: common

scheduler:
pool:
size: 2
#等待任务完成退出最大秒数
await-seconds: 600
task:
cron: "0 */30 * * * *"

pos:
ipPositionRequestPath: https://restapi.amap.com/v3/ip
ipPositionRequestKey: 46eb0eba39494a6e9a90a0dc9e76639e
centerProvince: 湖北省
astServer: agnss.techtotop.com
astPosAstPort: 8012
astEphAstHexPort: 9012
astTimeout: 30000

position-server:
serverAddr: 172.19.42.45
timeAsycPort: 9011
posAsycPort: 9013
starsAsycPort: 9012

OkHttp-config:
pool:
max-conn: 200
keep-alive: 5
read-timeout: 10
conn-timeout: 10
write-timeout: 10

async:
pool:
corePoolSize: 4
maxPoolSize: 8
queueCapacity: 5000

+ 87
- 0
src/main/resources/bootstrap-test.yaml Целия файл

@@ -0,0 +1,87 @@
server:
port: 8105

logging:
config: classpath:log/logback-spring.xml
level:
com:
telpo:
dipperposition:
service:
impl: debug
mapper: debug
org.springframework.data.mongodb.core.MongoTemplate: DEBUG
spring:
application:
name: dipperposition-service
cloud:
nacos:
config:
server-addr: 172.19.42.44:8848
namespace: fee328ef-7348-4984-879a-fd75f9f59cd2
redis:
database: 1
host: 172.19.42.44
#8090
port: 8090
password: telpo#1234
timeout: 3000
lettuce:
pool:
max-active: 100 # 连接池最大连接数(使用负值表示没有限制)
max-idle: 100 # 连接池中的最大空闲连接
min-idle: 50 # 连接池中的最小空闲连接
max-wait: 6000 # 连接池最大阻塞等待时间(使用负值表示没有限制)
data:
mongodb:
host: 172.19.42.40
port: 27018
database: common
username: wangjx
password: wangjx#1234

mongo:
datasource:
dblist:
- uri: mongodb://wangjx:wangjx#1234@172.19.42.40:27018/common
database: common
- uri: mongodb://wangjx:wangjx#1234@172.19.42.40:27018/basicdata
database: basicdata

scheduler:
pool:
size: 2
#等待任务完成退出最大秒数
await-seconds: 600
task:
cron: "0 */30 * * * *"

pos:
centerProvinceFilePath: /csv/provinceLonAlt.csv
ipPositionRequestPath: https://restapi.amap.com/v3/ip
ipPositionRequestKey: 46eb0eba39494a6e9a90a0dc9e76639e
centerProvince: 湖北省
astServer: agnss.techtotop.com
astPosAstPort: 8012
astEphAstHexPort: 9112
astTimeout: 30000

position-server:
serverAddr: 172.19.42.44
timeAsycPort: 9011
posAsycPort: 9013
starsAsycPort: 9012

OkHttp-config:
pool:
max-conn: 200
keep-alive: 5
read-timeout: 10
conn-timeout: 10
write-timeout: 10

async:
pool:
corePoolSize: 4
maxPoolSize: 8
queueCapacity: 5000

+ 73
- 0
src/main/resources/bootstrap.yaml Целия файл

@@ -0,0 +1,73 @@
logging:
config: classpath:log/logback-spring.xml
level:
com:
telpo:
dipperposition: debug
spring:
application:
name: dipperposition-service
cloud:
nacos:
config:
server-addr: 172.16.192.26:8848
file-extension: yaml
redis:
database: 1
host: 172.16.192.26
port: 8090
password: telpo#1234
timeout: 3000
lettuce:
pool:
max-active: 100 # 连接池最大连接数(使用负值表示没有限制)
max-idle: 100 # 连接池中的最大空闲连接
min-idle: 50 # 连接池中的最小空闲连接
max-wait: 6000 # 连接池最大阻塞等待时间(使用负值表示没有限制)

scheduler:
pool:
size: 2
#等待任务完成退出最大秒数
await-seconds: 600
task:
cron: "0 0 1 * * ?"

pos:
centerProvinceFilePath: /csv/provinceLonAlt.csv
ipPositionRequestPath: https://restapi.amap.com/v3/ip
ipPositionRequestKey: 65e794b0a1a4b87eeec86f93fea05411
centerProvince: 湖北省
ast:
server: agnss.techtotop.com
ephAstPort: 8012
ephAstHexPort: 9012
timeout: 30000

position-server:
serverAddr: localhost
timeAsycPort: 9011
posAsycPort: 9013
starsAsycPort: 9012

mongo:
datasource:
dblist:
- uri: mongodb://wangjx:wangjx#1234@172.16.192.26:27017/basicdata
database: basicdata
- uri: mongodb://wangjx:wangjx#1234@172.16.192.26:27017/common
database: common

OkHttp-config:
pool:
max-conn: 200
keep-alive: 5
read-timeout: 10
conn-timeout: 10
write-timeout: 10

async:
pool:
corePoolSize: 4
maxPoolSize: 8
queueCapacity: 5000

+ 198
- 0
src/main/resources/log/logback-spring.xml Целия файл

@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">

<!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<!-- property name="log.path" value="/var/log/dipperposition"/ -->
<property name="log.path" value="/home/data/dipperposition"/>

<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>


<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>


<!--输出到文件-->

<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>


<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender>。<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
如果未设置此属性,那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
-->
<!--<logger name="org.springframework.web" level="info"/>-->
<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
-->


<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
-->

<!--开发环境:打印控制台-->
<springProfile name="dev">
<logger name="com.telpo.dipperposition" level="debug"/>
</springProfile>

<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="DEBUG_FILE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="WARN_FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>

<!--生产环境:输出到文件-->
<!--<springProfile name="pro">-->
<!--<root level="info">-->
<!--<appender-ref ref="CONSOLE" />-->
<!--<appender-ref ref="DEBUG_FILE" />-->
<!--<appender-ref ref="INFO_FILE" />-->
<!--<appender-ref ref="ERROR_FILE" />-->
<!--<appender-ref ref="WARN_FILE" />-->
<!--</root>-->
<!--</springProfile>-->

</configuration>

Loading…
Отказ
Запис