Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
yangxiujun
/
paidan_demo
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit d772bb98
authored
Nov 20, 2023
by
Ren Ping
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:路网更新为redis缓存
1 parent
810f3686
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
870 additions
and
217 deletions
project-dispatch/src/main/java/com/dituhui/pea/dispatch/DispatchServiceApplication.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/RedisConfig.java → project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/redis/RedisConfig.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/redis/RedisUtil.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/RedissonConfig.java → project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/redis/RedissonConfig.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/RedissonUtil.java → project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/redis/RedissonUtil.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/constraint/RedisKeyConstant.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/quartz/dispatch/AutoDispatchJob.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/scheduler/BatchScheduler.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/ExtractServiceImpl.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/SchedulerServiceImpl.java
project-dispatch/src/main/java/com/dituhui/pea/dispatch/utils/RoadDistanceUtils.java
project-dispatch/src/main/resources/application-dev.yaml
project-dispatch/src/main/java/com/dituhui/pea/dispatch/DispatchServiceApplication.java
View file @
d772bb9
...
...
@@ -19,6 +19,7 @@ package com.dituhui.pea.dispatch;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.cloud.openfeign.EnableFeignClients
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
/**
...
...
@@ -27,6 +28,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
@EnableFeignClients
(
basePackages
=
{
"com.dituhui.pea.user"
})
@Import
(
cn
.
hutool
.
extra
.
spring
.
SpringUtil
.
class
)
public
class
DispatchServiceApplication
{
public
static
void
main
(
String
[]
args
)
{
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/RedisConfig.java
→
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/
redis/
RedisConfig.java
View file @
d772bb9
package
com
.
dituhui
.
pea
.
dispatch
.
common
;
package
com
.
dituhui
.
pea
.
dispatch
.
common
.
redis
;
import
com.fasterxml.jackson.annotation.JsonAutoDetect
;
import
com.fasterxml.jackson.annotation.PropertyAccessor
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.data.redis.connection.RedisConnectionFactory
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
;
import
org.springframework.data.redis.serializer.StringRedisSerializer
;
@Configuration
...
...
@@ -16,10 +21,27 @@ public class RedisConfig {
// objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
// ObjectMapper.DefaultTyping.EVERYTHING, JsonTypeInfo.As.PROPERTY);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer
jacksonSerial
=
new
Jackson2JsonRedisSerializer
(
Object
.
class
);
ObjectMapper
objectMapper
=
new
ObjectMapper
();
// 指定要序列化的域,field, get和set,以及修饰符范围,ANY是都有包括private和public
objectMapper
.
setVisibility
(
PropertyAccessor
.
ALL
,
JsonAutoDetect
.
Visibility
.
ANY
);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会抛出异常
objectMapper
.
activateDefaultTyping
(
objectMapper
.
getPolymorphicTypeValidator
(),
ObjectMapper
.
DefaultTyping
.
NON_FINAL
);
// jsonToBean时,json中有的字段,bean中没有 无法匹配时,忽略此字段,不抛出异常(默认是抛出异常的)
objectMapper
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
jacksonSerial
.
setObjectMapper
(
objectMapper
);
RedisTemplate
<
String
,
String
>
redisTemplate
=
new
RedisTemplate
<>();
redisTemplate
.
setConnectionFactory
(
connectionFactory
);
redisTemplate
.
setKeySerializer
(
new
StringRedisSerializer
());
redisTemplate
.
setValueSerializer
(
new
StringRedisSerializer
());
redisTemplate
.
setValueSerializer
(
jacksonSerial
);
// 设置hash key 和 value 序列化模式
redisTemplate
.
setHashKeySerializer
(
new
StringRedisSerializer
());
redisTemplate
.
setHashValueSerializer
(
jacksonSerial
);
return
redisTemplate
;
}
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/redis/RedisUtil.java
0 → 100644
View file @
d772bb9
package
com
.
dituhui
.
pea
.
dispatch
.
common
.
redis
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.extra.spring.SpringUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.PostConstruct
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.TimeUnit
;
/**
* @Description: TODO redis 工具类
* @Author: RenPing
* @Date: 2022/7/25 10:27
* @Version: 1.0
*/
@Slf4j
@Component
public
class
RedisUtil
{
private
static
RedisTemplate
<
String
,
Object
>
redisTemplate
;
@PostConstruct
public
void
init
()
{
redisTemplate
=
SpringUtil
.
getBean
(
"redisTemplate"
);
}
// ============================ Common ============================
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public
static
boolean
expire
(
String
key
,
long
time
)
{
try
{
if
(
time
>
0
)
{
redisTemplate
.
expire
(
key
,
time
,
TimeUnit
.
SECONDS
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public
static
long
getExpire
(
String
key
)
{
return
redisTemplate
.
getExpire
(
key
,
TimeUnit
.
SECONDS
);
}
/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public
static
boolean
hasKey
(
String
key
)
{
try
{
return
redisTemplate
.
hasKey
(
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
public
static
void
del
(
String
...
key
)
{
if
(
ObjectUtil
.
isNotEmpty
(
key
))
{
redisTemplate
.
delete
(
Arrays
.
asList
(
key
));
}
}
/**
* 模糊查询并删除key,如:cache:user:*
*
* @param regex
*/
public
static
void
deleteByKeys
(
String
regex
)
{
Set
<
String
>
keys
=
redisTemplate
.
keys
(
regex
);
if
(
ObjectUtil
.
isNotEmpty
(
keys
))
{
redisTemplate
.
delete
(
keys
);
}
}
// ============================ String ============================
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public
static
Object
get
(
String
key
)
{
return
key
==
null
?
null
:
redisTemplate
.
opsForValue
().
get
(
key
);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public
static
boolean
set
(
String
key
,
Object
value
)
{
try
{
redisTemplate
.
opsForValue
().
set
(
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public
static
boolean
set
(
String
key
,
Object
value
,
long
time
)
{
try
{
if
(
time
>
0
)
{
redisTemplate
.
opsForValue
().
set
(
key
,
value
,
time
,
TimeUnit
.
SECONDS
);
}
else
{
set
(
key
,
value
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 递增
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public
static
long
incr
(
String
key
,
long
delta
)
{
if
(
delta
<
0
)
{
throw
new
RuntimeException
(
"递增因子必须大于0"
);
}
return
redisTemplate
.
opsForValue
().
increment
(
key
,
delta
);
}
/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public
static
long
decr
(
String
key
,
long
delta
)
{
if
(
delta
<
0
)
{
throw
new
RuntimeException
(
"递减因子必须大于0"
);
}
return
redisTemplate
.
opsForValue
().
increment
(
key
,
-
delta
);
}
// ============================ Map ============================
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public
static
Object
hget
(
String
key
,
String
item
)
{
return
redisTemplate
.
opsForHash
().
get
(
key
,
item
);
}
/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public
static
Map
<
Object
,
Object
>
hmget
(
String
key
)
{
return
redisTemplate
.
opsForHash
().
entries
(
key
);
}
/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public
static
boolean
hmset
(
String
key
,
Map
<
Object
,
Object
>
map
)
{
try
{
redisTemplate
.
opsForHash
().
putAll
(
key
,
map
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public
static
boolean
hmset
(
String
key
,
Map
<
Object
,
Object
>
map
,
long
time
)
{
try
{
redisTemplate
.
opsForHash
().
putAll
(
key
,
map
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public
static
boolean
hset
(
String
key
,
String
item
,
Object
value
)
{
try
{
redisTemplate
.
opsForHash
().
put
(
key
,
item
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public
static
boolean
hset
(
String
key
,
String
item
,
Object
value
,
long
time
)
{
try
{
redisTemplate
.
opsForHash
().
put
(
key
,
item
,
value
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public
static
void
hdel
(
String
key
,
Object
...
item
)
{
redisTemplate
.
opsForHash
().
delete
(
key
,
item
);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public
static
boolean
hHasKey
(
String
key
,
String
item
)
{
return
redisTemplate
.
opsForHash
().
hasKey
(
key
,
item
);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public
static
double
hincr
(
String
key
,
String
item
,
double
by
)
{
return
redisTemplate
.
opsForHash
().
increment
(
key
,
item
,
by
);
}
/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public
static
double
hdecr
(
String
key
,
String
item
,
double
by
)
{
return
redisTemplate
.
opsForHash
().
increment
(
key
,
item
,
-
by
);
}
// ============================ set ============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public
static
Set
<
Object
>
sGet
(
String
key
)
{
try
{
return
redisTemplate
.
opsForSet
().
members
(
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
null
;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public
static
boolean
sHasKey
(
String
key
,
Object
value
)
{
try
{
return
redisTemplate
.
opsForSet
().
isMember
(
key
,
value
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public
static
long
sSet
(
String
key
,
Object
...
values
)
{
try
{
return
redisTemplate
.
opsForSet
().
add
(
key
,
values
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
0
;
}
}
/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public
static
long
sSetAndTime
(
String
key
,
long
time
,
Object
...
values
)
{
try
{
Long
count
=
redisTemplate
.
opsForSet
().
add
(
key
,
values
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
count
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
0
;
}
}
/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public
static
long
sGetSetSize
(
String
key
)
{
try
{
return
redisTemplate
.
opsForSet
().
size
(
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
0
;
}
}
/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public
static
long
setRemove
(
String
key
,
Object
...
values
)
{
try
{
Long
count
=
redisTemplate
.
opsForSet
().
remove
(
key
,
values
);
return
count
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
0
;
}
}
// ============================ list ============================
/**
* 获取list缓存的内容
*
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public
static
List
<
Object
>
lGet
(
String
key
,
long
start
,
long
end
)
{
try
{
return
redisTemplate
.
opsForList
().
range
(
key
,
start
,
end
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
null
;
}
}
/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public
static
long
lGetListSize
(
String
key
)
{
try
{
return
redisTemplate
.
opsForList
().
size
(
key
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
0
;
}
}
/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public
static
Object
lGetIndex
(
String
key
,
long
index
)
{
try
{
return
redisTemplate
.
opsForList
().
index
(
key
,
index
);
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
null
;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public
static
boolean
lSet
(
String
key
,
Object
value
)
{
try
{
redisTemplate
.
opsForList
().
rightPush
(
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public
static
boolean
lSet
(
String
key
,
Object
value
,
long
time
)
{
try
{
redisTemplate
.
opsForList
().
rightPush
(
key
,
value
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public
static
boolean
lSet
(
String
key
,
List
<
Object
>
value
)
{
try
{
redisTemplate
.
opsForList
().
rightPushAll
(
key
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public
static
boolean
lSet
(
String
key
,
List
<
Object
>
value
,
long
time
)
{
try
{
redisTemplate
.
opsForList
().
rightPushAll
(
key
,
value
);
if
(
time
>
0
)
{
expire
(
key
,
time
);
}
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* 507
* @param value 值
* @return
*/
public
static
boolean
lUpdateIndex
(
String
key
,
long
index
,
Object
value
)
{
try
{
redisTemplate
.
opsForList
().
set
(
key
,
index
,
value
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
false
;
}
}
/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public
static
long
lRemove
(
String
key
,
long
count
,
Object
value
)
{
try
{
Long
remove
=
redisTemplate
.
opsForList
().
remove
(
key
,
count
,
value
);
return
remove
;
}
catch
(
Exception
e
)
{
log
.
error
(
e
.
getMessage
(),
e
);
return
0
;
}
}
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/RedissonConfig.java
→
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/
redis/
RedissonConfig.java
View file @
d772bb9
package
com
.
dituhui
.
pea
.
dispatch
.
common
;
package
com
.
dituhui
.
pea
.
dispatch
.
common
.
redis
;
import
org.redisson.Redisson
;
import
org.redisson.api.RedissonClient
;
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/RedissonUtil.java
→
project-dispatch/src/main/java/com/dituhui/pea/dispatch/common/
redis/
RedissonUtil.java
View file @
d772bb9
package
com
.
dituhui
.
pea
.
dispatch
.
common
;
package
com
.
dituhui
.
pea
.
dispatch
.
common
.
redis
;
import
cn.hutool.extra.spring.SpringUtil
;
import
lombok.extern.slf4j.Slf4j
;
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/constraint/RedisKeyConstant.java
0 → 100644
View file @
d772bb9
package
com
.
dituhui
.
pea
.
dispatch
.
constraint
;
public
class
RedisKeyConstant
{
public
static
final
String
LOCATION_DISTANCE_KEY
=
"location:%s:distance:%s"
;
public
static
final
String
LOCATION_DISTANCE_TIME_KEY
=
"location:%s:distanceTime:%s"
;
}
project-dispatch/src/main/java/com/dituhui/pea/dispatch/quartz/dispatch/AutoDispatchJob.java
View file @
d772bb9
package
com
.
dituhui
.
pea
.
dispatch
.
quartz
.
dispatch
;
import
com.dituhui.pea.dispatch.common.RedissonUtil
;
import
com.dituhui.pea.dispatch.service.SchedulerService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.quartz.DisallowConcurrentExecution
;
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/scheduler/BatchScheduler.java
View file @
d772bb9
...
...
@@ -40,9 +40,9 @@ public class BatchScheduler {
@Autowired
ExtractService
extractService
;
@Autowired
OrgTeamDao
orgTeamDao
;
@Autowired
OrgTeamDao
orgTeamDao
;
private
DefaultSolverFactory
<
DispatchSolution
>
solverFactory
;
private
Solver
<
DispatchSolution
>
solver
;
...
...
@@ -52,22 +52,22 @@ public class BatchScheduler {
solver
=
solverFactory
.
buildSolver
();
}
/*
* 异步执行任务开始
*/
//@Scheduled(cron = "${dispatch.cron.expr}")
public
void
dispatchRun2
()
{
String
groupId
=
"gsuzhou"
;
log
.
info
(
"dispatchRun group:{}"
,
groupId
);
// TODO 分布式任务,循环大区/分部/分站/小队
// 循环分站/网点下面的小队
List
<
OrgTeamEntity
>
teams
=
orgTeamDao
.
findByGroupId
(
groupId
);
for
(
OrgTeamEntity
team
:
teams
)
{
String
teamId
=
team
.
getTeamId
();
for
(
int
i
=
1
;
i
<=
nextDaysLimit
;
i
++)
{
String
currDay
=
LocalDate
.
now
().
plusDays
(
i
).
format
(
DateTimeFormatter
.
ISO_LOCAL_DATE
);
log
.
info
(
"dispatchRun begin----- teamId:{}, day:{}"
,
teamId
,
currDay
);
/*
* 异步执行任务开始
*/
//@Scheduled(cron = "${dispatch.cron.expr}")
public
void
dispatchRun2
()
{
String
groupId
=
"gsuzhou"
;
log
.
info
(
"dispatchRun group:{}"
,
groupId
);
// TODO 分布式任务,循环大区/分部/分站/小队
// 循环分站/网点下面的小队
List
<
OrgTeamEntity
>
teams
=
orgTeamDao
.
findByGroupId
(
groupId
);
for
(
OrgTeamEntity
team
:
teams
)
{
String
teamId
=
team
.
getTeamId
();
for
(
int
i
=
1
;
i
<=
nextDaysLimit
;
i
++)
{
String
currDay
=
LocalDate
.
now
().
plusDays
(
i
).
format
(
DateTimeFormatter
.
ISO_LOCAL_DATE
);
log
.
info
(
"dispatchRun begin----- teamId:{}, day:{}"
,
teamId
,
currDay
);
String
batchNo
=
batchService
.
buildBatchData2
(
teamId
,
currDay
,
false
);
UUID
problemId
=
solveService
.
generateProblemId
(
teamId
,
batchNo
);
...
...
@@ -88,19 +88,19 @@ public class BatchScheduler {
log
.
info
(
"dispatchRun done ------ teamId:{}, day:{}"
,
teamId
,
currDay
);
JacksonSolutionFileIO
<
DispatchSolution
>
exporter
=
new
JacksonSolutionFileIO
<
DispatchSolution
>(
DispatchSolution
.
class
);
exporter
.
write
(
solution
,
new
File
(
String
.
format
(
"dispatchSolution_%s_%s.json"
,
teamId
,
currDay
)));
}
}
exporter
.
write
(
solution
,
new
File
(
String
.
format
(
"dispatchSolution_%s_%s.json"
,
teamId
,
currDay
)));
}
}
log
.
info
(
"dispatchRun group:{} done"
,
groupId
);
}
log
.
info
(
"dispatchRun group:{} done"
,
groupId
);
}
/*
* 异步执行任务开始
* */
//@Scheduled(cron = "${dispatch.cron.expr}")
public
void
dispatchRun
()
{
String
groupId
=
"gsuzhou"
;
String
groupId
=
"gsuzhou"
;
log
.
info
(
"dispatchRun group:{}"
,
groupId
);
try
{
for
(
int
i
=
0
;
i
<=
nextDaysLimit
;
i
++)
{
...
...
@@ -155,7 +155,7 @@ public class BatchScheduler {
// Set the output file.
exporter
.
write
(
solution
,
new
File
(
String
.
format
(
"dispatchSolution_%s_%s.json"
,
groupId
,
currDay
)));
exporter
.
write
(
solution
,
new
File
(
String
.
format
(
"dispatchSolution_%s_%s.json"
,
groupId
,
currDay
)));
Thread
.
sleep
(
1000
*
5
);
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/ExtractServiceImpl.java
View file @
d772bb9
...
...
@@ -3,9 +3,12 @@ package com.dituhui.pea.dispatch.service.impl;
import
cn.hutool.core.date.DateTime
;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.alibaba.nacos.common.utils.CollectionUtils
;
import
com.dituhui.pea.dispatch.dao.*
;
import
com.dituhui.pea.dispatch.entity.*
;
import
com.dituhui.pea.dispatch.pojo.Customer
;
import
com.dituhui.pea.dispatch.pojo.DispatchSolution
;
import
com.dituhui.pea.dispatch.service.ExtractService
;
import
com.google.common.collect.Maps
;
...
...
@@ -295,7 +298,13 @@ public class ExtractServiceImpl implements ExtractService {
orderInfo
.
setArriveElapsed
(
0
);
orderInfo
.
setArriveDistance
(
0
);
orderInfo
.
setAppointmentStatus
(
"INIT"
);
orderInfo
.
setDispatcher
(
"AUTO_BATCH"
);
if
(
cutOff
)
{
orderInfo
.
setAppointmentMethod
(
"MANUAL"
);
orderInfo
.
setDispatcher
(
"MANUAL"
);
log
.
info
(
"算法结果更新到工单为人工, teamId:{}, batchNo:{}, orderId:{}"
,
teamId
,
batchNo
,
orderId
);
}
else
{
orderInfo
.
setDispatcher
(
"AUTO_BATCH"
);
}
orderInfo
.
setUpdateTime
(
LocalDateTime
.
now
());
orderInfoRepo
.
save
(
orderInfo
);
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/service/impl/SchedulerServiceImpl.java
View file @
d772bb9
...
...
@@ -3,7 +3,6 @@ package com.dituhui.pea.dispatch.service.impl;
import
cn.hutool.core.date.DateUtil
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.core.util.StrUtil
;
import
com.dituhui.pea.dispatch.common.RedissonUtil
;
import
com.dituhui.pea.dispatch.dao.DispatchBatchRepository
;
import
com.dituhui.pea.dispatch.dao.OrgGroupRepository
;
import
com.dituhui.pea.dispatch.dao.OrgTeamDao
;
...
...
@@ -11,7 +10,6 @@ import com.dituhui.pea.dispatch.entity.DispatchBatch;
import
com.dituhui.pea.dispatch.entity.OrgGroup
;
import
com.dituhui.pea.dispatch.entity.OrgTeamEntity
;
import
com.dituhui.pea.dispatch.pojo.DispatchSolution
;
import
com.dituhui.pea.dispatch.quartz.dispatch.AutoDispatchJob
;
import
com.dituhui.pea.dispatch.service.BatchService
;
import
com.dituhui.pea.dispatch.service.ExtractService
;
import
com.dituhui.pea.dispatch.service.SchedulerService
;
...
...
project-dispatch/src/main/java/com/dituhui/pea/dispatch/utils/RoadDistanceUtils.java
View file @
d772bb9
...
...
@@ -2,6 +2,7 @@ package com.dituhui.pea.dispatch.utils;
import
java.io.BufferedReader
;
import
java.io.InputStreamReader
;
import
java.math.BigDecimal
;
import
java.net.HttpURLConnection
;
import
java.net.URL
;
import
java.net.URLConnection
;
...
...
@@ -10,6 +11,8 @@ import java.util.HashMap;
import
java.util.List
;
import
java.util.Map
;
import
cn.hutool.core.util.StrUtil
;
import
com.dituhui.pea.dispatch.common.redis.RedisUtil
;
import
org.springframework.stereotype.Component
;
import
com.dituhui.pea.dispatch.pojo.Location
;
...
...
@@ -23,192 +26,214 @@ import lombok.extern.slf4j.Slf4j;
* 路网组件<br>
* TODO 需要做成分布式缓存模式,这里会造成内存问题<br>
* TODO 调用方式需要改成批量调用方式
*
* @author gpzhang
*
* @author gpzhang
*/
@Component
@Slf4j
public
class
RoadDistanceUtils
{
public
static
String
URL
=
"https://api.map.baidu.com/routematrix/v2/"
;
public
static
String
AK
=
"doR30pE7R0I7ivGLwMpkpsTT4bos9Akg"
;
/**
* 格式 x1,y1;x2,y2
*/
private
static
Map
<
String
,
Distance
>
distanceCache
=
Maps
.
newHashMap
();
private
static
Gson
gson
=
new
Gson
();
/**
* 获取路网距离和时间<br>
*
* @param from
* @param to
* @param vehicleType 不能为空
* @return
*/
public
Distance
getDistance2
(
Location
from
,
Location
to
,
int
vehicleType
)
{
try
{
String
key
=
from
.
getLongitude
()
+
","
+
from
.
getLatitude
()
+
";"
+
to
.
getLongitude
()
+
","
+
to
.
getLatitude
()
+
"|"
+
vehicleType
;
Distance
distance
=
distanceCache
.
get
(
key
);
if
(
null
==
distance
)
{
distance
=
getDistance
(
from
.
getLatitude
()
+
","
+
from
.
getLongitude
(),
to
.
getLatitude
()
+
","
+
to
.
getLongitude
(),
vehicleType
);
log
.
info
(
key
+
" "
+
distance
);
if
(
null
==
distance
)
{
Distance
dis
=
new
Distance
();
return
dis
;
}
else
{
distanceCache
.
put
(
key
,
distance
);
}
return
distance
;
}
else
{
log
.
info
(
key
+
" from cache "
+
distance
);
return
distance
;
}
}
catch
(
Exception
e
)
{
Distance
dis
=
new
Distance
();
return
dis
;
}
}
/**
* 获取路网距离和时间<br>
* TODO 需要做成分布式缓存模式,这里会造成内存问题<br>
* TODO 调用方式需要改成批量调用方式
*
* @param from
* @param to
* @param vehicleType 不能为空
* @return
*/
public
static
Distance
getDistance
(
Location
from
,
Location
to
,
int
vehicleType
)
{
try
{
String
key
=
from
.
getLongitude
()
+
","
+
from
.
getLatitude
()
+
";"
+
to
.
getLongitude
()
+
","
+
to
.
getLatitude
()
+
"|"
+
vehicleType
;
Distance
distance
=
distanceCache
.
get
(
key
);
if
(
null
==
distance
)
{
distance
=
getDistance
(
from
.
getLatitude
()
+
","
+
from
.
getLongitude
(),
to
.
getLatitude
()
+
","
+
to
.
getLongitude
(),
vehicleType
);
if
(
null
==
distance
)
{
Distance
dis
=
new
Distance
();
return
dis
;
}
else
{
distanceCache
.
put
(
key
,
distance
);
}
return
distance
;
}
else
{
return
distance
;
}
}
catch
(
Exception
e
)
{
Distance
dis
=
new
Distance
();
return
dis
;
}
}
private
static
Distance
getDistance
(
String
yx1
,
String
yx2
,
int
vehicleType
)
throws
Exception
{
Map
<
String
,
String
>
params
=
new
HashMap
<
String
,
String
>();
params
.
put
(
"origins"
,
yx1
);
params
.
put
(
"destinations"
,
yx2
);
params
.
put
(
"ak"
,
AK
);
params
.
put
(
"coord_type"
,
"gcj02"
);
String
url
=
""
;
switch
(
vehicleType
)
{
case
1
:
url
=
URL
+
"driving?"
;
break
;
case
2
:
params
.
put
(
"riding_type"
,
"1"
);
// 电动自行车
url
=
URL
+
"riding?"
;
break
;
case
3
:
params
.
put
(
"riding_type"
,
"0"
);
// 普通自行车
url
=
URL
+
"riding?"
;
break
;
case
4
:
url
=
URL
+
"walking?"
;
break
;
}
String
text
=
requestGetAK
(
url
,
params
);
// System.out.println(url + " : " + gson.toJson(params) + " : " + text);
BDResult
webResult
=
gson
.
fromJson
(
text
,
BDResult
.
class
);
float
dis
=
webResult
.
getResult
().
get
(
0
).
getDistance
().
getValue
()
/
1000
F
;
int
time
=
webResult
.
getResult
().
get
(
0
).
getDuration
().
getValue
();
Distance
d
=
new
Distance
();
d
.
setDis
(
dis
);
d
.
setTime
(
time
);
return
d
;
}
/**
* 默认ak 选择了ak,使用IP白名单校验: 根据您选择的AK已为您生成调用代码 检测到您当前的ak设置了IP白名单校验
* 您的IP白名单中的IP非公网IP,请设置为公网IP,否则将请求失败 请在IP地址为xxxxxxx的计算发起请求,否则将请求失败
*/
public
static
String
requestGetAK
(
String
strUrl
,
Map
<
String
,
String
>
param
)
throws
Exception
{
if
(
strUrl
==
null
||
strUrl
.
length
()
<=
0
||
param
==
null
||
param
.
size
()
<=
0
)
{
return
""
;
}
StringBuffer
queryString
=
new
StringBuffer
();
queryString
.
append
(
strUrl
);
for
(
Map
.
Entry
<?,
?>
pair
:
param
.
entrySet
())
{
queryString
.
append
(
pair
.
getKey
()
+
"="
);
// 第一种方式使用的 jdk 自带的转码方式 第二种方式使用的 spring 的转码方法 两种均可
queryString
.
append
(
URLEncoder
.
encode
((
String
)
pair
.
getValue
(),
"UTF-8"
).
replace
(
"+"
,
"%20"
)
+
"&"
);
}
if
(
queryString
.
length
()
>
0
)
{
queryString
.
deleteCharAt
(
queryString
.
length
()
-
1
);
}
java
.
net
.
URL
url
=
new
URL
(
queryString
.
toString
());
URLConnection
httpConnection
=
(
HttpURLConnection
)
url
.
openConnection
();
httpConnection
.
connect
();
InputStreamReader
isr
=
new
InputStreamReader
(
httpConnection
.
getInputStream
());
BufferedReader
reader
=
new
BufferedReader
(
isr
);
StringBuffer
buffer
=
new
StringBuffer
();
String
line
;
while
((
line
=
reader
.
readLine
())
!=
null
)
{
buffer
.
append
(
line
);
}
reader
.
close
();
isr
.
close
();
return
(
buffer
.
toString
());
}
@Data
public
static
class
Distance
{
float
dis
;
int
time
;
}
@Data
static
class
BDResult
{
List
<
BDDistance
>
result
;
}
@Data
static
class
BDDistance
{
Dis
distance
;
Dur
duration
;
}
@Data
static
class
Dis
{
Float
value
;
}
@Data
static
class
Dur
{
Integer
value
;
}
public
static
String
URL
=
"https://api.map.baidu.com/routematrix/v2/"
;
public
static
String
AK
=
"doR30pE7R0I7ivGLwMpkpsTT4bos9Akg"
;
/**
* 格式 x1,y1;x2,y2
*/
//private static Map<String, Distance> distanceCache = Maps.newHashMap();
private
static
Gson
gson
=
new
Gson
();
/**
* 获取路网距离和时间<br>
*
* @param from
* @param to
* @param vehicleType 不能为空
* @return
*/
public
Distance
getDistance2
(
Location
from
,
Location
to
,
int
vehicleType
)
{
try
{
String
key
=
getLocationKey
(
from
,
to
,
vehicleType
);
//Distance distance = distanceCache.get(key);
Distance
distance
=
(
Distance
)
RedisUtil
.
get
(
key
);
if
(
null
==
distance
)
{
distance
=
getDistance
(
from
.
getLatitude
()
+
","
+
from
.
getLongitude
(),
to
.
getLatitude
()
+
","
+
to
.
getLongitude
(),
vehicleType
);
log
.
info
(
key
+
" "
+
distance
);
if
(
null
==
distance
)
{
Distance
dis
=
new
Distance
();
return
dis
;
}
else
{
//distanceCache.put(key, distance);
RedisUtil
.
set
(
key
,
distance
);
}
return
distance
;
}
else
{
log
.
info
(
key
+
" from cache "
+
distance
);
return
distance
;
}
}
catch
(
Exception
e
)
{
Distance
dis
=
new
Distance
();
return
dis
;
}
}
/**
* 获取路网距离和时间<br>
* TODO 需要做成分布式缓存模式,这里会造成内存问题<br>
* TODO 调用方式需要改成批量调用方式
*
* @param from
* @param to
* @param vehicleType 不能为空
* @return
*/
public
static
Distance
getDistance
(
Location
from
,
Location
to
,
int
vehicleType
)
{
try
{
String
key
=
getLocationKey
(
from
,
to
,
vehicleType
);
//Distance distance = distanceCache.get(key);
Distance
distance
=
(
Distance
)
RedisUtil
.
get
(
key
);
if
(
null
==
distance
)
{
distance
=
getDistance
(
from
.
getLatitude
()
+
","
+
from
.
getLongitude
(),
to
.
getLatitude
()
+
","
+
to
.
getLongitude
(),
vehicleType
);
if
(
null
==
distance
)
{
Distance
dis
=
new
Distance
();
return
dis
;
}
else
{
//distanceCache.put(key, distance);
RedisUtil
.
set
(
key
,
distance
);
}
return
distance
;
}
else
{
return
distance
;
}
}
catch
(
Exception
e
)
{
Distance
dis
=
new
Distance
();
return
dis
;
}
}
public
static
String
getLocationKey
(
Location
from
,
Location
to
,
int
vehicleType
)
{
return
convertDoubleToStr
(
from
.
getLongitude
())
+
","
+
convertDoubleToStr
(
from
.
getLatitude
())
+
";"
+
convertDoubleToStr
(
to
.
getLongitude
())
+
","
+
convertDoubleToStr
(
to
.
getLatitude
())
+
"|"
+
vehicleType
;
}
public
static
String
convertDoubleToStr
(
double
value
)
{
String
[]
ss
=
BigDecimal
.
valueOf
(
value
).
toString
().
split
(
"\\."
);
if
(
ss
.
length
==
1
)
{
return
ss
[
0
]
+
".00000"
;
}
if
(
ss
[
1
].
length
()
>=
5
)
{
return
ss
[
0
]
+
"."
+
ss
[
1
].
substring
(
0
,
5
);
}
return
ss
[
0
]
+
"."
+
StrUtil
.
padAfter
(
ss
[
1
],
5
,
"0"
);
}
private
static
Distance
getDistance
(
String
yx1
,
String
yx2
,
int
vehicleType
)
throws
Exception
{
Map
<
String
,
String
>
params
=
new
HashMap
<
String
,
String
>();
params
.
put
(
"origins"
,
yx1
);
params
.
put
(
"destinations"
,
yx2
);
params
.
put
(
"ak"
,
AK
);
params
.
put
(
"coord_type"
,
"gcj02"
);
String
url
=
""
;
switch
(
vehicleType
)
{
case
1
:
url
=
URL
+
"driving?"
;
break
;
case
2
:
params
.
put
(
"riding_type"
,
"1"
);
// 电动自行车
url
=
URL
+
"riding?"
;
break
;
case
3
:
params
.
put
(
"riding_type"
,
"0"
);
// 普通自行车
url
=
URL
+
"riding?"
;
break
;
case
4
:
url
=
URL
+
"walking?"
;
break
;
}
String
text
=
requestGetAK
(
url
,
params
);
// System.out.println(url + " : " + gson.toJson(params) + " : " + text);
BDResult
webResult
=
gson
.
fromJson
(
text
,
BDResult
.
class
);
float
dis
=
webResult
.
getResult
().
get
(
0
).
getDistance
().
getValue
()
/
1000
F
;
int
time
=
webResult
.
getResult
().
get
(
0
).
getDuration
().
getValue
();
Distance
d
=
new
Distance
();
d
.
setDis
(
dis
);
d
.
setTime
(
time
);
return
d
;
}
/**
* 默认ak 选择了ak,使用IP白名单校验: 根据您选择的AK已为您生成调用代码 检测到您当前的ak设置了IP白名单校验
* 您的IP白名单中的IP非公网IP,请设置为公网IP,否则将请求失败 请在IP地址为xxxxxxx的计算发起请求,否则将请求失败
*/
public
static
String
requestGetAK
(
String
strUrl
,
Map
<
String
,
String
>
param
)
throws
Exception
{
if
(
strUrl
==
null
||
strUrl
.
length
()
<=
0
||
param
==
null
||
param
.
size
()
<=
0
)
{
return
""
;
}
StringBuffer
queryString
=
new
StringBuffer
();
queryString
.
append
(
strUrl
);
for
(
Map
.
Entry
<?,
?>
pair
:
param
.
entrySet
())
{
queryString
.
append
(
pair
.
getKey
()
+
"="
);
// 第一种方式使用的 jdk 自带的转码方式 第二种方式使用的 spring 的转码方法 两种均可
queryString
.
append
(
URLEncoder
.
encode
((
String
)
pair
.
getValue
(),
"UTF-8"
).
replace
(
"+"
,
"%20"
)
+
"&"
);
}
if
(
queryString
.
length
()
>
0
)
{
queryString
.
deleteCharAt
(
queryString
.
length
()
-
1
);
}
java
.
net
.
URL
url
=
new
URL
(
queryString
.
toString
());
URLConnection
httpConnection
=
(
HttpURLConnection
)
url
.
openConnection
();
httpConnection
.
connect
();
InputStreamReader
isr
=
new
InputStreamReader
(
httpConnection
.
getInputStream
());
BufferedReader
reader
=
new
BufferedReader
(
isr
);
StringBuffer
buffer
=
new
StringBuffer
();
String
line
;
while
((
line
=
reader
.
readLine
())
!=
null
)
{
buffer
.
append
(
line
);
}
reader
.
close
();
isr
.
close
();
return
(
buffer
.
toString
());
}
@Data
public
static
class
Distance
{
float
dis
;
int
time
;
}
@Data
static
class
BDResult
{
List
<
BDDistance
>
result
;
}
@Data
static
class
BDDistance
{
Dis
distance
;
Dur
duration
;
}
@Data
static
class
Dis
{
Float
value
;
}
@Data
static
class
Dur
{
Integer
value
;
}
}
project-dispatch/src/main/resources/application-dev.yaml
View file @
d772bb9
...
...
@@ -3,7 +3,7 @@ server:
dispatch
:
cron
:
expr
:
0
9
8-23 * * ?
expr
:
0
37
8-23 * * ?
next-day-limit
:
2
scheduler
:
...
...
Write
Preview
Markdown
is supported
Attach a file
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 post a comment