@@ -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/ |
@@ -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= |
@@ -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 |
@@ -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> |
@@ -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启动=======================' |
@@ -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 |
@@ -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 |
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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 ""; | |||
} |
@@ -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; | |||
} |
@@ -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(); | |||
} | |||
} | |||
} | |||
} |
@@ -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 )); | |||
// } | |||
} |
@@ -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); | |||
} | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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()); | |||
}; | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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 | |||
} | |||
} |
@@ -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> {} |
@@ -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> {} |
@@ -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(); | |||
} | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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(); | |||
} |
@@ -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(); | |||
} |
@@ -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(); | |||
} |
@@ -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); | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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; | |||
} |
@@ -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 | |||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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> |