@@ -0,0 +1,2 @@ | |||||
# Default ignored files | |||||
/workspace.xml |
@@ -0,0 +1,9 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<module type="JAVA_MODULE" version="4"> | |||||
<component name="NewModuleRootManager" inherit-compiler-output="true"> | |||||
<exclude-output /> | |||||
<content url="file://$MODULE_DIR$" /> | |||||
<orderEntry type="inheritedJdk" /> | |||||
<orderEntry type="sourceFolder" forTests="false" /> | |||||
</component> | |||||
</module> |
@@ -0,0 +1,6 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project version="4"> | |||||
<component name="GoogleJavaFormatSettings"> | |||||
<option name="enabled" value="false" /> | |||||
</component> | |||||
</project> |
@@ -0,0 +1,36 @@ | |||||
<component name="InspectionProjectProfileManager"> | |||||
<profile version="1.0"> | |||||
<option name="myName" value="Project Default" /> | |||||
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true"> | |||||
<option name="TOP_LEVEL_CLASS_OPTIONS"> | |||||
<value> | |||||
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> | |||||
<option name="REQUIRED_TAGS" value="" /> | |||||
</value> | |||||
</option> | |||||
<option name="INNER_CLASS_OPTIONS"> | |||||
<value> | |||||
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> | |||||
<option name="REQUIRED_TAGS" value="" /> | |||||
</value> | |||||
</option> | |||||
<option name="METHOD_OPTIONS"> | |||||
<value> | |||||
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> | |||||
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" /> | |||||
</value> | |||||
</option> | |||||
<option name="FIELD_OPTIONS"> | |||||
<value> | |||||
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" /> | |||||
<option name="REQUIRED_TAGS" value="" /> | |||||
</value> | |||||
</option> | |||||
<option name="IGNORE_DEPRECATED" value="false" /> | |||||
<option name="IGNORE_JAVADOC_PERIOD" value="true" /> | |||||
<option name="IGNORE_DUPLICATED_THROWS" value="false" /> | |||||
<option name="IGNORE_POINT_TO_ITSELF" value="false" /> | |||||
<option name="myAdditionalJavadocTags" value="date" /> | |||||
</inspection_tool> | |||||
</profile> | |||||
</component> |
@@ -0,0 +1,6 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project version="4"> | |||||
<component name="JavaScriptSettings"> | |||||
<option name="languageLevel" value="ES6" /> | |||||
</component> | |||||
</project> |
@@ -0,0 +1,8 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project version="4"> | |||||
<component name="ProjectModuleManager"> | |||||
<modules> | |||||
<module fileurl="file://$PROJECT_DIR$/.idea/BeidouAstPos.iml" filepath="$PROJECT_DIR$/.idea/BeidouAstPos.iml" /> | |||||
</modules> | |||||
</component> | |||||
</project> |
@@ -0,0 +1,6 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project version="4"> | |||||
<component name="VcsDirectoryMappings"> | |||||
<mapping directory="" vcs="Git" /> | |||||
</component> | |||||
</project> |
@@ -0,0 +1,148 @@ | |||||
<?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>beidouast</artifactId> | |||||
<version>1.0-SNAPSHOT</version> | |||||
<name>beidouast</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>com.telpo</groupId> | |||||
<artifactId>common</artifactId> | |||||
<version>1.1.19</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>com.mongodb</groupId> | |||||
<artifactId>mongo</artifactId> | |||||
<version>1.0</version> | |||||
</dependency> | |||||
</dependencies> | |||||
<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,64 @@ | |||||
#!/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/beidou_ast/target/beidouast.jar /usr/local/beidou_ast/beidou_ast.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 beidou |awk '{print $2}'|xargs kill -9 | |||||
java -jar -Xms256m -Xmx256m -Xss256k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m /usr/local/beidou_ast/beidouast.jar | |||||
echo '=================完成NettyAPP启动=======================' |
@@ -0,0 +1,53 @@ | |||||
package com.telpo.dipperposition; | |||||
import com.alibaba.nacos.api.NacosFactory; | |||||
import com.alibaba.nacos.api.config.ConfigService; | |||||
import com.alibaba.nacos.api.config.listener.Listener; | |||||
import com.alibaba.nacos.api.PropertyKeyConst; | |||||
import com.alibaba.nacos.api.exception.NacosException; | |||||
import com.telpo.dipperposition.co.PositionConfigInfo; | |||||
import com.telpo.dipperposition.server.DipperPositionServer; | |||||
import com.telpo.dipperposition.server.EphAsyncServer; | |||||
import com.telpo.dipperposition.server.TimeAsyncServer; | |||||
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.boot.context.properties.EnableConfigurationProperties; | |||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; | |||||
import org.springframework.context.ConfigurableApplicationContext; | |||||
import org.springframework.core.env.ConfigurableEnvironment; | |||||
import org.springframework.scheduling.annotation.EnableAsync; | |||||
import org.springframework.scheduling.annotation.EnableScheduling; | |||||
import java.util.Properties; | |||||
import java.util.concurrent.Executor; | |||||
/** | |||||
* @program: gateway | |||||
* @description: 网关启动类 | |||||
* @author: linwl | |||||
* @create: 2020-06-18 16:39 | |||||
*/ | |||||
@SpringBootApplication | |||||
@EnableDiscoveryClient | |||||
@ConfigurationPropertiesScan | |||||
@EnableAsync | |||||
@EnableScheduling | |||||
@Slf4j | |||||
public class BaidouAstApplication { | |||||
public static void main(String[] args) { | |||||
try { | |||||
log.info("北斗定位服务开始!"); | |||||
ConfigurableApplicationContext applicationContext = SpringApplication.run(BaidouAstApplication.class, args); | |||||
log.info("北斗定位服务启动!"); | |||||
//启动服务端 | |||||
ConfigurableEnvironment environment = applicationContext.getEnvironment(); | |||||
DipperPositionServer nettyServer = new DipperPositionServer(environment); | |||||
nettyServer.start2(); | |||||
} 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); | |||||
// 读表头 | |||||
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,140 @@ | |||||
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; | |||||
} | |||||
// | |||||
// 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,154 @@ | |||||
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 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; | |||||
/** | |||||
* 根据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请求发送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,665 @@ | |||||
package com.telpo.dipperposition.common; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.data.redis.core.RedisTemplate; | |||||
import org.springframework.stereotype.Component; | |||||
import org.springframework.util.CollectionUtils; | |||||
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; | |||||
// =============================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,98 @@ | |||||
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 String sendCmd(String astCmd, String ackAckCheckRef) { | |||||
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]; | |||||
//StringBuffer ackResultBuf= new StringBuffer(); | |||||
//String ackHexOut = HexConvert.convertStringToHex(ackAckCheckRef); | |||||
// reply=br.readLine(); | |||||
// while(reply!=null){ | |||||
// //log.debug("接收服务器的信息:"+reply); | |||||
// //if (ackHexOut.equals(reply)) { | |||||
// ackResultBuf.append(reply); | |||||
// reply=br.readLine(); | |||||
// // break; | |||||
// //} | |||||
// } | |||||
int rc = 0; | |||||
while ((rc = is.read(buff, 0, 100)) > 0) { | |||||
swapStream.write(buff, 0, rc); | |||||
} | |||||
byte[] in2b = swapStream.toByteArray(); | |||||
//String ackResult = HexConvert.convertHexToString(ackResultBuf.toString()); | |||||
//4.关闭资源 | |||||
swapStream.close(); | |||||
is.close(); | |||||
pw.close(); | |||||
os.close(); | |||||
//log.debug(ackResult); | |||||
log.debug("接收服务器的信息:"+HexConvert.BinaryToHexString(in2b)); | |||||
return HexConvert.BinaryToHexString(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,69 @@ | |||||
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 | |||||
*/ | |||||
@Configuration | |||||
@Slf4j | |||||
public class AsyncExecutorConfig implements AsyncConfigurer { | |||||
@Value("${async.pool.corePoolSize}") | |||||
private int corePoolSize; | |||||
@Value("${async.pool.maxPoolSize}") | |||||
private int maxPoolSize; | |||||
@Value("${async.pool.queueCapacity}") | |||||
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,99 @@ | |||||
package com.telpo.dipperposition.config; | |||||
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 | |||||
*/ | |||||
@Configuration | |||||
@Slf4j | |||||
public class OkHttpConfig { | |||||
@Value("${OkHttp-config.pool.max-conn}") | |||||
private Integer maxConn; | |||||
@Value("${OkHttp-config.pool.keep-alive}") | |||||
private Integer keepAlive; | |||||
@Value("${OkHttp-config.read-timeout}") | |||||
private long readTimeout; | |||||
@Value("${OkHttp-config.conn-timeout}") | |||||
private long connTimeout; | |||||
@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,61 @@ | |||||
package com.telpo.dipperposition.config; | |||||
import com.telpo.dipperposition.co.PositionConfigInfo; | |||||
import lombok.Getter; | |||||
import lombok.Setter; | |||||
import lombok.ToString; | |||||
import okhttp3.OkHttpClient; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.context.ConfigurableApplicationContext; | |||||
import org.springframework.context.annotation.Bean; | |||||
import org.springframework.context.annotation.Configuration; | |||||
/** | |||||
* @program: gateway | |||||
* @description: jwt设置 | |||||
* @author: linwl | |||||
* @create: 2020-06-18 17:45 | |||||
*/ | |||||
@Getter | |||||
@Setter | |||||
@Configuration | |||||
public class PositionConfig { | |||||
//@Autowired | |||||
//private ConfigurableApplicationContext configurableApplicationContext; | |||||
//@Value(value = "${position.hello}") | |||||
//private String hello; | |||||
//@Value(value = "${spring.application.name}") | |||||
//private String name; | |||||
// @Value(value = "${position.server.serverAddr}") | |||||
// private String serverAddr; | |||||
// | |||||
// @Value(value = "${position.server.timeAsycPort}") | |||||
// private String timeAsycServerPort; | |||||
// | |||||
// @Value(value = "${position.server.posAsycPort}") | |||||
// private String posAsycServerPort; | |||||
// | |||||
// @Value(value = "${position.server.starsAsycPort}") | |||||
// private String starsAsycServerPort; | |||||
PositionConfig() | |||||
{ | |||||
//hello = configurableApplicationContext.getEnvironment().getProperty("position.hello"); | |||||
//name = configurableApplicationContext.getEnvironment().getProperty("spring.application.name"); | |||||
} | |||||
// | |||||
// @Bean (name = "positionConfigInfo") | |||||
// public PositionConfigInfo positionConfigInfo(){ | |||||
// PositionConfigInfo configInfo = new PositionConfigInfo(); | |||||
// configInfo.setServerAddr(this.serverAddr); | |||||
// configInfo.setTimeAsycServerPort(this.timeAsycServerPort); | |||||
// configInfo.setPosAsycServerPort(this.posAsycServerPort); | |||||
// configInfo.setStarsAsycServerPort(this.starsAsycServerPort); | |||||
// System.out.print(configInfo.toString()); | |||||
// return configInfo; | |||||
// } | |||||
} |
@@ -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("${scheduler.pool.size}") | |||||
private int pollSize; | |||||
@Value("${scheduler.pool.await-seconds}") | |||||
private int awaitSeconds; | |||||
@Value("${pos.ast.server}") | |||||
private String astServer; | |||||
@Value("${pos.ast.ephAstPort}") | |||||
private int ephAstPort; | |||||
@Value("${pos.ast.ephAstHexPort}") | |||||
private int ephAstHexPort; | |||||
@Value("${pos.ast.timeout}") | |||||
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,65 @@ | |||||
package com.telpo.dipperposition.config.db; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.context.annotation.Bean; | |||||
import org.springframework.data.mongodb.MongoDbFactory; | |||||
import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory; | |||||
import org.springframework.stereotype.Component; | |||||
import org.springframework.util.CollectionUtils; | |||||
import javax.annotation.PostConstruct; | |||||
import java.util.HashMap; | |||||
import java.util.Iterator; | |||||
import java.util.Map; | |||||
/** | |||||
* @program: DataPushServer | |||||
* @description: mongdb数据库连接上下文 | |||||
* @author: linwl | |||||
* @create: 2020-07-11 14:31 | |||||
*/ | |||||
@Component | |||||
public class MongoDbContext { | |||||
private static final Map<String, MongoDbFactory> MONGO_CLIENT_DB_FACTORY_MAP = new HashMap<>(); | |||||
private static final ThreadLocal<MongoDbFactory> MONGO_DB_FACTORY_THREAD_LOCAL = new ThreadLocal<>(); | |||||
@Autowired | |||||
MongoListProperties mongoListProperties; | |||||
public static MongoDbFactory getMongoDbFactory() { | |||||
return MONGO_DB_FACTORY_THREAD_LOCAL.get(); | |||||
} | |||||
public static void setMongoDbFactory(String name) { | |||||
MONGO_DB_FACTORY_THREAD_LOCAL.set(MONGO_CLIENT_DB_FACTORY_MAP.get(name)); | |||||
} | |||||
public static void removeMongoDbFactory() { | |||||
MONGO_DB_FACTORY_THREAD_LOCAL.remove(); | |||||
} | |||||
@PostConstruct | |||||
public void afterPropertiesSet() { | |||||
if (!CollectionUtils.isEmpty(mongoListProperties.getDblist())) { | |||||
mongoListProperties | |||||
.getDblist() | |||||
.forEach( | |||||
info -> { | |||||
MONGO_CLIENT_DB_FACTORY_MAP.put( | |||||
info.getDatabase(), new SimpleMongoClientDbFactory(info.getUri())); | |||||
}); | |||||
} | |||||
} | |||||
@Bean(name = "mongoTemplate") | |||||
public MultiMongoTemplate dynamicMongoTemplate() { | |||||
Iterator<MongoDbFactory> iterator = MONGO_CLIENT_DB_FACTORY_MAP.values().iterator(); | |||||
return new MultiMongoTemplate(iterator.next()); | |||||
} | |||||
@Bean(name = "mongoDbFactory") | |||||
public MongoDbFactory mongoDbFactory() { | |||||
Iterator<MongoDbFactory> iterator = MONGO_CLIENT_DB_FACTORY_MAP.values().iterator(); | |||||
return iterator.next(); | |||||
} | |||||
} |
@@ -0,0 +1,30 @@ | |||||
package com.telpo.dipperposition.config.db; | |||||
import lombok.Data; | |||||
import lombok.Getter; | |||||
import lombok.Setter; | |||||
import lombok.ToString; | |||||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
import java.util.List; | |||||
/** | |||||
* @program: DataPushServer | |||||
* @description: mongo连接配置类 | |||||
* @author: linwl | |||||
* @create: 2020-07-11 14:41 | |||||
*/ | |||||
@Getter | |||||
@Setter | |||||
@ToString | |||||
@ConfigurationProperties(prefix = "mongo.datasource") | |||||
public class MongoListProperties { | |||||
private List<MongoList> dblist; | |||||
@Data | |||||
public static class MongoList { | |||||
private String uri; | |||||
private String database; | |||||
} | |||||
} |
@@ -0,0 +1,26 @@ | |||||
package com.telpo.dipperposition.config.db; | |||||
import com.mongodb.client.MongoDatabase; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.data.mongodb.MongoDbFactory; | |||||
import org.springframework.data.mongodb.core.MongoTemplate; | |||||
/** | |||||
* @program: DataPushServer | |||||
* @description: 多mongo数据源配置 | |||||
* @author: linwl | |||||
* @create: 2020-07-11 14:21 | |||||
*/ | |||||
@Slf4j | |||||
public class MultiMongoTemplate extends MongoTemplate { | |||||
public MultiMongoTemplate(MongoDbFactory mongoDbFactory) { | |||||
super(mongoDbFactory); | |||||
} | |||||
@Override | |||||
protected MongoDatabase doGetDatabase() { | |||||
MongoDbFactory mongoDbFactory = MongoDbContext.getMongoDbFactory(); | |||||
return mongoDbFactory == null ? super.doGetDatabase() : mongoDbFactory.getDb(); | |||||
} | |||||
} |
@@ -0,0 +1,26 @@ | |||||
package com.telpo.dipperposition.controller; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.web.bind.annotation.RequestMapping; | |||||
import org.springframework.web.bind.annotation.RestController; | |||||
/** | |||||
* @program: DipperPositionController | |||||
* @description: 北斗定位 | |||||
* @author: linwl | |||||
* @create: 2020-07-10 14:01 | |||||
*/ | |||||
@RestController | |||||
@Slf4j | |||||
public class DipperPositionController { | |||||
@Value(value = "${position-server.serverAddr}") | |||||
private String hello; | |||||
//RzlAccount rzlAccount; | |||||
@RequestMapping("/getPos") | |||||
public String getPos() { | |||||
return "return serverAddr = " + hello; | |||||
} | |||||
} |
@@ -0,0 +1,24 @@ | |||||
package com.telpo.dipperposition.entity.mongo; | |||||
import com.telpo.dipperposition.vo.IPProvinceVo; | |||||
import lombok.Getter; | |||||
import lombok.Setter; | |||||
import lombok.ToString; | |||||
import models.BaseMongoDbEntity; | |||||
/** | |||||
* @program: IPProvinceEntity | |||||
* @description: 位置实体类 | |||||
* @author: linwl | |||||
* @create: 2020-07-11 15:33 | |||||
*/ | |||||
@ToString | |||||
@Getter | |||||
@Setter | |||||
public class IPProvinceEntity extends BaseMongoDbEntity { | |||||
/** Ip */ | |||||
private String ip; | |||||
/** Ip所在省份 */ | |||||
private String province; | |||||
} |
@@ -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,181 @@ | |||||
package com.telpo.dipperposition.handler; | |||||
import com.telpo.dipperposition.enums.DipperReturnValue; | |||||
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.Unpooled; | |||||
import io.netty.channel.socket.SocketChannel; | |||||
import io.netty.channel.ChannelHandlerContext; | |||||
import io.netty.channel.ChannelInboundHandlerAdapter; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.beans.factory.annotation.Value; | |||||
import java.io.InputStream; | |||||
import java.time.LocalDateTime; | |||||
/** | |||||
* @program: dipperposition | |||||
* @description: Netty服务器处理句柄 | |||||
* @author: linwl | |||||
* @create: 2021-01-13 13:56 | |||||
**/ | |||||
@Slf4j | |||||
public class NettyServerHandler extends ChannelInboundHandlerAdapter { | |||||
private static String AST_TIME_CMD = "54494d45"; | |||||
private static String AST_POS_CMD = "504f53"; | |||||
private static String AST_EPH_CMD = "455048"; | |||||
@Autowired | |||||
private IDipperAstTimeAsyncTaskService dipperTimeAsyncTaskService; | |||||
@Autowired | |||||
private IDipperAstPosAsyncTaskService dipperAstPosAsyncTaskService; | |||||
@Autowired | |||||
private IDipperDataAsyncTaskService dipperDataAsyncTaskService; | |||||
@Value(value = "${position-server.timeAsycPort}") | |||||
private String timeAsycServerPort; | |||||
@Value(value = "${position-server.posAsycPort}") | |||||
private String posAsycServerPort; | |||||
@Value(value = "${position-server.starsAsycPort}") | |||||
private String starsAsycServerPort; | |||||
@Value("${pos.centerProvinceFilePath}") | |||||
String centerProvinceFilePath; | |||||
@Value("${pos.ipPositionRequestPath}") | |||||
String ipPositionRequestPath; | |||||
@Value("${pos.ipPositionRequestKey}") | |||||
String ipPositionRequestKey; | |||||
@Value("${pos.centerProvince}") | |||||
String centerProvince; | |||||
@Value("${pos.ast.server}") | |||||
String astServer; | |||||
@Value("${pos.ast.posAstPort}") | |||||
int posAstPort; | |||||
@Value("${pos.ast.timeout}") | |||||
int astTimeout; | |||||
/** | |||||
* 客户端连接会触发 | |||||
*/ | |||||
@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"; | |||||
if (Integer.parseInt(posAsycServerPort) == channel.localAddress().getPort()) { | |||||
ackAckCheckRef = "233E010102000401091C"; | |||||
} | |||||
if (Integer.parseInt(starsAsycServerPort) == channel.localAddress().getPort()) { | |||||
ackAckCheckRef = "233E010102000421293C"; | |||||
} | |||||
//String str = "通知客户端链接建立成功" + " " + LocalDateTime.now() + " " + channel.localAddress().getHostString() + | |||||
// "\r\n"; | |||||
ByteBuf buf = Unpooled.buffer(ackAckCheckRef.getBytes().length); | |||||
buf.writeBytes(ackAckCheckRef.getBytes("GBK")); | |||||
ctx.writeAndFlush(buf); | |||||
} | |||||
/** | |||||
* 当客户端主动断开服务端的链接后,这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据 | |||||
*/ | |||||
@Override | |||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception { | |||||
log.info("客户端断开链接,IP:{}", ctx.channel().localAddress().toString()); | |||||
} | |||||
/** | |||||
* 客户端发消息会触发 | |||||
*/ | |||||
@Override | |||||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { | |||||
//接收msg消息{与上一章节相比,此处已经不需要自己进行解码} | |||||
SocketChannel channel = (SocketChannel) ctx.channel(); | |||||
String ipAddress = channel.remoteAddress().toString(); | |||||
String message = " 接收到消息:{0}, 客户端IP:{1}"; | |||||
log.info(message ,msg, ipAddress); | |||||
String channelAns = ""; | |||||
// 返回时间指令 | |||||
//if (Integer.parseInt(timeAsycServerPort) == channel.localAddress().getPort()) { | |||||
ByteBuf recvmg = (ByteBuf) msg; | |||||
ByteBuf buf = null; | |||||
String recvmgStr = recvmg.toString(); | |||||
if (AST_TIME_CMD.equals(recvmg)) { | |||||
// 初始时间辅助输入; | |||||
channelAns = dipperTimeAsyncTaskService.pushAstTime(); | |||||
buf = Unpooled.buffer(channelAns.getBytes().length); | |||||
} | |||||
// 发送SDBP-AST-POS获取辅助位置信息 | |||||
// if (Integer.parseInt(posAsycServerPort) == channel.localAddress().getPort()) { | |||||
if (AST_POS_CMD.equals(recvmg)) { | |||||
channelAns = dipperAstPosAsyncTaskService.pushAstPos(ipAddress, | |||||
centerProvinceFilePath, | |||||
centerProvince, | |||||
ipPositionRequestPath, | |||||
ipPositionRequestKey); | |||||
buf = Unpooled.buffer(channelAns.getBytes().length); | |||||
} | |||||
// 从缓存获取SDBP-AST-EPH星历数 | |||||
//if (Integer.parseInt(starsAsycServerPort) == channel.localAddress().getPort()) { | |||||
if (AST_POS_CMD.equals(recvmg)) { | |||||
String astEPHBytes = dipperDataAsyncTaskService.getAstEPH(); | |||||
buf = Unpooled.buffer(astEPHBytes.getBytes().length); | |||||
} | |||||
// 最后把SDBP-AST-TIME、SDBP-AST-POS、SDBP-AST-EPH并包一起发给设备。 | |||||
// 设备采用16进制获取数据,则代理服务器也是采用16进制返回数据。 | |||||
// 通知客户端链消息发送成功 | |||||
// String str = "服务端收到:" + LocalDateTime.now() + " " + msg + "\r\n"; | |||||
buf.writeBytes(channelAns.getBytes("GBK")); | |||||
ctx.writeAndFlush(buf); | |||||
//ctx.write("你也好哦"); | |||||
//ctx.flush(); | |||||
} | |||||
// @Override | |||||
// public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) | |||||
// throws Exception { | |||||
// if (msg instanceof HttpRequest) { | |||||
// HttpRequest mReq = (HttpRequest) msg; | |||||
// String clientIP = mReq.headers().get("X-Forwarded-For"); | |||||
// if (clientIP == null) { | |||||
// InetSocketAddress insocket = (InetSocketAddress) ctx.channel() | |||||
// .remoteAddress(); | |||||
// clientIP = insocket.getAddress().getHostAddress(); | |||||
// } | |||||
// } | |||||
// } | |||||
/** | |||||
* 发生异常触发 | |||||
*/ | |||||
@Override | |||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { | |||||
cause.printStackTrace(); | |||||
ctx.close(); | |||||
} | |||||
} |
@@ -0,0 +1,24 @@ | |||||
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)); | |||||
socketChannel.pipeline().addLast(new NettyServerHandler()); | |||||
} | |||||
} |
@@ -0,0 +1,58 @@ | |||||
package com.telpo.dipperposition.mapper; | |||||
import com.telpo.dipperposition.annotation.MongoSwitch; | |||||
import com.telpo.dipperposition.entity.mongo.IPProvinceEntity; | |||||
import db.BaseMongoDbDao; | |||||
import org.springframework.stereotype.Repository; | |||||
import java.util.List; | |||||
/** | |||||
* @program: DataPushServer | |||||
* @description: 推送记录mapper | |||||
* @author: linwl | |||||
* @create: 2020-07-20 11:12 | |||||
*/ | |||||
@Repository | |||||
public class IPProvinceMapper extends BaseMongoDbDao<IPProvinceEntity> { | |||||
@Override | |||||
protected Class<IPProvinceEntity> getEntityClass() { | |||||
return IPProvinceEntity.class; | |||||
} | |||||
@Override | |||||
@MongoSwitch("common") | |||||
public void save(IPProvinceEntity entity, String collectionName) { | |||||
super.save(entity, collectionName); | |||||
} | |||||
@Override | |||||
@MongoSwitch("common") | |||||
public void updateFirst(IPProvinceEntity srcObj, IPProvinceEntity targetObj) { | |||||
super.updateFirst(srcObj, targetObj); | |||||
} | |||||
@Override | |||||
public List<IPProvinceEntity> getPage(IPProvinceEntity object, int start, int size) { | |||||
return super.getPage(object, start, size); | |||||
} | |||||
@Override | |||||
@MongoSwitch("common") | |||||
public List<IPProvinceEntity> queryList(IPProvinceEntity object) { | |||||
return super.queryList(object); | |||||
} | |||||
@Override | |||||
@MongoSwitch("common") | |||||
public List<IPProvinceEntity> queryList(IPProvinceEntity object, String collectionName) { | |||||
return super.queryList(object, collectionName); | |||||
} | |||||
@Override | |||||
@MongoSwitch("common") | |||||
public void deleteById(String id) { | |||||
super.deleteById(id); | |||||
} | |||||
} |
@@ -0,0 +1,257 @@ | |||||
package com.telpo.dipperposition.server; | |||||
import com.alibaba.nacos.api.NacosFactory; | |||||
import com.alibaba.nacos.api.PropertyKeyConst; | |||||
import com.alibaba.nacos.api.config.ConfigService; | |||||
import com.alibaba.nacos.api.exception.NacosException; | |||||
import com.telpo.dipperposition.co.PositionConfigInfo; | |||||
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 java.net.InetSocketAddress; | |||||
/** | |||||
* @program: DipperPositionServer | |||||
* @description: 北斗定位 | |||||
* @author: king | |||||
* @create: 2021-01-13 14:01 | |||||
*/ | |||||
@Slf4j | |||||
public class DipperPositionServer { | |||||
// @Autowired PositionConfigInfo positionConfigInfo; | |||||
private String serverAddr; | |||||
private Integer serverPort; | |||||
private Integer timeAsycPort; | |||||
private Integer posAsycPort; | |||||
private Integer starsAsycPort; | |||||
public DipperPositionServer(ConfigurableEnvironment environment) throws NacosException { | |||||
this.serverAddr = environment.getProperty("position-server.serverAddr"); | |||||
this.serverPort = Integer.parseInt(environment.getProperty("server.port")); | |||||
this.timeAsycPort = Integer.parseInt(environment.getProperty("position-server.timeAsycPort")); | |||||
this.posAsycPort = Integer.parseInt(environment.getProperty("position-server.posAsycPort")); | |||||
this.starsAsycPort = Integer.parseInt(environment.getProperty("position-server.starsAsycPort")); | |||||
//String serverAddr = positionConfigInfo.getServerAddr(); | |||||
// try { | |||||
// try { | |||||
// InetAddress ip4 = Inet4Address.getLocalHost(); | |||||
// serverAddr = ip4.getHostAddress(); | |||||
// } catch (Exception ex) { | |||||
// serverAddr = "172.16.192.26"; | |||||
// ex.printStackTrace(); | |||||
// } | |||||
// String dataId = "dipperposition-service"; | |||||
// String group = "DEFAULT_GROUP"; | |||||
// Properties properties = new Properties(); | |||||
// properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr); | |||||
// ConfigService configService = NacosFactory.createConfigService(properties); | |||||
// String content = configService.getConfig(dataId, group, 5000); | |||||
// | |||||
// ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(content.getBytes()); | |||||
// Yaml yaml = new Yaml(); | |||||
// Map m1 = yaml.load(tInputStringStream); | |||||
// Map m2 = (Map) m1.get("position-server"); | |||||
// this.serverAddr = (String)m2.get("serverAddr"); | |||||
// this.timeAsycPort = (Integer)m2.get("timeAsycPort"); | |||||
// this.posAsycPort = (Integer)m2.get("posAsycPort"); | |||||
// this.starsAsycPort = (Integer)m2.get("starsAsycPort"); | |||||
// log.info("Map server is:" + m2.get("serverAddr")); | |||||
// } catch (Exception ex) { | |||||
// ex.printStackTrace(); | |||||
// } | |||||
} | |||||
// /* | |||||
// * 时间同步进程线程 | |||||
// */ | |||||
// public void startTimeAsnc() { | |||||
// | |||||
// //new 一个主线程组 | |||||
// EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1); | |||||
// //new 一个工作线程组 | |||||
// EventLoopGroup workThreadGroup = new NioEventLoopGroup(200); | |||||
// InetSocketAddress socketAddress = new InetSocketAddress(serverAddr, | |||||
// timeAsycPort); | |||||
// ServerBootstrap bootstrap = new ServerBootstrap() | |||||
// .group(mainThreadGroup, workThreadGroup) | |||||
// .channel(NioServerSocketChannel.class) | |||||
// .childHandler(new ServerChannelInitializer()) | |||||
// .localAddress(socketAddress) | |||||
// //设置队列大小 | |||||
// .option(ChannelOption.SO_BACKLOG, 1024) | |||||
// // 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文 | |||||
// .childOption(ChannelOption.SO_KEEPALIVE, true); | |||||
// | |||||
// | |||||
// //绑定端口,开始接收进来的连接 | |||||
// try { | |||||
// ChannelFuture future = bootstrap.bind(socketAddress).sync(); | |||||
// log.info("服务器启动开始监听端口: {}", socketAddress.getPort()); | |||||
// | |||||
// | |||||
// future.channel().closeFuture().sync(); | |||||
// } catch (InterruptedException e) { | |||||
// e.printStackTrace(); | |||||
// } finally { | |||||
// //关闭主线程组 | |||||
// mainThreadGroup.shutdownGracefully(); | |||||
// //关闭工作线程组 | |||||
// workThreadGroup.shutdownGracefully(); | |||||
// } | |||||
// } | |||||
// /* | |||||
// * 时间同步进程线程 | |||||
// */ | |||||
// public void startPosAsnc() { | |||||
// | |||||
// //new 一个主线程组 | |||||
// EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1); | |||||
// //new 一个工作线程组 | |||||
// EventLoopGroup workThreadGroup = new NioEventLoopGroup(200); | |||||
// InetSocketAddress socketAddress = new InetSocketAddress(serverAddr, | |||||
// posAsycPort); | |||||
// ServerBootstrap bootstrap = new ServerBootstrap() | |||||
// .group(mainThreadGroup, workThreadGroup) | |||||
// .channel(NioServerSocketChannel.class) | |||||
// .childHandler(new ServerChannelInitializer()) | |||||
// .localAddress(socketAddress) | |||||
// //设置队列大小 | |||||
// .option(ChannelOption.SO_BACKLOG, 1024) | |||||
// // 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文 | |||||
// .childOption(ChannelOption.SO_KEEPALIVE, true); | |||||
// | |||||
// | |||||
// //绑定端口,开始接收进来的连接 | |||||
// try { | |||||
// ChannelFuture future = bootstrap.bind(socketAddress).sync(); | |||||
// log.info("服务器启动开始监听端口: {}", socketAddress.getPort()); | |||||
// | |||||
// | |||||
// future.channel().closeFuture().sync(); | |||||
// } catch (InterruptedException e) { | |||||
// e.printStackTrace(); | |||||
// } finally { | |||||
// //关闭主线程组 | |||||
// mainThreadGroup.shutdownGracefully(); | |||||
// //关闭工作线程组 | |||||
// workThreadGroup.shutdownGracefully(); | |||||
// } | |||||
// } | |||||
/* | |||||
* 星历同步进程线程 | |||||
*/ | |||||
//public void startStarsAsnc() { | |||||
public void start() { | |||||
//new 一个主线程组 | |||||
EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1); | |||||
//new 一个工作线程组 | |||||
EventLoopGroup workThreadGroup = new NioEventLoopGroup(200); | |||||
//InetSocketAddress socketAddress = new InetSocketAddress(serverAddr,null); | |||||
ServerBootstrap bootstrap = new ServerBootstrap() | |||||
.group(mainThreadGroup, workThreadGroup) | |||||
.channel(NioServerSocketChannel.class) | |||||
.childHandler(new ServerChannelInitializer()) | |||||
//.localAddress(socketAddress) | |||||
//设置队列大小 | |||||
.option(ChannelOption.SO_BACKLOG, 1024) | |||||
// 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文 | |||||
.childOption(ChannelOption.SO_KEEPALIVE, true); | |||||
//绑定端口,开始接收进来的连接 | |||||
try { | |||||
ChannelFuture channelFuture = bootstrap.bind(timeAsycPort).sync(); | |||||
log.info("时间辅助服务器启动开始监听端口: {}", timeAsycPort); | |||||
channelFuture.addListener(future -> { | |||||
if (future.isSuccess()){ | |||||
System.out.println("start success"); | |||||
}else{ | |||||
System.out.println("start failed"); | |||||
} | |||||
}); | |||||
ChannelFuture channelFuture2 = bootstrap.bind(posAsycPort).sync(); | |||||
log.info("位置服务器启动开始监听端口: {}", posAsycPort); | |||||
channelFuture2.addListener(future -> { | |||||
if (future.isSuccess()){ | |||||
System.out.println("start success"); | |||||
}else{ | |||||
System.out.println("start failed"); | |||||
} | |||||
}); | |||||
ChannelFuture channelFuture3 = bootstrap.bind(starsAsycPort).sync(); | |||||
log.info("星历服务器启动开始监听端口: {}", starsAsycPort); | |||||
channelFuture3.addListener(future -> { | |||||
if (future.isSuccess()){ | |||||
System.out.println("start success"); | |||||
}else{ | |||||
System.out.println("start failed"); | |||||
} | |||||
}); | |||||
//channelFuture.channel().closeFuture().sync(); | |||||
} catch (InterruptedException e) { | |||||
e.printStackTrace(); | |||||
} finally { | |||||
//关闭主线程组 | |||||
mainThreadGroup.shutdownGracefully(); | |||||
//关闭工作线程组 | |||||
workThreadGroup.shutdownGracefully(); | |||||
} | |||||
} | |||||
public void start2() { | |||||
//new 一个主线程组 | |||||
EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1); | |||||
//new 一个工作线程组 | |||||
EventLoopGroup workThreadGroup = new NioEventLoopGroup(200); | |||||
//InetSocketAddress socketAddress = new InetSocketAddress(serverAddr,null); | |||||
ServerBootstrap bootstrap = new ServerBootstrap() | |||||
.group(mainThreadGroup, workThreadGroup) | |||||
.channel(NioServerSocketChannel.class) | |||||
.childHandler(new ServerChannelInitializer()) | |||||
//.localAddress(socketAddress) | |||||
//设置队列大小 | |||||
.option(ChannelOption.SO_BACKLOG, 1024) | |||||
// 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文 | |||||
.childOption(ChannelOption.SO_KEEPALIVE, true); | |||||
//绑定端口,开始接收进来的连接 | |||||
try { | |||||
ChannelFuture channelFuture = bootstrap.bind(timeAsycPort).sync(); | |||||
log.info("时间辅助服务器启动开始监听端口: {}", timeAsycPort); | |||||
channelFuture.addListener(future -> { | |||||
if (future.isSuccess()){ | |||||
System.out.println("start success"); | |||||
}else{ | |||||
System.out.println("start failed"); | |||||
} | |||||
}); | |||||
//channelFuture.channel().closeFuture().sync(); | |||||
} catch (InterruptedException e) { | |||||
e.printStackTrace(); | |||||
} finally { | |||||
//关闭主线程组 | |||||
mainThreadGroup.shutdownGracefully(); | |||||
//关闭工作线程组 | |||||
workThreadGroup.shutdownGracefully(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,27 @@ | |||||
package com.telpo.dipperposition.service; | |||||
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 centerProvinceFilePath, | |||||
String centerProvince, | |||||
String ipPositionRequestPath, | |||||
String ipPositionRequestKey) throws UnsupportedEncodingException; | |||||
} |
@@ -0,0 +1,17 @@ | |||||
package com.telpo.dipperposition.service; | |||||
/** | |||||
* @program: IDipperDataAsyncTaskService | |||||
* @description: 发送SDBP-AST-TIME获取时间信息 | |||||
* @author: king | |||||
* @create: 2021-01-17 16:24 | |||||
*/ | |||||
public interface IDipperAstTimeAsyncTaskService { | |||||
/** | |||||
* 同步任务 | |||||
* | |||||
*/ | |||||
String pushAstTime(); | |||||
} |
@@ -0,0 +1,28 @@ | |||||
package com.telpo.dipperposition.service; | |||||
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 { | |||||
/** | |||||
* 同步任务 | |||||
* | |||||
*/ | |||||
void pullAstEPH(); | |||||
/** | |||||
* 根据IP获取EPH | |||||
* | |||||
*/ | |||||
String getAstEPH(); | |||||
} |
@@ -0,0 +1,45 @@ | |||||
package com.telpo.dipperposition.service; | |||||
import com.telpo.dipperposition.entity.mongo.IPProvinceEntity; | |||||
import com.telpo.dipperposition.vo.IPProvinceVo; | |||||
/** | |||||
* @program: IPProvinceService | |||||
* @description: IP省份服务接口 | |||||
* @author: king | |||||
* @create: 2020-07-20 11:09 | |||||
*/ | |||||
public interface IPProvinceService { | |||||
/** | |||||
* 保存IP省份 | |||||
* | |||||
* @param entity | |||||
* @return | |||||
*/ | |||||
boolean saveIPProvince(IPProvinceEntity entity); | |||||
/** | |||||
* 更新IP省份 | |||||
* | |||||
* @param query | |||||
* @param update | |||||
* @return | |||||
*/ | |||||
boolean updateIPProvince( | |||||
IPProvinceEntity query, IPProvinceEntity update); | |||||
/** | |||||
* 根据ID移除IP省份记录 | |||||
* | |||||
* @param id | |||||
* @return | |||||
*/ | |||||
boolean romveById(String id); | |||||
/* | |||||
* @param ipAddress | |||||
* 获取IP省份 | |||||
*/ | |||||
IPProvinceEntity getIPProvince(String ipAddress); | |||||
} |
@@ -0,0 +1,247 @@ | |||||
package com.telpo.dipperposition.service.impl; | |||||
import com.alibaba.fastjson.JSONObject; | |||||
import com.google.common.base.Joiner; | |||||
import com.telpo.dipperposition.common.*; | |||||
import com.telpo.dipperposition.entity.mongo.IPProvinceEntity; | |||||
import com.telpo.dipperposition.mapper.IPProvinceMapper; | |||||
import com.telpo.dipperposition.service.IDipperAstPosAsyncTaskService; | |||||
import com.telpo.dipperposition.service.IPProvinceService; | |||||
import com.telpo.dipperposition.vo.IPProvinceVo; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.commons.lang3.ObjectUtils; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.scheduling.annotation.Async; | |||||
import org.springframework.stereotype.Service; | |||||
import java.io.UnsupportedEncodingException; | |||||
import java.time.LocalDateTime; | |||||
import java.time.format.DateTimeFormatter; | |||||
import java.util.List; | |||||
/** | |||||
* @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 RedisUtil redisUtil; | |||||
@Autowired | |||||
private OkHttpUtil okHttpUtil; | |||||
@Autowired | |||||
private IPProvinceService iPProvinceService; | |||||
private String centerProvince; | |||||
private String centerProvinceFilePath; | |||||
private String ipPositionRequestPath; | |||||
private String ipPositionRequestKey; | |||||
// private String getAstPos(String ipAddress) throws UnsupportedEncodingException { | |||||
// | |||||
// String centerAddress = getIpPositionProvince(ipAddress); | |||||
// if (ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) { | |||||
// log.warn("IP地址非法,无法获取辅助位置信息!"); | |||||
// // 返回武汉的定位数据 | |||||
// centerAddress = centerProvince; | |||||
// } else { | |||||
// // 保存到mongoDB | |||||
// createIPProvince(ipAddress, centerAddress); | |||||
// } | |||||
// | |||||
// String lonAndAlt; | |||||
// if (redisUtil.hasKey(centerAddress)) { | |||||
// // 获取省会城市定位信息 | |||||
// lonAndAlt= (String) redisUtil.get(centerAddress); | |||||
// } else { | |||||
// // 请求高德IP定位服务 | |||||
// this.getPosFromFile(centerAddress); | |||||
// lonAndAlt = (String) redisUtil.get(centerAddress); | |||||
// } | |||||
// | |||||
// return lonAndAlt; | |||||
// } | |||||
// 从CSV文件读取省会城市中心点位置信息 | |||||
private void getPosFromFile(String centerAddress) { | |||||
// 不存在说明token是已过期了 | |||||
String centerProvinceName = ""; | |||||
String centerProvinceLonAndAlt = ""; | |||||
List<String> centerAddressSets = CSVUtil.readCSV(this.centerProvinceFilePath); | |||||
for (String centerAddressSet:centerAddressSets) { | |||||
String[] centerAddressSetArray = centerAddressSet.split(","); | |||||
if (centerAddressSetArray.length < 3) { | |||||
log.warn("CSV数据格式错误"); | |||||
} else { | |||||
centerProvinceName = centerAddressSetArray[3]; | |||||
centerProvinceLonAndAlt = centerAddressSetArray[1]+","+centerAddressSetArray[2]; | |||||
redisUtil.set(centerProvinceName, centerProvinceLonAndAlt, 0); | |||||
} | |||||
} | |||||
} | |||||
// 根据IP获取省会信息 | |||||
private String getIpPositionProvince(String ipAddress) { | |||||
// 关于IP与省份的关系保存到缓存中 | |||||
// 使用时,先在缓存中获取匹配信息 | |||||
// 用mongodb实现 | |||||
IPProvinceEntity ipProvinceEntity = iPProvinceService.getIPProvince(ipAddress); | |||||
if (ipProvinceEntity == null) { | |||||
// 匹配不到,再请求高德IP定位服务。 | |||||
JSONObject userObj = new JSONObject(); | |||||
userObj.put("ip", ipAddress); | |||||
userObj.put("key", ipPositionRequestKey); | |||||
JSONObject json = okHttpUtil.postRequestWithJson(ipPositionRequestPath, null, userObj); | |||||
if (ObjectUtils.isNotEmpty(json)) { | |||||
String province = (String) json.get("province"); | |||||
if (ObjectUtils.isEmpty(province)) { | |||||
log.debug("json is :" + json.toString()); | |||||
return null; | |||||
} | |||||
return province; | |||||
} else { | |||||
// 意外错误 | |||||
log.debug("ip address is null"); | |||||
return null; | |||||
} | |||||
} else { | |||||
return ipProvinceEntity.getProvince(); | |||||
} | |||||
} | |||||
// 将IP对应的省会保存到mongoDB | |||||
@Async("asyncServiceExecutor") | |||||
public void createIPProvince(String ipAddress, String province) { | |||||
log.debug("异步创建推送失败任务记录!"); | |||||
try { | |||||
IPProvinceEntity ipProvinceEntity = iPProvinceService.getIPProvince(ipAddress); | |||||
if (ipProvinceEntity == null) { | |||||
//DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | |||||
ipProvinceEntity.setIp(ipAddress); | |||||
ipProvinceEntity.setProvince(province); | |||||
iPProvinceService.saveIPProvince(ipProvinceEntity); | |||||
// } else { | |||||
// | |||||
// ipProvinceEntity.setProvince(province); | |||||
// iPProvinceService.updateIPProvince(ipProvinceEntity, ipProvinceEntity); | |||||
} | |||||
} catch (Exception e) { | |||||
log.error("创建推送失败记录异常:", e); | |||||
} | |||||
} | |||||
/* | |||||
* 获取定位辅助信息 | |||||
* @param ipAddress | |||||
*/ | |||||
@Override | |||||
@Async("asyncServiceExecutor") | |||||
public String pushAstPos(String ipAddress, | |||||
String centerProvinceFilePath, | |||||
String centerProvince, | |||||
String ipPositionRequestPath, | |||||
String ipPositionRequestKey) throws UnsupportedEncodingException { | |||||
this.ipPositionRequestKey = ipPositionRequestKey; | |||||
this.ipPositionRequestPath = ipPositionRequestPath; | |||||
this.centerProvince = centerProvince; | |||||
this.centerProvinceFilePath = centerProvinceFilePath; | |||||
// (1) 获取省会城市信息 | |||||
String centerAddress = getIpPositionProvince(ipAddress); | |||||
if (ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) { | |||||
log.warn("IP地址非法,无法获取辅助位置信息!"); | |||||
// 返回武汉的定位数据 | |||||
centerAddress = this.centerProvince; | |||||
} else { | |||||
// 保存到mongoDB | |||||
createIPProvince(ipAddress, centerAddress); | |||||
} | |||||
String lonAndAlt; | |||||
if (redisUtil.hasKey(centerAddress)) { | |||||
// 获取省会城市定位信息 | |||||
lonAndAlt= (String) redisUtil.get(centerAddress); | |||||
} else { | |||||
// 请求高德IP定位服务 | |||||
this.getPosFromFile(centerAddress); | |||||
lonAndAlt = (String) redisUtil.get(centerAddress); | |||||
} | |||||
// (2) 处理返回结果 | |||||
if (lonAndAlt == null) { | |||||
// null处理 | |||||
log.error("系统错误,请联系系统管理员。"); | |||||
return null; | |||||
//return; | |||||
} | |||||
// push to GNNS Server | |||||
String pushResult = getCmdOfPos(lonAndAlt); | |||||
return pushResult; | |||||
} | |||||
// 组装命令发送给设备 | |||||
private String getCmdOfPos(String astPos) { | |||||
// 创建Socket客户端实例; | |||||
// SocketClient client = new SocketClient(astServer, posAstPort, astTimeout); | |||||
// 时间和位置不是从服务器获取,而是本地生成 | |||||
String[] astPosArray = astPos.split(","); | |||||
String lan = astPosArray[0].trim(); | |||||
String alt = astPosArray[1].trim(); | |||||
double lanValue = Double.parseDouble(lan) * 10000000; | |||||
long lanLongValue = Double.doubleToLongBits(lanValue); | |||||
if (lanLongValue < 0) { | |||||
lanLongValue = lanLongValue + 4294967295L + 1; | |||||
} | |||||
double altValue = Double.parseDouble(alt) * 10000000; | |||||
long altLongValue = Double.doubleToLongBits(altValue); | |||||
if (altLongValue < 0) { | |||||
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 度 | |||||
// 00 2F 为校验和 | |||||
// astTimeCmd 组装 | |||||
String astTimeCmd = "233E0401"; | |||||
astTimeCmd += "1000"; | |||||
astTimeCmd += HexConvert.encodeHEX(lanLongValue); | |||||
astTimeCmd += HexConvert.encodeHEX(altLongValue); | |||||
String hexIn = HexConvert.convertStringToHex(astTimeCmd) + HexConvert.makeChecksum(astTimeCmd); | |||||
//String sendResult = client.sendCmd(hexIn, ackAckCheckRef); | |||||
//client.closeConnection(); | |||||
//return sendResult; | |||||
return hexIn; | |||||
} | |||||
} |
@@ -0,0 +1,106 @@ | |||||
package com.telpo.dipperposition.service.impl; | |||||
import com.telpo.dipperposition.common.HexConvert; | |||||
import com.telpo.dipperposition.common.SocketClient; | |||||
import com.telpo.dipperposition.service.IDipperAstTimeAsyncTaskService; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.springframework.beans.factory.annotation.Value; | |||||
import org.springframework.scheduling.annotation.Async; | |||||
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 | |||||
@Async("asyncServiceExecutor") | |||||
public String pushAstTime() { | |||||
// (1) 发送SDBP-AST-TIME | |||||
// String sendResult = pushTimeToDipper(); | |||||
//if (sendResult == null) { | |||||
// log.error("取不到时间。"); | |||||
// return null; | |||||
//} | |||||
// (2) 获取时间信息 | |||||
return pushTimeToDipper(); | |||||
//return sendResult; | |||||
} | |||||
private String pushTimeToDipper() { | |||||
// 创建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 2F 为校验和 | |||||
// TODO astTimeCmd 组装 | |||||
String astTimeCmd = "233E0402"; | |||||
astTimeCmd += "1000"; | |||||
astTimeCmd += "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; | |||||
astTimeCmd += hexYearString.substring(2,2) + hexYearString.substring(0,2); | |||||
String hexMonthString = Integer.toHexString(month); | |||||
hexMonthString = "0" + hexMonthString; | |||||
astTimeCmd += hexMonthString; | |||||
String hexDayString = Integer.toHexString(day); | |||||
if (day < 16) { | |||||
hexDayString = "0" + hexDayString; | |||||
} | |||||
astTimeCmd += hexDayString; | |||||
int hour = now.getHour(); | |||||
int minitor = now.getMinute(); | |||||
int second = now.getSecond(); | |||||
String hexHourString = Integer.toHexString(hour); | |||||
if (hour < 16) { | |||||
hexHourString = "0" + hexHourString; | |||||
} | |||||
astTimeCmd += hexHourString; | |||||
String hexMinitorString = Integer.toHexString(minitor); | |||||
if (minitor < 16) { | |||||
hexMinitorString = "0" + hexMinitorString; | |||||
} | |||||
astTimeCmd += hexMinitorString; | |||||
String hexSecondString = Integer.toHexString(second); | |||||
if (second < 16) { | |||||
hexSecondString = "0" + hexSecondString; | |||||
} | |||||
astTimeCmd += hexSecondString; | |||||
astTimeCmd += "0000000000"; | |||||
astTimeCmd += "00286BEE"; | |||||
String hexIn = HexConvert.convertStringToHex(astTimeCmd) + HexConvert.makeChecksum(astTimeCmd); | |||||
//String ackAckCheckRef = "233E0101020004020A1D"; | |||||
//String sendResult = client.sendCmd(hexIn, ackAckCheckRef); | |||||
//client.closeConnection(); | |||||
return hexIn; | |||||
} | |||||
} |
@@ -0,0 +1,68 @@ | |||||
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; | |||||
/** | |||||
* @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 | |||||
public void pullAstEPH() { | |||||
// (1) 发送bds获取星历数据 | |||||
String dipperData = pullEPHFromDipper(); | |||||
// (2) 获取星历数据 | |||||
if (dipperData == null) { | |||||
log.error("获取星历数据错误,取不到星历数据。"); | |||||
} else { | |||||
// 保存到DB或者缓存 | |||||
redisUtil.set(DIPPER_DATA_KEY,dipperData); | |||||
} | |||||
} | |||||
private String pullEPHFromDipper() { | |||||
// 创建Socket客户端实例; | |||||
SocketClient client = new SocketClient(schedulingExecutorConfig.getAstServer(), schedulingExecutorConfig.getEphAstHexPort(),schedulingExecutorConfig.getAstTimeout()); | |||||
// astTimeCmd 组装 | |||||
String astTimeCmd = DIPPER_ALL_DATA_REQ; | |||||
String hexIn = astTimeCmd + HexConvert.makeChecksum(astTimeCmd); | |||||
String ackAckCheckRef = "233E010102000421293C"; | |||||
String sendResult = client.sendCmd(hexIn, ackAckCheckRef); | |||||
client.closeConnection(); | |||||
return sendResult; | |||||
} | |||||
@Override | |||||
@Async("asyncServiceExecutor") | |||||
public String getAstEPH(){ | |||||
return (String)redisUtil.get(DIPPER_DATA_KEY); | |||||
} | |||||
} |
@@ -0,0 +1,62 @@ | |||||
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 com.telpo.dipperposition.vo.IPProvinceVo; | |||||
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.List; | |||||
/** | |||||
* @program: DataPushServer | |||||
* @description: 推送记录服务接口实现类 | |||||
* @author: linwl | |||||
* @create: 2020-07-20 11:09 | |||||
*/ | |||||
@Slf4j | |||||
@Service | |||||
public class IPProvinceServiceImpl implements IPProvinceService { | |||||
@Autowired | |||||
private IPProvinceMapper iPProvinceMapper; | |||||
@Override | |||||
public boolean saveIPProvince(IPProvinceEntity entity) { | |||||
iPProvinceMapper.save(entity); | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean updateIPProvince( | |||||
IPProvinceEntity query, IPProvinceEntity update) { | |||||
iPProvinceMapper.updateFirst(query, update); | |||||
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); | |||||
List<IPProvinceEntity> pushRecords = iPProvinceMapper.queryList(query); | |||||
if (ObjectUtils.isNotEmpty(pushRecords)) { | |||||
return pushRecords.get(0); | |||||
} else { | |||||
return null; | |||||
} | |||||
} catch (Exception e) { | |||||
log.error("获取IP省份异常:", e); | |||||
return null; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,40 @@ | |||||
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.beans.factory.annotation.Value; | |||||
import org.springframework.scheduling.annotation.Scheduled; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* @program: ScheduleService | |||||
* @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 { | |||||
dipperDataAsyncTaskService.pullAstEPH(); | |||||
} 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,69 @@ | |||||
logging: | |||||
config: classpath:log/logback-spring.xml | |||||
level: | |||||
com: | |||||
telpo: | |||||
dipperposition: debug | |||||
spring: | |||||
application: | |||||
name: dipperposition-service | |||||
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,35 @@ | |||||
城市,经度,纬度,省份 | |||||
沈阳市,123.429092,41.796768,辽宁省 | |||||
长春市,125.324501,43.886841,吉林省 | |||||
哈尔滨市,126.642464,45.756966,黑龙江省 | |||||
北京市,116.405289,39.904987,北京市 | |||||
天津市,117.190186,39.125595,天津市 | |||||
呼和浩特市,111.75199,40.84149,内蒙古自治区 | |||||
银川市,106.23248,38.48644,宁夏回族自治区 | |||||
太原市,112.549248,37.857014,山西省 | |||||
石家庄市,114.502464,38.045475,河北省 | |||||
济南市,117.000923,36.675808,山东省 | |||||
郑州市,113.665413,34.757977,河南省 | |||||
西安市,108.948021,34.263161,陕西省 | |||||
武汉市,114.298569,30.584354,湖北省 | |||||
南京市,118.76741,32.041546,江苏省 | |||||
合肥市,117.283043,31.861191,安徽省 | |||||
上海市,121.472641,31.231707,上海市 | |||||
长沙市,112.982277,28.19409,湖南省 | |||||
南昌市,115.892151,28.676493,江西省 | |||||
杭州市,120.15358,30.287458,浙江省 | |||||
福州市,119.306236,26.075302,福建省 | |||||
广州市,113.28064,23.125177,广东省 | |||||
台北市,121.520076,25.030724,台湾省 | |||||
海口市,110.19989,20.04422,海南省 | |||||
南宁市,108.320007,22.82402,广西壮族自治区 | |||||
重庆市,106.504959,29.533155,重庆市 | |||||
昆明市,102.71225,25.040609,云南省 | |||||
贵阳市,106.713478,26.578342,贵州省 | |||||
成都市,104.065735,30.659462,四川省 | |||||
兰州市,103.83417,36.06138,甘肃省 | |||||
西宁市,101.77782,36.61729,青海省 | |||||
拉萨市,91.1145,29.64415,西藏自治区 | |||||
乌鲁木齐市,87.61688,43.82663,新疆维吾尔自治区 | |||||
香港,114.16546,22.27534,香港特别行政区 | |||||
澳门,113.54913,22.19875,澳门特别行政区 |
@@ -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> |