gitweixin
  • 首页
  • 小程序代码
    • 资讯读书
    • 工具类
    • O2O
    • 地图定位
    • 社交
    • 行业软件
    • 电商类
    • 互联网类
    • 企业类
    • UI控件
  • 大数据开发
    • Hadoop
    • Spark
    • Hbase
    • Elasticsearch
    • Kafka
    • Flink
    • 数据仓库
    • 数据挖掘
    • flume
    • Kafka
    • Hive
    • shardingsphere
    • solr
  • 开发博客
    • Android
    • php
    • python
    • 运维
    • 技术架构
    • 数据库
  • 程序员网赚
  • bug清单
  • 量化投资
  • 在线查询工具
    • 去行号
    • 在线时间戳转换工具
    • 免费图片批量修改尺寸在线工具
    • SVG转JPG在线工具

分类归档Java

精品微信小程序开发门户,代码全部亲测可用

  • 首页   /  大数据开发
  • 分类归档: "Java"
  • ( 页面6 )
Java 11月 8,2020

GAT1400视图库通用说明

调用方式(必读)

所有接口(以下简称API)以HTTP/REST方式接入,使用URI 唯一标识,各类接口的URI参照API概览

请求结构

对视图库API调用是通过向视图库服务端地址发送请求,并按照接口说明在请求中加入相应的请求参数来完成的。视图库接口的请求结构由以下几个部分组成:

1.服务地址

HTTP URL格式的形式为:

<Protocol>://<Hostname>:<Port><URI>(?P1=v1&p2=v2…&pn=vn)。

其中:Protocol为HTTP;Hostname指视图库服务设备的主机名称、IP地址或域名;Port指端口号;URI指资源URI;(?P1=v1&p2=v2…&pn=vn)指查询字符串,每个资源都会定义需要的或可选的查询字符串参数,查询字符串参数以名字/值对形式出现。

2.请求方法

视图库API的HTTP请求方法包括GET、PUT、POST、DELETE。

方法的选取参照对应接口说明。

注意:

1、如果接口的请求方法是POST, PUT则需要对请求内容进行指定编码处理,且内容均从消息体中取得。

2、如果接口的请求方法是GET,则对所有请求参数值均需要做URL编码。

3.请求参数

视图库API每个请求都需要指定请求头参数,参数列表如下

表1 请求参数列表

序号 参数名称 参数说明 必填 备注
1 Content-Type 消息体对象的媒体类型 是/否 带有消息体的POST,PUT请求必填,支持 application/json或xml;charset=utf-8
2 Accept 请求方能接收的媒体类型 否 支持application/json或xml;charset=utf-8,默认 返回application/json;charset=utf-8
3 User-Identify 请求方系统编码 是/否 用于校验访问者身份,参考注册、保活、注销
备注:参数命名和取值,大小写敏感

返回结果

REST HTTP请求响应保留HTTP协议相关内容,其中返回结果(响应消息体)由视图库API维护。

视图库API的返回结果由请求方法决定,总结如下表:

表2 各类请求返回结果

序号 请求方法 说明 返回结果
1 GET 查询单个目标对象属性 单个目标结果
2 GET 查询符合条件的多个对象 多个目标集合
3 GET 查询异常 ResponseStatus
4 POST 提交单个目标对象 ResponseStatus
5 POST 提交多个目标对象集合 List<ResponseStatus>
6 PUT 修改单个目标对象 ResponseStatus
7 PUT 修改多个目标对象集合 List<ResponseStatus>
8 DELETE 修改单个目标对象 ResponseStatus
9 DELETE 修改多个目标对象集合 List<ResponseStatus>

ResponseStatus(应答状态对象)特征属性参照A.26 应答状态对象

其他的对象特征参见 附录A

字符编码

视图库API的请求及返回结果均使用UTF-8字符集进行编码。

通用说明

1、所有时间格式字段,若无特殊说明,均采用如下时间格式:yyyyMMddHHmmss如 20170101021020

2、所有URI中的 <ID> 在请求时需替换为具体对象的标识ID。例如:

HTTP PUT请求访问取消订阅接口 /VIID/Subscribes/<ID> 时,需要把URI中的<ID>替换成目标对象的订阅标识,如 /VIID/Subscribes/330101020001032017113010580006371

3、下文接口示例中的消息体和响应体都是基于如下请求头参数

请求头名称 取值
Content-Type application/json;charset=utf-8
Accept application/json;charset=utf-8
作者 east
Java 11月 8,2020

GAT1400视图库注册保活注销

注册、保活、注销

如果现场环境开启了注册认证机制,则需要关注本小节内容。

注册

视图库API的访问,需要进行身份验证,身份信息放在请求头部参数User-Identify,即一个新请求方的访问需要向视图库进行注册,注册成功后,才能进行后续操作。注册流程如下:

注意:在上面流程图中对接程序向视图库发起的两次请求中,请求体都应该为key为DeviceID,value为对应发起方系统的标识ID的JSON字符串,例:{“RegisterObject”:{“DeviceID”:”33010299011190000253″}},注册成功后,每次请求需添加请求头部参数User-Identify,值为DeviceID的value(33010299011190000253),详情参考接口注册。

保活

注册成功后,会有一定的有效期(一般为5分钟),在有效期内,如果没有接收到新的请求,注册信息将会失效,下次访问将需要重新注册;当然任何形式的成功请求,都能触发保活机制,重置有效期。

注销

当请求方无需和视图库进行通信时,可以请求注销接口,撤销注册消息。

注册

1.接口概览

URI /VIID/System/Register
方法 查询字符串 消息体 返回结果
POST 无 <Register> <ResponseStatus>
备注  

2.消息体特征参数

消息体结构参考C.26,字段定义参考A.27 。

3.返回结果

结构参考C.25,字段定义参考A.26。

4.示例

URI /VIID/System/Register
请求方法 POST
请求头 参见请求参数 其他请求头参照注册流程图
请求体 {“RegisterObject”:{“DeviceID”:”33010299011190000253″}}
响应体 {     “ResponseStatusObject”: {             “RequestURL”: “http://localhost:8080/VIID/Register”,             “StatusCode”: 0,             “StatusString”: “正常”,             “Id”: “33010299011190000253”,             “LocalTime”: “20171220204451”     } }

注销

1.接口概览

URI /VIID/System/UnRegister
方法 查询字符串 消息体 返回结果
POST 无 <Register> <ResponseStatus>
备注  

2.消息体特征参数

消息体结构参考C.28,字段定义参考A.29 。

3.返回结果

结构参考C.25,字段定义参考A.26。

4.示例

URI /VIID/System/UnRegister
请求方法 POST
请求头 参见请求参数
请求体 {“DeviceID”:”33010299011190000253″}
响应体 {     “ResponseStatusObject”: [         {             “RequestURL”: “http://localhost:8080/VIID/UnRegister”,             “StatusCode”: 0,             “StatusString”: “正常”,             “Id”: “33010299011190000253”,             “LocalTime”: “20171220204451”         }     ] }

保活

1.接口概览

URI /VIID/System/Keepalive
方法 查询字符串 消息体 返回结果
POST 无 < Keepalive > <ResponseStatus>
备注  

2.消息体特征参数

消息体结构参考C.27,字段定义参考A.28 。

3.返回结果

结构参考C.25,字段定义参考A.26。

4.示例

URI /VIID/System/Keepalive
请求方法 POST
请求头 参见请求参数
请求体 {“DeviceID”:”33010299011190000253″}
响应体 {     “ResponseStatusObject”: [         {             “RequestURL”: “http://localhost:8080/VIID/Keepalive”,             “StatusCode”: 0,             “StatusString”: “正常”,             “Id”: “33010299011190000253”,             “LocalTime”: “20171220204451”         }     ] }

C.25 应答状态对象

//应答状态对象

<complexType name=”ResponseStatus”>

<sequence>

<element name=”RequestURL” type=”string ” use=”required”/>

<element name=”StatusCode” type=” int” use=”required”/>

<element name=”StatusString” type=”string” />

<element name=”Id” type=”string” minOccurs=”0″ maxOccurs=”1″/>

<element name=”LocalTime” type=”dateTime” minOccurs=”0″ maxOccurs=”1″/>

</sequence>

</ complexType>

//应答状态对象列表

<complexType name=”ResponseStatusList”>

<sequence>

<element name=”ResponseStatusObject” type=”ResponseStatus” minOccurs=”1″ />

</sequence>

</complexType>

C.26 注册对象

//注册对象

<complexType name=”Register”>

<sequence>

<element name=”DeviceID” type=”DeviceIDType” use=”required”/>

</sequence>

</ complexType>

C.27 保活对象

//保活对象

<complexType name=”Keepalive”>

<sequence>

<element name=”DeviceID” type=”DeviceIDType” use=”required”/>

</sequence>

</complexType>

C.28 注销对象

//注销对象

<complexType name=”UnRegister “>

<sequence>

<element name=”DeviceID” type=”DeviceIDType” use=”required”/>

</sequence>

</ complexType>

作者 east
Java, spring 6月 26,2020

Mysql 查询今天、昨天、前天的sql语句

查询今天的
SELECT * FROM t_table WHERE TO_DAYS(CREATE_TIME) = TO_DAYS(NOW())

查询昨天的
SELECT * FROM t_table WHERE TO_DAYS(NOW()) - TO_DAYS(CREATE_TIME) = 1


查询前天天的
SELECT * FROM t_table WHERE TO_DAYS(NOW()) - TO_DAYS(CREATE_TIME) = 1
作者 east
Java 6月 25,2020

shardingsphere 4.0的2种配置格式

首先配置pom.xml


        <!-- shardingsphere最新版本 -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.0.0-RC1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-namespace</artifactId>
            <version>4.0.0-RC1</version>
        </dependency>

yml格式只分表,不分库的写法

Spring:
  shardingsphere:
    datasource:
      names: master
      master:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://197.1.26.138:53306/test?serverTimezone=Asia/Shanghai&useSSL=false&allowMultiQueries=true
        username: root
        password: root
#数据分表规则
#指定所需分的表
    sharding:
      tables:
        test_user:
          actual-data-nodes: master.test_user$->{0..2}
          table-strategy:
            inline:
              sharding-column: night_id
              algorithm-expression: test_user$->{night_id % 3}
    props:
      sql:
        show: false

properties分库分表的写法


#指定mybatis信息
mybatis.config-location=classpath:mybatis-config.xml

#数据库
spring.shardingsphere.datasource.names=master0,slave0

spring.shardingsphere.datasource.master0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.master0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master0.url=jdbc:mysql://localhost:3306/master?characterEncoding=utf-8
spring.shardingsphere.datasource.master0.username=root
spring.shardingsphere.datasource.master0.password=123456

spring.shardingsphere.datasource.slave0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave0.url=jdbc:mysql://localhost:3306/slave?characterEncoding=utf-8
spring.shardingsphere.datasource.slave0.username=root
spring.shardingsphere.datasource.slave0.password=root

#数据分表规则
#指定所需分的表
spring.shardingsphere.sharding.tables.tab_user.actual-data-nodes=master0.tab_user$->{0..1}
#指定主键
spring.shardingsphere.sharding.tables.tab_user.table-strategy.inline.sharding-column=id
#分表规则为主键除以2取模
spring.shardingsphere.sharding.tables.tab_user.table-strategy.inline.algorithm-expression=tab_user$->{id % 2}

# 读写分离
spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
spring.shardingsphere.masterslave.name=ms
#这里配置读写分离的时候一定要记得添加主库的数据源名称 这里为master0
spring.shardingsphere.sharding.master-slave-rules.master0.master-data-source-name=master0
spring.shardingsphere.sharding.master-slave-rules.master0.slave-data-source-names=slave0

#打印sql
spring.shardingsphere.props.sql.show=true
作者 east
Java 6月 10,2020

千万级别数据实时复杂统计效率优化

有个业务需求:千万级别数据,要根据位置、白天出现时间、晚上不出现时间,出现次数大于某个范围的复杂组合统计。

mysql在千万级别的数据时,查询效率就有明细的下降。而时间数据从上千万级上升到上亿级,查询效率很慢,等待很久。

除了加索引等常规优化,想到用
shardingsphere 来分库分表,调研之后,发现
shardingsphere 不支持having等统计查询,对子查询支持也不是非常友好。后来发现这些数据,大部分数据其实是很难用到到,因为业务要统计大于多少次的,并按次数倒序,于是把那些出现次数少的进行删除,数据一下降到百万级别的,查询效率明细提升。

优化不光是考虑技术上的,一些技术难做到的,还要结合业务进行优化。

作者 east
Java, spring 5月 31,2020

分库分表利器sharding-sphere入门学习资料


当mysql达到单表1千万数据以上时,性能就下降得厉害,添加索引等方式还是不能根本解决问题,需要进行分库分表。sharding-sphere是开源的分布式数据库中间件解决方案 ,只需要开发人员像添加普通jar依赖一样添加依赖,不需要运维人员额外配置。是一个轻量级、性能较好的解决方案。但sharding-sphere学习资料较少,下面推荐一下入门学习资料。

学习视频https://www.bilibili.com/video/BV1rJ411n7QH

官网

官网是必须要学习的一手材料。

http://shardingjdbc.io/

Github

https://github.com/sharding-sphere

很好入门例子:https://github.com/yudiandemingzi/spring-boot-sharding-sphere

作者 east
Java 5月 30,2020

springboot如何多线程异步执行定时任务

 在后台开发时,经常需要执行后台任务,相比使用quartz等复杂定时框架,使用springboot自带定时框架,能简单轻松满足大部分定时任务。

工具/原料

  • 已经配置好springboot依赖

方法/步骤

  1. 创建一个后台定时任务的类,并标明@Component标注。创建一个普通方式,加上@Scheduled标注,例如:@Scheduled(cron = “0 27 10 * * ?”)

2.在Scheduled标注加上cron的定时标注。cron的6或7个字段从前到后对应的是: 秒 分钟 小时 日期 月份 星期 年例如:要每天10点27分执行   @Scheduled(cron = “0 27 10 * * ?”)每小时执行1次            @Scheduled(cron = “0 0 0/1 * * ?”)


3.在启动类BootApplication添加@EnableScheduling标注,这时定时任务就可以执行了。完成了上面3步,如果有多个定时任务,这时是串行的,只有前面1个定时任务执行完,后面的定时任务才能执行。要异步执行,首先在在启动类BootApplication添加@EnableAsync标注

4.在定时任务执行方法上添加@Async标注

5.添加多线程配置类,设置线程池并发个数等。


@Configuration
@EnableAsync
public class SpringAsycConfigurer implements AsyncConfigurer {

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(12);
executor.setMaxPoolSize(20);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds( 60 * 15);
executor.setThreadNamePrefix("MyAsync-");
executor.initialize();
return executor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
作者 east
bug清单, Java, spring 5月 24,2020

MyBaits 无法打印sql,日志冲突解决

springboot的mybatis之前能打印出日志,后来一直没打印,不方便调试。刚开始以为是设置问题,但application.yml已经设置开启了。

logging:
level:
com:
xxx:
xxx:
mapper: debug

后来怀疑是加入了别的日志jar包,日志冲突。然后搜索这方面关键字找到解决方案。

对于不同日志框架:SLF4J、 Apache Commons Logging、 Log4j 2、 Log4j
JDK logging 具体选择哪个日志实现由MyBatis的内置日志工厂确定。它会使用最先找到的(按上文列举的顺序查找)。 如果一个都未找到,日志功能就会被禁用。
因此当您的maven工程中引入了SLF4J-API和Log4J, 而您使用Log4j.properties进行日志配置时,便无法打印sql语句到控制台,按照优先级他会先选择使用SLF4J





<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.6</version>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
</dependency>
<!-- 添加该jar, 解决MyBaits 无法打印sql语句到控制台, -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.6</version>
</dependency>

然后修改log4j.properties


###显示SQL语句部分
# MyBatis logging configuration...
log4j.logger.cn.com.softvan.cms.dao=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
### mybatis loggers ###
log4j.logger.com.ibatis=DEBUG,stdout
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG,stdout
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG,stdout
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG,stdout
# sql loggers
log4j.logger.java.sql.Connection=DEBUG,stdout
log4j.logger.java.sql.Statement=DEBUG,stdout
log4j.logger.java.sql.PreparedStatement=DEBUG,stdout
log4j.logger.java.sql.ResultSet=DEBUG,stdout

log4j.logger.cn.com.softvan.cms.dao=TRACE 这句一定要加 不然无法打印SQL,其它的自己看情况简化

cn.com.softvan.cms.dao为包路径

作者 east
Java 4月 24,2020

空间几何运算方法

private static final Logger logger = LoggerFactory.getLogger(AnalyseKit.class);
/***************************************************************************
* 边界
*/
private static final double dis = 0.0000000001;
// 地图常量
public final static double _C_P = 0.017453292519943295;
// 地球经纬度, 偏差度
public final static double EARTH_RADIUS = 6371008.77141506;
// 单位经度
public static final long LONGITUDE_METER = 111413;
// 单位纬度
public static final long LATITUDE_METER = 111133;

/**
* 求亮点之间的距离
*
* @param str 坐标1
* @param str2 坐标2
* @return
*/
public static double getDistance(String str, String str2) {

PointBean point1 = new PointBean();
point1.setX(Double.parseDouble(str.split(",")[0]));
point1.setY(Double.parseDouble(str.split(",")[1]));

PointBean point2 = new PointBean();
point2.setX(Double.parseDouble(str2.split(",")[0]));
point2.setY(Double.parseDouble(str2.split(",")[1]));

double meter = getDistance(point1, point2);
return meter;
}

/**
* 计算点是否在圆内
*
* @param point 点坐标
* @param pointPolygon 面边框坐标
* @return
*/
public static boolean judgeMeetCircle(String point, String criclePoint, float r) {
PointBean point1 = new PointBean();
point1.setX(Double.parseDouble(point.split(",")[0]));
point1.setY(Double.parseDouble(point.split(",")[1]));

PointBean point2 = new PointBean();
point2.setX(Double.parseDouble(criclePoint.split(",")[0]));
point2.setY(Double.parseDouble(criclePoint.split(",")[1]));

double d = getDistance(point1, point2);
if (d <= r)
return true;
else
return false;

}

/**
* 判断是否在矩形内
*
* @param minPt
* @param maxPt
* @param pt
* @return
*/
public static boolean judgeInRect(PointBean minPt, PointBean maxPt, PointBean pt) {
if (pt.getX() >= minPt.getX() && pt.getX() <= maxPt.getX() && pt.getY() >= minPt.getY()
&& pt.getY() <= maxPt.getY()) {
return true;
} else {
return false;
}
}

/**
* 计算点是否在多边形内
*
* @param point 点坐标
* @param pointPolygon 面边框坐标
* @return
*/
public static boolean judgeMeetPolygon(String linestr, String pointPolygon) {
String string = pointPolygon;
int index = 0;
// 判断是否是飞地
if (string.indexOf(";") != -1) {
String[] points = string.split(";");
for (String point : points) {
if (AnalyseKit.judgeMeetPoint(linestr, point)) {
return true;
} else {
index++;
}
}
return (index == 0 || index > 1) ? false : true;
} else if (string.indexOf("|") != -1) {// 判断是否是有洞
String[] points = string.split("|");
for (String point : points) {
if (AnalyseKit.judgeMeetPoint(linestr, point))
index++;
}
return (index == 0 || index > 1) ? false : true;
} else {
return AnalyseKit.judgeMeetPoint(linestr, string);
}
}

// #################################私有方法#################################
private static boolean judgeMeetPoint(String point, String pointPolygon) {
PointBean point2 = new PointBean();
point2.setX(Double.parseDouble(point.split(",")[0]));
point2.setY(Double.parseDouble(point.split(",")[1]));
List<PointBean> list = AnalyseKit.evalPoints(pointPolygon);
if (list.size() == 2) {
return AnalyseKit.judgeInRect(list.get(0), list.get(1), point2);
} else {
return AnalyseKit.judgeMeetPoint(point2, list);
}
}

/**
* 转换坐标串
*
* @param points
* @return
*/
private static List<PointBean> evalPoints(String points) {
List<PointBean> list = new ArrayList<PointBean>();
String[] split = points.split(",");
for (int i = 1; i < split.length; i++) {
if (i % 2 == 1) {
PointBean point3 = new PointBean();
point3.setX(Double.parseDouble(split[i - 1]));
point3.setY(Double.parseDouble(split[i]));
list.add(point3);
}
}
return list;
}

/**
* 判断点是否在面内的算法
*
* @param tpt 点坐标
* @param polygonPtArray 面外边框坐标集合
* @return
*/
private static boolean judgeMeetPoint(PointBean tpt, List<PointBean> polygonPtArray) {
int MeetPointNum = 0;
for (int i = 1; i < polygonPtArray.size(); i++) {
PointBean pt1 = polygonPtArray.get(i - 1);
PointBean pt2 = polygonPtArray.get(i);
if (((tpt.getX() <= pt1.getX() && tpt.getX() >= pt2.getX())
|| (tpt.getX() >= pt1.getX() && tpt.getX() <= pt2.getX()))
& (tpt.getY() >= pt1.getY() || tpt.getY() >= pt2.getY())
& (pt1.getX() != pt2.getX() && pt1.getY() != pt2.getY())) {
// 判断点是否在线上
if (judgePtInLine(pt1, pt2, tpt)) {
return true;
}
// 处理特殊情况,交点是端点的情况
double temp;
// temp相当于被除数(斜率的分母)
temp = pt1.getX() - pt2.getX();
if (temp >= -dis && temp <= dis) {
// 处理交点情况
double dx = tpt.getX() - pt1.getX();
if (dx >= -dis && dx <= dis) {
int[] indexs = new int[2];
indexs[0] = 0;
indexs[1] = 0;
getNotSame(polygonPtArray, i, indexs);
PointBean linePt1, linePt2;
linePt1 = polygonPtArray.get(indexs[0]);
linePt2 = polygonPtArray.get(indexs[1]);
if (i > indexs[0]) {
break;
} else {
i = indexs[0] + 1;
}
if (tpt.getY() > pt1.getY() && ((tpt.getX() >= linePt1.getX() && tpt.getX() <= linePt2.getX())
|| (tpt.getX() >= linePt2.getX() && tpt.getX() <= linePt1.getX())))
MeetPointNum++;
}

} else {
double kk, bb;
double MeetPtY, MeetPtX;
kk = (pt1.getY() - pt2.getY()) / (pt1.getX() - pt2.getX());
bb = pt1.getY() - kk * pt1.getX();
MeetPtY = kk * tpt.getX() + bb;
MeetPtX = tpt.getX();
// 处理特殊情况,交点是端点的情况
double dx, dy, dx2, dy2;
dx = MeetPtX - pt1.getX();
dy = MeetPtY - pt1.getY();
dx2 = MeetPtX - pt2.getX();
dy2 = MeetPtY - pt2.getY();
if ((dx >= -dis && dx <= dis && dy >= -dis && dy <= dis)) {
PointBean pt3;
if (i == 1) {
pt3 = polygonPtArray.get(polygonPtArray.size() - 2);
} else {
pt3 = polygonPtArray.get(i - 2);
}
// 提取交点的上下两点分别在垂线的两侧
if (tpt.getY() > MeetPtY && ((MeetPtX >= pt3.getY() && MeetPtX <= pt2.getX())
|| (MeetPtX >= pt2.getX() && MeetPtX <= pt3.getX())))
MeetPointNum++;
} else if (!(dx2 >= -dis && dx2 <= dis && dy2 >= -dis && dy2 <= dis)) {
if (tpt.getY() > MeetPtY) {
MeetPointNum++;
}
}
}
}
}
if (MeetPointNum % 2 == 1)
return true;
else
return false;
}

/**
* 判断点是否在线上
*
* @param tpt1
* @param tpt2
* @param tpt
* @return
*/
private static boolean judgePtInLine(PointBean tpt1, PointBean tpt2, PointBean tpt) {
double dx1 = getDistance(tpt1, tpt2);
double dx2 = getDistance(tpt, tpt1);
double dx3 = getDistance(tpt, tpt2);
double dx = dx3 + dx2 - dx1;
if (dx >= -dis && dx <= dis) {
return true;
}
return false;
}

private static double getDistance(PointBean p1, PointBean p2) {
double k = 0.0;
double h = (p2.x - p1.x) * _C_P;
double g = (p2.y - p1.y) * _C_P;
double f = Math.sin(0.5 * g) * Math.sin(0.5 * g)
+ Math.cos(p1.y * _C_P) * Math.cos(p2.y * _C_P) * (Math.sin(0.5 * h) * Math.sin(0.5 * h));

f = Math.abs(f);

if (f > 1) {
logger.info("不合法数据:" + f + ",P1:" + p1.toString() + ",P2:" + p2.toString());
return -1;
}
double m = 2 * Math.atan2(Math.sqrt(f), Math.sqrt(1 - f));
k = m * EARTH_RADIUS;
if (Math.abs(p2.x - p1.x) > 180 || Math.abs(p2.y - p1.y) > 180) {
k = 2 * Math.PI * EARTH_RADIUS - k;
}
k = Math.ceil(k);

int meter = (int) k;

return meter;
}

/**
* 在链表中获取x轴不相同的点
*
* @param pointArray
* @param index
* @param indexs
*/
private static void getNotSame(List<PointBean> pointArray, int index, int[] indexs) {
indexs[0] = indexs[1] = -1;
int size = pointArray.size();
PointBean buftpt, tpt;
tpt = pointArray.get(index);
for (int i = index; i < size; i++) {
buftpt = pointArray.get(i);
if (buftpt.getX() != tpt.getX()) {
indexs[0] = i;
break;
}
}
if (indexs[0] == -1) {
for (int i = 0; i < size; i++) {
buftpt = (PointBean) pointArray.get(i);
if (buftpt.getX() != tpt.getX()) {
indexs[0] = i;
break;
}
}
}
for (int j = index; j >= 0; j--) {
buftpt = (PointBean) pointArray.get(j);
if (buftpt.getX() != tpt.getX()) {
indexs[1] = j;
break;
}
}
if (indexs[1] == -1) {
for (int j = size - 1; j >= 0; j--) {
buftpt = pointArray.get(j);
if (buftpt.getX() != tpt.getX()) {
indexs[1] = j;
break;
}
}
}
}

/**
* 计算指定处的距离(米)换算为距离(度) ---纬度方向上
*
* @param distance 单位m
* @return 纬度方向上
*/
public static double lenToLat(double distance) {
return distance / LATITUDE_METER;
}

/**
* 计算指定处的距离(米)换算为距离(度) ---经度方向上
*
* @param distnace 单位m
* @param r 指定点的纬度值
* @return
*/
public static double lenToLong(double distnace, double degree) {
double dLatRaian = degree * Math.PI / 180;
return distnace / (LONGITUDE_METER * Math.cos(dLatRaian));
}
作者 east
Java 4月 24,2020

计算地图2点距离-地图工具类

private static final double DEF_PI = 3.14159265359;

private static final double DEF_2PI = 6.28318530712;

private static final double DEF_PI180 = 0.01745329252;

private static final double DEF_R = 6370693.5; // 地球半径

/**
* 利用勾股定理计算,适用两点距离很近的情况
*
* @param lon1 第一个坐标经度
* @param lat1 第一个坐标纬度
* @param lon2 第二个坐标经度
* @param lat2 第二个坐标纬度
* @return
*/
public static double getShortDistance(double lon1, double lat1, double lon2, double lat2) {
double ew1;
double ns1;
double ew2;
double ns2;

double dx;
double dy;
double dew;

double distance;
// 角度转换为弧度
ew1 = lon1 * DEF_PI180;
ns1 = lat1 * DEF_PI180;
ew2 = lon2 * DEF_PI180;
ns2 = lat2 * DEF_PI180;
// 经度差
dew = ew1 - ew2;
// 若跨东经和西经180度,进行调整
if (dew > DEF_PI) {
dew = DEF_2PI - dew;
} else if (dew < -DEF_PI) {
dew = DEF_2PI + dew;
}
dx = DEF_R * Math.cos(ns1) * dew; // 东西方向长度(在纬度圆上的投影长度)
dy = DEF_R * (ns1 - ns2); // 南北方向长度(在经度圆上的投影长度)
// 勾股定理求你斜边长
distance = Math.sqrt(dx * dx + dy * dy);
return distance;
}

/**
* 按标准的球面大圆劣弧长度计算,适用距离较远的情况
*
* @param lon1 第一个坐标经度
* @param lat1 第一个坐标纬度
* @param lon2 第二个坐标经度
* @param lat2 第二个坐标纬度
* @return
*/
public static double getLongDistance(double lon1, double lat1, double lon2, double lat2) {
double ew1;
double ns1;
double ew2;
double ns2;
double distance;
// 角度转换为弧度
ew1 = lon1 * DEF_PI180;
ns1 = lat1 * DEF_PI180;
ew2 = lon2 * DEF_PI180;
ns2 = lat2 * DEF_PI180;
// 求大圆劣弧与球心所夹的角(弧度)
distance = Math.sin(ns1) * Math.sin(ns2) + Math.cos(ns1) * Math.cos(ns2) * Math.cos(ew1 - ew2);
// 调整到[-1..1]范围内,避免溢出
if (distance > 1.0) {
distance = 1.0;
} else if (distance < -1.0) {
distance = -1.0;
}
// 求大圆劣弧长度
distance = DEF_R * Math.acos(distance);
return distance;
}
作者 east
Java 3月 2,2020

springboot导出excel工具类

try{
//捕获内存缓冲区的数据,转换为字节数组
ByteArrayOutputStream out = new ByteArrayOutputStream();
workbook.write(out);
//获取内存缓冲中的数据
byte[] content = out.toByteArray();
//将字节数据转化为输入流
InputStream in = new ByteArrayInputStream(content);
//通过调用reset()方法可以重新定位
response.reset();
//JSONP 解决跨域问题
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE,OPTIONS");
response.addHeader("Access-Control-Allow-Headers", "WWW-Authenticate,Authorization,Set-Cookie," +
"X-Requested-With,Accept-Version,Content-Length,Content-Type,Date,X-Api-Version,name");
response.addHeader("Access-Control-Allow-Credentials", "true");
// response.setContentType("application/octet-stream");
//如果文件名是英文名不需要加编码格式,如果是中文名需要添加"ios-8859-1"防止乱码
response.setHeader("Content-Disposition", "attachment;filename=" +
new String((fileName + ".xls").getBytes("gb2312"), "iso-8859-1"));
response.setHeader("Content-Length", "" + content.length);
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
ServletOutputStream outputStream = response.getOutputStream();
BufferedInputStream bis = new BufferedInputStream(in);
BufferedOutputStream bos = new BufferedOutputStream(outputStream);
byte[] buff = new byte[8192];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))){
bos.write(buff, 0, bytesRead);
}
bis.close();
bos.close();
outputStream.flush();
outputStream.close();

}catch (IOException ex){
ex.printStackTrace();
}
作者 east

上一 1 … 5 6

关注公众号“大模型全栈程序员”回复“小程序”获取1000个小程序打包源码。回复”chatgpt”获取免注册可用chatgpt。回复“大数据”获取多本大数据电子书

标签

AIGC AI创作 bert chatgpt github GPT-3 gpt3 GTP-3 hive mysql O2O tensorflow UI控件 不含后台 交流 共享经济 出行 图像 地图定位 外卖 多媒体 娱乐 小程序 布局 带后台完整项目 开源项目 搜索 支付 效率 教育 日历 机器学习 深度学习 物流 用户系统 电商 画图 画布(canvas) 社交 签到 联网 读书 资讯 阅读 预订

官方QQ群

小程序开发群:74052405

大数据开发群: 952493060

近期文章

  • 详解Python当中的pip常用命令
  • AUTOSAR如何在多个供应商交付的配置中避免ARXML不兼容?
  • C++thread pool(线程池)设计应关注哪些扩展性问题?
  • 各类MCAL(Microcontroller Abstraction Layer)如何与AUTOSAR工具链解耦?
  • 如何设计AUTOSAR中的“域控制器”以支持未来扩展?
  • C++ 中避免悬挂引用的企业策略有哪些?
  • 嵌入式电机:如何在低速和高负载状态下保持FOC(Field-Oriented Control)算法的电流控制稳定?
  • C++如何在插件式架构中使用反射实现模块隔离?
  • C++如何追踪内存泄漏(valgrind/ASan等)并定位到业务代码?
  • C++大型系统中如何组织头文件和依赖树?

文章归档

  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年1月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年7月
  • 2018年6月

分类目录

  • Android (73)
  • bug清单 (79)
  • C++ (34)
  • Fuchsia (15)
  • php (4)
  • python (43)
  • sklearn (1)
  • 云计算 (20)
  • 人工智能 (61)
    • chatgpt (21)
      • 提示词 (6)
    • Keras (1)
    • Tensorflow (3)
    • 大模型 (1)
    • 智能体 (4)
    • 深度学习 (14)
  • 储能 (44)
  • 前端 (4)
  • 大数据开发 (488)
    • CDH (6)
    • datax (4)
    • doris (30)
    • Elasticsearch (15)
    • Flink (78)
    • flume (7)
    • Hadoop (19)
    • Hbase (23)
    • Hive (40)
    • Impala (2)
    • Java (71)
    • Kafka (10)
    • neo4j (5)
    • shardingsphere (6)
    • solr (5)
    • Spark (99)
    • spring (11)
    • 数据仓库 (9)
    • 数据挖掘 (7)
    • 海豚调度器 (10)
    • 运维 (34)
      • Docker (3)
  • 小游戏代码 (1)
  • 小程序代码 (139)
    • O2O (16)
    • UI控件 (5)
    • 互联网类 (23)
    • 企业类 (6)
    • 地图定位 (9)
    • 多媒体 (6)
    • 工具类 (25)
    • 电商类 (22)
    • 社交 (7)
    • 行业软件 (7)
    • 资讯读书 (11)
  • 嵌入式 (70)
    • autosar (63)
    • RTOS (1)
    • 总线 (1)
  • 开发博客 (16)
    • Harmony (9)
  • 技术架构 (6)
  • 数据库 (32)
    • mongodb (1)
    • mysql (13)
    • pgsql (2)
    • redis (1)
    • tdengine (4)
  • 未分类 (6)
  • 程序员网赚 (20)
    • 广告联盟 (3)
    • 私域流量 (5)
    • 自媒体 (5)
  • 量化投资 (4)
  • 面试 (14)

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org

All Rights Reserved by Gitweixin.本站收集网友上传代码, 如有侵犯版权,请发邮件联系yiyuyos@gmail.com删除.