Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
有来技术
youlai-mall
提交
c58479a4
Y
youlai-mall
项目概览
有来技术
/
youlai-mall
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
youlai-mall
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c58479a4
编写于
3月 10, 2021
作者:
H
haoxr
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat:添加控制台IP统计数据
上级
174d78a9
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
129 addition
and
52 deletion
+129
-52
mall-sms/sms-boot/src/main/java/com/youlai/mall/sms/service/impl/SeckillServiceImpl.java
.../com/youlai/mall/sms/service/impl/SeckillServiceImpl.java
+0
-3
youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DashboardController.java
...java/com/youlai/admin/controller/DashboardController.java
+46
-11
youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/LoginRecordController.java
...va/com/youlai/admin/controller/LoginRecordController.java
+0
-4
youlai-auth/pom.xml
youlai-auth/pom.xml
+1
-1
youlai-common/common-elasticsearch/src/main/java/com/youlai/common/elasticsearch/service/ElasticSearchService.java
...ai/common/elasticsearch/service/ElasticSearchService.java
+31
-12
youlai-common/common-web/src/main/java/com/youlai/common/web/aspect/LoginLogAspect.java
...ain/java/com/youlai/common/web/aspect/LoginLogAspect.java
+3
-3
youlai-common/common-web/src/main/java/com/youlai/common/web/util/IPUtils.java
...web/src/main/java/com/youlai/common/web/util/IPUtils.java
+48
-18
未找到文件。
mall-sms/sms-boot/src/main/java/com/youlai/mall/sms/service/impl/SeckillServiceImpl.java
浏览文件 @
c58479a4
...
...
@@ -6,7 +6,6 @@ import cn.hutool.core.date.DateUtil;
import
cn.hutool.core.util.RandomUtil
;
import
com.youlai.common.redis.utils.RedisUtils
;
import
com.youlai.common.web.util.BeanMapperUtils
;
import
com.youlai.mall.pms.api.ProductFeignService
;
import
com.youlai.mall.sms.pojo.domain.SmsSeckillSession
;
import
com.youlai.mall.sms.pojo.domain.SmsSeckillSkuRelation
;
import
com.youlai.mall.sms.pojo.to.SeckillSkuRedisTO
;
...
...
@@ -48,8 +47,6 @@ public class SeckillServiceImpl implements SeckillService {
@Autowired
private
RedisUtils
redisUtils
;
@Resource
private
ProductFeignService
productFeignService
;
@Autowired
private
RedissonClient
redissonClient
;
...
...
youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DashboardController.java
浏览文件 @
c58479a4
...
...
@@ -13,6 +13,7 @@ import lombok.extern.slf4j.Slf4j;
import
org.elasticsearch.index.query.BoolQueryBuilder
;
import
org.elasticsearch.index.query.QueryBuilders
;
import
org.elasticsearch.index.query.RangeQueryBuilder
;
import
org.elasticsearch.index.query.TermQueryBuilder
;
import
org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
...
...
@@ -39,10 +40,43 @@ public class DashboardController {
ElasticSearchService
elasticSearchService
;
@ApiOperation
(
value
=
"登录次数统计"
,
httpMethod
=
"GET"
)
@GetMapping
(
"/login_counts"
)
public
Result
loginCounts
()
{
int
days
=
10
;
//统计天数
@ApiOperation
(
value
=
"控制台数据"
,
httpMethod
=
"GET"
)
@GetMapping
public
Result
data
()
{
Map
<
String
,
Object
>
data
=
new
HashMap
<>();
// 今日IP数
long
todayIpCount
=
getTodayIpCount
();
data
.
put
(
"todayIpCount"
,
todayIpCount
);
// 总IP数
long
totalIpCount
=
getTotalIpCount
();
data
.
put
(
"totalIpCount"
,
totalIpCount
);
// 登录统计
int
days
=
10
;
// 统计天数
Map
loginCount
=
getLoginCount
(
days
);
data
.
put
(
"loginCount"
,
loginCount
);
return
Result
.
success
(
data
);
}
private
long
getTodayIpCount
()
{
String
date
=
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd"
));
TermQueryBuilder
termQueryBuilder
=
QueryBuilders
.
termQuery
(
"date"
,
date
);
String
indexName
=
ESConstants
.
LOGIN_INDEX_PATTERN
+
date
;
//索引名称
long
todayIpCount
=
elasticSearchService
.
countDistinct
(
termQueryBuilder
,
"clientIP.keyword"
,
indexName
);
return
todayIpCount
;
}
private
long
getTotalIpCount
()
{
long
totalIpCount
=
elasticSearchService
.
countDistinct
(
null
,
"clientIP.keyword"
,
ESConstants
.
LOGIN_INDEX_PATTERN
);
return
totalIpCount
;
}
private
Map
getLoginCount
(
int
days
)
{
LocalDateTime
now
=
LocalDateTime
.
now
();
DateTimeFormatter
formatter
=
DateTimeFormatter
.
ofPattern
(
"yyyy-MM-dd"
);
...
...
@@ -62,16 +96,17 @@ public class DashboardController {
BoolQueryBuilder
boolQueryBuilder
=
QueryBuilders
.
boolQuery
()
.
must
(
rangeQueryBuilder
);
// 总数统计
Map
<
String
,
Long
>
totalCountMap
=
elasticSearchService
.
dateHistogram
(
boolQueryBuilder
,
"date"
,
// 根据date字段聚合统计登录数 logback-spring.xml 中的自定义扩展字段 date
DateHistogramInterval
.
days
(
1
),
indices
);
boolQueryBuilder
,
"date"
,
// 根据date字段聚合统计登录数 logback-spring.xml 中的自定义扩展字段 date
DateHistogramInterval
.
days
(
1
),
indices
);
// 当前用户统计
HttpServletRequest
request
=
RequestUtils
.
getRequest
();
String
clientIP
=
IPUtils
.
get
ClientIP
(
request
);
String
clientIP
=
IPUtils
.
get
IpAddr
(
request
);
boolQueryBuilder
.
must
(
QueryBuilders
.
termQuery
(
"clientIP"
,
clientIP
));
Map
<
String
,
Long
>
myCountMap
=
elasticSearchService
.
dateHistogram
(
boolQueryBuilder
,
"date"
,
DateHistogramInterval
.
days
(
1
),
indices
);
...
...
@@ -79,7 +114,7 @@ public class DashboardController {
// 组装echarts数据
Long
[]
totalCount
=
new
Long
[
days
];
Long
[]
myCount
=
new
Long
[
days
];
Long
[]
myCount
=
new
Long
[
days
];
Arrays
.
sort
(
xData
);
// 默认升序
for
(
int
i
=
0
;
i
<
days
;
i
++)
{
...
...
@@ -93,7 +128,7 @@ public class DashboardController {
map
.
put
(
"totalCount"
,
totalCount
);
// 总数
map
.
put
(
"myCount"
,
myCount
);
// 我的
return
Result
.
success
(
map
)
;
return
map
;
}
...
...
youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/LoginRecordController.java
浏览文件 @
c58479a4
...
...
@@ -18,9 +18,6 @@ import org.elasticsearch.index.query.RangeQueryBuilder;
import
org.elasticsearch.search.sort.FieldSortBuilder
;
import
org.elasticsearch.search.sort.SortOrder
;
import
org.springframework.web.bind.annotation.*
;
import
java.io.IOException
;
import
java.util.Arrays
;
import
java.util.List
;
/**
...
...
@@ -36,7 +33,6 @@ public class LoginRecordController {
ElasticSearchService
elasticSearchService
;
@ApiOperation
(
value
=
"列表分页"
,
httpMethod
=
"GET"
)
@ApiImplicitParams
({
@ApiImplicitParam
(
name
=
"page"
,
value
=
"页码"
,
defaultValue
=
"1"
,
paramType
=
"query"
,
dataType
=
"Long"
),
...
...
youlai-auth/pom.xml
浏览文件 @
c58479a4
...
...
@@ -180,7 +180,7 @@
<entryPoint>
["java","-jar","${project.build.finalName}.jar"]
</entryPoint>
<!-- 指定远程 Docker API地址 -->
<dockerHost>
http
s://f.youlai.store:2376
</dockerHost>
<dockerHost>
http
://f.youlai.store:2375
</dockerHost>
<!-- 指定tls证书的目录 -->
<dockerCertPath>
C:\cert\docker\f.youlai.store
</dockerCertPath>
...
...
youlai-common/common-elasticsearch/src/main/java/com/youlai/common/elasticsearch/service/ElasticSearchService.java
浏览文件 @
c58479a4
...
...
@@ -28,6 +28,8 @@ import org.elasticsearch.search.aggregations.AggregationBuilders;
import
org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval
;
import
org.elasticsearch.search.aggregations.bucket.histogram.Histogram
;
import
org.elasticsearch.search.aggregations.bucket.histogram.ParsedDateHistogram
;
import
org.elasticsearch.search.aggregations.metrics.CardinalityAggregationBuilder
;
import
org.elasticsearch.search.aggregations.metrics.ParsedCardinality
;
import
org.elasticsearch.search.builder.SearchSourceBuilder
;
import
org.elasticsearch.search.sort.SortBuilder
;
import
org.springframework.stereotype.Service
;
...
...
@@ -52,12 +54,35 @@ public class ElasticSearchService {
// 构造请求
CountRequest
countRequest
=
new
CountRequest
(
indices
);
countRequest
.
query
(
queryBuilder
);
// 执行请求
CountResponse
countResponse
=
client
.
count
(
countRequest
,
RequestOptions
.
DEFAULT
);
long
count
=
countResponse
.
getCount
();
return
count
;
}
@SneakyThrows
public
long
countDistinct
(
QueryBuilder
queryBuilder
,
String
field
,
String
...
indices
)
{
String
distinctKey
=
"distinctKey"
;
// 自定义计数去重key,保证上下文一致
// 构造计数聚合 cardinality:集合中元素的个数
CardinalityAggregationBuilder
aggregationBuilder
=
AggregationBuilders
.
cardinality
(
distinctKey
).
field
(
field
);
// 构造搜索源
SearchSourceBuilder
searchSourceBuilder
=
new
SearchSourceBuilder
();
searchSourceBuilder
.
query
(
queryBuilder
).
aggregation
(
aggregationBuilder
);
// 构造请求
SearchRequest
searchRequest
=
new
SearchRequest
(
indices
);
searchRequest
.
source
(
searchSourceBuilder
);
// 执行请求
SearchResponse
searchResponse
=
client
.
search
(
searchRequest
,
RequestOptions
.
DEFAULT
);
ParsedCardinality
result
=
searchResponse
.
getAggregations
().
get
(
distinctKey
);
return
result
.
getValue
();
}
/**
* 日期统计
*
...
...
@@ -70,15 +95,17 @@ public class ElasticSearchService {
@SneakyThrows
public
Map
<
String
,
Long
>
dateHistogram
(
QueryBuilder
queryBuilder
,
String
field
,
DateHistogramInterval
interval
,
String
...
indices
)
{
// 构造AggregationBuilder
String
dateHistogramKey
=
"dateHistogramKey"
;
// 自定义日期聚合key,保证上下文一致
// 构造聚合
AggregationBuilder
aggregationBuilder
=
AggregationBuilders
.
dateHistogram
(
"dateHistogram"
)
//自定义统计名,和下文获取需一致
.
dateHistogram
(
dateHistogramKey
)
//自定义统计名,和下文获取需一致
.
field
(
field
)
// 日期字段名
.
format
(
"yyyy-MM-dd"
)
// 时间格式
.
calendarInterval
(
interval
)
// 日历间隔,例: 1s->1秒 1d->1天 1w->1周 1M->1月 1y->1年 ...
.
minDocCount
(
0
);
// 最小文档数,比该值小就忽略
// 构造
SearchSourceBuilder
// 构造
搜索源
SearchSourceBuilder
searchSourceBuilder
=
new
SearchSourceBuilder
();
searchSourceBuilder
.
query
(
queryBuilder
)
...
...
@@ -101,7 +128,7 @@ public class ElasticSearchService {
SearchResponse
searchResponse
=
client
.
search
(
searchRequest
,
RequestOptions
.
DEFAULT
);
// 处理结果
ParsedDateHistogram
dateHistogram
=
searchResponse
.
getAggregations
().
get
(
"dateHistogram"
);
ParsedDateHistogram
dateHistogram
=
searchResponse
.
getAggregations
().
get
(
dateHistogramKey
);
Iterator
<?
extends
Histogram
.
Bucket
>
iterator
=
dateHistogram
.
getBuckets
().
iterator
();
...
...
@@ -119,14 +146,6 @@ public class ElasticSearchService {
return
list
;
}
@SneakyThrows
public
<
T
extends
BaseDocument
>
List
<
T
>
search
(
QueryBuilder
queryBuilder
,
Integer
page
,
Integer
size
,
Class
<
T
>
clazz
,
String
...
indices
)
{
List
<
T
>
list
=
this
.
search
(
queryBuilder
,
null
,
1
,
ESConstants
.
DEFAULT_PAGE_SIZE
,
clazz
,
indices
);
return
list
;
}
@SneakyThrows
public
<
T
extends
BaseDocument
>
List
<
T
>
search
(
QueryBuilder
queryBuilder
,
SortBuilder
sortBuilder
,
Integer
page
,
Integer
size
,
Class
<
T
>
clazz
,
String
...
indices
)
{
// 构造SearchSourceBuilder
...
...
youlai-common/common-web/src/main/java/com/youlai/common/web/aspect/LoginLogAspect.java
浏览文件 @
c58479a4
...
...
@@ -73,9 +73,9 @@ public class LoginLogAspect {
JSONObject
jsonObject
=
JSONUtil
.
parseObj
(
result
);
token
=
jsonObject
.
getStr
(
"value"
);
}
String
clientIP
=
IPUtils
.
getClientIP
(
request
);
// 客户端请求IP(注意:如果使用Nginx代理需配置)
log
.
info
(
"222. {}"
,
clientIP
);
String
region
=
IPUtils
.
ip2region
(
clientIP
);
// IP对应的城市信息
String
clientIP
=
IPUtils
.
getIpAddr
(
request
);
// 客户端请求IP(注意:如果使用Nginx代理需配置)
String
region
=
IPUtils
.
getCityInfo
(
clientIP
);
// IP对应的城市信息
// MDC 扩展logback字段,具体请看logback-spring.xml的自定义日志输出格式
MDC
.
put
(
"elapsedTime"
,
StrUtil
.
toString
(
elapsedTime
));
...
...
youlai-common/common-web/src/main/java/com/youlai/common/web/util/IPUtils.java
浏览文件 @
c58479a4
...
...
@@ -2,6 +2,7 @@ package com.youlai.common.web.util;
import
cn.hutool.core.util.StrUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.io.FileUtils
;
import
org.apache.logging.log4j.util.Strings
;
import
org.lionsoul.ip2region.DataBlock
;
import
org.lionsoul.ip2region.DbConfig
;
...
...
@@ -10,21 +11,25 @@ import org.lionsoul.ip2region.Util;
import
javax.servlet.http.HttpServletRequest
;
import
java.io.File
;
import
java.io.IOException
;
import
java.lang.reflect.Method
;
import
java.net.InetAddress
;
import
java.net.UnknownHostException
;
/**
* IP工具类
*/
@Slf4j
public
class
IPUtils
{
private
static
String
LOCAL_IP
=
"127.0.0.1"
;
private
static
String
LOCAL_IP
=
"127.0.0.1"
;
/**
* 获取IP地址
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public
static
String
get
ClientIP
(
HttpServletRequest
request
)
{
public
static
String
get
IpAddr
(
HttpServletRequest
request
)
{
String
ip
=
null
;
try
{
if
(
request
==
null
)
{
...
...
@@ -81,34 +86,61 @@ public class IPUtils {
/**
* 解析IP获取城市区域信息
*
* 根据IP获取城市信息
* @param ip
* @return
*/
public
static
String
ip2region
(
String
ip
)
{
public
static
String
getCityInfo
(
String
ip
)
{
return
getCityInfo
(
ip
,
DbSearcher
.
BTREE_ALGORITHM
);
}
public
static
String
getCityInfo
(
String
ip
,
Integer
algorithm
)
{
if
(
Util
.
isIpAddress
(
ip
)
==
false
)
{
return
Strings
.
EMPTY
;
}
log
.
info
(
"1. {}"
,
ip
);
if
(
LOCAL_IP
.
equals
(
ip
)){
if
(
LOCAL_IP
.
equals
(
ip
))
{
return
"本地访问"
;
}
log
.
info
(
"2. {}"
,
ip
);
String
filePath
=
IPUtils
.
class
.
getResource
(
"/data/ip2region.db"
).
getPath
();
File
file
=
new
File
(
filePath
);
String
dbPath
=
IPUtils
.
class
.
getResource
(
"/ip2region.db"
).
getPath
();
File
file
=
new
File
(
dbPath
);
// 打成jar包时,ip2region.db文件路径发生变化,导致File无法读取,通过stream流方式复制生成临时的ip2region.db文件
if
(
file
.
exists
()
==
false
)
{
return
Strings
.
EMPTY
;
String
tmpdir
=
System
.
getProperties
().
getProperty
(
"java.io.tmpdir"
);
dbPath
=
tmpdir
+
"/ip2region.db"
;
file
=
new
File
(
dbPath
);
if
(
file
.
exists
()
==
false
)
{
try
{
FileUtils
.
copyInputStreamToFile
(
IPUtils
.
class
.
getClassLoader
()
.
getResourceAsStream
(
"classpath:ip2region.db"
),
file
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
log
.
info
(
"3. {}"
,
ip
);
try
{
DbConfig
config
=
new
DbConfig
();
DbSearcher
searcher
=
new
DbSearcher
(
config
,
filePath
);
log
.
info
(
"4. {}"
,
ip
);
Method
method
=
searcher
.
getClass
().
getMethod
(
"btreeSearch"
,
String
.
class
);
DbSearcher
searcher
=
new
DbSearcher
(
config
,
dbPath
);
Method
method
;
switch
(
algorithm
)
{
case
DbSearcher
.
BTREE_ALGORITHM
:
method
=
searcher
.
getClass
().
getMethod
(
"btreeSearch"
,
String
.
class
);
break
;
case
DbSearcher
.
BINARY_ALGORITHM
:
method
=
searcher
.
getClass
().
getMethod
(
"binarySearch"
,
String
.
class
);
break
;
case
DbSearcher
.
MEMORY_ALGORITYM
:
method
=
searcher
.
getClass
().
getMethod
(
"memorySearch"
,
String
.
class
);
break
;
default
:
method
=
searcher
.
getClass
().
getMethod
(
"memorySearch"
,
String
.
class
);
break
;
}
DataBlock
dataBlock
=
(
DataBlock
)
method
.
invoke
(
searcher
,
ip
);
log
.
info
(
"5. {}"
,
ip
);
searcher
.
close
(
);
return
dataBlock
.
getRegion
();
}
catch
(
Exception
e
)
{
...
...
@@ -117,6 +149,4 @@ public class IPUtils {
return
Strings
.
EMPTY
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录