Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wj-datacenter-platform
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
jinan
wj-datacenter-platform
Commits
45271677
Commit
45271677
authored
Dec 15, 2023
by
hanbing
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
路口事件数据接入Redis
parent
12711daa
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
2530 additions
and
71 deletions
+2530
-71
RedisConfig.java
...rc/main/java/net/wanji/datacenter/config/RedisConfig.java
+126
-0
Constant.java
...src/main/java/net/wanji/datacenter/constant/Constant.java
+26
-0
EventAbnormalEnum.java
...java/net/wanji/datacenter/constant/EventAbnormalEnum.java
+419
-0
ConsumerHandler.java
...main/java/net/wanji/datacenter/kafka/ConsumerHandler.java
+71
-1
CrossEventDTO.java
...ain/java/net/wanji/datacenter/pojo/dto/CrossEventDTO.java
+47
-0
LanePeriodicDataProcessServiceImpl.java
...nter/service/impl/LanePeriodicDataProcessServiceImpl.java
+11
-4
RedisTask.java
...ce/src/main/java/net/wanji/datacenter/task/RedisTask.java
+39
-0
DateStyle.java
...ce/src/main/java/net/wanji/datacenter/util/DateStyle.java
+62
-0
DateUtils.java
...ce/src/main/java/net/wanji/datacenter/util/DateUtils.java
+1220
-0
FastJson2JsonRedisSerializer.java
...t/wanji/datacenter/util/FastJson2JsonRedisSerializer.java
+36
-0
RedisUtils.java
...e/src/main/java/net/wanji/datacenter/util/RedisUtils.java
+333
-0
application-local.yaml
...acenter-service/src/main/resources/application-local.yaml
+13
-1
VehicleGapTimeProcessFunction.java
...s/task/trajectory/func/VehicleGapTimeProcessFunction.java
+127
-65
No files found.
wj-datacenter-service/src/main/java/net/wanji/datacenter/config/RedisConfig.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
config
;
import
net.wanji.datacenter.util.FastJson2JsonRedisSerializer
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.cache.CacheManager
;
import
org.springframework.cache.annotation.CachingConfigurerSupport
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.data.redis.cache.RedisCacheConfiguration
;
import
org.springframework.data.redis.cache.RedisCacheManager
;
import
org.springframework.data.redis.cache.RedisCacheWriter
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
;
import
org.springframework.data.redis.serializer.RedisSerializer
;
import
org.springframework.data.redis.serializer.StringRedisSerializer
;
import
redis.clients.jedis.Jedis
;
import
redis.clients.jedis.JedisPool
;
import
redis.clients.jedis.JedisPoolConfig
;
@Configuration
@EnableAutoConfiguration
public
class
RedisConfig
extends
CachingConfigurerSupport
{
@Value
(
"${spring.redis.host}"
)
private
String
host
;
@Value
(
"${spring.redis.port}"
)
private
int
port
;
@Value
(
"${spring.redis.password}"
)
private
String
password
;
@Value
(
"${spring.redis.database}"
)
private
int
database
;
@Value
(
"${spring.redis.timeout}"
)
private
int
timeout
;
@Value
(
"${spring.redis.jedis.pool.max-idle}"
)
private
int
maxIdle
;
@Value
(
"${spring.redis.jedis.pool.max-active}"
)
private
int
maxTotal
;
@Value
(
"${spring.redis.jedis.pool.min-idle}"
)
private
int
minIdle
;
@Value
(
"${spring.redis.jedis.pool.max-wait}"
)
private
long
maxWaitMillis
;
/**
* 获取Jedis连接工厂
* <p>用于创建Jedis对象</p>
* @return JedisPool
*/
@Bean
public
JedisPool
redisPoolFactory
()
{
JedisPoolConfig
jedisPoolConfig
=
new
JedisPoolConfig
();
jedisPoolConfig
.
setMaxTotal
(
maxTotal
);
jedisPoolConfig
.
setMaxIdle
(
maxIdle
);
jedisPoolConfig
.
setMaxWaitMillis
(
maxWaitMillis
);
jedisPoolConfig
.
setMinIdle
(
minIdle
);
jedisPoolConfig
.
setTestOnBorrow
(
false
);
jedisPoolConfig
.
setTestOnReturn
(
false
);
return
new
JedisPool
(
jedisPoolConfig
,
host
,
port
,
timeout
,
password
,
database
);
}
/**
* retemplate相关配置
* @param factory
* @return
*/
@Bean
public
RedisTemplate
<
String
,
Object
>
redisTemplate
(
RedisConnectionFactory
factory
)
{
RedisTemplate
<
String
,
Object
>
template
=
new
RedisTemplate
<>();
// 配置连接工厂
template
.
setConnectionFactory
(
factory
);
//不开启事务
template
.
setEnableTransactionSupport
(
false
);
// 值采用json序列化value
template
.
setValueSerializer
(
fastJson2JsonRedisSerializer
());
//使用StringRedisSerializer来序列化和反序列化redis的key值
template
.
setKeySerializer
(
new
StringRedisSerializer
());
// 设置hash key 和value序列化模式
template
.
setHashKeySerializer
(
new
StringRedisSerializer
());
template
.
setHashValueSerializer
(
new
GenericJackson2JsonRedisSerializer
());
template
.
afterPropertiesSet
();
return
template
;
}
/**
* 选择redis作为默认缓存工具
* @param redisConnectionFactory
* @return
*/
@Bean
public
CacheManager
cacheManager
(
RedisConnectionFactory
redisConnectionFactory
)
{
RedisCacheConfiguration
redisCacheConfiguration
=
RedisCacheConfiguration
.
defaultCacheConfig
();
return
RedisCacheManager
.
builder
(
RedisCacheWriter
.
nonLockingRedisCacheWriter
(
redisConnectionFactory
))
.
cacheDefaults
(
redisCacheConfiguration
).
build
();
}
/**
* @description: 自定义Redis序列化类
* @date 2019/4/29 20:23
*/
@Bean
public
RedisSerializer
fastJson2JsonRedisSerializer
()
{
return
new
FastJson2JsonRedisSerializer
(
Object
.
class
);
}
@Value
(
"${spring.redis.host}"
)
private
String
redisHost
;
@Value
(
"${spring.redis.port}"
)
private
Integer
redisPort
;
@Bean
public
Jedis
jedis
()
{
Jedis
jedis
=
new
Jedis
(
redisHost
,
redisPort
);
jedis
.
auth
(
"Wanji300552"
);
return
jedis
;
}
}
\ No newline at end of file
wj-datacenter-service/src/main/java/net/wanji/datacenter/constant/Constant.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
constant
;
/**
* @author duanruiming
* @date 2023/01/16 10:45
*/
public
class
Constant
{
/**
* Redis存储Key前缀
*/
public
static
final
String
KEY_PREFIX
=
"utcsystem_"
;
/**
* 分隔符:减号
**/
public
static
final
String
SEPARATOR_MINUS
=
"-"
;
public
static
final
String
WEBSOCKET_TOPIC_EVENT_WARN
=
"eventWarn"
;
public
static
final
String
WEBSOCKET_TOPIC_SYS_SERVICE_STATUS
=
"sysStatus"
;
public
static
final
String
WEBSOCKET_TOPIC_CAR_TRAIL_INFO
=
"carTrailInfo"
;
// WebSocket自动解锁路口topic
public
static
final
String
WEBSOCKET_AUTO_UNLOCK
=
"autoUnlock"
;
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/constant/EventAbnormalEnum.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
constant
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Objects
;
/**
* @ClassName EventAbnormalEnum
* @Description
* @Date 2021/4/15 11:13
* @Version 1.0
*/
public
enum
EventAbnormalEnum
{
//机动车违停
ILLEGALSTOP
(
"1"
,
"机动车违停"
,
1
,
3
),
//非机动车逆行
NONMOTORETROGRADE
(
"2"
,
"非机动车逆行"
,
1
,
2
),
//机动车逆行
RETROGRADE
(
"3"
,
"机动车逆行"
,
1
,
2
),
//占用专用车道
OCCUPYEXCLUSIVELANE
(
"4"
,
"占用专用车道"
,
1
,
1
),
//行人在机动车道逗留
PEDESTRIANSTAYINVEHICLELANE
(
"5"
,
"行人在机动车道逗留"
,
1
,
1
),
//机动车超速
VEHICLEOVERSPEED
(
"6"
,
"机动车超速"
,
1
,
1
),
//非机动车超速
NONMOTOOVERSPEED
(
"7"
,
"非机动车超速"
,
1
,
1
),
//机动车慢行
VEHICLESLOW
(
"8"
,
"机动车慢行"
,
1
,
1
),
//机动车压线
VEHICLELINEPRESS
(
"9"
,
"机动车压线"
,
1
,
1
),
//非机动车横穿马路
NONMOTOCROSSROAD
(
"10"
,
"非机动车横穿马路"
,
1
,
1
),
//行人横穿马路
PEDESTRIANCROSSROAD
(
"11"
,
"行人横穿马路"
,
1
,
3
),
//机动车横穿马路
VEHICLECROSSROAD
(
"12"
,
"机动车横穿马路"
,
1
,
1
),
//机动车闯红灯
VEHICLERUNREDLIGHT
(
"13"
,
"机动车闯红灯"
,
0.5
,
2
),
//行人闯红灯
PEDESTRIANRUNREDLIGHT
(
"14"
,
"行人闯红灯"
,
1
,
2
),
//占用公交车道
OCCUPYBUSLANE
(
"15"
,
"占用公交车道"
,
0.5
,
2
),
//变道
CHANGELANE
(
"16"
,
"实线违规变道"
,
0.5
,
2
),
//遗撒物
LITTER
(
"17"
,
"遗撒物"
,
1
,
3
),
//交通事故
TRAFFICACCIDENT
(
"18"
,
"交通事故"
,
0.5
,
2
),
//占用应急车道
OCCUPYEMERGENCYLANE
(
"19"
,
"占用应急车道"
,
1
,
1
),
//隧道悬臂物
CANTILEVER
(
"20"
,
"隧道悬臂物"
,
1
,
1
),
//行人进入隧道
PEDESTRIANENTERTUNNEL
(
"21"
,
"行人进入隧道"
,
1
,
1
),
//非机动车进入隧道
NONMOTOENTERTUNNEL
(
"22"
,
"非机动车进入隧道"
,
1
,
1
),
//非机动车越线停车
NONMOTO_PARK_ON_LINE
(
"23"
,
"非机动车越线停车"
,
1
,
3
),
// 非机动车占用机动车道
NONMOTO_RUN_IN_OTHER_LINE
(
"24"
,
"非机动车占用机动车道"
,
1
,
2
),
// 非机动车闯红灯
NONMOTO_RUN_REDLIGHT
(
"25"
,
"非机动车闯红灯"
,
1
,
2
),
// 非机动车载人
NONMOTO_CARRY_PEOPLE
(
"26"
,
"非机动车载人"
,
1
,
1
),
// 机动车不按车道方向行驶
MOTO_RUN_WRONG_DIRECTION
(
"27"
,
"机动车不按车道方向行驶"
,
1
,
1
),
// 机动车占用非机动车道
MOTO_RUN_IN_OTHER_LINE
(
"28"
,
"机动车占用非机动车道"
,
1
,
2
),
// 机动车越线停车
MOTO_PARK_ON_LINE
(
"29"
,
"机动车越线停车"
,
0.5
,
2
),
// 施工
CONSTRUCTION
(
"30"
,
"施工"
,
1
,
3
),
// 机动车未礼让行人
MOTO_NO_YIEDLD_PEDESTRIAN
(
"31"
,
"机动车未礼让行人"
,
0.5
,
2
),
// 限号出行【大屏需求改为货车限行】
RESTRICTION_LICENSE_PLATE
(
"32"
,
"机动车限号出行"
,
0.5
,
2
),
RAPID_ACCELERATION
(
"33"
,
"急加速"
,
1
,
1
),
RAPID_DECELERATION
(
"34"
,
"急减速"
,
1
,
1
),
SHARP_TURN
(
"35"
,
"急转弯"
,
1
,
1
),
//能见度异常
ABNORMALVISIBILITY
(
"101"
,
"能见度异常"
,
1
,
1
),
//光强异常
ABNORMALLIGHT
(
"102"
,
"光强异常"
,
1
,
1
),
//CO异常
ABNORMALCO
(
"103"
,
"CO异常"
,
1
,
1
),
//火灾
FIR
(
"104"
,
"火灾"
,
1
,
1
),
// ***** 事故
ACCIDENT_YS
(
"401"
,
"疑似事故"
,
1
,
1
),
ACCIDENT_ONE_YS
(
"402"
,
"疑似单车事故"
,
1
,
1
),
ACCIDENT_TWO_YS
(
"403"
,
"疑似双车事故"
,
1
,
1
),
ACCIDENT_MORE_YS
(
"404"
,
"疑似多车事故"
,
1
,
1
),
// ***** 拥堵
NO_CONGEST
(
"501"
,
"畅通"
,
1
,
1
),
LIGHT_CONGEST
(
"502"
,
"轻微拥堵"
,
1
,
1
),
MODERATE_CONGEST
(
"503"
,
"中度拥堵"
,
1
,
1
),
HEAVY_CONGEST
(
"504"
,
"重度拥堵"
,
1
,
1
),
PHASE_EMPTY
(
"701"
,
"相位空放"
,
1
,
1
),
CROSS_UNBALANCE
(
"702"
,
"路口失衡"
,
1
,
1
),
CROSS_OVERFLOW
(
"703"
,
"路口溢出"
,
1
,
1
),
CROSS_DEADLOCK
(
"704"
,
"路口死锁"
,
1
,
1
),
/*危险驾驶*/
CONFLICT_POINT
(
"601"
,
"冲突点"
,
1
,
1
),
OVERFLOW_CONGESTION
(
"605"
,
"路口溢出"
,
1
,
1
),
ROADSEGMENT_U_TURN
(
"606"
,
"路段掉头"
,
1
,
1
),
DANGER_S_DRIVER
(
"607"
,
"危险驾驶-S形驾驶"
,
1
,
1
),
ABNORMAL_STOP_CAR
(
"608"
,
"异常停车"
,
1
,
1
)
;
public
final
static
double
step_default
=
1
;
String
type
;
String
desc
;
double
step_turn
;
// 转向时步长 s
double
step_noTurn
;
// 无转向时步长 s
EventAbnormalEnum
(
String
type
,
String
desc
,
double
step_turn
,
double
step_noTurn
)
{
this
.
type
=
type
;
this
.
desc
=
desc
;
this
.
step_turn
=
step_turn
;
this
.
step_noTurn
=
step_noTurn
;
//命令字
}
public
String
getType
(){
return
type
;
}
public
String
getDesc
()
{
return
desc
;
}
public
double
getStep_turn
()
{
return
step_turn
;
}
public
double
getStep_noTurn
()
{
return
step_noTurn
;
}
public
static
EventAbnormalEnum
getByType
(
String
type
){
for
(
EventAbnormalEnum
abnormalEnum
:
EventAbnormalEnum
.
values
())
{
if
(
abnormalEnum
.
getType
().
equals
(
type
)){
return
abnormalEnum
;
}
}
return
null
;
}
//隐患事件类型
public
static
final
List
<
EventAbnormalEnum
>
HiddenDangerEvents
=
Arrays
.
asList
(
new
EventAbnormalEnum
[]
{
EventAbnormalEnum
.
CONFLICT_POINT
,
EventAbnormalEnum
.
RAPID_ACCELERATION
,
EventAbnormalEnum
.
RAPID_DECELERATION
,
EventAbnormalEnum
.
SHARP_TURN
,
EventAbnormalEnum
.
OVERFLOW_CONGESTION
,
EventAbnormalEnum
.
ROADSEGMENT_U_TURN
,
EventAbnormalEnum
.
DANGER_S_DRIVER
,
EventAbnormalEnum
.
MOTO_NO_YIEDLD_PEDESTRIAN
,
EventAbnormalEnum
.
MOTO_RUN_WRONG_DIRECTION
,
EventAbnormalEnum
.
ABNORMAL_STOP_CAR
}
);
//违法事件类型
public
static
final
List
<
EventAbnormalEnum
>
IllegalEvents
=
Arrays
.
asList
(
new
EventAbnormalEnum
[]
{
EventAbnormalEnum
.
CHANGELANE
,
EventAbnormalEnum
.
ILLEGALSTOP
,
EventAbnormalEnum
.
VEHICLERUNREDLIGHT
,
EventAbnormalEnum
.
VEHICLEOVERSPEED
,
EventAbnormalEnum
.
RETROGRADE
}
);
//事故事件类型
public
static
final
List
<
EventAbnormalEnum
>
AccidentEvents
=
Arrays
.
asList
(
new
EventAbnormalEnum
[]
{
EventAbnormalEnum
.
ACCIDENT_ONE_YS
,
EventAbnormalEnum
.
ACCIDENT_TWO_YS
,
EventAbnormalEnum
.
ACCIDENT_MORE_YS
}
);
// 机动车事件
public
static
final
List
<
EventAbnormalEnum
>
VehicleEvents
=
Arrays
.
asList
(
new
EventAbnormalEnum
[]{
EventAbnormalEnum
.
ILLEGALSTOP
,
EventAbnormalEnum
.
RETROGRADE
,
EventAbnormalEnum
.
OCCUPYEXCLUSIVELANE
,
EventAbnormalEnum
.
VEHICLEOVERSPEED
,
EventAbnormalEnum
.
VEHICLESLOW
,
EventAbnormalEnum
.
VEHICLELINEPRESS
,
EventAbnormalEnum
.
VEHICLECROSSROAD
,
EventAbnormalEnum
.
VEHICLERUNREDLIGHT
,
EventAbnormalEnum
.
OCCUPYBUSLANE
,
EventAbnormalEnum
.
CHANGELANE
,
EventAbnormalEnum
.
OCCUPYEMERGENCYLANE
,
EventAbnormalEnum
.
MOTO_RUN_WRONG_DIRECTION
,
EventAbnormalEnum
.
MOTO_RUN_IN_OTHER_LINE
,
EventAbnormalEnum
.
MOTO_PARK_ON_LINE
,
EventAbnormalEnum
.
MOTO_NO_YIEDLD_PEDESTRIAN
,
EventAbnormalEnum
.
RESTRICTION_LICENSE_PLATE
,
EventAbnormalEnum
.
RAPID_ACCELERATION
,
EventAbnormalEnum
.
RAPID_DECELERATION
,
EventAbnormalEnum
.
SHARP_TURN
});
// 非机动车事件
public
static
final
List
<
EventAbnormalEnum
>
NonVehicleEvents
=
Arrays
.
asList
(
new
EventAbnormalEnum
[]{
EventAbnormalEnum
.
NONMOTORETROGRADE
,
EventAbnormalEnum
.
NONMOTOOVERSPEED
,
EventAbnormalEnum
.
NONMOTOCROSSROAD
,
EventAbnormalEnum
.
NONMOTOENTERTUNNEL
,
EventAbnormalEnum
.
NONMOTO_PARK_ON_LINE
,
EventAbnormalEnum
.
NONMOTO_RUN_IN_OTHER_LINE
,
EventAbnormalEnum
.
NONMOTO_RUN_REDLIGHT
,
EventAbnormalEnum
.
NONMOTO_CARRY_PEOPLE
});
// 行人事件
public
static
final
List
<
EventAbnormalEnum
>
PedestrianentEvents
=
Arrays
.
asList
(
new
EventAbnormalEnum
[]{
EventAbnormalEnum
.
PEDESTRIANSTAYINVEHICLELANE
,
EventAbnormalEnum
.
PEDESTRIANCROSSROAD
,
EventAbnormalEnum
.
PEDESTRIANRUNREDLIGHT
,
EventAbnormalEnum
.
PEDESTRIANENTERTUNNEL
});
// 拥堵事件
public
static
final
List
<
EventAbnormalEnum
>
CongestionEvents
=
Arrays
.
asList
(
new
EventAbnormalEnum
[]{
EventAbnormalEnum
.
NO_CONGEST
,
EventAbnormalEnum
.
LIGHT_CONGEST
,
EventAbnormalEnum
.
MODERATE_CONGEST
,
EventAbnormalEnum
.
HEAVY_CONGEST
});
/**
* 是否为 机动车事件
* @param type 车辆类型
* @return
*/
public
static
boolean
isVehicleEvent
(
String
type
){
return
VehicleEvents
.
stream
().
anyMatch
(
event
->
event
.
getType
().
equals
(
type
));
}
/**
* 是否为 机动车闯红灯
* @param type 车辆类型
* @return
*/
public
static
boolean
isVehicleEvent_runRedlight
(
String
type
){
return
EventAbnormalEnum
.
VEHICLERUNREDLIGHT
.
type
.
equals
(
type
);
}
/**
* 是否为 机动车越线停车
* @param type 车辆类型
* @return
*/
public
static
boolean
isVehicleEvent_parkOnLine
(
String
type
){
return
EventAbnormalEnum
.
MOTO_PARK_ON_LINE
.
type
.
equals
(
type
);
}
/**
* 是否为 机动车不按车道方向行驶
* @param type 车辆类型
* @return
*/
public
static
boolean
isVehicleEvent_runWrongDirection
(
String
type
){
return
EventAbnormalEnum
.
MOTO_RUN_WRONG_DIRECTION
.
type
.
equals
(
type
);
}
/**
* 是否为 机动车占用非机动车道
* @param type 车辆类型
* @return
*/
public
static
boolean
isVehicleEvent_runInOtherLine
(
String
type
){
return
EventAbnormalEnum
.
MOTO_RUN_IN_OTHER_LINE
.
type
.
equals
(
type
);
}
/**
* 是否为 机动车未礼让行人
* @param type 车辆类型
* @return
*/
public
static
boolean
isVehicleEvent_NoYiedldPedestrian
(
String
type
){
return
EventAbnormalEnum
.
MOTO_NO_YIEDLD_PEDESTRIAN
.
type
.
equals
(
type
);
}
/**
* 是否为 非机动车事件
* @param type 车辆类型
* @return
*/
public
static
boolean
isNonVehicleEvent
(
String
type
){
return
NonVehicleEvents
.
stream
().
anyMatch
(
event
->
event
.
getType
().
equals
(
type
));
}
/**
* 是否为 非机动车闯红灯
* @param type 车辆类型
* @return
*/
public
static
boolean
isNonVehicleEvent_runRedlight
(
String
type
){
return
EventAbnormalEnum
.
NONMOTO_RUN_REDLIGHT
.
type
.
equals
(
type
);
}
/**
* 是否为 非机动车逆行
* @param type 车辆类型
* @return
*/
public
static
boolean
isNonVehicleEvent_retrograde
(
String
type
){
return
EventAbnormalEnum
.
NONMOTORETROGRADE
.
type
.
equals
(
type
);
}
/**
* 是否为 非机动车占用机动车道
* @param type 车辆类型
* @return
*/
public
static
boolean
isNonVehicleEvent_runInOtherLine
(
String
type
){
return
EventAbnormalEnum
.
NONMOTO_RUN_IN_OTHER_LINE
.
type
.
equals
(
type
);
}
/**
* 是否为 非机动车越线停车
* @param type 车辆类型
* @return
*/
public
static
boolean
isNonVehicleEvent_parkOnLine
(
String
type
){
return
EventAbnormalEnum
.
NONMOTO_PARK_ON_LINE
.
type
.
equals
(
type
);
}
/**
* 是否为 非机动车违规载人
* @param type 车辆类型
* @return
*/
public
static
boolean
isNonVehicleEvent_carryPeople
(
String
type
){
return
EventAbnormalEnum
.
NONMOTO_CARRY_PEOPLE
.
type
.
equals
(
type
);
}
/**
* 是否为 行人事件
* @param type 车辆类型
* @return
*/
public
static
boolean
isPedestrianentEvent
(
String
type
){
return
PedestrianentEvents
.
stream
().
anyMatch
(
event
->
event
.
getType
().
equals
(
type
));
}
/**
* 是否为 行人闯红灯
* @param type 车辆类型
* @return
*/
public
static
boolean
isPedestrianentEvent_runRedlight
(
String
type
){
return
EventAbnormalEnum
.
PEDESTRIANRUNREDLIGHT
.
type
.
equals
(
type
);
}
/**
* 是否为 行人横穿马路
* @param type 车辆类型
* @return
*/
public
static
boolean
isPedestrianentEvent_crossroad
(
String
type
){
return
EventAbnormalEnum
.
PEDESTRIANCROSSROAD
.
type
.
equals
(
type
);
}
/**
* 是否为 事故
* @return
*/
public
static
boolean
isAccidentEvent
(
String
type
){
return
EventAbnormalEnum
.
ACCIDENT_YS
.
type
.
equals
(
type
);
}
/**
* 是否为 拥堵
* @return
*/
public
static
boolean
isCongestionEvent
(
String
type
){
return
CongestionEvents
.
stream
().
anyMatch
(
event
->
event
.
getType
().
equals
(
type
));
}
//事件子类型
public
static
List
<
String
>
getEventTypeList
(
String
eventCategory
)
{
List
<
EventAbnormalEnum
>
enumList
=
new
ArrayList
<>();
if
(
Objects
.
equals
(
"4"
,
eventCategory
))
{
enumList
=
EventAbnormalEnum
.
AccidentEvents
;
}
else
if
(
Objects
.
equals
(
"6"
,
eventCategory
))
{
enumList
=
EventAbnormalEnum
.
HiddenDangerEvents
;
}
else
if
(
Objects
.
equals
(
"7"
,
eventCategory
))
{
enumList
=
EventAbnormalEnum
.
IllegalEvents
;
}
else
{
enumList
.
addAll
(
EventAbnormalEnum
.
AccidentEvents
);
enumList
.
addAll
(
EventAbnormalEnum
.
HiddenDangerEvents
);
enumList
.
addAll
(
EventAbnormalEnum
.
IllegalEvents
);
}
List
<
String
>
list
=
new
ArrayList
<>();
for
(
EventAbnormalEnum
eventEnum
:
enumList
)
{
list
.
add
(
eventEnum
.
getType
());
}
return
list
;
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/kafka/ConsumerHandler.java
View file @
45271677
package
net
.
wanji
.
datacenter
.
kafka
;
package
net
.
wanji
.
datacenter
.
kafka
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
lombok.NonNull
;
import
lombok.NonNull
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
net.wanji.common.utils.tool.JacksonUtils
;
import
net.wanji.datacenter.constant.EventAbnormalEnum
;
import
net.wanji.datacenter.pojo.dto.CrossEventDTO
;
import
net.wanji.datacenter.pojo.dto.CrossLaneSnapshotDataDTO
;
import
net.wanji.datacenter.pojo.dto.CrossLaneSnapshotDataDTO
;
import
net.wanji.datacenter.pojo.dto.CrossSnapshotDataDTO
;
import
net.wanji.datacenter.pojo.dto.CrossSnapshotDataDTO
;
import
net.wanji.datacenter.service.DataProcessService
;
import
net.wanji.datacenter.service.DataProcessService
;
import
net.wanji.datacenter.util.RedisUtils
;
import
org.apache.kafka.clients.consumer.Consumer
;
import
org.apache.kafka.clients.consumer.Consumer
;
import
org.apache.kafka.clients.consumer.ConsumerRecord
;
import
org.apache.kafka.clients.consumer.ConsumerRecord
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.kafka.annotation.KafkaListener
;
import
org.springframework.kafka.annotation.KafkaListener
;
import
org.springframework.kafka.listener.KafkaListenerErrorHandler
;
import
org.springframework.kafka.listener.KafkaListenerErrorHandler
;
import
org.springframework.kafka.listener.ListenerExecutionFailedException
;
import
org.springframework.kafka.listener.ListenerExecutionFailedException
;
...
@@ -19,6 +25,7 @@ import javax.annotation.Resource;
...
@@ -19,6 +25,7 @@ import javax.annotation.Resource;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
/**
...
@@ -29,6 +36,8 @@ import java.util.concurrent.ConcurrentHashMap;
...
@@ -29,6 +36,8 @@ import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Slf4j
public
class
ConsumerHandler
implements
KafkaListenerErrorHandler
{
public
class
ConsumerHandler
implements
KafkaListenerErrorHandler
{
// Redis缓存过期时间
public
static
final
int
TTL_IN_MILLIS
=
10
*
60
*
1000
;
@Resource
(
name
=
"lanePeriodicDataProcessService"
)
@Resource
(
name
=
"lanePeriodicDataProcessService"
)
DataProcessService
lanePeriodicDataProcessService
;
DataProcessService
lanePeriodicDataProcessService
;
@Resource
(
name
=
"crossSnapshotDataProcessService"
)
@Resource
(
name
=
"crossSnapshotDataProcessService"
)
...
@@ -36,10 +45,13 @@ public class ConsumerHandler implements KafkaListenerErrorHandler {
...
@@ -36,10 +45,13 @@ public class ConsumerHandler implements KafkaListenerErrorHandler {
@Resource
(
name
=
"laneSnapshotDataProcessService"
)
@Resource
(
name
=
"laneSnapshotDataProcessService"
)
DataProcessService
laneSnapshotDataProcessService
;
DataProcessService
laneSnapshotDataProcessService
;
@Autowired
RedisUtils
redisUtils
;
public
static
final
Map
<
String
,
List
<
CrossSnapshotDataDTO
>>
crossSnapshotDataMap
=
new
ConcurrentHashMap
<>();
public
static
final
Map
<
String
,
List
<
CrossSnapshotDataDTO
>>
crossSnapshotDataMap
=
new
ConcurrentHashMap
<>();
@KafkaListener
(
topics
=
{
"JN050001LanePeriodicData"
},
groupId
=
"group"
)
@KafkaListener
(
topics
=
{
"JN050001LanePeriodicData"
},
groupId
=
"group"
)
public
void
receiveLanePeriodicData
(
ConsumerRecord
<
Object
,
Object
>
record
,
Acknowledgment
acknowledgment
)
throws
Exception
{
public
void
receiveLanePeriodicData
(
ConsumerRecord
<
Object
,
Object
>
record
,
Acknowledgment
acknowledgment
)
throws
Exception
{
Object
convert
=
lanePeriodicDataProcessService
.
convert
(
String
.
valueOf
(
record
.
value
()));
Object
convert
=
lanePeriodicDataProcessService
.
convert
(
String
.
valueOf
(
record
.
value
()));
// 修改逻辑,将保存逻辑改为将方向,转向数据返回kafka
// 修改逻辑,将保存逻辑改为将方向,转向数据返回kafka
lanePeriodicDataProcessService
.
save
(
convert
);
lanePeriodicDataProcessService
.
save
(
convert
);
...
@@ -77,6 +89,64 @@ public class ConsumerHandler implements KafkaListenerErrorHandler {
...
@@ -77,6 +89,64 @@ public class ConsumerHandler implements KafkaListenerErrorHandler {
acknowledgment
.
acknowledge
();
acknowledgment
.
acknowledge
();
}
}
@KafkaListener
(
topics
=
{
"cross.event.index"
},
groupId
=
"group2"
)
public
void
receiveCrossEventData
(
ConsumerRecord
<
Object
,
Object
>
record
,
Acknowledgment
acknowledgment
)
throws
Exception
{
try
{
ObjectMapper
objectMapper
=
new
ObjectMapper
();
String
recordStr
=
String
.
valueOf
(
record
.
value
());
CrossEventDTO
crossEventDTO
=
JacksonUtils
.
getInstance
().
readValue
(
recordStr
,
CrossEventDTO
.
class
);
String
msgType
=
crossEventDTO
.
getMsgType
();
String
crossId
=
crossEventDTO
.
getCrossId
();
if
(
Objects
.
equals
(
msgType
,
EventAbnormalEnum
.
CROSS_UNBALANCE
.
getType
()))
{
String
redisListElement
=
objectMapper
.
writeValueAsString
(
crossEventDTO
);
// 失衡事件
// 方向缓存
Integer
unbalanceDir
=
crossEventDTO
.
getUnbalanceDir
();
String
redisKey
=
crossId
+
":"
+
unbalanceDir
;
redisUtils
.
addToSortedSetWithExpiry
(
redisKey
,
redisListElement
,
TTL_IN_MILLIS
);
// 路口缓存
redisUtils
.
addToSortedSetWithExpiry
(
crossId
,
redisListElement
,
TTL_IN_MILLIS
);
}
else
if
(
msgType
.
startsWith
(
"50"
))
{
// 拥堵事件
// 方向缓存
List
<
CrossEventDTO
>
details
=
crossEventDTO
.
getDetails
();
for
(
CrossEventDTO
detail
:
details
)
{
detail
.
setMsgType
(
detail
.
getCongestionCode
());
Integer
dir
=
detail
.
getDir
();
String
redisKey
=
crossId
+
":"
+
dir
;
String
redisListElement
=
objectMapper
.
writeValueAsString
(
detail
);
redisUtils
.
addToSortedSetWithExpiry
(
redisKey
,
redisListElement
,
TTL_IN_MILLIS
);
}
// 路口缓存
String
redisListElement
=
objectMapper
.
writeValueAsString
(
crossEventDTO
);
redisUtils
.
addToSortedSetWithExpiry
(
crossId
,
redisListElement
,
TTL_IN_MILLIS
);
}
else
if
(
Objects
.
equals
(
msgType
,
EventAbnormalEnum
.
CROSS_OVERFLOW
.
getType
())
||
Objects
.
equals
(
msgType
,
EventAbnormalEnum
.
CROSS_DEADLOCK
.
getType
()))
{
// 溢出和死锁事件
// 方向缓存
List
<
CrossEventDTO
>
details
=
crossEventDTO
.
getDetails
();
for
(
CrossEventDTO
detail
:
details
)
{
detail
.
setMsgType
(
EventAbnormalEnum
.
CROSS_OVERFLOW
.
getType
());
Integer
dir
=
detail
.
getDir
();
String
redisKey
=
crossId
+
":"
+
dir
;
String
redisListElement
=
objectMapper
.
writeValueAsString
(
detail
);
redisUtils
.
addToSortedSetWithExpiry
(
redisKey
,
redisListElement
,
TTL_IN_MILLIS
);
}
// 路口缓存
String
redisListElement
=
objectMapper
.
writeValueAsString
(
crossEventDTO
);
redisUtils
.
addToSortedSetWithExpiry
(
crossId
,
redisListElement
,
TTL_IN_MILLIS
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"Kafka收到路口事件数据异常"
,
e
);
throw
new
Exception
(
e
);
}
acknowledgment
.
acknowledge
();
}
@Override
@Override
@NonNull
@NonNull
public
Object
handleError
(
Message
<?>
message
,
ListenerExecutionFailedException
e
)
{
public
Object
handleError
(
Message
<?>
message
,
ListenerExecutionFailedException
e
)
{
...
...
wj-datacenter-service/src/main/java/net/wanji/datacenter/pojo/dto/CrossEventDTO.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
pojo
.
dto
;
import
lombok.Data
;
import
java.util.List
;
@Data
public
class
CrossEventDTO
{
private
Integer
dir
;
private
String
rid
;
//该路段的结束路口
private
String
crossId
;
private
Double
index
;
private
String
indexName
;
// 501畅通 502轻微拥堵 503中度拥堵 504重度拥堵
private
String
congestionCode
;
private
String
timestamp
;
private
Long
globalTimeStamp
;
private
Long
startTime
;
private
Long
endTime
;
private
Integer
duration
;
// 事件序列号
private
String
eventSerialNumber
;
// 检测时间
private
Long
detectTime
;
private
List
<
CrossEventDTO
>
details
;
private
String
msgType
;
// 失衡方向
private
Integer
unbalanceDir
;
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/service/impl/LanePeriodicDataProcessServiceImpl.java
View file @
45271677
...
@@ -98,22 +98,27 @@ public class LanePeriodicDataProcessServiceImpl implements DataProcessService {
...
@@ -98,22 +98,27 @@ public class LanePeriodicDataProcessServiceImpl implements DataProcessService {
List
<
CrossDirDataRealtimePO
>
crossDirDataRealtimePOS
=
new
ArrayList
<>(
laneNum
);
List
<
CrossDirDataRealtimePO
>
crossDirDataRealtimePOS
=
new
ArrayList
<>(
laneNum
);
List
<
CrossTurnDataRealtimePO
>
crossTurnDataRealtimePOS
=
new
ArrayList
<>(
laneNum
);
List
<
CrossTurnDataRealtimePO
>
crossTurnDataRealtimePOS
=
new
ArrayList
<>(
laneNum
);
List
<
CrossLaneDataRealTimePO
>
crossLaneDataRealTimePOS
=
new
ArrayList
<>(
laneNum
);
List
<
CrossLaneDataRealTimePO
>
crossLaneDataRealTimePOS
=
new
ArrayList
<>(
laneNum
);
List
<
LanePeriodicDataDTO
.
EventList
>
eventLists
=
lanePeriodicDataDTO
.
getEventList
();
List
<
LanePeriodicDataDTO
.
EventList
>
eventLists
=
lanePeriodicDataDTO
.
getEventList
();
String
timeStamp
=
lanePeriodicDataDTO
.
getTimeStamp
();
String
timeStamp
=
lanePeriodicDataDTO
.
getTimeStamp
();
Date
endDate
=
DateUtil
.
parse
(
timeStamp
,
DateStyle
.
YYYY_MM_DD_HH_MM_SS
.
getValue
());
Date
endDate
=
DateUtil
.
parse
(
timeStamp
,
DateStyle
.
YYYY_MM_DD_HH_MM_SS
.
getValue
());
Date
startDate
=
DateUtil
.
offsetMinute
(
endDate
,
-
5
);
Date
startDate
=
DateUtil
.
offsetMinute
(
endDate
,
-
5
);
if
(
CollectionUtils
.
isEmpty
(
eventLists
))
{
if
(
CollectionUtils
.
isEmpty
(
eventLists
))
{
log
.
error
(
"当前车道周期实时数据车道列表为空,参数信息:"
,
lanePeriodicDataDTO
);
log
.
error
(
"当前车道周期实时数据车道列表为空,参数信息:"
,
lanePeriodicDataDTO
);
throw
new
Exception
(
"当前车道周期实时数据车道列表为空"
);
throw
new
Exception
(
"当前车道周期实时数据车道列表为空"
);
}
}
// 通过车道编号获取车道信息
// 通过车道编号获取车道信息
List
<
String
>
LaneIdList
=
eventLists
.
stream
().
map
(
LanePeriodicDataDTO
.
EventList
::
getLaneId
).
collect
(
Collectors
.
toList
());
List
<
String
>
LaneIdList
=
eventLists
.
stream
()
.
map
(
LanePeriodicDataDTO
.
EventList
::
getLaneId
)
.
collect
(
Collectors
.
toList
());
List
<
CrossBaseLaneInfoPO
>
crossBaseLaneInfoPOS
=
crossBaseLaneInfoMapper
.
selectBatchIds
(
LaneIdList
);
List
<
CrossBaseLaneInfoPO
>
crossBaseLaneInfoPOS
=
crossBaseLaneInfoMapper
.
selectBatchIds
(
LaneIdList
);
DecimalFormat
decimalFormat
=
new
DecimalFormat
(
"#.##"
);
DecimalFormat
decimalFormat
=
new
DecimalFormat
(
"#.##"
);
// 将kafka车道数据与路口车道数据对应,获取路口编号,方向,转向,分组计算
// 将kafka车道数据与路口车道数据对应,获取路口编号,方向,转向,分组计算
for
(
LanePeriodicDataDTO
.
EventList
laneRealTimeItem
:
eventLists
)
{
for
(
LanePeriodicDataDTO
.
EventList
laneRealTimeItem
:
eventLists
)
{
String
laneId
=
laneRealTimeItem
.
getLaneId
();
String
laneId
=
laneRealTimeItem
.
getLaneId
();
for
(
CrossBaseLaneInfoPO
laneInfoPO
:
crossBaseLaneInfoPOS
)
{
for
(
CrossBaseLaneInfoPO
laneInfoPO
:
crossBaseLaneInfoPOS
)
{
String
id
=
laneInfoPO
.
getId
();
String
id
=
laneInfoPO
.
getId
();
if
(
StringUtils
.
equals
(
laneId
,
id
))
{
if
(
StringUtils
.
equals
(
laneId
,
id
))
{
...
@@ -270,11 +275,13 @@ public class LanePeriodicDataProcessServiceImpl implements DataProcessService {
...
@@ -270,11 +275,13 @@ public class LanePeriodicDataProcessServiceImpl implements DataProcessService {
DecimalFormat
decimalFormat
,
ProducerHandler
producerHandler
,
Date
startDate
)
throws
Exception
{
DecimalFormat
decimalFormat
,
ProducerHandler
producerHandler
,
Date
startDate
)
throws
Exception
{
// 方向数据
// 方向数据
List
<
CrossDirDataRealtimePO
>
insertCrossDirDataRealtimePOS
=
new
ArrayList
<>();
List
<
CrossDirDataRealtimePO
>
insertCrossDirDataRealtimePOS
=
new
ArrayList
<>();
Map
<
String
,
List
<
CrossDirDataRealtimePO
>>
crossDirDataRealTimePOSMap
=
crossDirDataRealtimePOS
.
stream
().
collect
(
Collectors
.
groupingBy
(
CrossDirDataRealtimePO:
:
getCrossId
));
Map
<
String
,
List
<
CrossDirDataRealtimePO
>>
crossDirDataRealTimePOSMap
=
crossDirDataRealtimePOS
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
CrossDirDataRealtimePO:
:
getCrossId
));
for
(
Map
.
Entry
<
String
,
List
<
CrossDirDataRealtimePO
>>
entry
:
crossDirDataRealTimePOSMap
.
entrySet
())
{
for
(
Map
.
Entry
<
String
,
List
<
CrossDirDataRealtimePO
>>
entry
:
crossDirDataRealTimePOSMap
.
entrySet
())
{
String
crossId
=
entry
.
getKey
();
String
crossId
=
entry
.
getKey
();
List
<
CrossDirDataRealtimePO
>
value
=
entry
.
getValue
();
List
<
CrossDirDataRealtimePO
>
value
=
entry
.
getValue
();
Map
<
Integer
,
List
<
CrossDirDataRealtimePO
>>
crossIdMap
=
value
.
stream
().
collect
(
Collectors
.
groupingBy
(
CrossDirDataRealtimePO:
:
getDirType
));
Map
<
Integer
,
List
<
CrossDirDataRealtimePO
>>
crossIdMap
=
value
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
CrossDirDataRealtimePO:
:
getDirType
));
Double
congestionIndex
=
0.0
;
Double
congestionIndex
=
0.0
;
Double
spilloverIndex
=
0.0
;
Double
spilloverIndex
=
0.0
;
Double
saturationAverage
=
0.0
;
Double
saturationAverage
=
0.0
;
...
@@ -448,7 +455,7 @@ public class LanePeriodicDataProcessServiceImpl implements DataProcessService {
...
@@ -448,7 +455,7 @@ public class LanePeriodicDataProcessServiceImpl implements DataProcessService {
if
(
delayTimeIndexMin
<=
0.0
)
{
if
(
delayTimeIndexMin
<=
0.0
)
{
delayTimeIndexMin
=
1.0
;
delayTimeIndexMin
=
1.0
;
}
}
// 负载均衡
都
// 负载均衡
度
Double
loadBalance
=
Math
.
sqrt
(
saturationSum
/
crossIdMap
.
size
());
Double
loadBalance
=
Math
.
sqrt
(
saturationSum
/
crossIdMap
.
size
());
CrossDataIndexDTO
crossDataIndexDTO
=
new
CrossDataIndexDTO
();
CrossDataIndexDTO
crossDataIndexDTO
=
new
CrossDataIndexDTO
();
crossDataIndexDTO
.
setCongestionIndex
(
Double
.
valueOf
(
decimalFormat
.
format
(
congestionIndex
)));
crossDataIndexDTO
.
setCongestionIndex
(
Double
.
valueOf
(
decimalFormat
.
format
(
congestionIndex
)));
...
...
wj-datacenter-service/src/main/java/net/wanji/datacenter/task/RedisTask.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
task
;
import
lombok.extern.slf4j.Slf4j
;
import
net.wanji.datacenter.util.RedisUtils
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
import
java.util.Set
;
/**
* @author Kent HAN
* @date 2023/12/15 16:41
*/
@Component
@Slf4j
public
class
RedisTask
{
@Resource
private
RedisUtils
redisUtils
;
/**
* 每分钟清理路口事件缓存
* @author Kent HAN
* @date 2023/12/15 16:42
*/
@Scheduled
(
fixedRate
=
1000
*
60
)
public
void
cleanCrossEventCache
()
throws
Exception
{
try
{
Set
<
String
>
keys
=
redisUtils
.
keys
();
for
(
String
key
:
keys
)
{
redisUtils
.
removeExpiredElements
(
key
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"清理路口事件缓存失败"
,
e
);
throw
new
Exception
(
e
);
}
}
}
wj-datacenter-service/src/main/java/net/wanji/datacenter/util/DateStyle.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
util
;
/**
* @author wanji
* @version 1.0
* @Description: [日期风格工具类]
* Created on 2019/4/16 15:07
*/
public
enum
DateStyle
{
YYYY_MM
(
"yyyy-MM"
,
false
),
YYYY_MM_DD
(
"yyyy-MM-dd"
,
false
),
YYYY_MM_DD_HH_MM
(
"yyyy-MM-dd HH:mm"
,
false
),
YYYY_MM_DD_HH_MM_SS
(
"yyyy-MM-dd HH:mm:ss"
,
false
),
YYYYMMDDHHMMSS
(
"yyyyMMddHHmmss"
,
false
),
YYYYMMDDHHMMSSSSS
(
"yyyyMMddHHmmssSSS"
,
false
),
YYYYMMDD
(
"yyyyMMdd"
,
false
),
YYYY_MM_EN
(
"yyyy/MM"
,
false
),
YYYY_MM_DD_EN
(
"yyyy/MM/dd"
,
false
),
YYYY_MM_DD_HH_MM_EN
(
"yyyy/MM/dd HH:mm"
,
false
),
YYYY_MM_DD_HH_MM_SS_EN
(
"yyyy/MM/dd HH:mm:ss"
,
false
),
DD_MM_YYYY_EN
(
"dd/MM/yyyy"
,
false
),
YYYY_MM_CN
(
"yyyy年MM月"
,
false
),
YYYY_MM_DD_CN
(
"yyyy年MM月dd日"
,
false
),
YYYY_MM_DD_HH_MM_CN
(
"yyyy年MM月dd日 HH:mm"
,
false
),
YYYY_MM_DD_HH_MM_SS_CN
(
"yyyy年MM月dd日 HH:mm:ss"
,
false
),
HH_MM
(
"HH:mm"
,
true
),
HH_MM_SS
(
"HH:mm:ss"
,
true
),
MM_DD
(
"MM-dd"
,
true
),
MM_DD_HH_MM
(
"MM-dd HH:mm"
,
true
),
MM_DD_HH_MM_SS
(
"MM-dd HH:mm:ss"
,
true
),
MM_DD_EN
(
"MM/dd"
,
true
),
MM_DD_HH_MM_EN
(
"MM/dd HH:mm"
,
true
),
MM_DD_HH_MM_SS_EN
(
"MM/dd HH:mm:ss"
,
true
),
MM_DD_CN
(
"MM月dd日"
,
true
),
MM_DD_HH_MM_CN
(
"MM月dd日 HH:mm"
,
true
),
MM_DD_HH_MM_SS_CN
(
"MM月dd日 HH:mm:ss"
,
true
);
private
String
value
;
private
boolean
isShowOnly
;
DateStyle
(
String
value
,
boolean
isShowOnly
)
{
this
.
value
=
value
;
this
.
isShowOnly
=
isShowOnly
;
}
public
String
getValue
()
{
return
value
;
}
public
boolean
isShowOnly
()
{
return
isShowOnly
;
}
}
\ No newline at end of file
wj-datacenter-service/src/main/java/net/wanji/datacenter/util/DateUtils.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
util
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
java.math.BigDecimal
;
import
java.text.ParsePosition
;
import
java.text.SimpleDateFormat
;
import
java.util.*
;
/**
* @author wanji
* @version 1.0
* Created on 2019/4/16 15:28
* @Description: [日期工具类]
*/
@Slf4j
public
class
DateUtils
{
private
static
final
ThreadLocal
<
SimpleDateFormat
>
threadLocal
=
new
ThreadLocal
<>();
private
static
final
Object
object
=
new
Object
();
private
DateUtils
()
{}
/**
* 获取SimpleDateFormat
*
* @param pattern 日期格式
* @return SimpleDateFormat对象
* @throws RuntimeException 异常:非法日期格式
*/
public
static
SimpleDateFormat
getDateFormat
(
String
pattern
)
{
SimpleDateFormat
dateFormat
=
threadLocal
.
get
();
if
(
dateFormat
==
null
)
{
synchronized
(
object
)
{
dateFormat
=
new
SimpleDateFormat
(
pattern
);
dateFormat
.
setLenient
(
false
);
threadLocal
.
set
(
dateFormat
);
}
}
dateFormat
.
applyPattern
(
pattern
);
return
dateFormat
;
}
/**
* 获取日期中的某数值。如获取月份
*
* @param date 日期
* @param dateType 日期格式
* @return 数值
*/
private
static
int
getInteger
(
Date
date
,
int
dateType
)
{
int
num
=
0
;
Calendar
calendar
=
Calendar
.
getInstance
();
if
(
date
!=
null
)
{
calendar
.
setTime
(
date
);
num
=
calendar
.
get
(
dateType
);
}
return
num
;
}
/**
* 增加日期中某类型的某数值。如增加日期
*
* @param date 日期字符串
* @param dateType 类型
* @param amount 数值
* @return 计算后日期字符串
*/
private
static
String
addInteger
(
String
date
,
int
dateType
,
int
amount
)
{
String
dateString
=
null
;
DateStyle
dateStyle
=
getDateStyle
(
date
);
if
(
dateStyle
!=
null
)
{
Date
myDate
=
stringToDate
(
date
,
dateStyle
);
myDate
=
addInteger
(
myDate
,
dateType
,
amount
);
dateString
=
dateToString
(
myDate
,
dateStyle
);
}
return
dateString
;
}
/**
* 增加日期中某类型的某数值。如增加日期
*
* @param date 日期
* @param dateType 类型
* @param amount 数值
* @return 计算后日期
*/
private
static
Date
addInteger
(
Date
date
,
int
dateType
,
int
amount
)
{
Date
myDate
=
null
;
if
(
date
!=
null
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
setTime
(
date
);
calendar
.
add
(
dateType
,
amount
);
myDate
=
calendar
.
getTime
();
}
return
myDate
;
}
/**
* 获取精确的日期
*
* @param timestamps 时间long集合
* @return 日期
*/
private
static
Date
getAccurateDate
(
List
<
Long
>
timestamps
)
{
Date
date
=
null
;
long
timestamp
=
0
;
Map
<
Long
,
long
[]>
map
=
new
HashMap
<>();
List
<
Long
>
absoluteValues
=
new
ArrayList
<>();
if
(
timestamps
!=
null
&&
!
timestamps
.
isEmpty
())
{
if
(
timestamps
.
size
()
>
1
)
{
for
(
int
i
=
0
;
i
<
timestamps
.
size
();
i
++)
{
for
(
int
j
=
i
+
1
;
j
<
timestamps
.
size
();
j
++)
{
long
absoluteValue
=
Math
.
abs
(
timestamps
.
get
(
i
)
-
timestamps
.
get
(
j
));
absoluteValues
.
add
(
absoluteValue
);
long
[]
timestampTmp
=
{
timestamps
.
get
(
i
),
timestamps
.
get
(
j
)};
map
.
put
(
absoluteValue
,
timestampTmp
);
}
}
// 有可能有相等的情况。如2012-11和2012-11-01。时间戳是相等的。此时minAbsoluteValue为0
// 因此不能将minAbsoluteValue取默认值0
long
minAbsoluteValue
=
-
1
;
if
(!
absoluteValues
.
isEmpty
())
{
minAbsoluteValue
=
absoluteValues
.
get
(
0
);
for
(
int
i
=
1
;
i
<
absoluteValues
.
size
();
i
++)
{
if
(
minAbsoluteValue
>
absoluteValues
.
get
(
i
))
{
minAbsoluteValue
=
absoluteValues
.
get
(
i
);
}
}
}
if
(
minAbsoluteValue
!=
-
1
)
{
long
[]
timestampsLastTmp
=
map
.
get
(
minAbsoluteValue
);
long
dateOne
=
timestampsLastTmp
[
0
];
long
dateTwo
=
timestampsLastTmp
[
1
];
if
(
absoluteValues
.
size
()
>
1
)
{
timestamp
=
Math
.
abs
(
dateOne
)
>
Math
.
abs
(
dateTwo
)
?
dateOne
:
dateTwo
;
}
}
}
else
{
timestamp
=
timestamps
.
get
(
0
);
}
}
if
(
timestamp
!=
0
)
{
date
=
new
Date
(
timestamp
);
}
return
date
;
}
/**
* 根据开始时间和结束时间获取间隔的时间(单位/小时)
*
* @param startTime
* @param endTime
* @return
*/
public
static
Double
getIntervalHours
(
String
startTime
,
String
endTime
)
{
Date
staDate
=
DateUtils
.
stringToDate
(
startTime
,
DateStyle
.
HH_MM_SS
);
Date
endDate
=
DateUtils
.
stringToDate
(
endTime
,
DateStyle
.
HH_MM_SS
);
if
(
staDate
==
null
||
endDate
==
null
)
return
null
;
BigDecimal
startTimeStamp
=
BigDecimal
.
valueOf
(
staDate
.
getTime
());
BigDecimal
endTimeStamp
=
BigDecimal
.
valueOf
(
endDate
.
getTime
());
BigDecimal
hours
=
endTimeStamp
.
subtract
(
startTimeStamp
).
divide
(
new
BigDecimal
(
1000
*
60
*
60
),
2
,
BigDecimal
.
ROUND_DOWN
);
return
hours
.
doubleValue
();
}
/**
* 判断字符串是否为日期字符串
*
* @param date 日期字符串
* @return true or false
*/
public
static
boolean
isDate
(
String
date
)
{
boolean
isDate
=
false
;
if
(
date
!=
null
&&
getDateStyle
(
date
)
!=
null
)
{
isDate
=
true
;
}
return
isDate
;
}
/**
* 获取日期字符串的日期风格。失敗返回null。
*
* @param date 日期字符串
* @return 日期风格
*/
public
static
DateStyle
getDateStyle
(
String
date
)
{
DateStyle
dateStyle
=
null
;
Map
<
Long
,
DateStyle
>
map
=
new
HashMap
<>();
List
<
Long
>
timestamps
=
new
ArrayList
<>();
for
(
DateStyle
style
:
DateStyle
.
values
())
{
if
(
style
.
isShowOnly
())
{
continue
;
}
Date
dateTmp
=
null
;
if
(
date
!=
null
)
{
try
{
ParsePosition
pos
=
new
ParsePosition
(
0
);
dateTmp
=
getDateFormat
(
style
.
getValue
()).
parse
(
date
,
pos
);
if
(
pos
.
getIndex
()
!=
date
.
length
())
{
dateTmp
=
null
;
}
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
}
}
if
(
dateTmp
!=
null
)
{
timestamps
.
add
(
dateTmp
.
getTime
());
map
.
put
(
dateTmp
.
getTime
(),
style
);
}
}
Date
accurateDate
=
getAccurateDate
(
timestamps
);
if
(
accurateDate
!=
null
)
{
dateStyle
=
map
.
get
(
accurateDate
.
getTime
());
}
return
dateStyle
;
}
/**
* 将日期字符串转化为日期。失败返回null。
*
* @param date 日期字符串
* @return 日期
*/
public
static
Date
stringToDate
(
String
date
)
{
DateStyle
dateStyle
=
getDateStyle
(
date
);
return
stringToDate
(
date
,
dateStyle
);
}
/**
* 将日期字符串转化为日期。失败返回null。
*
* @param date 日期字符串
* @param pattern 日期格式
* @return 日期
*/
public
static
Date
stringToDate
(
String
date
,
String
pattern
)
{
Date
myDate
=
null
;
if
(
date
!=
null
)
{
try
{
myDate
=
getDateFormat
(
pattern
).
parse
(
date
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
());
}
}
return
myDate
;
}
/**
* 将日期字符串转化为日期。失败返回null。
*
* @param date 日期字符串
* @param dateStyle 日期风格
* @return 日期
*/
public
static
Date
stringToDate
(
String
date
,
DateStyle
dateStyle
)
{
Date
myDate
=
null
;
if
(
dateStyle
!=
null
)
{
myDate
=
stringToDate
(
date
,
dateStyle
.
getValue
());
}
return
myDate
;
}
/**
* 将日期转化为日期字符串。失败返回null。
*
* @param date 日期
* @param pattern 日期格式
* @return 日期字符串
*/
public
static
String
dateToString
(
Date
date
,
String
pattern
)
{
return
getDateFormat
(
pattern
).
format
(
date
);
}
/**
* 将日期转化为日期字符串。失败返回null。
*
* @param date 日期
* @param dateStyle 日期风格
* @return 日期字符串
*/
public
static
String
dateToString
(
Date
date
,
DateStyle
dateStyle
)
{
String
dateString
=
""
;
if
(
dateStyle
!=
null
)
{
dateString
=
dateToString
(
date
,
dateStyle
.
getValue
());
}
return
dateString
;
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
*
* @param date 旧日期字符串
* @param newPattern 新日期格式
* @return 新日期字符串
*/
public
static
String
stringToString
(
String
date
,
String
newPattern
)
{
DateStyle
oldDateStyle
=
getDateStyle
(
date
);
return
stringToString
(
date
,
oldDateStyle
,
newPattern
);
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
*
* @param date 旧日期字符串
* @param newDateStyle 新日期风格
* @return 新日期字符串
*/
public
static
String
stringToString
(
String
date
,
DateStyle
newDateStyle
)
{
DateStyle
oldDateStyle
=
getDateStyle
(
date
);
return
stringToString
(
date
,
oldDateStyle
,
newDateStyle
);
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
*
* @param date 旧日期字符串
* @param olddPattern 旧日期格式
* @param newPattern 新日期格式
* @return 新日期字符串
*/
public
static
String
stringToString
(
String
date
,
String
olddPattern
,
String
newPattern
)
{
return
dateToString
(
stringToDate
(
date
,
olddPattern
),
newPattern
);
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
*
* @param date 旧日期字符串
* @param olddDteStyle 旧日期风格
* @param newParttern 新日期格式
* @return 新日期字符串
*/
public
static
String
stringToString
(
String
date
,
DateStyle
olddDteStyle
,
String
newParttern
)
{
String
dateString
=
null
;
if
(
olddDteStyle
!=
null
)
{
dateString
=
stringToString
(
date
,
olddDteStyle
.
getValue
(),
newParttern
);
}
return
dateString
;
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
*
* @param date 旧日期字符串
* @param olddPattern 旧日期格式
* @param newDateStyle 新日期风格
* @return 新日期字符串
*/
public
static
String
stringToString
(
String
date
,
String
olddPattern
,
DateStyle
newDateStyle
)
{
String
dateString
=
null
;
if
(
newDateStyle
!=
null
)
{
dateString
=
stringToString
(
date
,
olddPattern
,
newDateStyle
.
getValue
());
}
return
dateString
;
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
*
* @param date 旧日期字符串
* @param olddDteStyle 旧日期风格
* @param newDateStyle 新日期风格
* @return 新日期字符串
*/
public
static
String
stringToString
(
String
date
,
DateStyle
olddDteStyle
,
DateStyle
newDateStyle
)
{
String
dateString
=
null
;
if
(
olddDteStyle
!=
null
&&
newDateStyle
!=
null
)
{
dateString
=
stringToString
(
date
,
olddDteStyle
.
getValue
(),
newDateStyle
.
getValue
());
}
return
dateString
;
}
/**
* 格式化时间
*
* @param date
* @param dateStyle
* @return 时间
*/
public
static
Date
dateForMat
(
Date
date
,
DateStyle
dateStyle
)
{
return
stringToDate
(
dateToString
(
date
,
dateStyle
),
dateStyle
);
}
/**
* 增加日期的年份。失败返回null。
*
* @param date 日期
* @param yearAmount 增加数量。可为负数
* @return 增加年份后的日期字符串
*/
public
static
String
addYear
(
String
date
,
int
yearAmount
)
{
return
addInteger
(
date
,
Calendar
.
YEAR
,
yearAmount
);
}
/**
* 增加日期的值。失败返回null。
*
* @param date 日期
* @param type 添加的类型 年、月、日、时、分、秒
* @param amount 增加数量
* @return
*/
public
static
Date
add
(
Date
date
,
int
type
,
int
amount
)
{
return
addInteger
(
date
,
type
,
amount
);
}
/**
* 增加日期的年份。失败返回null。
*
* @param date 日期
* @param yearAmount 增加数量。可为负数
* @return 增加年份后的日期
*/
public
static
Date
addYear
(
Date
date
,
int
yearAmount
)
{
return
addInteger
(
date
,
Calendar
.
YEAR
,
yearAmount
);
}
/**
* 增加日期的月份。失败返回null。
*
* @param date 日期
* @param monthAmount 增加数量。可为负数
* @return 增加月份后的日期字符串
*/
public
static
String
addMonth
(
String
date
,
int
monthAmount
)
{
return
addInteger
(
date
,
Calendar
.
MONTH
,
monthAmount
);
}
/**
* 增加日期的月份。失败返回null。
*
* @param date 日期
* @param monthAmount 增加数量。可为负数
* @return 增加月份后的日期
*/
public
static
Date
addMonth
(
Date
date
,
int
monthAmount
)
{
return
addInteger
(
date
,
Calendar
.
MONTH
,
monthAmount
);
}
/**
* 增加日期的天数。失败返回null。
*
* @param date 日期字符串
* @param dayAmount 增加数量。可为负数
* @return 增加天数后的日期字符串
*/
public
static
String
addDay
(
String
date
,
int
dayAmount
)
{
return
addInteger
(
date
,
Calendar
.
DATE
,
dayAmount
);
}
/**
* 增加日期的天数。失败返回null。
*
* @param date 日期
* @param dayAmount 增加数量。可为负数
* @return 增加天数后的日期
*/
public
static
Date
addDay
(
Date
date
,
int
dayAmount
)
{
return
addInteger
(
date
,
Calendar
.
DATE
,
dayAmount
);
}
/**
* 增加日期的小时。失败返回null。
*
* @param date 日期字符串
* @param hourAmount 增加数量。可为负数
* @return 增加小时后的日期字符串
*/
public
static
String
addHour
(
String
date
,
int
hourAmount
)
{
return
addInteger
(
date
,
Calendar
.
HOUR_OF_DAY
,
hourAmount
);
}
/**
* 增加日期的小时。失败返回null。
*
* @param date 日期
* @param hourAmount 增加数量。可为负数
* @return 增加小时后的日期
*/
public
static
Date
addHour
(
Date
date
,
int
hourAmount
)
{
return
addInteger
(
date
,
Calendar
.
HOUR_OF_DAY
,
hourAmount
);
}
/**
* 增加日期的分钟。失败返回null。
*
* @param date 日期字符串
* @param minuteAmount 增加数量。可为负数
* @return 增加分钟后的日期字符串
*/
public
static
String
addMinute
(
String
date
,
int
minuteAmount
)
{
return
addInteger
(
date
,
Calendar
.
MINUTE
,
minuteAmount
);
}
/**
* 增加日期的分钟。失败返回null。
*
* @param date 日期
* @param minuteAmount 增加数量。可为负数
* @return 增加分钟后的日期
*/
public
static
Date
addMinute
(
Date
date
,
int
minuteAmount
)
{
return
addInteger
(
date
,
Calendar
.
MINUTE
,
minuteAmount
);
}
/**
* 增加日期的秒钟。失败返回null。
*
* @param date 日期字符串
* @param secondAmount 增加数量。可为负数
* @return 增加秒钟后的日期字符串
*/
public
static
String
addSecond
(
String
date
,
int
secondAmount
)
{
return
addInteger
(
date
,
Calendar
.
SECOND
,
secondAmount
);
}
/**
* 增加日期的秒钟。失败返回null。
*
* @param date 日期
* @param secondAmount 增加数量。可为负数
* @return 增加秒钟后的日期
*/
public
static
Date
addSecond
(
Date
date
,
int
secondAmount
)
{
return
addInteger
(
date
,
Calendar
.
SECOND
,
secondAmount
);
}
/**
* 获取日期的年份。失败返回0。
*
* @param date 日期字符串
* @return 年份
*/
public
static
int
getYear
(
String
date
)
{
return
getYear
(
stringToDate
(
date
));
}
/**
* 获取日期的年份。失败返回0。
*
* @param date 日期
* @return 年份
*/
public
static
int
getYear
(
Date
date
)
{
return
getInteger
(
date
,
Calendar
.
YEAR
);
}
/**
* 获取日期的月份。失败返回0。
*
* @param date 日期字符串
* @return 月份
*/
public
static
int
getMonth
(
String
date
)
{
return
getMonth
(
stringToDate
(
date
));
}
/**
* 获取日期的月份。失败返回0。
*
* @param date 日期
* @return 月份
*/
public
static
int
getMonth
(
Date
date
)
{
return
getInteger
(
date
,
Calendar
.
MONTH
)
+
1
;
}
/**
* 获取日期的星期。失败返回0
*
* @param date 日期
* @return 星期
*/
public
static
int
getWeek
(
String
date
)
{
return
getWeek
(
stringToDate
(
date
));
}
/**
* 获取日期的星期。失败返回0
*
* @param date 日期
* @return 星期
*/
public
static
int
getWeek
(
Date
date
)
{
return
getInteger
(
date
,
Calendar
.
DAY_OF_WEEK
)
-
1
;
}
/**
* 获取日期的天数。失败返回0。
*
* @param date 日期字符串
* @return 天
*/
public
static
int
getDay
(
String
date
)
{
return
getDay
(
stringToDate
(
date
));
}
/**
* 获取日期的天数。失败返回0。
*
* @param date 日期
* @return 天
*/
public
static
int
getDay
(
Date
date
)
{
return
getInteger
(
date
,
Calendar
.
DATE
);
}
/**
* 获取日期的小时。失败返回0。
*
* @param date 日期字符串
* @return 小时
*/
public
static
int
getHour
(
String
date
)
{
return
getHour
(
stringToDate
(
date
));
}
/**
* 获取日期的小时。失败返回0。
*
* @param date 日期
* @return 小时
*/
public
static
int
getHour
(
Date
date
)
{
return
getInteger
(
date
,
Calendar
.
HOUR_OF_DAY
);
}
/**
* 获取日期的分钟。失败返回0。
*
* @param date 日期字符串
* @return 分钟
*/
public
static
int
getMinute
(
String
date
)
{
return
getMinute
(
stringToDate
(
date
));
}
/**
* 获取日期的分钟。失败返回0。
*
* @param date 日期
* @return 分钟
*/
public
static
int
getMinute
(
Date
date
)
{
return
getInteger
(
date
,
Calendar
.
MINUTE
);
}
/**
* 获取日期的秒钟。失败返回0。
*
* @param date 日期字符串
* @return 秒钟
*/
public
static
int
getSecond
(
String
date
)
{
return
getSecond
(
stringToDate
(
date
));
}
/**
* 获取日期的秒钟。失败返回0。
*
* @param date 日期
* @return 秒钟
*/
public
static
int
getSecond
(
Date
date
)
{
return
getInteger
(
date
,
Calendar
.
SECOND
);
}
/**
* 获取日期 。默认yyyy-MM-dd格式。失败返回null。
*
* @param date 日期字符串
* @return 日期
*/
public
static
String
getDate
(
String
date
)
{
return
stringToString
(
date
,
DateStyle
.
YYYY_MM_DD
);
}
/**
* 获取日期。默认yyyy-MM-dd格式。失败返回null。
*
* @param date 日期
* @return 日期
*/
public
static
String
getDate
(
Date
date
)
{
return
dateToString
(
date
,
DateStyle
.
YYYY_MM_DD
);
}
/**
* 获取日期的时间。默认HH:mm:ss格式。失败返回null。
*
* @param date 日期字符串
* @return 时间
*/
public
static
String
getTime
(
String
date
)
{
return
stringToString
(
date
,
DateStyle
.
HH_MM_SS
);
}
/**
* 获取日期的时间。默认HH:mm:ss格式。失败返回null。
*
* @param date 日期
* @return 时间
*/
public
static
String
getTime
(
Date
date
)
{
return
dateToString
(
date
,
DateStyle
.
HH_MM_SS
);
}
/**
* 获取两个日期相差的天数
*
* @param date 日期字符串
* @param otherDate 另一个日期字符串
* @return 相差天数。如果失败则返回-1
*/
public
static
int
getIntervalDays
(
String
date
,
String
otherDate
)
{
return
getIntervalDays
(
stringToDate
(
date
),
stringToDate
(
otherDate
));
}
/**
* @param date 日期
* @param otherDate 另一个日期
* @return 相差天数。如果失败则返回-1
*/
public
static
int
getIntervalDays
(
Date
date
,
Date
otherDate
)
{
int
num
=
-
1
;
Date
dateTmp
=
DateUtils
.
stringToDate
(
DateUtils
.
getDate
(
date
),
DateStyle
.
YYYY_MM_DD
);
Date
otherDateTmp
=
DateUtils
.
stringToDate
(
DateUtils
.
getDate
(
otherDate
),
DateStyle
.
YYYY_MM_DD
);
if
(
dateTmp
!=
null
&&
otherDateTmp
!=
null
)
{
long
time
=
Math
.
abs
(
dateTmp
.
getTime
()
-
otherDateTmp
.
getTime
());
num
=
(
int
)
(
time
/
(
24
*
60
*
60
*
1000
));
}
return
num
;
}
/**
* @param date 日期
* @param otherDate 另一个日期
* @return 相差分钟数。如果失败则返回-1
*/
public
static
int
getIntervalMinute
(
Date
date
,
Date
otherDate
)
{
int
num
=
-
1
;
if
(
date
!=
null
&&
otherDate
!=
null
)
{
long
time
=
Math
.
abs
(
date
.
getTime
()
-
otherDate
.
getTime
());
num
=
(
int
)
(
time
/
(
1000
*
60
));
}
return
num
;
}
/**
* Description :获取当前时间yyyyMMddHHmmss字符串
*
* @return String 当前时间yyyyMMddHHmmss字符串
*/
public
static
String
getSecondString
()
{
return
dateToString
(
new
Date
(),
DateStyle
.
YYYYMMDDHHMMSS
);
}
/**
* Description : 获取当前时间yyyyMMddHHmmssSSS字符串
*
* @return String 当前时间yyyyMMddHHmmssSSS字符串
*/
public
static
String
getMillisecondString
()
{
return
dateToString
(
new
Date
(),
DateStyle
.
YYYYMMDDHHMMSSSSS
);
}
/**
* 比较两个日期的大小
*
* @param date1 日期1
* @param date2 日期2
* @return 1 date1 > date2; -1 date1 < date2 ; 0 date1 = date2
*/
public
static
int
compareDate
(
String
date1
,
String
date2
)
{
Date
dt1
=
stringToDate
(
date1
);
Date
dt2
=
stringToDate
(
date2
);
return
compareDate
(
dt1
,
dt2
);
}
/**
* 比较两个日期的大小
*
* @param date1 日期1
* @param date2 日期2
* @return 1 date1 > date2; -1 date1 < date2 ; 0 date1 = date2
*/
public
static
int
compareDate
(
Date
date1
,
Date
date2
)
{
if
(
date1
==
null
||
date2
==
null
)
return
0
;
if
(
date1
.
getTime
()
>
date2
.
getTime
())
{
return
1
;
}
else
if
(
date1
.
getTime
()
<
date2
.
getTime
())
{
return
-
1
;
}
else
{
return
0
;
}
}
/**
* Description:[判断两个日期是否相等]
*
* @param d1 日期1
* @param d2 日期2
* @return boolean 相等true
* <p>
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
boolean
isSameDate
(
Date
d1
,
Date
d2
)
{
if
(
null
==
d1
||
null
==
d2
)
return
false
;
Calendar
cal1
=
Calendar
.
getInstance
();
cal1
.
setTime
(
d1
);
Calendar
cal2
=
Calendar
.
getInstance
();
cal2
.
setTime
(
d2
);
return
cal1
.
get
(
0
)
==
cal2
.
get
(
0
)
&&
cal1
.
get
(
1
)
==
cal2
.
get
(
1
)
&&
cal1
.
get
(
6
)
==
cal2
.
get
(
6
);
}
/**
* Description:[获取两个时间的时间差]
*
* @param date1 时间一
* @param date2 时间二
* @param type 获取的类型 天 时 分 秒
* @return 时间一 减 时间二 的值
* <p>
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
int
dayDiff
(
Date
date1
,
Date
date2
,
int
type
)
{
long
diff
=
date1
.
getTime
()
-
date2
.
getTime
();
int
nd
=
1000
*
24
*
60
*
60
;
int
nh
=
1000
*
60
*
60
;
int
nm
=
1000
*
60
;
int
ns
=
1000
;
// 计算差多少天
long
day
=
diff
/
nd
;
// 计算差多少小时
long
hour
=
diff
/
nh
;
// 计算差多少分钟
long
min
=
diff
/
nm
;
// 计算差多少秒
long
sec
=
diff
/
ns
;
if
(
Calendar
.
DATE
==
type
)
{
return
(
int
)
day
;
}
else
if
(
Calendar
.
HOUR_OF_DAY
==
type
)
{
return
(
int
)
hour
;
}
else
if
(
Calendar
.
MINUTE
==
type
)
{
return
(
int
)
min
;
}
else
if
(
Calendar
.
SECOND
==
type
)
{
return
(
int
)
sec
;
}
else
{
return
(
int
)
diff
;
}
}
/**
* Description:[根据参数时间获取前推的整点时间:列2017-11-22 17:13返回17:00;列2017-11-22 17:59返回17:30]
*
* @param date 时间
* @return 列2017-11-22 17:13返回17:00;列2017-11-22 17:59返回17:30
* <p>
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
Date
wholeHour
(
Date
date
)
{
int
hour
=
DateUtils
.
getHour
(
date
);
int
minute
=
DateUtils
.
getMinute
(
date
);
if
(
minute
>=
30
)
{
minute
=
30
;
}
else
{
minute
=
00
;
}
String
endTime
=
hour
+
":"
+
minute
;
return
DateUtils
.
stringToDate
(
endTime
,
DateStyle
.
HH_MM
);
}
/**
* <p>Description:[计算两个日期相差的月数,不足15天按照半个月计算,超过15天按照一个月计算]</p>
*
* @param startDate 开始时间
* @param endDate 结束时间
* @return 相差的月数0.5的倍数
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
double
getMonths
(
Date
startDate
,
Date
endDate
)
{
int
startYear
=
DateUtils
.
getYear
(
startDate
);
int
endYear
=
DateUtils
.
getYear
(
endDate
);
int
startMonth
=
DateUtils
.
getMonth
(
startDate
);
int
endMonth
=
DateUtils
.
getMonth
(
endDate
);
int
startDay
=
DateUtils
.
getDay
(
startDate
);
int
endDay
=
DateUtils
.
getDay
(
endDate
);
int
endLastDay
=
DateUtils
.
getLastDay
(
endDate
);
int
startLastDay
=
DateUtils
.
getLastDay
(
startDate
);
int
intervalYears
=
endYear
-
startYear
;
double
intervalMonths
;
int
intervalDays
;
if
(
intervalYears
>=
1
)
{
intervalDays
=
(
startLastDay
-
startDay
)
+
endDay
+
1
;
intervalMonths
=
(
12.0
-
startMonth
)
+
endMonth
+
1
;
if
(
startDay
==
1
&&
endDay
==
endLastDay
)
{
intervalDays
=
0
;
}
else
{
if
(
startDay
!=
1
)
{
intervalMonths
-=
1.0
;
}
else
{
intervalDays
=
endDay
;
}
if
(
endDay
!=
endLastDay
)
{
intervalMonths
-=
1.0
;
}
else
{
intervalDays
=
startLastDay
-
startDay
+
1
;
}
}
}
else
{
intervalMonths
=
endMonth
-
startMonth
+
1.0
;
if
(
intervalMonths
>
1.0
)
{
intervalDays
=
(
startLastDay
-
startDay
)
+
endDay
+
1
;
if
(
startDay
==
1
&&
endDay
==
endLastDay
)
{
intervalDays
=
0
;
}
else
{
if
(
startDay
!=
1
)
{
intervalMonths
-=
1.0
;
}
else
{
intervalDays
=
endDay
;
}
if
(
endDay
!=
endLastDay
)
{
intervalMonths
-=
1.0
;
}
else
{
intervalDays
=
startLastDay
-
startDay
+
1
;
}
}
intervalMonths
=
intervalMonths
<
0.0
?
0.0
:
intervalMonths
;
}
else
{
intervalMonths
=
0.0
;
intervalDays
=
endDay
-
startDay
+
1
;
}
}
if
(
intervalDays
==
0
)
{
intervalMonths
+=
0.0
;
}
else
if
(
intervalDays
<=
15
)
{
intervalMonths
+=
0.5
;
}
else
if
(
intervalDays
>=
31
)
{
intervalMonths
+=
1.0
;
if
(
intervalDays
-
31
>
15
)
{
intervalMonths
+=
1.0
;
}
else
if
(
intervalDays
-
31
>=
1
)
{
intervalMonths
+=
0.5
;
}
}
else
{
intervalMonths
+=
1.0
;
}
for
(
int
i
=
1
;
i
<
intervalYears
;
i
++)
{
intervalMonths
+=
12.0
;
}
return
intervalMonths
;
}
/**
* <p>Description:[计算当前时间所处的拆分时间段]</p>
*
* @return 拆分时间段Integer值
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
Integer
getSplitTimeByNow
()
{
return
getSplitTime
(
new
Date
());
}
/**
* <p>Description:[计算时间所处的拆分时间段]</p>
*
* @return 拆分时间段Integer值
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
Integer
getSplitTime
(
Date
date
)
{
int
hour
=
DateUtils
.
getHour
(
date
);
int
minute
=
DateUtils
.
getMinute
(
date
);
if
(
minute
>
0
&&
minute
<
30
)
{
minute
=
30
;
}
int
splitTime
=
hour
*
2
+
1
;
if
(
minute
>=
30
)
{
splitTime
+=
1
;
}
return
splitTime
;
}
/**
* Description:[获取当前月的第一天的日期]
*
* @return 当前月第一天
* <p>
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
Date
getfirstDate
()
{
Calendar
c
=
Calendar
.
getInstance
();
c
.
add
(
Calendar
.
MONTH
,
0
);
c
.
set
(
Calendar
.
DAY_OF_MONTH
,
1
);
//设置为1号,当前日期既为本月第一天
return
stringToDate
(
getDateFormat
(
DateStyle
.
YYYY_MM_DD
.
getValue
()).
format
(
c
.
getTime
()));
}
/**
* Description:[获取当前月的最后一天的日期]
*
* @return 当前月的最后一天
* <p>
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
Date
getlastDate
()
{
Calendar
c
=
Calendar
.
getInstance
();
c
.
add
(
Calendar
.
MONTH
,
0
);
c
.
set
(
Calendar
.
DAY_OF_MONTH
,
c
.
getActualMaximum
(
Calendar
.
DAY_OF_MONTH
));
return
stringToDate
(
getDateFormat
(
DateStyle
.
YYYY_MM_DD
.
getValue
()).
format
(
c
.
getTime
()));
}
/**
* Description:[获取指定月的最后一天的日期]
*
* @return 指定的最后一天
* <p>
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
int
getLastDay
(
Date
date
)
{
Calendar
c
=
Calendar
.
getInstance
();
c
.
setTime
(
date
);
return
c
.
getActualMaximum
(
Calendar
.
DAY_OF_MONTH
);
}
/**
* Description:[获取指定月的第一天的日期]
*
* @return 指定的第一天
* <p>
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
int
getFirstDay
(
Date
date
)
{
Calendar
c
=
Calendar
.
getInstance
();
c
.
setTime
(
date
);
return
c
.
getActualMinimum
(
Calendar
.
DAY_OF_MONTH
);
}
/**
* <p>Description:[获取当前日期字符串]</p>
* Created on 2019/4/17
*
* @author: yinguijin
*/
public
static
String
getCurrentDateString
()
{
return
dateToString
(
new
Date
(),
DateStyle
.
YYYY_MM_DD
);
}
/**
* <p>Description:[获取当前日期]</p>
* Created on 2019/4/17
*
* @author: yinguijin
*/
public
static
Date
getCurrentDate
()
{
return
stringToDate
(
getCurrentDateString
(),
DateStyle
.
YYYY_MM_DD
);
}
/**
* <p>Description:[获取某月最大日期]</p>
* Created on 2019/4/17
*
* @author: yinguijin
*/
public
static
int
getMonthMaxDay
(
Date
date
)
{
Calendar
calendar
=
Calendar
.
getInstance
();
calendar
.
set
(
getYear
(
date
),
getMonth
(
date
)
-
1
,
1
);
return
calendar
.
getActualMaximum
(
Calendar
.
DAY_OF_MONTH
);
}
/**
* <p>Discription:[根据传入的两个时间计算相差几个小时,结果保留一位小数]</p>
*
* @param dateLast date类型的时间1
* @param dateNext date类型的时间2
* @return Double 返回保留一位小数的绝对值
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
Double
calculateHour
(
Date
dateLast
,
Date
dateNext
)
{
long
millisLast
=
dateLast
.
getTime
();
long
millisNext
=
dateNext
.
getTime
();
double
differenceMillis
=
(
double
)
(
millisNext
-
millisLast
);
double
hourDouble
=
differenceMillis
/
1000
/
60
/
60
;
hourDouble
=
BigDecimal
.
valueOf
(
hourDouble
).
setScale
(
1
,
BigDecimal
.
ROUND_HALF_UP
).
doubleValue
();
return
Math
.
abs
(
hourDouble
);
}
/**
* 判断一个时间是否在一个时间段之间
*
* @param date 为目标时间
* @param startDate 为起始时间
* @param endDate 为结束时间
* @return true or false
* Created on 2019/4/17
* @author: yinguijin
*/
public
static
boolean
getInDate
(
String
date
,
String
startDate
,
String
endDate
)
{
boolean
flag
=
false
;
Date
targetTime
=
DateUtils
.
stringToDate
(
date
,
DateStyle
.
HH_MM
);
Date
startTime
=
DateUtils
.
stringToDate
(
startDate
,
DateStyle
.
HH_MM
);
Date
endTime
;
if
(
endDate
.
equals
(
"24:00"
))
{
endTime
=
addDay
(
DateUtils
.
stringToDate
(
"00:00"
,
DateStyle
.
HH_MM
),
1
);
}
else
{
endTime
=
DateUtils
.
stringToDate
(
endDate
,
DateStyle
.
HH_MM
);
}
//目标时间大于等于开始时间 且 目标时间小于结束时间 时返回true
if
(
targetTime
!=
null
&&
targetTime
.
compareTo
(
startTime
)
>=
0
&&
targetTime
.
compareTo
(
endTime
)
<
0
)
{
flag
=
true
;
}
return
flag
;
}
/**
* @param startTime 开始时间
* @param endTime 结束时间
* @return java.lang.String 时段名称
* @description: 获取时段名称
* @author yinguijin
* @date 2019/5/5 20:12
*/
public
static
String
getSectimeName
(
String
startTime
,
String
endTime
)
{
String
secname
=
"平峰"
;
String
st
=
startTime
.
split
(
":"
)[
0
];
String
et
=
endTime
.
split
(
":"
)[
0
];
if
(
StringUtils
.
isEmpty
(
st
)
||
StringUtils
.
isEmpty
(
et
))
{
return
secname
;
}
int
s
=
Integer
.
parseInt
(
st
);
int
e
=
Integer
.
parseInt
(
et
);
if
(
s
>=
0
&&
e
<=
6
)
{
secname
=
"低峰"
;
}
else
if
(
s
>=
6
&&
e
<=
7
)
{
secname
=
"早平峰"
;
}
else
if
(
s
>=
7
&&
e
<=
9
)
{
secname
=
"早高峰"
;
}
else
if
(
s
>=
9
&&
e
<=
12
)
{
secname
=
"平峰"
;
}
else
if
(
s
>=
12
&&
e
<=
14
)
{
secname
=
"次平峰"
;
}
else
if
(
s
>=
14
&&
e
<=
17
)
{
secname
=
"平峰"
;
}
else
if
(
s
>=
17
&&
e
<=
19
)
{
secname
=
"晚高峰"
;
}
else
if
(
s
>=
19
&&
e
<=
22
)
{
secname
=
"次平峰"
;
}
else
if
(
s
>=
22
&&
e
<=
24
)
{
secname
=
"低峰"
;
}
return
secname
;
}
/**
* @param cntDateBeg 开始时间
* @param cntDateEnd 结束时间
* @return
*/
public
static
List
<
String
>
addDates
(
String
cntDateBeg
,
String
cntDateEnd
)
{
List
<
String
>
list
=
new
ArrayList
<>();
//拆分成数组
String
[]
dateBegs
=
cntDateBeg
.
split
(
"-"
);
String
[]
dateEnds
=
cntDateEnd
.
split
(
"-"
);
//开始时间转换成时间戳
Calendar
start
=
Calendar
.
getInstance
();
start
.
set
(
Integer
.
valueOf
(
dateBegs
[
0
]),
Integer
.
valueOf
(
dateBegs
[
1
])
-
1
,
Integer
.
valueOf
(
dateBegs
[
2
]));
Long
startTIme
=
start
.
getTimeInMillis
();
//结束时间转换成时间戳
Calendar
end
=
Calendar
.
getInstance
();
end
.
set
(
Integer
.
valueOf
(
dateEnds
[
0
]),
Integer
.
valueOf
(
dateEnds
[
1
])
-
1
,
Integer
.
valueOf
(
dateEnds
[
2
]));
Long
endTime
=
end
.
getTimeInMillis
();
//定义一个一天的时间戳时长
Long
oneDay
=
1000
*
60
*
60
*
24
l
;
Long
time
=
startTIme
;
//循环得出
while
(
time
<=
endTime
)
{
list
.
add
(
new
SimpleDateFormat
(
"yyyy-MM-dd"
).
format
(
new
Date
(
time
)));
time
+=
oneDay
;
}
return
list
;
}
}
\ No newline at end of file
wj-datacenter-service/src/main/java/net/wanji/datacenter/util/FastJson2JsonRedisSerializer.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
util
;
import
com.alibaba.fastjson.JSON
;
import
com.alibaba.fastjson.serializer.SerializerFeature
;
import
org.springframework.data.redis.serializer.RedisSerializer
;
import
org.springframework.data.redis.serializer.SerializationException
;
import
java.nio.charset.Charset
;
public
class
FastJson2JsonRedisSerializer
<
T
>
implements
RedisSerializer
<
T
>
{
public
static
final
Charset
DEFAULT_CHARSET
=
Charset
.
forName
(
"UTF-8"
);
private
Class
<
T
>
clazz
;
public
FastJson2JsonRedisSerializer
(
Class
<
T
>
clazz
)
{
super
();
this
.
clazz
=
clazz
;
}
@Override
public
byte
[]
serialize
(
T
t
)
throws
SerializationException
{
if
(
t
==
null
)
{
return
new
byte
[
0
];
}
return
JSON
.
toJSONString
(
t
,
SerializerFeature
.
WriteClassName
).
getBytes
(
DEFAULT_CHARSET
);
}
@Override
public
T
deserialize
(
byte
[]
bytes
)
throws
SerializationException
{
if
(
bytes
==
null
||
bytes
.
length
<=
0
)
{
return
null
;
}
String
str
=
new
String
(
bytes
,
DEFAULT_CHARSET
);
return
(
T
)
JSON
.
parseObject
(
str
,
clazz
);
}
}
\ No newline at end of file
wj-datacenter-service/src/main/java/net/wanji/datacenter/util/RedisUtils.java
0 → 100644
View file @
45271677
package
net
.
wanji
.
datacenter
.
util
;
import
net.wanji.datacenter.constant.Constant
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.core.ValueOperations
;
import
org.springframework.data.redis.support.atomic.RedisAtomicLong
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.Resource
;
import
java.text.DecimalFormat
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.TimeUnit
;
/**
* @description: redis工具类
* @author wanji
* @version 1.0
* Created on 2019/4/29 20:34
*/
@Component
public
class
RedisUtils
{
/**
* 注入redisTemplate
*/
@Resource
private
RedisTemplate
<
String
,
Object
>
redisTemplate
;
/**
* @description: 判断是否存在Key
* @param key redis的Key
* @return boolean true:有 false:无
*/
public
boolean
hasKey
(
String
key
)
{
return
redisTemplate
.
hasKey
(
key
);
}
/**
* @description: 添加字符串
* @param key redis的Key
* @param value 添加redis的value
*/
public
void
set
(
String
key
,
String
value
)
{
redisTemplate
.
opsForValue
().
set
(
key
,
value
);
}
/**
* @description: 添加对象
* @param key redis的Key
* @param object 添加redis的value
*/
public
void
set
(
String
key
,
Object
object
)
{
redisTemplate
.
opsForValue
().
set
(
key
,
object
);
}
/**
* @description: 添加带生命周期的对象
* @param key redis的Key
* @param object 添加redis的value
* @param seconds 失效时间
*/
public
void
setAndExpire
(
String
key
,
Object
object
,
int
seconds
)
{
redisTemplate
.
opsForValue
().
set
(
key
,
object
);
redisTemplate
.
expire
(
key
,
seconds
,
TimeUnit
.
SECONDS
);
}
/**
* @description: 添加带生命周期的对象
* @param key redis的Key
* @param value 添加redis的value
* @param seconds 失效时间
*/
public
void
setAndExpire
(
String
key
,
String
value
,
int
seconds
)
{
redisTemplate
.
opsForValue
().
set
(
key
,
value
);
redisTemplate
.
expire
(
key
,
seconds
,
TimeUnit
.
SECONDS
);
}
/**
* @description: 获取对象
* @param key redis的Key
* @return Object 返回对象
*/
public
Object
get
(
String
key
)
{
return
redisTemplate
.
opsForValue
().
get
(
key
);
}
/**
* @description: 存入redis的hash
* @param key redis的Key
* @param field 字段值
* @param value 存入的值
*/
public
void
setHash
(
String
key
,
String
field
,
String
value
)
{
redisTemplate
.
opsForHash
().
put
(
key
,
field
,
value
);
}
/**
* @description: 存入redis的hash
* @param key redis的Key
* @param field 字段值
* @param value 存入的值
*/
public
void
setHash
(
String
key
,
String
field
,
Object
value
)
{
redisTemplate
.
opsForHash
().
put
(
key
,
field
,
value
);
}
/**
* @description: 根据key和字段值获取内容值
* @param key redis的Key
* @param field 字段值
* @return String 返回字符串
*/
public
String
getHash
(
String
key
,
String
field
)
{
return
(
String
)
redisTemplate
.
opsForHash
().
get
(
key
,
field
);
}
/**
* @description: 根据field删除值
* @param key redis的Key
* @param field 字段值
*/
public
void
delHashMap
(
String
key
,
String
field
)
{
redisTemplate
.
boundHashOps
(
key
).
delete
(
field
);
}
/**
* @description: 存入hash集合
* @param key redis的Key
* @param hashmap 存入的Map集合
*/
public
void
setHashMap
(
String
key
,
Map
<
String
,
Object
>
hashmap
){
redisTemplate
.
opsForHash
().
putAll
(
key
,
hashmap
);
}
/**
* @description: 取出hash集合
* @param key redis的Key
* @return Map<Object, Object> 返回Map集合
*/
public
Map
<
Object
,
Object
>
getHashMap
(
String
key
)
{
return
redisTemplate
.
opsForHash
().
entries
(
key
);
}
/**
* @description: 存入redis的Set
* @param key redis的Key
* @param object 对象
*/
public
void
setSet
(
String
key
,
Object
object
){
redisTemplate
.
opsForSet
().
add
(
key
,
object
);
}
/**
* @description: 获取redis的Set
* @param key redis的Key
* @return Set<Object> Set集合
*/
public
Set
<
Object
>
getSet
(
String
key
){
return
redisTemplate
.
opsForSet
().
members
(
key
);
}
/**
* @discription: 查看值是否是set成员
* @param key set的key
* @param value set的成员
* @return 是否是set成员
*/
public
Boolean
isSetMember
(
String
key
,
Object
value
)
{
return
redisTemplate
.
opsForSet
().
isMember
(
key
,
value
);
}
/**
* @description:设置key的过期时间,endTime格式:yyyy-MM-dd hh:mm:ss
* @param key redis的Key
* @param endTime 结束时间
*/
public
void
setExpire
(
String
key
,
Date
endTime
)
{
long
seconds
=
endTime
.
getTime
()
-
System
.
currentTimeMillis
();
redisTemplate
.
expire
(
key
,
(
int
)
(
seconds
/
1000
),
TimeUnit
.
SECONDS
);
}
/**
* @description: 设置key的过期时间
* @param key redis的Key
* @param time 过期时间(秒)
*/
public
void
setExpire
(
String
key
,
int
time
)
{
redisTemplate
.
expire
(
key
,
time
,
TimeUnit
.
SECONDS
);
}
/**
* <p>Discription:获取key的过期时间
* @param key redis的Key
* @return 过期时间(秒)
*/
public
Long
getExpire
(
String
key
)
{
return
redisTemplate
.
getExpire
(
key
,
TimeUnit
.
SECONDS
);
}
/**
* @description: 在redis消息队列队尾插入数据
* @param key redis的Key
* @param object 添加的对象
*/
public
void
tailPush
(
String
key
,
Object
object
){
redisTemplate
.
opsForList
().
rightPush
(
key
,
object
);
}
/**
* @description: 在redis消息队列对头插入数据
* @param key redis的Key
* @param object 添加的对象
*/
public
void
headPush
(
String
key
,
Object
object
){
redisTemplate
.
opsForList
().
leftPush
(
key
,
object
);
}
/**
* @description: 在redis消息队列队尾删除数据
* @param key redis的Key
* @return Object 删除的对象
*/
public
Object
tailPop
(
String
key
){
return
redisTemplate
.
opsForList
().
rightPop
(
key
);
}
/**
* @description: 在redis消息队列队头删除数据
* @param key redis的Key
* @return Object 删除的对象
*/
public
Object
headPop
(
String
key
){
return
redisTemplate
.
opsForList
().
leftPop
(
key
);
}
/**
* @description: 删除redis的值
* @param key redis的Key
*/
public
void
del
(
String
key
)
{
if
(
hasKey
(
key
))
{
redisTemplate
.
delete
(
key
);
}
}
/**
* @description: 清理redis缓存
*/
public
void
flushDB
(){
redisTemplate
.
getConnectionFactory
().
getConnection
().
flushDb
();
}
/**
* @description: 根据类型生成版本号
* @param type 类型key区分
* @return 版本号
* @author wanji
* @date 2019/5/5 19:26
*/
public
String
getVersion
(
String
type
)
{
String
formatDate
=
DateUtils
.
dateToString
(
new
Date
(),
DateStyle
.
YYYYMMDD
);
String
key
=
Constant
.
KEY_PREFIX
+
type
+
formatDate
;
//当前时间到第二天还剩多少时间
Date
newDate
=
DateUtils
.
dateForMat
(
DateUtils
.
addDay
(
new
Date
(),
1
),
DateStyle
.
YYYY_MM_DD
);
int
liveTime
=
DateUtils
.
dayDiff
(
newDate
,
new
Date
(),
Calendar
.
MILLISECOND
);
//获取自增号
Long
incr
=
getIncr
(
key
,
liveTime
);
if
(
incr
==
0
)
{
incr
=
getIncr
(
key
,
liveTime
);
//从001开始
}
DecimalFormat
df
=
new
DecimalFormat
(
"000"
);
//三位序列号
return
formatDate
+
Constant
.
SEPARATOR_MINUS
+
df
.
format
(
incr
);
}
/**
* 自增ID
* @param key 建
* @param liveTime 过期时间
* @return 自增结果
*/
public
Long
getIncr
(
String
key
,
long
liveTime
)
{
RedisAtomicLong
entityIdCounter
=
new
RedisAtomicLong
(
key
,
redisTemplate
.
getConnectionFactory
());
Long
increment
=
entityIdCounter
.
getAndIncrement
();
if
((
null
==
increment
||
increment
.
longValue
()
==
0
)
&&
liveTime
>
0
)
{
//初始设置过期时间
entityIdCounter
.
expire
(
liveTime
,
TimeUnit
.
MILLISECONDS
);
//单位毫秒
}
return
increment
;
}
/**
* 获取全部Redis的key
* @return
*/
public
Set
<
String
>
keys
()
{
return
redisTemplate
.
keys
(
"*"
);
}
/**
* 获取全局ID范围
*
* @param key 建
* @param increment ID范围
* @return
*/
public
Long
getGlobalIdRange
(
String
key
,
long
increment
)
{
ValueOperations
<
String
,
Object
>
ops
=
redisTemplate
.
opsForValue
();
Long
newIdRangeStart
=
ops
.
increment
(
key
,
increment
);
// The range of IDs that are now reserved are from newIdRangeStart - increment + 1 to newIdRangeStart.
return
newIdRangeStart
-
increment
+
1
;
}
/**
* 带过期时间存入 zset
* @param ttlInMillis 存活时间毫秒数
*/
public
void
addToSortedSetWithExpiry
(
String
key
,
String
value
,
long
ttlInMillis
)
{
long
score
=
new
Date
().
getTime
()
+
ttlInMillis
;
redisTemplate
.
opsForZSet
().
add
(
key
,
value
,
score
);
}
/**
* 删除过期的 zset 元素
*/
public
void
removeExpiredElements
(
String
key
)
{
long
now
=
new
Date
().
getTime
();
redisTemplate
.
opsForZSet
().
removeRangeByScore
(
key
,
0
,
now
);
}
}
wj-datacenter-service/src/main/resources/application-local.yaml
View file @
45271677
...
@@ -43,7 +43,7 @@ spring:
...
@@ -43,7 +43,7 @@ spring:
max-poll-records
:
1
max-poll-records
:
1
broker-id
:
0
broker-id
:
0
auto-commit-interval
:
1S
auto-commit-interval
:
1S
auto-offset-reset
:
earli
est
auto-offset-reset
:
lat
est
enable-auto-commit
:
false
enable-auto-commit
:
false
key-deserializer
:
org.apache.kafka.common.serialization.StringDeserializer
key-deserializer
:
org.apache.kafka.common.serialization.StringDeserializer
value-deserializer
:
org.apache.kafka.common.serialization.StringDeserializer
value-deserializer
:
org.apache.kafka.common.serialization.StringDeserializer
...
@@ -52,6 +52,18 @@ spring:
...
@@ -52,6 +52,18 @@ spring:
concurrency
:
3
concurrency
:
3
ack-mode
:
manual_immediate
ack-mode
:
manual_immediate
missing-topics-fatal
:
false
missing-topics-fatal
:
false
redis
:
host
:
37.12.182.29
port
:
6379
password
:
Wanji300552
jedis
:
pool
:
max-active
:
200
max-wait
:
5000
max-idle
:
20
min-idle
:
10
timeout
:
5000
database
:
7
mybatis-plus
:
mybatis-plus
:
mapper-locations
:
classpath*:mapper/*.xml,classpath:mapper/*/*.xml
mapper-locations
:
classpath*:mapper/*.xml,classpath:mapper/*/*.xml
...
...
wj-realtime-computing/src/main/java/com/wanji/indicators/task/trajectory/func/VehicleGapTimeProcessFunction.java
View file @
45271677
...
@@ -11,12 +11,12 @@ import com.wanji.indicators.task.lightstatus.model.VehicleHeadTimeModel;
...
@@ -11,12 +11,12 @@ import com.wanji.indicators.task.lightstatus.model.VehicleHeadTimeModel;
import
com.wanji.indicators.task.trajectory.pojo.CrossEventResult
;
import
com.wanji.indicators.task.trajectory.pojo.CrossEventResult
;
import
com.wanji.indicators.task.trajectory.pojo.StartDuration
;
import
com.wanji.indicators.task.trajectory.pojo.StartDuration
;
import
com.wanji.indicators.util.GeomsConvertUtil
;
import
com.wanji.indicators.util.GeomsConvertUtil
;
import
com.wanji.indicators.util.PtInPolyUtil
;
import
org.apache.flink.api.common.state.MapState
;
import
org.apache.flink.api.common.state.MapState
;
import
org.apache.flink.api.common.state.MapStateDescriptor
;
import
org.apache.flink.api.common.state.MapStateDescriptor
;
import
org.apache.flink.configuration.Configuration
;
import
org.apache.flink.configuration.Configuration
;
import
org.apache.flink.streaming.api.functions.KeyedProcessFunction
;
import
org.apache.flink.streaming.api.functions.KeyedProcessFunction
;
import
org.apache.flink.util.Collector
;
import
org.apache.flink.util.Collector
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringUtils
;
import
java.time.Instant
;
import
java.time.Instant
;
...
@@ -32,14 +32,16 @@ import java.util.stream.StreamSupport;
...
@@ -32,14 +32,16 @@ import java.util.stream.StreamSupport;
* @Description :
* @Description :
*/
*/
public
class
VehicleGapTimeProcessFunction
extends
KeyedProcessFunction
<
String
,
CrossFrameModel
,
CrossEventResult
>
{
public
class
VehicleGapTimeProcessFunction
extends
KeyedProcessFunction
<
String
,
CrossFrameModel
,
CrossEventResult
>
{
//
车道上离停止线最近的车辆缓存
//
车道上离停止线最近的车辆缓存。Key:方向-车道ID
private
transient
MapState
<
String
,
CarTrackModel
>
mapState
;
private
transient
MapState
<
String
,
CarTrackModel
>
mapState
;
//
绿灯总时长
//
绿灯总时长。Key:路口ID-方向
private
transient
MapState
<
String
,
Integer
>
greenTotalTimeState
;
private
transient
MapState
<
String
,
Integer
>
greenTotalTimeState
;
//
车道车头时距缓存
//
车道车头时距缓存。Key:方向-车道ID
private
transient
MapState
<
String
,
VehicleHeadTimeModel
>
resultState
;
private
transient
MapState
<
String
,
VehicleHeadTimeModel
>
resultState
;
// 开始时间和持续时长状态。Key:方向
// 开始时间和持续时长状态。Key:方向
private
transient
MapState
<
Integer
,
StartDuration
>
dirState
;
private
transient
MapState
<
Integer
,
StartDuration
>
dirState
;
// 方向最近一次灯色。Key:方向,Value:灯色
private
transient
MapState
<
Integer
,
String
>
dirLastSecondState
;
@Override
@Override
public
void
open
(
Configuration
parameters
)
{
public
void
open
(
Configuration
parameters
)
{
...
@@ -47,6 +49,7 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -47,6 +49,7 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
resultState
=
getRuntimeContext
().
getMapState
(
new
MapStateDescriptor
<>(
"light_result_map"
,
String
.
class
,
VehicleHeadTimeModel
.
class
));
resultState
=
getRuntimeContext
().
getMapState
(
new
MapStateDescriptor
<>(
"light_result_map"
,
String
.
class
,
VehicleHeadTimeModel
.
class
));
greenTotalTimeState
=
getRuntimeContext
().
getMapState
(
new
MapStateDescriptor
<>(
"light_total_time_map"
,
String
.
class
,
Integer
.
class
));
greenTotalTimeState
=
getRuntimeContext
().
getMapState
(
new
MapStateDescriptor
<>(
"light_total_time_map"
,
String
.
class
,
Integer
.
class
));
dirState
=
getRuntimeContext
().
getMapState
(
new
MapStateDescriptor
<>(
"dir_map"
,
Integer
.
class
,
StartDuration
.
class
));
dirState
=
getRuntimeContext
().
getMapState
(
new
MapStateDescriptor
<>(
"dir_map"
,
Integer
.
class
,
StartDuration
.
class
));
dirLastSecondState
=
getRuntimeContext
().
getMapState
(
new
MapStateDescriptor
<>(
"dir_last_minute"
,
Integer
.
class
,
String
.
class
));
}
}
@Override
@Override
...
@@ -55,23 +58,26 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -55,23 +58,26 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
List
<
CarTrackModel
>
trackList
=
value
.
getTrackList
();
List
<
CarTrackModel
>
trackList
=
value
.
getTrackList
();
//灯态数据
//灯态数据
List
<
CrossRidTurnLampStatusModel
>
ridLightStatusList
=
value
.
getRidTurnLampList
();
List
<
CrossRidTurnLampStatusModel
>
ridLightStatusList
=
value
.
getRidTurnLampList
();
//当前南北绿灯放行进口车道
//
当前南北绿灯放行进口车道
Map
<
Integer
,
List
<
CrossRidTurnLampStatusModel
>>
groupLightStatus
=
Map
<
Integer
,
List
<
CrossRidTurnLampStatusModel
>>
groupLightStatus
=
ridLightStatusList
.
stream
()
ridLightStatusList
.
stream
()
.
filter
(
o
->
Objects
.
nonNull
(
o
)
&&
!
StringUtils
.
isEmpty
(
o
.
getLampState
())
&&
o
.
getLampState
().
trim
().
equals
(
LightStatusEnum
.
GREEN
.
getType
()))
.
filter
(
o
->
Objects
.
nonNull
(
o
)
&&
!
StringUtils
.
isEmpty
(
o
.
getLampState
())
.
filter
(
o
->
o
.
getDir
()
==
1
||
o
.
getDir
()
==
4
||
o
.
getDir
()
==
5
)
//非协调方向
&&
o
.
getLampState
().
trim
().
equals
(
LightStatusEnum
.
GREEN
.
getType
()))
.
filter
(
o
->
o
.
getDir
()
==
1
||
o
.
getDir
()
==
4
||
o
.
getDir
()
==
5
)
// 非协调方向
.
filter
(
o
->
!
o
.
getTurn
().
equals
(
Constant
.
PEDESTRAIN_LIGHT_CODE
))
// 非行人灯
.
filter
(
o
->
!
o
.
getTurn
().
equals
(
Constant
.
PEDESTRAIN_LIGHT_CODE
))
// 非行人灯
.
filter
(
o
->
!
o
.
getTurn
().
equals
(
Constant
.
RIGHT_LIGHT_CODE
))
// 非右转灯
.
filter
(
o
->
!
o
.
getTurn
().
equals
(
Constant
.
RIGHT_LIGHT_CODE
))
// 非右转灯
.
collect
(
Collectors
.
groupingBy
(
CrossRidTurnLampStatusModel:
:
getDir
));
.
collect
(
Collectors
.
groupingBy
(
CrossRidTurnLampStatusModel:
:
getDir
));
//存储当前非协调方向绿灯结束的路口和绿灯时长
//
存储当前非协调方向绿灯结束的路口和绿灯时长
Map
<
Integer
,
Integer
>
expiredGreenLightMap
=
new
HashMap
<>();
Map
<
Integer
,
Integer
>
expiredGreenLightMap
=
new
HashMap
<>();
if
(!
greenTotalTimeState
.
isEmpty
())
{
if
(!
greenTotalTimeState
.
isEmpty
())
{
Iterable
<
String
>
keys
=
greenTotalTimeState
.
keys
();
Iterable
<
String
>
keys
=
greenTotalTimeState
.
keys
();
for
(
String
key:
keys
)
{
for
(
String
key
:
keys
)
{
String
[]
split
=
key
.
trim
().
split
(
"-"
);
// "路口ID-方向"
String
[]
split
=
key
.
trim
().
split
(
"-"
);
// "路口ID-方向"
int
dir
=
Integer
.
parseInt
(
split
[
1
]);
int
dir
=
Integer
.
parseInt
(
split
[
1
]);
if
(!
groupLightStatus
.
containsKey
(
dir
)){
String
dirLastSecond
=
dirLastSecondState
.
get
(
dir
);
if
(!
groupLightStatus
.
containsKey
(
dir
)
&&
Objects
.
equals
(
dirLastSecond
,
LightStatusEnum
.
GREEN
.
getType
()))
{
expiredGreenLightMap
.
put
(
dir
,
greenTotalTimeState
.
get
(
key
));
expiredGreenLightMap
.
put
(
dir
,
greenTotalTimeState
.
get
(
key
));
}
}
}
}
...
@@ -83,20 +89,21 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -83,20 +89,21 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
// 更新绿灯相位周期总时长
// 更新绿灯相位周期总时长
String
combinedKey
=
crossId
+
"-"
+
dir
;
String
combinedKey
=
crossId
+
"-"
+
dir
;
if
(!
greenTotalTimeState
.
contains
(
combinedKey
))
{
if
(!
greenTotalTimeState
.
contains
(
combinedKey
))
{
greenTotalTimeState
.
put
(
combinedKey
,
value1
.
get
(
0
).
getCyclePhaseCountDown
());
greenTotalTimeState
.
put
(
combinedKey
,
value1
.
get
(
0
).
getCyclePhaseCountDown
());
}
}
//绿灯放行进入路口内的车辆
//
绿灯放行进入路口内的车辆
List
<
CarTrackModel
>
runList
=
trackList
.
stream
()
List
<
CarTrackModel
>
runList
=
trackList
.
stream
()
.
filter
(
o
->
entry
.
getKey
().
equals
(
o
.
getRoadnet
().
getRidDir8
())
&&
o
.
getRoadnet
().
getInCrossFlag
()
==
Constant
.
CROSSING
)
.
filter
(
o
->
entry
.
getKey
().
equals
(
o
.
getRoadnet
().
getRidDir8
())
&&
o
.
getRoadnet
().
getInCrossFlag
()
==
Constant
.
CROSSING
)
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
if
(!
runList
.
isEmpty
())
{
if
(!
runList
.
isEmpty
())
{
//按车道分组
//
按车道分组
Map
<
String
,
List
<
CarTrackModel
>>
groupByLane
=
runList
.
stream
()
.
collect
(
Collectors
.
groupingBy
(
O
->
O
.
getRoadnet
().
getLaneId
()));
Map
<
String
,
List
<
CarTrackModel
>>
groupByLane
=
runList
.
stream
()
for
(
Map
.
Entry
<
String
,
List
<
CarTrackModel
>>
entry1
:
groupByLane
.
entrySet
())
{
.
collect
(
Collectors
.
groupingBy
(
O
->
O
.
getRoadnet
().
getLaneId
()));
for
(
Map
.
Entry
<
String
,
List
<
CarTrackModel
>>
entry1
:
groupByLane
.
entrySet
())
{
List
<
CarTrackModel
>
laneCarList
=
entry1
.
getValue
();
List
<
CarTrackModel
>
laneCarList
=
entry1
.
getValue
();
// 计算路口内车辆到停止线距离
// 计算路口内车辆到停止线距离
laneCarList
.
forEach
(
o
->
{
laneCarList
.
forEach
(
o
->
{
...
@@ -107,10 +114,11 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -107,10 +114,11 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
double
stopLineDist
=
GeomsConvertUtil
.
getDistance
(
o
.
getLongitude
(),
o
.
getLatitude
(),
Double
.
parseDouble
(
sps
[
0
]),
Double
.
parseDouble
(
sps
[
1
]));
double
stopLineDist
=
GeomsConvertUtil
.
getDistance
(
o
.
getLongitude
(),
o
.
getLatitude
(),
Double
.
parseDouble
(
sps
[
0
]),
Double
.
parseDouble
(
sps
[
1
]));
o
.
setStopLineDist
(
stopLineDist
);
o
.
setStopLineDist
(
stopLineDist
);
}
}
});
});
//按距离排序
//按距离排序
laneCarList
=
laneCarList
.
stream
().
sorted
(
Comparator
.
comparing
(
CarTrackModel:
:
getStopLineDist
)).
collect
(
Collectors
.
toList
());
laneCarList
=
laneCarList
.
stream
()
.
sorted
(
Comparator
.
comparing
(
CarTrackModel:
:
getStopLineDist
))
.
collect
(
Collectors
.
toList
());
//取靠近停止线的一辆车
//取靠近停止线的一辆车
CarTrackModel
lastCar
=
laneCarList
.
get
(
0
);
CarTrackModel
lastCar
=
laneCarList
.
get
(
0
);
...
@@ -119,30 +127,23 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -119,30 +127,23 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
String
key
=
dir
+
"-"
+
laneId
;
String
key
=
dir
+
"-"
+
laneId
;
CarTrackModel
agoCar
=
mapState
.
get
(
key
);
CarTrackModel
agoCar
=
mapState
.
get
(
key
);
//绿灯区间计算
//
绿灯区间计算
if
(
agoCar
!=
null
)
{
if
(
agoCar
!=
null
)
{
Integer
trackId
=
lastCar
.
getId
();
Integer
trackId
=
lastCar
.
getId
();
Integer
agoTrackId
=
agoCar
.
getId
();
Integer
agoTrackId
=
agoCar
.
getId
();
//新的车辆驶出停止线
//新的车辆驶出停止线
if
(!
Objects
.
equals
(
agoTrackId
,
trackId
))
{
if
(!
Objects
.
equals
(
agoTrackId
,
trackId
))
{
//车辆类型
Integer
lastCarType
=
lastCar
.
getOriginalType
();
//车长配置,单位米
//车长配置,单位米
int
carLength
=
4
;
int
carLength
=
4
;
//前车车辆类型
Integer
agoCarType
=
agoCar
.
getOriginalType
();
int
agoCarLength
=
4
;
//TODO 不同车型长度配置
double
distance
=
PtInPolyUtil
.
getDistance
(
agoCar
.
getLongitude
(),
agoCar
.
getLongitude
(),
lastCar
.
getLongitude
(),
lastCar
.
getLatitude
());
double
lastCarSpeed
=
lastCar
.
getSpeed
()
/
3.6
;
double
lastCarSpeed
=
lastCar
.
getSpeed
()
/
3.6
;
//计算车头时距(空当时间)
(前车车尾到后车车头距离)/后车速度
//计算车头时距(空当时间)
// double time = (distance - carLength / 2 - agoCarLength / 2) / lastCarSpeed;
double
time
=
(
lastCar
.
getGlobalTimeStamp
()
-
agoCar
.
getGlobalTimeStamp
())
/
1000.0
double
time
=
(
lastCar
.
getGlobalTimeStamp
()
-
agoCar
.
getGlobalTimeStamp
())
/
1000.0
-
carLength
/
lastCarSpeed
;
-
carLength
/
lastCarSpeed
;
VehicleHeadTimeModel
agoTimeModel
=
resultState
.
get
(
key
);
VehicleHeadTimeModel
agoTimeModel
=
resultState
.
get
(
key
);
if
(
agoTimeModel
!=
null
)
{
if
(
agoTimeModel
!=
null
)
{
//空当时间累加
//空当时间累加
time
=
agoTimeModel
.
getHeadTime
()
+
time
;
time
+=
agoTimeModel
.
getHeadTime
()
;
}
}
VehicleHeadTimeModel
timeModel
=
new
VehicleHeadTimeModel
();
VehicleHeadTimeModel
timeModel
=
new
VehicleHeadTimeModel
();
...
@@ -160,14 +161,15 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -160,14 +161,15 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
}
else
{
}
else
{
mapState
.
put
(
key
,
lastCar
);
mapState
.
put
(
key
,
lastCar
);
}
}
}
}
}
}
}
}
// 存在绿灯倒计时结束
if
(!
expiredGreenLightMap
.
isEmpty
())
{
if
(!
expiredGreenLightMap
.
isEmpty
()){
// 存在绿灯倒计时结束
for
(
Map
.
Entry
<
Integer
,
Integer
>
expiredLight:
expiredGreenLightMap
.
entrySet
()){
Iterator
<
Map
.
Entry
<
Integer
,
Integer
>>
iterator
=
expiredGreenLightMap
.
entrySet
().
iterator
();
while
(
iterator
.
hasNext
())
{
Map
.
Entry
<
Integer
,
Integer
>
expiredLight
=
iterator
.
next
();
Integer
dir
=
expiredLight
.
getKey
();
Integer
dir
=
expiredLight
.
getKey
();
Integer
totalGreenLightTime
=
expiredLight
.
getValue
();
Integer
totalGreenLightTime
=
expiredLight
.
getValue
();
...
@@ -176,44 +178,48 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -176,44 +178,48 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
.
filter
(
stat
->
stat
.
getDir
().
compareTo
(
dir
)
==
0
)
.
filter
(
stat
->
stat
.
getDir
().
compareTo
(
dir
)
==
0
)
.
collect
(
Collectors
.
toList
());
.
collect
(
Collectors
.
toList
());
//删除统计结果缓存
if
(!
stats
.
isEmpty
())
{
Iterator
<
String
>
resultStateIterator
=
resultState
.
keys
().
iterator
();
while
(
resultStateIterator
.
hasNext
()){
String
key
=
resultStateIterator
.
next
();
if
(
key
.
startsWith
(
String
.
valueOf
(
dir
))){
resultStateIterator
.
remove
();
}
}
//删除车道相关缓存
Iterator
<
String
>
mapStateIterator
=
mapState
.
keys
().
iterator
();
while
(
mapStateIterator
.
hasNext
()){
String
key
=
mapStateIterator
.
next
();
if
(
key
.
startsWith
(
String
.
valueOf
(
dir
))){
mapStateIterator
.
remove
();
}
}
if
(!
stats
.
isEmpty
()){
double
average
=
stats
.
stream
()
double
average
=
stats
.
stream
()
.
mapToDouble
(
VehicleHeadTimeModel:
:
getHeadTime
)
.
mapToDouble
(
VehicleHeadTimeModel:
:
getHeadTime
)
.
summaryStatistics
()
.
summaryStatistics
()
.
getAverage
();
.
getAverage
();
double
index
=
(
totalGreenLightTime
-
average
)
/
totalGreenLightTime
;
double
index
=
0
;
List
<
Long
>
lastCarTimeStampList
=
new
ArrayList
<>();
for
(
String
key
:
mapState
.
keys
())
{
if
(
key
.
startsWith
(
dir
.
toString
()))
{
CarTrackModel
carTrackModel
=
mapState
.
get
(
key
);
long
globalTimeStamp
=
carTrackModel
.
getGlobalTimeStamp
();
lastCarTimeStampList
.
add
(
globalTimeStamp
);
}
}
if
(!
ObjectUtils
.
isEmpty
(
lastCarTimeStampList
))
{
// 将空放时间计入空当时间
long
currentTimeMillis
=
System
.
currentTimeMillis
();
double
average2
=
lastCarTimeStampList
.
stream
()
.
mapToDouble
(
i
->
currentTimeMillis
-
i
)
.
average
().
getAsDouble
();
double
finalAvg
=
average
+
average2
;
index
=
(
totalGreenLightTime
-
finalAvg
)
/
totalGreenLightTime
;
}
else
{
index
=
(
totalGreenLightTime
-
average
)
/
totalGreenLightTime
;
}
double
convertedIndex
=
convertIndex
(
index
);
// 转换非协调方向拥堵指数
double
convertedIndex
=
convertIndex
(
index
);
// 转换非协调方向拥堵指数
String
indexName
;
String
indexName
;
String
congestionType
;
String
congestionType
;
if
(
convertedIndex
<=
1.5
)
{
if
(
convertedIndex
<=
1.5
)
{
indexName
=
"畅通"
;
indexName
=
"畅通"
;
congestionType
=
CongestEnum
.
NO_CONGEST
.
getCode
();
congestionType
=
CongestEnum
.
NO_CONGEST
.
getCode
();
}
else
if
(
convertedIndex
<=
2.0
)
{
}
else
if
(
convertedIndex
<=
2.0
)
{
indexName
=
"轻度拥堵"
;
indexName
=
"轻度拥堵"
;
congestionType
=
CongestEnum
.
LIGHT_CONGEST
.
getCode
();
congestionType
=
CongestEnum
.
LIGHT_CONGEST
.
getCode
();
}
else
if
(
convertedIndex
<
3.0
)
{
// 按照换算公式,最大只到3.0,因此这里不取等于
}
else
if
(
convertedIndex
<
3.0
)
{
// 按照换算公式,最大只到3.0,因此这里不取等于
indexName
=
"中度拥堵"
;
indexName
=
"中度拥堵"
;
congestionType
=
CongestEnum
.
MODERATE_CONGEST
.
getCode
();
congestionType
=
CongestEnum
.
MODERATE_CONGEST
.
getCode
();
}
else
{
}
else
{
indexName
=
"重度拥堵"
;
indexName
=
"重度拥堵"
;
congestionType
=
CongestEnum
.
HEAVY_CONGEST
.
getCode
();
congestionType
=
CongestEnum
.
HEAVY_CONGEST
.
getCode
();
}
}
...
@@ -226,14 +232,15 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -226,14 +232,15 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
long
time
=
new
Date
().
getTime
();
long
time
=
new
Date
().
getTime
();
stat
.
setGlobalTimeStamp
(
time
);
stat
.
setGlobalTimeStamp
(
time
);
stat
.
setDetectTime
(
time
);
stat
.
setDetectTime
(
time
);
stat
.
setIndexName
(
indexName
);
stat
.
setCongestionCode
(
congestionType
);
stat
.
setDir
(
dir
);
stat
.
setDir
(
dir
);
boolean
isCongestion
=
convertedIndex
>
1.5
;
boolean
isCongestion
=
convertedIndex
>
1.5
;
Integer
stateKey
=
dir
;
if
(
isCongestion
)
{
if
(
isCongestion
)
{
try
{
try
{
if
(!
dirState
.
contains
(
stateKey
))
{
if
(!
dirState
.
contains
(
dir
))
{
StartDuration
startDuration
=
new
StartDuration
();
StartDuration
startDuration
=
new
StartDuration
();
// 获取当前的时间戳
// 获取当前的时间戳
Instant
now
=
Instant
.
now
();
Instant
now
=
Instant
.
now
();
...
@@ -253,9 +260,9 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -253,9 +260,9 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
stat
.
setCongestionCode
(
congestionType
);
stat
.
setCongestionCode
(
congestionType
);
startDuration
.
setCongestionCode
(
congestionType
);
startDuration
.
setCongestionCode
(
congestionType
);
dirState
.
put
(
stateKey
,
startDuration
);
dirState
.
put
(
dir
,
startDuration
);
}
else
{
}
else
{
StartDuration
startDuration
=
dirState
.
get
(
stateKey
);
StartDuration
startDuration
=
dirState
.
get
(
dir
);
Long
startTimeMilli
=
startDuration
.
getStartTime
();
Long
startTimeMilli
=
startDuration
.
getStartTime
();
stat
.
setStartTime
(
startTimeMilli
);
stat
.
setStartTime
(
startTimeMilli
);
...
@@ -270,7 +277,7 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -270,7 +277,7 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
String
congestionCode
=
startDuration
.
getCongestionCode
();
String
congestionCode
=
startDuration
.
getCongestionCode
();
String
maxCongestionCode
=
calcMaxCongestionCode
(
congestionType
,
congestionCode
);
String
maxCongestionCode
=
calcMaxCongestionCode
(
congestionType
,
congestionCode
);
stat
.
setCongestionCode
(
maxCongestionCode
);
stat
.
setCongestionCode
(
maxCongestionCode
);
dirState
.
put
(
stateKey
,
startDuration
);
dirState
.
put
(
dir
,
startDuration
);
}
}
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
throw
new
RuntimeException
(
e
);
...
@@ -279,9 +286,9 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -279,9 +286,9 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
// 删除状态
// 删除状态
try
{
try
{
Iterator
<
Integer
>
dirStateKeysIter
=
dirState
.
keys
().
iterator
();
Iterator
<
Integer
>
dirStateKeysIter
=
dirState
.
keys
().
iterator
();
while
(
dirStateKeysIter
.
hasNext
()){
while
(
dirStateKeysIter
.
hasNext
())
{
Integer
key
=
dirStateKeysIter
.
next
();
Integer
key
=
dirStateKeysIter
.
next
();
if
(
key
.
equals
(
stateKey
))
{
if
(
key
.
equals
(
dir
))
{
dirStateKeysIter
.
remove
();
dirStateKeysIter
.
remove
();
}
}
}
}
...
@@ -290,7 +297,62 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
...
@@ -290,7 +297,62 @@ public class VehicleGapTimeProcessFunction extends KeyedProcessFunction<String,
}
}
}
}
out
.
collect
(
stat
);
out
.
collect
(
stat
);
}
else
{
// 无车或一辆车算畅通
CrossEventResult
stat
=
new
CrossEventResult
();
stat
.
setCrossId
(
crossId
);
stat
.
setCongestionCode
(
CongestEnum
.
NO_CONGEST
.
getType
());
stat
.
setRid
(
""
);
stat
.
setIndex
(
1.5
);
stat
.
setIndexName
(
CongestEnum
.
NO_CONGEST
.
getName
());
long
time
=
new
Date
().
getTime
();
stat
.
setGlobalTimeStamp
(
time
);
stat
.
setDetectTime
(
time
);
stat
.
setDir
(
dir
);
// 删除状态
try
{
Iterator
<
Integer
>
dirStateKeysIter
=
dirState
.
keys
().
iterator
();
while
(
dirStateKeysIter
.
hasNext
())
{
Integer
key
=
dirStateKeysIter
.
next
();
if
(
key
.
equals
(
dir
))
{
dirStateKeysIter
.
remove
();
}
}
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
out
.
collect
(
stat
);
}
// 删除统计结果缓存
Iterator
<
String
>
resultStateIterator
=
resultState
.
keys
().
iterator
();
while
(
resultStateIterator
.
hasNext
())
{
String
key
=
resultStateIterator
.
next
();
if
(
key
.
startsWith
(
String
.
valueOf
(
dir
)))
{
resultStateIterator
.
remove
();
}
}
}
//删除车道相关缓存
Iterator
<
String
>
mapStateIterator
=
mapState
.
keys
().
iterator
();
while
(
mapStateIterator
.
hasNext
())
{
String
key
=
mapStateIterator
.
next
();
if
(
key
.
startsWith
(
String
.
valueOf
(
dir
)))
{
mapStateIterator
.
remove
();
}
}
iterator
.
remove
();
}
}
// 存储每个方向上一秒灯色
for
(
CrossRidTurnLampStatusModel
model
:
ridLightStatusList
)
{
String
turn
=
model
.
getTurn
();
if
(!
turn
.
equals
(
Constant
.
PEDESTRAIN_LIGHT_CODE
)
&&
!
turn
.
equals
(
Constant
.
RIGHT_LIGHT_CODE
))
{
// 非行人灯,非右转灯
Integer
dir
=
model
.
getDir
();
String
lampState
=
model
.
getLampState
();
dirLastSecondState
.
put
(
dir
,
lampState
);
}
}
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment