Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6fc5501a4 | ||
|
|
e517aced2c | ||
|
|
fe30b5f532 | ||
|
|
8565e1bb59 | ||
|
|
8165dfcc7b | ||
|
|
c6ae88e136 |
@@ -1,9 +0,0 @@
|
|||||||
## 组织结构
|
|
||||||
|
|
||||||
```
|
|
||||||
allv6.py #汇总所有v6地址结果
|
|
||||||
ch_dns.py #全国探针发送程序
|
|
||||||
dnsfound_util.py #DNSv6工具包
|
|
||||||
ipmatch.py #IP段匹配(山东)
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
'''
|
|
||||||
用于将多个NS端pcap导出结果进行合并(另一种方法是将pcap文件合并后再导出)
|
|
||||||
'''
|
|
||||||
import pandas as pd
|
|
||||||
|
|
||||||
# 结果保存位置
|
|
||||||
res_path="./result/v6/allv6dns.csv"
|
|
||||||
# 创建结果文件
|
|
||||||
allip=pd.DataFrame(columns=["IPv6","Count"])
|
|
||||||
allip.to_csv("./result/v6/allv6dns.csv",encoding='gbk', header=True, index=False)
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
# 资源路径
|
|
||||||
path="./result/v6/v6-"+str(i+1)+".csv"
|
|
||||||
ip_datas=pd.read_csv(path,skiprows=2,names=["level","parent","IPv6","count","ave","min","max","rate","per","BR","BS"])
|
|
||||||
data = ip_datas.iloc[1:, [2,3]]
|
|
||||||
data.to_csv(res_path,mode="a", encoding='gbk', header=False, index=False)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
'''
|
|
||||||
探针发送主程序
|
|
||||||
'''
|
|
||||||
import pandas as pd
|
|
||||||
import dnsfound_util as dnsu
|
|
||||||
|
|
||||||
alphabet=dnsu.alphabet
|
|
||||||
#IPv4地址
|
|
||||||
spath="./res_data/china/forwarder.xlsx"
|
|
||||||
#返回结果保存
|
|
||||||
dpath="./result/china/forward/res-5.csv"
|
|
||||||
ch_dns=pd.read_excel(spath,names=["rdns","loc","company"])
|
|
||||||
# 对于直接响应dns
|
|
||||||
# ch_dns=pd.read_excel(spath,names=["rdns","dns"])
|
|
||||||
# dns_result = pd.DataFrame(columns=["rdns", "result"],)
|
|
||||||
|
|
||||||
#保存所有多线程生成器
|
|
||||||
List=[dnsu.dnsresolver(i,ch_dns) for i in dnsu.tqdm(range(ch_dns.shape[0]))]
|
|
||||||
|
|
||||||
#从所有多线程生成器中读取结果
|
|
||||||
dns_result=pd.concat([pd.DataFrame([res.result()],columns=["rdns","result"]) for res in List],ignore_index=True)
|
|
||||||
|
|
||||||
dns_result.to_csv(dpath)
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
'''
|
|
||||||
DNSv6工具包,注意tomorrow3无法在arm架构处理器上使用(m1)
|
|
||||||
'''
|
|
||||||
import dns.resolver
|
|
||||||
import pandas as pd
|
|
||||||
import random as rd
|
|
||||||
import tomorrow3 as tm
|
|
||||||
from tqdm import tqdm
|
|
||||||
|
|
||||||
|
|
||||||
alphabet = "abcdefghijklmnopqrstuvwxyz1234567890"
|
|
||||||
|
|
||||||
|
|
||||||
result = pd.DataFrame(columns=["rdns", "result"])
|
|
||||||
dot_ressult = pd.DataFrame(columns=["dot", "result"])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# val负责定位,dataframe指定数据来源
|
|
||||||
@tm.threads(200)
|
|
||||||
def dnsresolver(val,dataframe):
|
|
||||||
characters = "".join(rd.sample(alphabet, 10)) # 生成子域名
|
|
||||||
test = dataframe.loc[val, "rdns"]
|
|
||||||
reso = dns.resolver.Resolver()
|
|
||||||
reso.nameservers = [test]
|
|
||||||
reso.timeout = 10
|
|
||||||
try:
|
|
||||||
AAAA = reso.resolve(characters + ".v4.testv4-v6.live", "AAAA").response
|
|
||||||
# result = result.append([[test, AAAA.rcode()]], ignore_index=True)
|
|
||||||
return [test,AAAA.rcode()]
|
|
||||||
except:
|
|
||||||
# result=result.append([[test, 1]], ignore_index=True)
|
|
||||||
return [test,1]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# if __name__=="__main__":
|
|
||||||
# mode="main"
|
|
||||||
# rdns = pd.read_csv("./res_data/rdns-shandong.csv", names=["rdns"])
|
|
||||||
# dot = pd.read_csv("./res_data/853-shandong.csv", names=["dot"])
|
|
||||||
# ch_rdns = pd.read_excel("./res_data/全国-递归DNS测量结果.xlsx", names=["rdns", "loc", "company"])
|
|
||||||
#
|
|
||||||
# for i in tqdm(range(ch_rdns.shape[0])):
|
|
||||||
# dnsresolver(i,ch_rdns,result)
|
|
||||||
#
|
|
||||||
# if (mode == "rdns"):
|
|
||||||
# result.to_csv("./result/"+str(2)+"-ch_rdns.csv")
|
|
||||||
# else:
|
|
||||||
# dot_ressult.to_csv("./result/dot.csv")
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
'''
|
|
||||||
IP段匹配
|
|
||||||
'''
|
|
||||||
import ipaddress as ipaddr
|
|
||||||
import pandas as pd
|
|
||||||
|
|
||||||
|
|
||||||
def makecidr(DATAframe):
|
|
||||||
cidr=pd.DataFrame()
|
|
||||||
for i in range(DATAframe.shape[0]):
|
|
||||||
if ":" in DATAframe.loc[i,"start_ip"]:
|
|
||||||
start_ip=ipaddr.ip_address(DATAframe.loc[i,"start_ip"])
|
|
||||||
end_ip=ipaddr.ip_address(DATAframe.loc[i,"end_ip"])
|
|
||||||
ipcidr=ipaddr.summarize_address_range(start_ip,end_ip)
|
|
||||||
for ips in ipcidr:
|
|
||||||
cidr = cidr.append([[ips]])
|
|
||||||
|
|
||||||
return cidr
|
|
||||||
def matchIP(ip,cidrs):
|
|
||||||
for c in cidrs.keys():
|
|
||||||
for j in range(cidrs[c].shape[0]):
|
|
||||||
if (ipaddr.IPv6Address(ip) in ipaddr.IPv6Network(cidrs[c].iloc[j, 0])):
|
|
||||||
|
|
||||||
return str(c)
|
|
||||||
if __name__=="__main__":
|
|
||||||
# 读取原始数据
|
|
||||||
cidrs=[]
|
|
||||||
dx = pd.read_excel("./res_data/IPrange/山东电信.xlsx", names=["time", "start_ip", "end_ip", "organization", "company"])
|
|
||||||
yd = pd.read_excel("./res_data/IPrange/山东移动.xlsx", names=["time", "start_ip", "end_ip", "organization", "company"])
|
|
||||||
lt = pd.read_excel("./res_data/IPrange/山东联通.xlsx", names=["time", "start_ip", "end_ip", "organization", "company"])
|
|
||||||
ips=pd.read_csv("./result/v6/allv6dns.csv",header=0)
|
|
||||||
|
|
||||||
# dx_cidr=makecidr(dx)
|
|
||||||
# yd_cidr=makecidr(yd)
|
|
||||||
# lt_cidr=makecidr(lt)
|
|
||||||
cidrs={"dx":makecidr(dx),"yd":makecidr(yd),"lt":makecidr(lt)}
|
|
||||||
ips["company"]=ips["IPv6"].map(lambda x:matchIP(x,cidrs))
|
|
||||||
ips_n=pd.pivot_table(ips,values=["Count"],index=["IPv6"],aggfunc=sum)
|
|
||||||
ips_c=ips.drop_duplicates(subset=["IPv6"],keep="first")
|
|
||||||
ips_L=ips_n.merge(ips_c.loc[:,["IPv6","company"]],how="left",on="IPv6")
|
|
||||||
ips_L.to_csv("./result/v6/v6DNSs.csv",index=False)
|
|
||||||
# for i in range(ips.shape[0]):
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 51 KiB |
@@ -1,33 +0,0 @@
|
|||||||
# DNSv6
|
|
||||||
|
|
||||||
### 组织结构
|
|
||||||
|
|
||||||
```
|
|
||||||
├─Code #dns探针发送代码
|
|
||||||
├─result #自建NS端的pcap结果以及5次探针发送情况
|
|
||||||
│ └─china
|
|
||||||
│ ├─forward #转发
|
|
||||||
│ ├─gkdg #公开递归
|
|
||||||
│ ├─jjdg #间接递归
|
|
||||||
│ └─zjxy #直接响应
|
|
||||||
└─src
|
|
||||||
├─china #ipv4的种子地址数据,来自@莫迪凯
|
|
||||||
└─shandong #山东v4数据
|
|
||||||
├─IPrange #三大运营商IPv4网段数据
|
|
||||||
└─dns #已知v4 dns
|
|
||||||
```
|
|
||||||
|
|
||||||
### 原理
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 配置
|
|
||||||
|
|
||||||
#### 自建NS端
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
#### godaddy端
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:8db10fe0868b210265cadfc885607c03de3b70323c21cd350b4c5113aad87be4
|
|
||||||
size 90037
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:aad73406bc157c7de98728e70862aabef110242fabaa1745bd07dd2746e33766
|
|
||||||
size 390231878
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:11dda37428083717e91bfef79c38d1bddfdbdb867b3b56519e891c5cdd7e2c3a
|
|
||||||
size 286315
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:39a04b88100a61ddf42a41481cebab2549e6cc902774987da60b5bc09cc6016b
|
|
||||||
size 18903728
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:4b6e478064c402803a7001197c24e5ea12ad561fe379bfd9792a4176b89be973
|
|
||||||
size 18903728
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:c3d2d29c0daa9e2a7340d37d837d65442fa53781f03f3a4146e5a19191592649
|
|
||||||
size 18903728
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:d4c55429f1611df000fefbf321852c175f5deeee5ab0049c24ed04b9989b6f34
|
|
||||||
size 18903728
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:3b0df54d837eee7cf3a1fb03ab54cd1a072f2f44763d9aaebfa6df8db28039f2
|
|
||||||
size 18903728
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:976ab6a95ee8fcc1ce0f3488542681e8743eb9e4e7df7f0aa36f5864c38ed3c5
|
|
||||||
size 685566
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:559f21c923ecd000065c18187f01f7763883c62a374545d293ffead7a43932ea
|
|
||||||
size 80110
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:bf9a2daa1810cd9645737530b306a28b5d4ea9510a0d13629c6a58d78b659ec3
|
|
||||||
size 80110
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:b08821bb3d4e58ff8b1f619f2aad87f615df04e9a394ece9718939e6c12e2712
|
|
||||||
size 80110
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:260216ea35f7a4f14d90dd6f617331f37ffbf50e50125c52c845b4be00fd72cc
|
|
||||||
size 80110
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:7124c588bd4210a8dd2a02b81411dc9b46ef7fc72e8921935a6a98fecba4364b
|
|
||||||
size 80110
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:0965522b8685befb3ba5bef5eb4a99a0e08a0c6cf1a02d76b7c01786a7af4212
|
|
||||||
size 39175
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:1449fb680f91609be49bcc85cd5d8fe94922cdc82c62e9087f0eaf16fbbb17a5
|
|
||||||
size 144906
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:5be788e7ab415b82a41adaea14874183b14db10aade4d5b7abfe1e2db23defa5
|
|
||||||
size 107407
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:256df35e84ef30fb21e4f5f81f315715ed4aeac694d17e13d5aa195e212268cc
|
|
||||||
size 107407
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:03ef11ce72f50841cb2a46d26473d1604a13ade41f6c7bee98e3b39410ec84f2
|
|
||||||
size 107407
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:9c43fa7fc18897bb2573f2558fdfbadb361435958eac94fe63466a53d9467d21
|
|
||||||
size 107407
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:66ff3e9df2b02cc4f18f521dd2dba7ff1e3225e05f43135414e7add68cce965d
|
|
||||||
size 107407
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:5cbeaf443756fd60e151da461595f19281e361c3a2b06d5408a6dcc7b75bf1ab
|
|
||||||
size 9473
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:b72992a643af3dc0e72ff0992550732f2280de6de082a5701cef990e141e6fba
|
|
||||||
size 147401
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:ef74027f8e4d7b464ca82187020768b184f6091dd2a6ef1dd5933c9c970e954d
|
|
||||||
size 31587
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:88582297fe0a20463a002984ea81e9d868d45d7f665f6d355553ed39dd7cd6d7
|
|
||||||
size 31587
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:88a3e7192e8a67cf18adb80e32596921844a8b4305fe816179461de5abbafe1f
|
|
||||||
size 31587
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:c0b2c4f2d1d161971d3127fb1722457550ecf29225e269ae3e037022f4f54033
|
|
||||||
size 31587
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:b23ae77b51b06c8b73d05069f23df7c526bcccb862aa1e009c5850c28dc60c73
|
|
||||||
size 31587
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:474277b8eb90a986fc6251fc28ceb4552c90ccafe9d56986362459deeb563be7
|
|
||||||
size 11632
|
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:44d48c187a3b433539040669c65008d876adb3ae13b0cc72111a708e57d7c203
|
|
||||||
size 36150
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:514cdca439bd9660ec8bde7ded09601e38ffa630edd3853565ce8d4646848105
|
|
||||||
size 677892
|
|
||||||
|
7
UI source code/dns-dev-2.0/.gitignore
vendored
Normal file
7
UI source code/dns-dev-2.0/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
### IDEA ###
|
||||||
|
.idea/*
|
||||||
|
*.iml
|
||||||
|
*/target/*
|
||||||
|
*/*.iml
|
||||||
|
/.gradle/
|
||||||
|
/application.pid
|
||||||
191
UI source code/dns-dev-2.0/LICENSE
Normal file
191
UI source code/dns-dev-2.0/LICENSE
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction, and
|
||||||
|
distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||||
|
owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||||
|
that control, are controlled by, or are under common control with that entity.
|
||||||
|
For the purposes of this definition, "control" means (i) the power, direct or
|
||||||
|
indirect, to cause the direction or management of such entity, whether by
|
||||||
|
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||||
|
permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications, including
|
||||||
|
but not limited to software source code, documentation source, and configuration
|
||||||
|
files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical transformation or
|
||||||
|
translation of a Source form, including but not limited to compiled object code,
|
||||||
|
generated documentation, and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||||
|
available under the License, as indicated by a copyright notice that is included
|
||||||
|
in or attached to the work (an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||||
|
is based on (or derived from) the Work and for which the editorial revisions,
|
||||||
|
annotations, elaborations, or other modifications represent, as a whole, an
|
||||||
|
original work of authorship. For the purposes of this License, Derivative Works
|
||||||
|
shall not include works that remain separable from, or merely link (or bind by
|
||||||
|
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including the original version
|
||||||
|
of the Work and any modifications or additions to that Work or Derivative Works
|
||||||
|
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||||
|
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||||
|
on behalf of the copyright owner. For the purposes of this definition,
|
||||||
|
"submitted" means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems, and
|
||||||
|
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||||
|
the purpose of discussing and improving the Work, but excluding communication
|
||||||
|
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||||
|
owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||||
|
of whom a Contribution has been received by Licensor and subsequently
|
||||||
|
incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License.
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this License, each Contributor hereby
|
||||||
|
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||||
|
Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License.
|
||||||
|
|
||||||
|
Subject to the terms and conditions of this License, each Contributor hereby
|
||||||
|
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||||
|
irrevocable (except as stated in this section) patent license to make, have
|
||||||
|
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||||
|
such license applies only to those patent claims licensable by such Contributor
|
||||||
|
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||||
|
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||||
|
submitted. If You institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||||
|
Contribution incorporated within the Work constitutes direct or contributory
|
||||||
|
patent infringement, then any patent licenses granted to You under this License
|
||||||
|
for that Work shall terminate as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution.
|
||||||
|
|
||||||
|
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||||
|
in any medium, with or without modifications, and in Source or Object form,
|
||||||
|
provided that You meet the following conditions:
|
||||||
|
|
||||||
|
You must give any other recipients of the Work or Derivative Works a copy of
|
||||||
|
this License; and
|
||||||
|
You must cause any modified files to carry prominent notices stating that You
|
||||||
|
changed the files; and
|
||||||
|
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||||
|
all copyright, patent, trademark, and attribution notices from the Source form
|
||||||
|
of the Work, excluding those notices that do not pertain to any part of the
|
||||||
|
Derivative Works; and
|
||||||
|
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||||
|
Derivative Works that You distribute must include a readable copy of the
|
||||||
|
attribution notices contained within such NOTICE file, excluding those notices
|
||||||
|
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||||
|
following places: within a NOTICE text file distributed as part of the
|
||||||
|
Derivative Works; within the Source form or documentation, if provided along
|
||||||
|
with the Derivative Works; or, within a display generated by the Derivative
|
||||||
|
Works, if and wherever such third-party notices normally appear. The contents of
|
||||||
|
the NOTICE file are for informational purposes only and do not modify the
|
||||||
|
License. You may add Your own attribution notices within Derivative Works that
|
||||||
|
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||||
|
provided that such additional attribution notices cannot be construed as
|
||||||
|
modifying the License.
|
||||||
|
You may add Your own copyright statement to Your modifications and may provide
|
||||||
|
additional or different license terms and conditions for use, reproduction, or
|
||||||
|
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||||
|
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||||
|
with the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions.
|
||||||
|
|
||||||
|
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||||
|
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||||
|
conditions of this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||||
|
any separate license agreement you may have executed with Licensor regarding
|
||||||
|
such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks.
|
||||||
|
|
||||||
|
This License does not grant permission to use the trade names, trademarks,
|
||||||
|
service marks, or product names of the Licensor, except as required for
|
||||||
|
reasonable and customary use in describing the origin of the Work and
|
||||||
|
reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||||
|
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||||
|
including, without limitation, any warranties or conditions of TITLE,
|
||||||
|
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||||
|
solely responsible for determining the appropriateness of using or
|
||||||
|
redistributing the Work and assume any risks associated with Your exercise of
|
||||||
|
permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability.
|
||||||
|
|
||||||
|
In no event and under no legal theory, whether in tort (including negligence),
|
||||||
|
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||||
|
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special, incidental,
|
||||||
|
or consequential damages of any character arising as a result of this License or
|
||||||
|
out of the use or inability to use the Work (including but not limited to
|
||||||
|
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||||
|
any and all other commercial damages or losses), even if such Contributor has
|
||||||
|
been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability.
|
||||||
|
|
||||||
|
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||||
|
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||||
|
other liability obligations and/or rights consistent with this License. However,
|
||||||
|
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||||
|
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||||
|
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason of your
|
||||||
|
accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following boilerplate
|
||||||
|
notice, with the fields enclosed by brackets "{}" replaced with your own
|
||||||
|
identifying information. (Don't include the brackets!) The text should be
|
||||||
|
enclosed in the appropriate comment syntax for the file format. We also
|
||||||
|
recommend that a file or class name and description of purpose be included on
|
||||||
|
the same "printed page" as the copyright notice for easier identification within
|
||||||
|
third-party archives.
|
||||||
|
|
||||||
|
Copyright 2019-2020 Zheng Jie
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
72
UI source code/dns-dev-2.0/README.md
Normal file
72
UI source code/dns-dev-2.0/README.md
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<h1 style="text-align: center">DiamondV
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
#### 项目简介
|
||||||
|
|
||||||
|
一个基于 Spring Boot 2.1.0 、 Spring Boot Jpa、mybatis-plus、 JWT、Spring Security、Redis、Vue的前后端分离的后台管理系统
|
||||||
|
|
||||||
|
**账号密码:** `admin / 123456`
|
||||||
|
|
||||||
|
**打包:** `mvn clean install`
|
||||||
|
|
||||||
|
#### 项目源码
|
||||||
|
|
||||||
|
| | 后端源码 | 前端源码 |
|
||||||
|
| ---- | ------------------------------ | ----------------------------------------- |
|
||||||
|
| 地址 | http://192.168.40.125/kjch/dns | http://192.168.40.125/kjch/dns_mapping_ui |
|
||||||
|
|
||||||
|
#### 主要特性
|
||||||
|
|
||||||
|
- 使用最新技术栈,社区资源丰富。
|
||||||
|
- 高效率开发,代码生成器可一键生成前后端代码
|
||||||
|
- 支持数据字典,可方便地对一些状态进行管理
|
||||||
|
- 支持接口限流,避免恶意请求导致服务层压力过大
|
||||||
|
- 支持接口级别的功能权限与数据权限,可自定义操作
|
||||||
|
- 自定义权限注解与匿名接口注解,可快速对接口拦截与放行
|
||||||
|
- 对一些常用地前端组件封装:表格数据请求、数据字典等
|
||||||
|
- 前后端统一异常拦截处理,统一输出异常,避免繁琐的判断
|
||||||
|
- 支持在线用户管理与服务器性能监控,支持限制单用户登录
|
||||||
|
- 支持运维管理,可方便地对远程服务器的应用进行部署与管理
|
||||||
|
|
||||||
|
#### 系统功能
|
||||||
|
|
||||||
|
- 用户管理:提供用户的相关配置,新增用户后,默认密码为123456
|
||||||
|
- 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限
|
||||||
|
- 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单
|
||||||
|
- 部门管理:可配置系统组织架构,树形表格展示
|
||||||
|
- 岗位管理:配置各个部门的职位
|
||||||
|
- 字典管理:可维护常用一些固定的数据,如:状态,性别等
|
||||||
|
- 系统日志:记录用户操作日志与异常日志,方便开发人员定位排错
|
||||||
|
- SQL监控:采用druid 监控数据库访问性能,默认用户名admin,密码123456
|
||||||
|
- 定时任务:整合Quartz做定时任务,加入任务日志,任务运行情况一目了然
|
||||||
|
- 代码生成:高灵活度生成前后端代码,减少大量重复的工作任务
|
||||||
|
- 邮件工具:配合富文本,发送html格式的邮件
|
||||||
|
- 七牛云存储:可同步七牛云存储的数据到系统,无需登录七牛云直接操作云数据
|
||||||
|
- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试
|
||||||
|
- 服务监控:监控服务器的负载情况
|
||||||
|
- 运维管理:一键部署你的应用
|
||||||
|
|
||||||
|
#### 项目结构
|
||||||
|
|
||||||
|
项目采用按功能分模块的开发方式,结构如下
|
||||||
|
|
||||||
|
- `dns-common` 为系统的公共模块,各种工具类,公共配置存在该模块
|
||||||
|
- `dns-system` 为系统核心模块也是项目入口模块,也是最终需要打包部署的模块
|
||||||
|
- `dns-logging` 为系统的日志模块,其他模块如果需要记录日志需要引入该模块
|
||||||
|
- 详细结构
|
||||||
|
|
||||||
|
```
|
||||||
|
- dns-common 公共模块
|
||||||
|
- annotation 为系统自定义注解
|
||||||
|
- aspect 自定义注解的切面
|
||||||
|
- base 提供了Entity、DTO基类和mapstruct的通用mapper
|
||||||
|
- config 自定义权限实现、redis配置、swagger配置、Rsa配置等
|
||||||
|
- exception 项目统一异常的处理
|
||||||
|
- utils 系统通用工具类
|
||||||
|
- dns-system 系统核心模块(系统启动入口)
|
||||||
|
- config 配置跨域与静态资源,与数据权限
|
||||||
|
- thread 线程池相关
|
||||||
|
- modules 系统相关模块(登录授权、系统监控、定时任务、运维管理,测绘等)
|
||||||
|
- dns-logging 系统日志模块
|
||||||
|
```
|
||||||
26
UI source code/dns-dev-2.0/dns-common/pom.xml
Normal file
26
UI source code/dns-dev-2.0/dns-common/pom.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>dns</artifactId>
|
||||||
|
<groupId>com.example</groupId>
|
||||||
|
<version>2.6</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<properties>
|
||||||
|
<hutool.version>5.3.4</hutool.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<artifactId>dns-common</artifactId>
|
||||||
|
<name>dns-common</name>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!--工具包-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>${hutool.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jacky
|
||||||
|
* 用于标记匿名访问方法
|
||||||
|
*/
|
||||||
|
@Inherited
|
||||||
|
@Documented
|
||||||
|
@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface AnonymousAccess {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 用于判断是否过滤数据权限
|
||||||
|
* 1、如果没有用到 @OneToOne 这种关联关系,只需要填写 fieldName [参考:DeptQueryCriteria.class]
|
||||||
|
* 2、如果用到了 @OneToOne ,fieldName 和 joinName 都需要填写,拿UserQueryCriteria.class举例:
|
||||||
|
* 应该是 @DataPermission(joinName = "dept", fieldName = "id")
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @website https://el-admin.vip
|
||||||
|
* 2020-05-07
|
||||||
|
**/
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface DataPermission {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity 中的字段名称
|
||||||
|
*/
|
||||||
|
String fieldName() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity 中与部门关联的字段名称
|
||||||
|
*/
|
||||||
|
String joinName() default "";
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.annotation;
|
||||||
|
|
||||||
|
import com.example.aspect.LimitType;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jacky
|
||||||
|
*/
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Limit {
|
||||||
|
|
||||||
|
// 资源名称,用于描述接口功能
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
// 资源 key
|
||||||
|
String key() default "";
|
||||||
|
|
||||||
|
// key prefix
|
||||||
|
String prefix() default "";
|
||||||
|
|
||||||
|
// 时间的,单位秒
|
||||||
|
int period();
|
||||||
|
|
||||||
|
// 限制访问次数
|
||||||
|
int count();
|
||||||
|
|
||||||
|
// 限制类型
|
||||||
|
LimitType limitType() default LimitType.CUSTOMER;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface Query {
|
||||||
|
|
||||||
|
// Dong ZhaoYang 2017/8/7 基本对象的属性名
|
||||||
|
String propName() default "";
|
||||||
|
// Dong ZhaoYang 2017/8/7 查询方式
|
||||||
|
Type type() default Type.EQUAL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接查询的属性名,如User类中的dept
|
||||||
|
*/
|
||||||
|
String joinName() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认左连接
|
||||||
|
*/
|
||||||
|
Join join() default Join.LEFT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多字段模糊搜索,仅支持String类型字段,多个用逗号隔开, 如@Query(blurry = "email,username")
|
||||||
|
*/
|
||||||
|
String blurry() default "";
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
// jie 2019/6/4 相等
|
||||||
|
EQUAL
|
||||||
|
// Dong ZhaoYang 2017/8/7 大于等于
|
||||||
|
, GREATER_THAN
|
||||||
|
// Dong ZhaoYang 2017/8/7 小于等于
|
||||||
|
, LESS_THAN
|
||||||
|
// Dong ZhaoYang 2017/8/7 中模糊查询
|
||||||
|
, INNER_LIKE
|
||||||
|
// Dong ZhaoYang 2017/8/7 左模糊查询
|
||||||
|
, LEFT_LIKE
|
||||||
|
// Dong ZhaoYang 2017/8/7 右模糊查询
|
||||||
|
, RIGHT_LIKE
|
||||||
|
// Dong ZhaoYang 2017/8/7 小于
|
||||||
|
, LESS_THAN_NQ
|
||||||
|
// jie 2019/6/4 包含
|
||||||
|
, IN
|
||||||
|
// 不包含
|
||||||
|
, NOT_IN
|
||||||
|
// 不等于
|
||||||
|
,NOT_EQUAL
|
||||||
|
// between
|
||||||
|
,BETWEEN
|
||||||
|
// 不为空
|
||||||
|
,NOT_NULL
|
||||||
|
// 为空
|
||||||
|
,IS_NULL
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 适用于简单连接查询,复杂的请自定义该注解,或者使用sql查询
|
||||||
|
*/
|
||||||
|
enum Join {
|
||||||
|
/** jie 2019-6-4 13:18:30 */
|
||||||
|
LEFT, RIGHT, INNER
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.annotation.rest;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import com.example.annotation.AnonymousAccess;
|
||||||
|
import org.springframework.core.annotation.AliasFor;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for mapping HTTP {@code DELETE} requests onto specific handler
|
||||||
|
* methods.
|
||||||
|
* 支持匿名访问 DeleteMapping
|
||||||
|
*
|
||||||
|
* @author liaojinlong
|
||||||
|
* @see AnonymousGetMapping
|
||||||
|
* @see AnonymousPostMapping
|
||||||
|
* @see AnonymousPutMapping
|
||||||
|
* @see AnonymousPatchMapping
|
||||||
|
* @see RequestMapping
|
||||||
|
*/
|
||||||
|
@AnonymousAccess
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@RequestMapping(method = RequestMethod.DELETE)
|
||||||
|
public @interface AnonymousDeleteMapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#name}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#value}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] value() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#path}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] path() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#params}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] params() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#headers}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] headers() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#consumes}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] consumes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#produces}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] produces() default {};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.annotation.rest;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import com.example.annotation.AnonymousAccess;
|
||||||
|
import org.springframework.core.annotation.AliasFor;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for mapping HTTP {@code GET} requests onto specific handler
|
||||||
|
* methods.
|
||||||
|
* <p>
|
||||||
|
* 支持匿名访问 GetMapping
|
||||||
|
*
|
||||||
|
* @author liaojinlong
|
||||||
|
* @see RequestMapping
|
||||||
|
*/
|
||||||
|
@AnonymousAccess
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@RequestMapping(method = RequestMethod.GET)
|
||||||
|
public @interface AnonymousGetMapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#name}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#value}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] value() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#path}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] path() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#params}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] params() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#headers}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] headers() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#consumes}.
|
||||||
|
*
|
||||||
|
* @since 4.3.5
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] consumes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#produces}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] produces() default {};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.annotation.rest;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import com.example.annotation.AnonymousAccess;
|
||||||
|
import org.springframework.core.annotation.AliasFor;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for mapping HTTP {@code PATCH} requests onto specific handler
|
||||||
|
* methods.
|
||||||
|
* * 支持匿名访问 PatchMapping
|
||||||
|
*
|
||||||
|
* @author liaojinlong
|
||||||
|
* @see AnonymousGetMapping
|
||||||
|
* @see AnonymousPostMapping
|
||||||
|
* @see AnonymousPutMapping
|
||||||
|
* @see AnonymousDeleteMapping
|
||||||
|
* @see RequestMapping
|
||||||
|
*/
|
||||||
|
@AnonymousAccess
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@RequestMapping(method = RequestMethod.PATCH)
|
||||||
|
public @interface AnonymousPatchMapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#name}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#value}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] value() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#path}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] path() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#params}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] params() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#headers}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] headers() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#consumes}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] consumes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#produces}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] produces() default {};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.annotation.rest;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import com.example.annotation.AnonymousAccess;
|
||||||
|
import org.springframework.core.annotation.AliasFor;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for mapping HTTP {@code POST} requests onto specific handler
|
||||||
|
* methods.
|
||||||
|
* 支持匿名访问 PostMapping
|
||||||
|
*
|
||||||
|
* @author liaojinlong
|
||||||
|
* @see AnonymousGetMapping
|
||||||
|
* @see AnonymousPostMapping
|
||||||
|
* @see AnonymousPutMapping
|
||||||
|
* @see AnonymousDeleteMapping
|
||||||
|
* @see RequestMapping
|
||||||
|
*/
|
||||||
|
@AnonymousAccess
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@RequestMapping(method = RequestMethod.POST)
|
||||||
|
public @interface AnonymousPostMapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#name}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#value}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] value() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#path}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] path() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#params}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] params() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#headers}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] headers() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#consumes}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] consumes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#produces}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] produces() default {};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2016 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.annotation.rest;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import com.example.annotation.AnonymousAccess;
|
||||||
|
import org.springframework.core.annotation.AliasFor;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for mapping HTTP {@code PUT} requests onto specific handler
|
||||||
|
* methods.
|
||||||
|
* * 支持匿名访问 PutMapping
|
||||||
|
*
|
||||||
|
* @author liaojinlong
|
||||||
|
* @see AnonymousGetMapping
|
||||||
|
* @see AnonymousPostMapping
|
||||||
|
* @see AnonymousPutMapping
|
||||||
|
* @see AnonymousDeleteMapping
|
||||||
|
* @see RequestMapping
|
||||||
|
*/
|
||||||
|
@AnonymousAccess
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@RequestMapping(method = RequestMethod.PUT)
|
||||||
|
public @interface AnonymousPutMapping {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#name}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String name() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#value}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] value() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#path}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] path() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#params}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] params() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#headers}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] headers() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#consumes}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] consumes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link RequestMapping#produces}.
|
||||||
|
*/
|
||||||
|
@AliasFor(annotation = RequestMapping.class)
|
||||||
|
String[] produces() default {};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.aspect;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.example.annotation.Limit;
|
||||||
|
import com.example.exception.BadRequestException;
|
||||||
|
import com.example.utils.RequestHolder;
|
||||||
|
import com.example.utils.StringUtils;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
|
import org.springframework.data.redis.core.script.RedisScript;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author /
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class LimitAspect {
|
||||||
|
|
||||||
|
private final RedisTemplate<Object,Object> redisTemplate;
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(LimitAspect.class);
|
||||||
|
|
||||||
|
public LimitAspect(RedisTemplate<Object,Object> redisTemplate) {
|
||||||
|
this.redisTemplate = redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Pointcut("@annotation(com.example.annotation.Limit)")
|
||||||
|
public void pointcut() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("pointcut()")
|
||||||
|
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
HttpServletRequest request = RequestHolder.getHttpServletRequest();
|
||||||
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
|
Method signatureMethod = signature.getMethod();
|
||||||
|
Limit limit = signatureMethod.getAnnotation(Limit.class);
|
||||||
|
LimitType limitType = limit.limitType();
|
||||||
|
String key = limit.key();
|
||||||
|
if (StringUtils.isEmpty(key)) {
|
||||||
|
if (limitType == LimitType.IP) {
|
||||||
|
key = StringUtils.getIp(request);
|
||||||
|
} else {
|
||||||
|
key = signatureMethod.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableList<Object> keys = ImmutableList.of(StringUtils.join(limit.prefix(), "_", key, "_", request.getRequestURI().replace("/","_")));
|
||||||
|
|
||||||
|
String luaScript = buildLuaScript();
|
||||||
|
RedisScript<Number> redisScript = new DefaultRedisScript<>(luaScript, Number.class);
|
||||||
|
Number count = redisTemplate.execute(redisScript, keys, limit.count(), limit.period());
|
||||||
|
if (null != count && count.intValue() <= limit.count()) {
|
||||||
|
logger.info("第{}次访问key为 {},描述为 [{}] 的接口", count, keys, limit.name());
|
||||||
|
return joinPoint.proceed();
|
||||||
|
} else {
|
||||||
|
throw new BadRequestException("访问次数受限制");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流脚本
|
||||||
|
*/
|
||||||
|
private String buildLuaScript() {
|
||||||
|
return "local c" +
|
||||||
|
"\nc = redis.call('get',KEYS[1])" +
|
||||||
|
"\nif c and tonumber(c) > tonumber(ARGV[1]) then" +
|
||||||
|
"\nreturn c;" +
|
||||||
|
"\nend" +
|
||||||
|
"\nc = redis.call('incr',KEYS[1])" +
|
||||||
|
"\nif tonumber(c) == 1 then" +
|
||||||
|
"\nredis.call('expire',KEYS[1],ARGV[2])" +
|
||||||
|
"\nend" +
|
||||||
|
"\nreturn c;";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.aspect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流枚举
|
||||||
|
* @author /
|
||||||
|
*/
|
||||||
|
public enum LimitType {
|
||||||
|
// 默认
|
||||||
|
CUSTOMER,
|
||||||
|
// by ip addr
|
||||||
|
IP
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.example.base;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 2019年10月24日20:48:53
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class BaseDTO implements Serializable {
|
||||||
|
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
private Timestamp createTime;
|
||||||
|
|
||||||
|
private Timestamp updateTime;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
ToStringBuilder builder = new ToStringBuilder(this);
|
||||||
|
Field[] fields = this.getClass().getDeclaredFields();
|
||||||
|
try {
|
||||||
|
for (Field f : fields) {
|
||||||
|
f.setAccessible(true);
|
||||||
|
builder.append(f.getName(), f.get(this)).append("\n");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
builder.append("toString builder encounter an error");
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.base;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.hibernate.annotations.CreationTimestamp;
|
||||||
|
import org.hibernate.annotations.UpdateTimestamp;
|
||||||
|
import org.springframework.data.annotation.CreatedBy;
|
||||||
|
import org.springframework.data.annotation.LastModifiedBy;
|
||||||
|
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.EntityListeners;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用字段, is_del 根据需求自行添加
|
||||||
|
*
|
||||||
|
* @Date 2019年10月24日20:46:32
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@MappedSuperclass
|
||||||
|
@EntityListeners(AuditingEntityListener.class)
|
||||||
|
public class BaseEntity implements Serializable {
|
||||||
|
|
||||||
|
@CreatedBy
|
||||||
|
@Column(name = "create_by", updatable = false)
|
||||||
|
@ApiModelProperty(value = "创建人", hidden = true)
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
@LastModifiedBy
|
||||||
|
@Column(name = "update_by")
|
||||||
|
@ApiModelProperty(value = "更新人", hidden = true)
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
@CreationTimestamp
|
||||||
|
@Column(name = "create_time", updatable = false)
|
||||||
|
@ApiModelProperty(value = "创建时间", hidden = true)
|
||||||
|
private Timestamp createTime;
|
||||||
|
|
||||||
|
@UpdateTimestamp
|
||||||
|
@Column(name = "update_time")
|
||||||
|
@ApiModelProperty(value = "更新时间", hidden = true)
|
||||||
|
private Timestamp updateTime;
|
||||||
|
|
||||||
|
/* 分组校验 */
|
||||||
|
public @interface Create {}
|
||||||
|
|
||||||
|
/* 分组校验 */
|
||||||
|
public @interface Update {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
ToStringBuilder builder = new ToStringBuilder(this);
|
||||||
|
Field[] fields = this.getClass().getDeclaredFields();
|
||||||
|
try {
|
||||||
|
for (Field f : fields) {
|
||||||
|
f.setAccessible(true);
|
||||||
|
builder.append(f.getName(), f.get(this)).append("\n");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
builder.append("toString builder encounter an error");
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.base;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public interface BaseMapper<D, E> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DTO转Entity
|
||||||
|
* @param dto /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
E toEntity(D dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity转DTO
|
||||||
|
* @param entity /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
D toDto(E entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DTO集合转Entity集合
|
||||||
|
* @param dtoList /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
List <E> toEntity(List<D> dtoList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity集合转DTO集合
|
||||||
|
* @param entityList /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
List <D> toDto(List<E> entityList);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.config;
|
||||||
|
|
||||||
|
import com.example.utils.SecurityUtils;
|
||||||
|
import org.springframework.data.domain.AuditorAware;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description : 设置审计
|
||||||
|
* @author : Dong ZhaoYang
|
||||||
|
* : 2019/10/28
|
||||||
|
*/
|
||||||
|
@Component("auditorAware")
|
||||||
|
public class AuditorConfig implements AuditorAware<String> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回操作员标志信息
|
||||||
|
*
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Optional<String> getCurrentAuditor() {
|
||||||
|
try {
|
||||||
|
// 这里应根据实际业务情况获取具体信息
|
||||||
|
return Optional.of(SecurityUtils.getCurrentUsername());
|
||||||
|
}catch (Exception ignored){}
|
||||||
|
// 用户定时任务,或者无Token调用的情况
|
||||||
|
return Optional.of("System");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @description
|
||||||
|
* 2021-11-22
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
public class ElAdminProperties {
|
||||||
|
|
||||||
|
public static Boolean ipLocal;
|
||||||
|
|
||||||
|
@Value("${ip.local-parsing}")
|
||||||
|
public void setIpLocal(Boolean ipLocal) {
|
||||||
|
ElAdminProperties.ipLocal = ipLocal;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.config;
|
||||||
|
|
||||||
|
import com.example.utils.SecurityUtils;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service(value = "el")
|
||||||
|
public class ElPermissionConfig {
|
||||||
|
|
||||||
|
public Boolean check(String ...permissions){
|
||||||
|
// 获取当前用户的所有权限
|
||||||
|
List<String> elPermissions = SecurityUtils.getCurrentUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
|
||||||
|
// 判断当前用户的所有权限是否包含接口上定义的权限
|
||||||
|
return elPermissions.contains("admin") || Arrays.stream(permissions).anyMatch(elPermissions::contains);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import com.example.utils.ElAdminConstant;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "file")
|
||||||
|
public class FileProperties {
|
||||||
|
|
||||||
|
/** 文件大小限制 */
|
||||||
|
private Long maxSize;
|
||||||
|
|
||||||
|
/** 头像大小限制 */
|
||||||
|
private Long avatarMaxSize;
|
||||||
|
|
||||||
|
private ElPath mac;
|
||||||
|
|
||||||
|
private ElPath linux;
|
||||||
|
|
||||||
|
private ElPath windows;
|
||||||
|
|
||||||
|
public ElPath getPath(){
|
||||||
|
String os = System.getProperty("os.name");
|
||||||
|
if(os.toLowerCase().startsWith(ElAdminConstant.WIN)) {
|
||||||
|
return windows;
|
||||||
|
} else if(os.toLowerCase().startsWith(ElAdminConstant.MAC)){
|
||||||
|
return mac;
|
||||||
|
}
|
||||||
|
return linux;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ElPath{
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
private String avatar;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.parser.ParserConfig;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.cache.Cache;
|
||||||
|
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.cache.interceptor.CacheErrorHandler;
|
||||||
|
import org.springframework.cache.interceptor.KeyGenerator;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.cache.RedisCacheConfiguration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisOperations;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.RedisSerializationContext;
|
||||||
|
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||||
|
import reactor.util.annotation.Nullable;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 2018-11-24
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
@EnableCaching
|
||||||
|
@ConditionalOnClass(RedisOperations.class)
|
||||||
|
@EnableConfigurationProperties(RedisProperties.class)
|
||||||
|
public class RedisConfig extends CachingConfigurerSupport {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置 redis 数据默认过期时间,默认2小时
|
||||||
|
* 设置@cacheable 序列化方式
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RedisCacheConfiguration redisCacheConfiguration(){
|
||||||
|
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||||||
|
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
|
||||||
|
configuration = configuration.serializeValuesWith(RedisSerializationContext.
|
||||||
|
SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(2));
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@Bean(name = "redisTemplate")
|
||||||
|
@ConditionalOnMissingBean(name = "redisTemplate")
|
||||||
|
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||||
|
RedisTemplate<Object, Object> template = new RedisTemplate<>();
|
||||||
|
//序列化
|
||||||
|
FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
|
||||||
|
// value值的序列化采用fastJsonRedisSerializer
|
||||||
|
template.setValueSerializer(fastJsonRedisSerializer);
|
||||||
|
template.setHashValueSerializer(fastJsonRedisSerializer);
|
||||||
|
// 全局开启AutoType,这里方便开发,使用全局的方式
|
||||||
|
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
||||||
|
// 建议使用这种方式,小范围指定白名单
|
||||||
|
// ParserConfig.getGlobalInstance().addAccept("com.example.domain");
|
||||||
|
// key的序列化采用StringRedisSerializer
|
||||||
|
template.setKeySerializer(new StringRedisSerializer());
|
||||||
|
template.setHashKeySerializer(new StringRedisSerializer());
|
||||||
|
template.setConnectionFactory(redisConnectionFactory);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义缓存key生成策略,默认将使用该策略
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@Override
|
||||||
|
public KeyGenerator keyGenerator() {
|
||||||
|
return (target, method, params) -> {
|
||||||
|
Map<String,Object> container = new HashMap<>(4);
|
||||||
|
Class<?> targetClassClass = target.getClass();
|
||||||
|
// 类地址
|
||||||
|
container.put("class",targetClassClass.toGenericString());
|
||||||
|
// 方法名称
|
||||||
|
container.put("methodName",method.getName());
|
||||||
|
// 包名称
|
||||||
|
container.put("package",targetClassClass.getPackage());
|
||||||
|
// 参数列表
|
||||||
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
container.put(String.valueOf(i),params[i]);
|
||||||
|
}
|
||||||
|
// 转为JSON字符串
|
||||||
|
String jsonString = JSON.toJSONString(container);
|
||||||
|
// 做SHA256 Hash计算,得到一个SHA256摘要作为Key
|
||||||
|
return DigestUtils.sha256Hex(jsonString);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Override
|
||||||
|
public CacheErrorHandler errorHandler() {
|
||||||
|
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
|
||||||
|
log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
|
||||||
|
return new CacheErrorHandler() {
|
||||||
|
@Override
|
||||||
|
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
|
||||||
|
log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
|
||||||
|
log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
|
||||||
|
log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCacheClearError(RuntimeException e, Cache cache) {
|
||||||
|
log.error("Redis occur handleCacheClearError:", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value 序列化
|
||||||
|
*
|
||||||
|
* @author /
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
|
||||||
|
|
||||||
|
private final Class<T> clazz;
|
||||||
|
|
||||||
|
FastJsonRedisSerializer(Class<T> clazz) {
|
||||||
|
super();
|
||||||
|
this.clazz = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] serialize(T t) {
|
||||||
|
if (t == null) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T deserialize(byte[] bytes) {
|
||||||
|
if (bytes == null || bytes.length <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String str = new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
return JSON.parseObject(str, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写序列化器
|
||||||
|
*
|
||||||
|
* @author /
|
||||||
|
*/
|
||||||
|
class StringRedisSerializer implements RedisSerializer<Object> {
|
||||||
|
|
||||||
|
private final Charset charset;
|
||||||
|
|
||||||
|
StringRedisSerializer() {
|
||||||
|
this(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringRedisSerializer(Charset charset) {
|
||||||
|
Assert.notNull(charset, "Charset must not be null!");
|
||||||
|
this.charset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String deserialize(byte[] bytes) {
|
||||||
|
return (bytes == null ? null : new String(bytes, charset));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable byte[] serialize(Object object) {
|
||||||
|
String string = JSON.toJSONString(object);
|
||||||
|
|
||||||
|
if (org.apache.commons.lang3.StringUtils.isBlank(string)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string = string.replace("\"", "");
|
||||||
|
return string.getBytes(charset);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @website https://el-admin.vip
|
||||||
|
* @description
|
||||||
|
* 2020-05-18
|
||||||
|
**/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
public class RsaProperties {
|
||||||
|
|
||||||
|
public static String privateKey;
|
||||||
|
|
||||||
|
@Value("${rsa.private_key}")
|
||||||
|
public void setPrivateKey(String privateKey) {
|
||||||
|
RsaProperties.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.config;
|
||||||
|
|
||||||
|
import com.fasterxml.classmate.TypeResolver;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import springfox.documentation.builders.ApiInfoBuilder;
|
||||||
|
import springfox.documentation.builders.PathSelectors;
|
||||||
|
import springfox.documentation.schema.AlternateTypeRule;
|
||||||
|
import springfox.documentation.schema.AlternateTypeRuleConvention;
|
||||||
|
import springfox.documentation.service.*;
|
||||||
|
import springfox.documentation.spi.DocumentationType;
|
||||||
|
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||||
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
|
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
|
import static springfox.documentation.schema.AlternateTypeRules.newRule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api页面 /doc.html
|
||||||
|
*
|
||||||
|
* 2018-11-23
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableSwagger2
|
||||||
|
public class SwaggerConfig {
|
||||||
|
|
||||||
|
@Value("${jwt.header}")
|
||||||
|
private String tokenHeader;
|
||||||
|
|
||||||
|
@Value("${swagger.enabled}")
|
||||||
|
private Boolean enabled;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public Docket createRestApi() {
|
||||||
|
return new Docket(DocumentationType.SWAGGER_2)
|
||||||
|
.enable(enabled)
|
||||||
|
.pathMapping("/")
|
||||||
|
.apiInfo(apiInfo())
|
||||||
|
.select()
|
||||||
|
.paths(Predicates.not(PathSelectors.regex("/error.*")))
|
||||||
|
.paths(PathSelectors.any())
|
||||||
|
.build()
|
||||||
|
//添加登陆认证
|
||||||
|
.securitySchemes(securitySchemes())
|
||||||
|
.securityContexts(securityContexts());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiInfo apiInfo() {
|
||||||
|
return new ApiInfoBuilder()
|
||||||
|
.description("一个简单且易上手的 Spring boot 后台管理框架")
|
||||||
|
.title("DNS测绘 接口文档")
|
||||||
|
.version("2.6")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SecurityScheme> securitySchemes() {
|
||||||
|
//设置请求头信息
|
||||||
|
List<SecurityScheme> securitySchemes = new ArrayList<>();
|
||||||
|
ApiKey apiKey = new ApiKey(tokenHeader, tokenHeader, "header");
|
||||||
|
securitySchemes.add(apiKey);
|
||||||
|
return securitySchemes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SecurityContext> securityContexts() {
|
||||||
|
//设置需要登录认证的路径
|
||||||
|
List<SecurityContext> securityContexts = new ArrayList<>();
|
||||||
|
// ^(?!auth).*$ 表示所有包含auth的接口不需要使用securitySchemes即不需要带token
|
||||||
|
// ^标识开始 ()里是一子表达式 ?!/auth表示匹配不是/auth的位置,匹配上则添加请求头,注意路径已/开头 .表示任意字符 *表示前面的字符匹配多次 $标识结束
|
||||||
|
securityContexts.add(getContextByPath());
|
||||||
|
return securityContexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecurityContext getContextByPath() {
|
||||||
|
return SecurityContext.builder()
|
||||||
|
.securityReferences(defaultAuth())
|
||||||
|
.forPaths(PathSelectors.regex("^(?!/auth).*$"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SecurityReference> defaultAuth() {
|
||||||
|
List<SecurityReference> securityReferences = new ArrayList<>();
|
||||||
|
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
||||||
|
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||||
|
authorizationScopes[0] = authorizationScope;
|
||||||
|
securityReferences.add(new SecurityReference(tokenHeader, authorizationScopes));
|
||||||
|
return securityReferences;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将Pageable转换展示在swagger中
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
class SwaggerDataConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AlternateTypeRuleConvention pageableConvention(final TypeResolver resolver) {
|
||||||
|
return new AlternateTypeRuleConvention() {
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return Ordered.HIGHEST_PRECEDENCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AlternateTypeRule> rules() {
|
||||||
|
return newArrayList(newRule(resolver.resolve(Pageable.class), resolver.resolve(Page.class)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiModel
|
||||||
|
@Data
|
||||||
|
private static class Page {
|
||||||
|
@ApiModelProperty("页码 (0..N)")
|
||||||
|
private Integer page;
|
||||||
|
|
||||||
|
@ApiModelProperty("每页显示的数目")
|
||||||
|
private Integer size;
|
||||||
|
|
||||||
|
@ApiModelProperty("以下列格式排序标准:property[,asc | desc]。 默认排序顺序为升序。 支持多种排序条件:如:id,asc")
|
||||||
|
private List<String> sort;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一关于错误配置信息 异常
|
||||||
|
*
|
||||||
|
* @author: liaojinlong
|
||||||
|
* : 2020/6/10 18:06
|
||||||
|
*/
|
||||||
|
public class BadConfigurationException extends RuntimeException {
|
||||||
|
/**
|
||||||
|
* Constructs a new runtime exception with {@code null} as its
|
||||||
|
* detail message. The cause is not initialized, and may subsequently be
|
||||||
|
* initialized by a call to {@link #initCause}.
|
||||||
|
*/
|
||||||
|
public BadConfigurationException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new runtime exception with the specified detail message.
|
||||||
|
* The cause is not initialized, and may subsequently be initialized by a
|
||||||
|
* call to {@link #initCause}.
|
||||||
|
*
|
||||||
|
* @param message the detail message. The detail message is saved for
|
||||||
|
* later retrieval by the {@link #getMessage()} method.
|
||||||
|
*/
|
||||||
|
public BadConfigurationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new runtime exception with the specified detail message and
|
||||||
|
* cause. <p>Note that the detail message associated with
|
||||||
|
* {@code cause} is <i>not</i> automatically incorporated in
|
||||||
|
* this runtime exception's detail message.
|
||||||
|
*
|
||||||
|
* @param message the detail message (which is saved for later retrieval
|
||||||
|
* by the {@link #getMessage()} method).
|
||||||
|
* @param cause the cause (which is saved for later retrieval by the
|
||||||
|
* {@link #getCause()} method). (A {@code null} value is
|
||||||
|
* permitted, and indicates that the cause is nonexistent or
|
||||||
|
* unknown.)
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public BadConfigurationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new runtime exception with the specified cause and a
|
||||||
|
* detail message of {@code (cause==null ? null : cause.toString())}
|
||||||
|
* (which typically contains the class and detail message of
|
||||||
|
* {@code cause}). This constructor is useful for runtime exceptions
|
||||||
|
* that are little more than wrappers for other throwables.
|
||||||
|
*
|
||||||
|
* @param cause the cause (which is saved for later retrieval by the
|
||||||
|
* {@link #getCause()} method). (A {@code null} value is
|
||||||
|
* permitted, and indicates that the cause is nonexistent or
|
||||||
|
* unknown.)
|
||||||
|
* @since 1.4
|
||||||
|
*/
|
||||||
|
public BadConfigurationException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new runtime exception with the specified detail
|
||||||
|
* message, cause, suppression enabled or disabled, and writable
|
||||||
|
* stack trace enabled or disabled.
|
||||||
|
*
|
||||||
|
* @param message the detail message.
|
||||||
|
* @param cause the cause. (A {@code null} value is permitted,
|
||||||
|
* and indicates that the cause is nonexistent or unknown.)
|
||||||
|
* @param enableSuppression whether or not suppression is enabled
|
||||||
|
* or disabled
|
||||||
|
* @param writableStackTrace whether or not the stack trace should
|
||||||
|
* be writable
|
||||||
|
* @since 1.7
|
||||||
|
*/
|
||||||
|
protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.exception;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class BadRequestException extends RuntimeException{
|
||||||
|
|
||||||
|
private Integer status = BAD_REQUEST.value();
|
||||||
|
|
||||||
|
public BadRequestException(String msg){
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BadRequestException(HttpStatus status,String msg){
|
||||||
|
super(msg);
|
||||||
|
this.status = status.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.exception;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
|
public class EntityExistException extends RuntimeException {
|
||||||
|
|
||||||
|
public EntityExistException(Class clazz, String field, String val) {
|
||||||
|
super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String generateMessage(String entity, String field, String val) {
|
||||||
|
return StringUtils.capitalize(entity)
|
||||||
|
+ " with " + field + " "+ val + " existed";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.exception;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
|
||||||
|
public class EntityNotFoundException extends RuntimeException {
|
||||||
|
|
||||||
|
public EntityNotFoundException(Class clazz, String field, String val) {
|
||||||
|
super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String generateMessage(String entity, String field, String val) {
|
||||||
|
return StringUtils.capitalize(entity)
|
||||||
|
+ " with " + field + " "+ val + " does not exist";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.exception.handler;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
class ApiError {
|
||||||
|
|
||||||
|
private Integer status = 400;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private LocalDateTime timestamp;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
private ApiError() {
|
||||||
|
timestamp = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiError error(String message){
|
||||||
|
ApiError apiError = new ApiError();
|
||||||
|
apiError.setMessage(message);
|
||||||
|
return apiError;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ApiError error(Integer status, String message){
|
||||||
|
ApiError apiError = new ApiError();
|
||||||
|
apiError.setStatus(status);
|
||||||
|
apiError.setMessage(message);
|
||||||
|
return apiError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.exception.handler;
|
||||||
|
|
||||||
|
import com.example.exception.BadRequestException;
|
||||||
|
import com.example.exception.EntityExistException;
|
||||||
|
import com.example.exception.EntityNotFoundException;
|
||||||
|
import com.example.utils.ThrowableUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.authentication.BadCredentialsException;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import java.util.Objects;
|
||||||
|
import static org.springframework.http.HttpStatus.*;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理所有不可知的异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(Throwable.class)
|
||||||
|
public ResponseEntity<ApiError> handleException(Throwable e){
|
||||||
|
// 打印堆栈信息
|
||||||
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
|
return buildResponseEntity(ApiError.error(e.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BadCredentialsException
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(BadCredentialsException.class)
|
||||||
|
public ResponseEntity<ApiError> badCredentialsException(BadCredentialsException e){
|
||||||
|
// 打印堆栈信息
|
||||||
|
String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage();
|
||||||
|
log.error(message);
|
||||||
|
return buildResponseEntity(ApiError.error(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理自定义异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(value = BadRequestException.class)
|
||||||
|
public ResponseEntity<ApiError> badRequestException(BadRequestException e) {
|
||||||
|
// 打印堆栈信息
|
||||||
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
|
return buildResponseEntity(ApiError.error(e.getStatus(),e.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 EntityExist
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(value = EntityExistException.class)
|
||||||
|
public ResponseEntity<ApiError> entityExistException(EntityExistException e) {
|
||||||
|
// 打印堆栈信息
|
||||||
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
|
return buildResponseEntity(ApiError.error(e.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 EntityNotFound
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(value = EntityNotFoundException.class)
|
||||||
|
public ResponseEntity<ApiError> entityNotFoundException(EntityNotFoundException e) {
|
||||||
|
// 打印堆栈信息
|
||||||
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
|
return buildResponseEntity(ApiError.error(NOT_FOUND.value(),e.getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理所有接口数据验证异常
|
||||||
|
*/
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
public ResponseEntity<ApiError> handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
|
||||||
|
// 打印堆栈信息
|
||||||
|
log.error(ThrowableUtil.getStackTrace(e));
|
||||||
|
String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
|
||||||
|
String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
|
||||||
|
String msg = "不能为空";
|
||||||
|
if(msg.equals(message)){
|
||||||
|
message = str[1] + ":" + message;
|
||||||
|
}
|
||||||
|
return buildResponseEntity(ApiError.error(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一返回
|
||||||
|
*/
|
||||||
|
private ResponseEntity<ApiError> buildResponseEntity(ApiError apiError) {
|
||||||
|
return new ResponseEntity<>(apiError, valueOf(apiError.getStatus()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: liaojinlong
|
||||||
|
* : 2020/6/11 15:49
|
||||||
|
* @apiNote: 关于缓存的Key集合
|
||||||
|
*/
|
||||||
|
public interface CacheKey {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户
|
||||||
|
*/
|
||||||
|
String USER_ID = "user::id:";
|
||||||
|
/**
|
||||||
|
* 数据
|
||||||
|
*/
|
||||||
|
String DATA_USER = "data::user:";
|
||||||
|
/**
|
||||||
|
* 菜单
|
||||||
|
*/
|
||||||
|
String MENU_ID = "menu::id:";
|
||||||
|
String MENU_USER = "menu::user:";
|
||||||
|
/**
|
||||||
|
* 角色授权
|
||||||
|
*/
|
||||||
|
String ROLE_AUTH = "role::auth:";
|
||||||
|
/**
|
||||||
|
* 角色信息
|
||||||
|
*/
|
||||||
|
String ROLE_ID = "role::id:";
|
||||||
|
/**
|
||||||
|
* 部门
|
||||||
|
*/
|
||||||
|
String DEPT_ID = "dept::id:";
|
||||||
|
/**
|
||||||
|
* 岗位
|
||||||
|
*/
|
||||||
|
String JOB_ID = "job::id:";
|
||||||
|
/**
|
||||||
|
* 数据字典
|
||||||
|
*/
|
||||||
|
String DICT_NAME = "dict::name:";
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: liaojinlong
|
||||||
|
* : 2020/6/9 17:02
|
||||||
|
* @since: 1.0
|
||||||
|
* @see {@link SpringContextHolder}
|
||||||
|
* 针对某些初始化方法,在SpringContextHolder 初始化前时,<br>
|
||||||
|
* 可提交一个 提交回调任务。<br>
|
||||||
|
* 在SpringContextHolder 初始化后,进行回调使用
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface CallBack {
|
||||||
|
/**
|
||||||
|
* 回调执行方法
|
||||||
|
*/
|
||||||
|
void executor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本回调任务名称
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
default String getCallBackName() {
|
||||||
|
return Thread.currentThread().getId() + ":" + this.getClass().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @website https://el-admin.vip
|
||||||
|
* @description 用于关闭各种连接,缺啥补啥
|
||||||
|
* 2021-03-05
|
||||||
|
**/
|
||||||
|
public class CloseUtil {
|
||||||
|
|
||||||
|
public static void close(Closeable closeable) {
|
||||||
|
if (null != closeable) {
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 静默关闭
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void close(AutoCloseable closeable) {
|
||||||
|
if (null != closeable) {
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 静默关闭
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常量
|
||||||
|
*/
|
||||||
|
public class Constant {
|
||||||
|
public static final String DOH = "dns-doh";
|
||||||
|
|
||||||
|
public static final String DO53 = "dns-do53";
|
||||||
|
|
||||||
|
public static final String SERVICE = "service";
|
||||||
|
|
||||||
|
public static final String IP = "ip";
|
||||||
|
|
||||||
|
public static final String PORT = "port";
|
||||||
|
|
||||||
|
public static final Integer NONE = 0;
|
||||||
|
|
||||||
|
public static final Integer OPENRDNS = 1;
|
||||||
|
|
||||||
|
public static final Integer FORWARDER = 2;
|
||||||
|
|
||||||
|
public static final Integer FWDRDNS = 3;
|
||||||
|
|
||||||
|
public static final Integer EGRESSRDNS = 4;
|
||||||
|
|
||||||
|
public static final Integer NONSTANDARD = 5;
|
||||||
|
|
||||||
|
public static final String PORT8443 = "8443";
|
||||||
|
|
||||||
|
public static final String PORT443 = "443";
|
||||||
|
|
||||||
|
public static final String PORT53 = "53";
|
||||||
|
|
||||||
|
public static final String DNSTAG = "dns";
|
||||||
|
|
||||||
|
public static final String DOHTAG = "DNS-DoH";
|
||||||
|
|
||||||
|
public static final String DO53TAG = "DNS-Do53";
|
||||||
|
|
||||||
|
public static final String OPENRDNSTAG = "open-rdns";
|
||||||
|
|
||||||
|
public static final String FORWARDERTAG = "forwarder";
|
||||||
|
|
||||||
|
public static final String FWDRDNSTAG = "fwd/rdns";
|
||||||
|
|
||||||
|
public static final String EGRESSRDNSTAG = "egress-dns";
|
||||||
|
|
||||||
|
public static final String NONSTANDARDTAG = "nonstandard";
|
||||||
|
|
||||||
|
public static final String PROTOC_TCP = "tcp";
|
||||||
|
|
||||||
|
public static final String PROTOC_UDP = "udp";
|
||||||
|
|
||||||
|
public static final String IP_IPV4 = "ipv4";
|
||||||
|
|
||||||
|
public static final String IP_IPV6 = "ipv6";
|
||||||
|
|
||||||
|
public static final String POINT = ".";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import java.time.*;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: liaojinlong
|
||||||
|
* : 2020/6/11 16:28
|
||||||
|
* @apiNote: JDK 8 新日期类 格式化与字符串转换 工具类
|
||||||
|
*/
|
||||||
|
public class DateUtil {
|
||||||
|
|
||||||
|
public static final DateTimeFormatter DFY_MD_HMS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
public static final DateTimeFormatter DFY_MD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDateTime 转时间戳
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static Long getTimeStamp(LocalDateTime localDateTime) {
|
||||||
|
return localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间戳转LocalDateTime
|
||||||
|
*
|
||||||
|
* @param timeStamp /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static LocalDateTime fromTimeStamp(Long timeStamp) {
|
||||||
|
return LocalDateTime.ofEpochSecond(timeStamp, 0, OffsetDateTime.now().getOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDateTime 转 Date
|
||||||
|
* Jdk8 后 不推荐使用 {@link Date} Date
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static Date toDate(LocalDateTime localDateTime) {
|
||||||
|
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalDate 转 Date
|
||||||
|
* Jdk8 后 不推荐使用 {@link Date} Date
|
||||||
|
*
|
||||||
|
* @param localDate /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static Date toDate(LocalDate localDate) {
|
||||||
|
return toDate(localDate.atTime(LocalTime.now(ZoneId.systemDefault())));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date转 LocalDateTime
|
||||||
|
* Jdk8 后 不推荐使用 {@link Date} Date
|
||||||
|
*
|
||||||
|
* @param date /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static LocalDateTime toLocalDateTime(Date date) {
|
||||||
|
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期 格式化
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @param patten /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static String localDateTimeFormat(LocalDateTime localDateTime, String patten) {
|
||||||
|
DateTimeFormatter df = DateTimeFormatter.ofPattern(patten);
|
||||||
|
return df.format(localDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期 格式化
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @param df /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static String localDateTimeFormat(LocalDateTime localDateTime, DateTimeFormatter df) {
|
||||||
|
return df.format(localDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期格式化 yyyy-MM-dd HH:mm:ss
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static String localDateTimeFormatyMdHms(LocalDateTime localDateTime) {
|
||||||
|
return DFY_MD_HMS.format(localDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日期格式化 yyyy-MM-dd
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public String localDateTimeFormatyMd(LocalDateTime localDateTime) {
|
||||||
|
return DFY_MD.format(localDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static LocalDateTime parseLocalDateTimeFormat(String localDateTime, String pattern) {
|
||||||
|
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
|
||||||
|
return LocalDateTime.from(dateTimeFormatter.parse(localDateTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static LocalDateTime parseLocalDateTimeFormat(String localDateTime, DateTimeFormatter dateTimeFormatter) {
|
||||||
|
return LocalDateTime.from(dateTimeFormatter.parse(localDateTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd HH:mm:ss
|
||||||
|
*
|
||||||
|
* @param localDateTime /
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static LocalDateTime parseLocalDateTimeFormatyMdHms(String localDateTime) {
|
||||||
|
return LocalDateTime.from(DFY_MD_HMS.parse(localDateTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常用静态常量
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 2018-12-26
|
||||||
|
*/
|
||||||
|
public class ElAdminConstant {
|
||||||
|
|
||||||
|
private ElAdminConstant() {
|
||||||
|
throw new IllegalStateException("Utility class");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于IP定位转换
|
||||||
|
*/
|
||||||
|
public static final String REGION = "内网IP|内网IP";
|
||||||
|
/**
|
||||||
|
* win 系统
|
||||||
|
*/
|
||||||
|
public static final String WIN = "win";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mac 系统
|
||||||
|
*/
|
||||||
|
public static final String MAC = "mac";
|
||||||
|
|
||||||
|
public static final List<String> openRdnsLabels = Arrays.asList("DNS", "DNS-Do53", "open-rdns");
|
||||||
|
|
||||||
|
public static final List<String> forwarderLabels = Arrays.asList("DNS", "DNS-Do53", "forwarder");
|
||||||
|
|
||||||
|
public static final List<String> fwdRdnsLabels = Arrays.asList("DNS", "DNS-Do53", "fwd/rdns");
|
||||||
|
|
||||||
|
public static final List<String> egressDnsLabels = Arrays.asList("DNS", "DNS-Do53", "egress-dns");
|
||||||
|
|
||||||
|
public static final List<String> nonstandardLabels = Arrays.asList("DNS", "DNS-Do53", "nonstandard");
|
||||||
|
|
||||||
|
public static final List<String> dnsLabels = Arrays.asList("DNS");
|
||||||
|
|
||||||
|
public static final List<String> dohLabels = Arrays.asList("DNS","DNS-DoH");
|
||||||
|
|
||||||
|
public static final List<String> do53Labels = Arrays.asList(new String[]{"DNS","DNS-Do53"});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常用接口
|
||||||
|
*/
|
||||||
|
public static class Url {
|
||||||
|
// IP归属地查询
|
||||||
|
public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.DESKeySpec;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
*
|
||||||
|
* 2018-11-23
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class EncryptUtils {
|
||||||
|
|
||||||
|
private static final String STR_PARAM = "Passw0rd";
|
||||||
|
|
||||||
|
private static Cipher cipher;
|
||||||
|
|
||||||
|
private static final IvParameterSpec IV = new IvParameterSpec(STR_PARAM.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
private static DESKeySpec getDesKeySpec(String source) throws Exception {
|
||||||
|
if (source == null || source.length() == 0){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
|
||||||
|
String strKey = "Passw0rd";
|
||||||
|
return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称加密
|
||||||
|
*/
|
||||||
|
public static String desEncrypt(String source) throws Exception {
|
||||||
|
DESKeySpec desKeySpec = getDesKeySpec(source);
|
||||||
|
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
|
||||||
|
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IV);
|
||||||
|
return byte2hex(
|
||||||
|
cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对称解密
|
||||||
|
*/
|
||||||
|
public static String desDecrypt(String source) throws Exception {
|
||||||
|
byte[] src = hex2byte(source.getBytes(StandardCharsets.UTF_8));
|
||||||
|
DESKeySpec desKeySpec = getDesKeySpec(source);
|
||||||
|
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
|
||||||
|
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, secretKey, IV);
|
||||||
|
byte[] retByte = cipher.doFinal(src);
|
||||||
|
return new String(retByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String byte2hex(byte[] inStr) {
|
||||||
|
String stmp;
|
||||||
|
StringBuilder out = new StringBuilder(inStr.length * 2);
|
||||||
|
for (byte b : inStr) {
|
||||||
|
stmp = Integer.toHexString(b & 0xFF);
|
||||||
|
if (stmp.length() == 1) {
|
||||||
|
// 如果是0至F的单位字符串,则添加0
|
||||||
|
out.append("0").append(stmp);
|
||||||
|
} else {
|
||||||
|
out.append(stmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] hex2byte(byte[] b) {
|
||||||
|
int size = 2;
|
||||||
|
if ((b.length % size) != 0){
|
||||||
|
throw new IllegalArgumentException("长度不是偶数");
|
||||||
|
}
|
||||||
|
byte[] b2 = new byte[b.length / 2];
|
||||||
|
for (int n = 0; n < b.length; n += size) {
|
||||||
|
String item = new String(b, n, 2);
|
||||||
|
b2[n / 2] = (byte) Integer.parseInt(item, 16);
|
||||||
|
}
|
||||||
|
return b2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import cn.hutool.poi.excel.BigExcelWriter;
|
||||||
|
import cn.hutool.poi.excel.ExcelUtil;
|
||||||
|
import com.example.exception.BadRequestException;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
import org.apache.poi.xssf.streaming.SXSSFSheet;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import javax.servlet.ServletOutputStream;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.*;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File工具类,扩展 hutool 工具包
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 2018-12-27
|
||||||
|
*/
|
||||||
|
public class FileUtil extends cn.hutool.core.io.FileUtil {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(FileUtil.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统临时目录
|
||||||
|
* <br>
|
||||||
|
* windows 包含路径分割符,但Linux 不包含,
|
||||||
|
* 在windows \\==\ 前提下,
|
||||||
|
* 为安全起见 同意拼装 路径分割符,
|
||||||
|
* <pre>
|
||||||
|
* java.io.tmpdir
|
||||||
|
* windows : C:\Users/xxx\AppData\Local\Temp\
|
||||||
|
* linux: /temp
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator;
|
||||||
|
/**
|
||||||
|
* 定义GB的计算常量
|
||||||
|
*/
|
||||||
|
private static final int GB = 1024 * 1024 * 1024;
|
||||||
|
/**
|
||||||
|
* 定义MB的计算常量
|
||||||
|
*/
|
||||||
|
private static final int MB = 1024 * 1024;
|
||||||
|
/**
|
||||||
|
* 定义KB的计算常量
|
||||||
|
*/
|
||||||
|
private static final int KB = 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化小数
|
||||||
|
*/
|
||||||
|
private static final DecimalFormat DF = new DecimalFormat("0.00");
|
||||||
|
|
||||||
|
public static final String IMAGE = "图片";
|
||||||
|
public static final String TXT = "文档";
|
||||||
|
public static final String MUSIC = "音乐";
|
||||||
|
public static final String VIDEO = "视频";
|
||||||
|
public static final String OTHER = "其他";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MultipartFile转File
|
||||||
|
*/
|
||||||
|
public static File toFile(MultipartFile multipartFile) {
|
||||||
|
// 获取文件名
|
||||||
|
String fileName = multipartFile.getOriginalFilename();
|
||||||
|
// 获取文件后缀
|
||||||
|
String prefix = "." + getExtensionName(fileName);
|
||||||
|
File file = null;
|
||||||
|
try {
|
||||||
|
// 用uuid作为文件名,防止生成的临时文件重复
|
||||||
|
file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix);
|
||||||
|
// MultipartFile to File
|
||||||
|
multipartFile.transferTo(file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件扩展名,不带 .
|
||||||
|
*/
|
||||||
|
public static String getExtensionName(String filename) {
|
||||||
|
if ((filename != null) && (filename.length() > 0)) {
|
||||||
|
int dot = filename.lastIndexOf('.');
|
||||||
|
if ((dot > -1) && (dot < (filename.length() - 1))) {
|
||||||
|
return filename.substring(dot + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java文件操作 获取不带扩展名的文件名
|
||||||
|
*/
|
||||||
|
public static String getFileNameNoEx(String filename) {
|
||||||
|
if ((filename != null) && (filename.length() > 0)) {
|
||||||
|
int dot = filename.lastIndexOf('.');
|
||||||
|
if ((dot > -1) && (dot < (filename.length()))) {
|
||||||
|
return filename.substring(0, dot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件大小转换
|
||||||
|
*/
|
||||||
|
public static String getSize(long size) {
|
||||||
|
String resultSize;
|
||||||
|
if (size / GB >= 1) {
|
||||||
|
//如果当前Byte的值大于等于1GB
|
||||||
|
resultSize = DF.format(size / (float) GB) + "GB ";
|
||||||
|
} else if (size / MB >= 1) {
|
||||||
|
//如果当前Byte的值大于等于1MB
|
||||||
|
resultSize = DF.format(size / (float) MB) + "MB ";
|
||||||
|
} else if (size / KB >= 1) {
|
||||||
|
//如果当前Byte的值大于等于1KB
|
||||||
|
resultSize = DF.format(size / (float) KB) + "KB ";
|
||||||
|
} else {
|
||||||
|
resultSize = size + "B ";
|
||||||
|
}
|
||||||
|
return resultSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inputStream 转 File
|
||||||
|
*/
|
||||||
|
static File inputStreamToFile(InputStream ins, String name){
|
||||||
|
File file = new File(SYS_TEM_DIR + name);
|
||||||
|
if (file.exists()) {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
OutputStream os = null;
|
||||||
|
try {
|
||||||
|
os = new FileOutputStream(file);
|
||||||
|
int bytesRead;
|
||||||
|
int len = 8192;
|
||||||
|
byte[] buffer = new byte[len];
|
||||||
|
while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
|
||||||
|
os.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
CloseUtil.close(os);
|
||||||
|
CloseUtil.close(ins);
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将文件名解析成文件的上传路径
|
||||||
|
*/
|
||||||
|
public static File upload(MultipartFile file, String filePath) {
|
||||||
|
Date date = new Date();
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS");
|
||||||
|
String name = getFileNameNoEx(file.getOriginalFilename());
|
||||||
|
String suffix = getExtensionName(file.getOriginalFilename());
|
||||||
|
String nowStr = "-" + format.format(date);
|
||||||
|
try {
|
||||||
|
String fileName = name + nowStr + "." + suffix;
|
||||||
|
String path = filePath + fileName;
|
||||||
|
// getCanonicalFile 可解析正确各种路径
|
||||||
|
File dest = new File(path).getCanonicalFile();
|
||||||
|
// 检测是否存在目录
|
||||||
|
if (!dest.getParentFile().exists()) {
|
||||||
|
if (!dest.getParentFile().mkdirs()) {
|
||||||
|
System.out.println("was not successful.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 文件写入
|
||||||
|
file.transferTo(dest);
|
||||||
|
return dest;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出excel
|
||||||
|
*/
|
||||||
|
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
|
||||||
|
String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
|
||||||
|
File file = new File(tempPath);
|
||||||
|
BigExcelWriter writer = ExcelUtil.getBigWriter(file);
|
||||||
|
// 一次性写出内容,使用默认样式,强制输出标题
|
||||||
|
writer.write(list, true);
|
||||||
|
SXSSFSheet sheet = (SXSSFSheet)writer.getSheet();
|
||||||
|
//上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法
|
||||||
|
sheet.trackAllColumnsForAutoSizing();
|
||||||
|
//列宽自适应
|
||||||
|
writer.autoSizeColumnAll();
|
||||||
|
//response为HttpServletResponse对象
|
||||||
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
|
||||||
|
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
|
||||||
|
response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
|
||||||
|
ServletOutputStream out = response.getOutputStream();
|
||||||
|
// 终止后删除临时文件
|
||||||
|
file.deleteOnExit();
|
||||||
|
writer.flush(out, true);
|
||||||
|
//此处记得关闭输出Servlet流
|
||||||
|
IoUtil.close(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getFileType(String type) {
|
||||||
|
String documents = "txt doc pdf ppt pps xlsx xls docx";
|
||||||
|
String music = "mp3 wav wma mpa ram ra aac aif m4a";
|
||||||
|
String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg";
|
||||||
|
String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg";
|
||||||
|
if (image.contains(type)) {
|
||||||
|
return IMAGE;
|
||||||
|
} else if (documents.contains(type)) {
|
||||||
|
return TXT;
|
||||||
|
} else if (music.contains(type)) {
|
||||||
|
return MUSIC;
|
||||||
|
} else if (video.contains(type)) {
|
||||||
|
return VIDEO;
|
||||||
|
} else {
|
||||||
|
return OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void checkSize(long maxSize, long size) {
|
||||||
|
// 1M
|
||||||
|
int len = 1024 * 1024;
|
||||||
|
if (size > (maxSize * len)) {
|
||||||
|
throw new BadRequestException("文件超出规定大小:" + maxSize + "MB");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断两个文件是否相同
|
||||||
|
*/
|
||||||
|
public static boolean check(File file1, File file2) {
|
||||||
|
String img1Md5 = getMd5(file1);
|
||||||
|
String img2Md5 = getMd5(file2);
|
||||||
|
if(img1Md5 != null){
|
||||||
|
return img1Md5.equals(img2Md5);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断两个文件是否相同
|
||||||
|
*/
|
||||||
|
public static boolean check(String file1Md5, String file2Md5) {
|
||||||
|
return file1Md5.equals(file2Md5);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] getByte(File file) {
|
||||||
|
// 得到文件长度
|
||||||
|
byte[] b = new byte[(int) file.length()];
|
||||||
|
InputStream in = null;
|
||||||
|
try {
|
||||||
|
in = new FileInputStream(file);
|
||||||
|
try {
|
||||||
|
System.out.println(in.read(b));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
CloseUtil.close(in);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getMd5(byte[] bytes) {
|
||||||
|
// 16进制字符
|
||||||
|
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
try {
|
||||||
|
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
|
||||||
|
mdTemp.update(bytes);
|
||||||
|
byte[] md = mdTemp.digest();
|
||||||
|
int j = md.length;
|
||||||
|
char[] str = new char[j * 2];
|
||||||
|
int k = 0;
|
||||||
|
// 移位 输出字符串
|
||||||
|
for (byte byte0 : md) {
|
||||||
|
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
|
||||||
|
str[k++] = hexDigits[byte0 & 0xf];
|
||||||
|
}
|
||||||
|
return new String(str);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文件
|
||||||
|
*
|
||||||
|
* @param request /
|
||||||
|
* @param response /
|
||||||
|
* @param file /
|
||||||
|
*/
|
||||||
|
public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
|
||||||
|
response.setCharacterEncoding(request.getCharacterEncoding());
|
||||||
|
response.setContentType("application/octet-stream");
|
||||||
|
FileInputStream fis = null;
|
||||||
|
try {
|
||||||
|
fis = new FileInputStream(file);
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
|
||||||
|
IOUtils.copy(fis, response.getOutputStream());
|
||||||
|
response.flushBuffer();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
if (fis != null) {
|
||||||
|
try {
|
||||||
|
fis.close();
|
||||||
|
if (deleteOnExit) {
|
||||||
|
file.deleteOnExit();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMd5(File file) {
|
||||||
|
return getMd5(getByte(file));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import org.springframework.data.domain.Page;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页工具
|
||||||
|
*
|
||||||
|
* 2018-12-10
|
||||||
|
*/
|
||||||
|
public class PageUtil extends cn.hutool.core.util.PageUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List 分页
|
||||||
|
*/
|
||||||
|
public static List toPage(int page, int size , List list) {
|
||||||
|
int fromIndex = page * size;
|
||||||
|
int toIndex = page * size + size;
|
||||||
|
if(fromIndex > list.size()){
|
||||||
|
return new ArrayList();
|
||||||
|
} else if(toIndex >= list.size()) {
|
||||||
|
return list.subList(fromIndex,list.size());
|
||||||
|
} else {
|
||||||
|
return list.subList(fromIndex,toIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page 数据处理,预防redis反序列化报错
|
||||||
|
*/
|
||||||
|
public static Map<String,Object> toPage(Page page) {
|
||||||
|
Map<String,Object> map = new LinkedHashMap<>(2);
|
||||||
|
map.put("content",page.getContent());
|
||||||
|
map.put("totalElements",page.getTotalElements());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义分页
|
||||||
|
*/
|
||||||
|
public static Map<String,Object> toPage(Object object, Object totalElements) {
|
||||||
|
Map<String,Object> map = new LinkedHashMap<>(2);
|
||||||
|
map.put("content",object);
|
||||||
|
map.put("totalElements",totalElements);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import com.example.annotation.DataPermission;
|
||||||
|
import com.example.annotation.Query;
|
||||||
|
import javax.persistence.criteria.*;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 2019-6-4 14:59:48
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings({"unchecked","all"})
|
||||||
|
public class QueryHelp {
|
||||||
|
|
||||||
|
public static <R, Q> Predicate getPredicate(Root<R> root, Q query, CriteriaBuilder cb) {
|
||||||
|
List<Predicate> list = new ArrayList<>();
|
||||||
|
if(query == null){
|
||||||
|
return cb.and(list.toArray(new Predicate[0]));
|
||||||
|
}
|
||||||
|
// 数据权限验证
|
||||||
|
DataPermission permission = query.getClass().getAnnotation(DataPermission.class);
|
||||||
|
if(permission != null){
|
||||||
|
// 获取数据权限
|
||||||
|
List<Long> dataScopes = SecurityUtils.getCurrentUserDataScope();
|
||||||
|
if(CollectionUtil.isNotEmpty(dataScopes)){
|
||||||
|
if(StringUtils.isNotBlank(permission.joinName()) && StringUtils.isNotBlank(permission.fieldName())) {
|
||||||
|
Join join = root.join(permission.joinName(), JoinType.LEFT);
|
||||||
|
list.add(getExpression(permission.fieldName(),join, root).in(dataScopes));
|
||||||
|
} else if (StringUtils.isBlank(permission.joinName()) && StringUtils.isNotBlank(permission.fieldName())) {
|
||||||
|
list.add(getExpression(permission.fieldName(),null, root).in(dataScopes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
List<Field> fields = getAllFields(query.getClass(), new ArrayList<>());
|
||||||
|
for (Field field : fields) {
|
||||||
|
boolean accessible = field.isAccessible();
|
||||||
|
// 设置对象的访问权限,保证对private的属性的访
|
||||||
|
field.setAccessible(true);
|
||||||
|
Query q = field.getAnnotation(Query.class);
|
||||||
|
if (q != null) {
|
||||||
|
String propName = q.propName();
|
||||||
|
String joinName = q.joinName();
|
||||||
|
String blurry = q.blurry();
|
||||||
|
String attributeName = isBlank(propName) ? field.getName() : propName;
|
||||||
|
Class<?> fieldType = field.getType();
|
||||||
|
Object val = field.get(query);
|
||||||
|
if (ObjectUtil.isNull(val) || "".equals(val)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Join join = null;
|
||||||
|
// 模糊多字段
|
||||||
|
if (ObjectUtil.isNotEmpty(blurry)) {
|
||||||
|
String[] blurrys = blurry.split(",");
|
||||||
|
List<Predicate> orPredicate = new ArrayList<>();
|
||||||
|
for (String s : blurrys) {
|
||||||
|
orPredicate.add(cb.like(root.get(s)
|
||||||
|
.as(String.class), "%" + val.toString() + "%"));
|
||||||
|
}
|
||||||
|
Predicate[] p = new Predicate[orPredicate.size()];
|
||||||
|
list.add(cb.or(orPredicate.toArray(p)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ObjectUtil.isNotEmpty(joinName)) {
|
||||||
|
String[] joinNames = joinName.split(">");
|
||||||
|
for (String name : joinNames) {
|
||||||
|
switch (q.join()) {
|
||||||
|
case LEFT:
|
||||||
|
if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
|
||||||
|
join = join.join(name, JoinType.LEFT);
|
||||||
|
} else {
|
||||||
|
join = root.join(name, JoinType.LEFT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
|
||||||
|
join = join.join(name, JoinType.RIGHT);
|
||||||
|
} else {
|
||||||
|
join = root.join(name, JoinType.RIGHT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case INNER:
|
||||||
|
if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){
|
||||||
|
join = join.join(name, JoinType.INNER);
|
||||||
|
} else {
|
||||||
|
join = root.join(name, JoinType.INNER);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (q.type()) {
|
||||||
|
case EQUAL:
|
||||||
|
list.add(cb.equal(getExpression(attributeName,join,root)
|
||||||
|
.as((Class<? extends Comparable>) fieldType),val));
|
||||||
|
break;
|
||||||
|
case GREATER_THAN:
|
||||||
|
list.add(cb.greaterThanOrEqualTo(getExpression(attributeName,join,root)
|
||||||
|
.as((Class<? extends Comparable>) fieldType), (Comparable) val));
|
||||||
|
break;
|
||||||
|
case LESS_THAN:
|
||||||
|
list.add(cb.lessThanOrEqualTo(getExpression(attributeName,join,root)
|
||||||
|
.as((Class<? extends Comparable>) fieldType), (Comparable) val));
|
||||||
|
break;
|
||||||
|
case LESS_THAN_NQ:
|
||||||
|
list.add(cb.lessThan(getExpression(attributeName,join,root)
|
||||||
|
.as((Class<? extends Comparable>) fieldType), (Comparable) val));
|
||||||
|
break;
|
||||||
|
case INNER_LIKE:
|
||||||
|
list.add(cb.like(getExpression(attributeName,join,root)
|
||||||
|
.as(String.class), "%" + val.toString() + "%"));
|
||||||
|
break;
|
||||||
|
case LEFT_LIKE:
|
||||||
|
list.add(cb.like(getExpression(attributeName,join,root)
|
||||||
|
.as(String.class), "%" + val.toString()));
|
||||||
|
break;
|
||||||
|
case RIGHT_LIKE:
|
||||||
|
list.add(cb.like(getExpression(attributeName,join,root)
|
||||||
|
.as(String.class), val.toString() + "%"));
|
||||||
|
break;
|
||||||
|
case IN:
|
||||||
|
if (CollUtil.isNotEmpty((Collection<Object>)val)) {
|
||||||
|
list.add(getExpression(attributeName,join,root).in((Collection<Object>) val));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOT_IN:
|
||||||
|
if (CollUtil.isNotEmpty((Collection<Object>)val)) {
|
||||||
|
list.add(getExpression(attributeName,join,root).in((Collection<Object>) val).not());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NOT_EQUAL:
|
||||||
|
list.add(cb.notEqual(getExpression(attributeName,join,root), val));
|
||||||
|
break;
|
||||||
|
case NOT_NULL:
|
||||||
|
list.add(cb.isNotNull(getExpression(attributeName,join,root)));
|
||||||
|
break;
|
||||||
|
case IS_NULL:
|
||||||
|
list.add(cb.isNull(getExpression(attributeName,join,root)));
|
||||||
|
break;
|
||||||
|
case BETWEEN:
|
||||||
|
List<Object> between = new ArrayList<>((List<Object>)val);
|
||||||
|
list.add(cb.between(getExpression(attributeName, join, root).as((Class<? extends Comparable>) between.get(0).getClass()),
|
||||||
|
(Comparable) between.get(0), (Comparable) between.get(1)));
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
field.setAccessible(accessible);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
int size = list.size();
|
||||||
|
return cb.and(list.toArray(new Predicate[size]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static <T, R> Expression<T> getExpression(String attributeName, Join join, Root<R> root) {
|
||||||
|
if (ObjectUtil.isNotEmpty(join)) {
|
||||||
|
return join.get(attributeName);
|
||||||
|
} else {
|
||||||
|
return root.get(attributeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isBlank(final CharSequence cs) {
|
||||||
|
int strLen;
|
||||||
|
if (cs == null || (strLen = cs.length()) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < strLen; i++) {
|
||||||
|
if (!Character.isWhitespace(cs.charAt(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Field> getAllFields(Class clazz, List<Field> fields) {
|
||||||
|
if (clazz != null) {
|
||||||
|
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
|
||||||
|
getAllFields(clazz.getSuperclass(), fields);
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,708 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnection;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.*;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author /
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@SuppressWarnings({"unchecked", "all"})
|
||||||
|
public class RedisUtils {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(RedisUtils.class);
|
||||||
|
private RedisTemplate<Object, Object> redisTemplate;
|
||||||
|
@Value("${jwt.online-key}")
|
||||||
|
private String onlineKey;
|
||||||
|
|
||||||
|
public RedisUtils(RedisTemplate<Object, Object> redisTemplate) {
|
||||||
|
this.redisTemplate = redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定缓存失效时间
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param time 时间(秒)
|
||||||
|
*/
|
||||||
|
public boolean expire(String key, long time) {
|
||||||
|
try {
|
||||||
|
if (time > 0) {
|
||||||
|
redisTemplate.expire(key, time, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定缓存失效时间
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param time 时间(秒)
|
||||||
|
* @param timeUnit 单位
|
||||||
|
*/
|
||||||
|
public boolean expire(String key, long time, TimeUnit timeUnit) {
|
||||||
|
try {
|
||||||
|
if (time > 0) {
|
||||||
|
redisTemplate.expire(key, time, timeUnit);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 key 获取过期时间
|
||||||
|
*
|
||||||
|
* @param key 键 不能为null
|
||||||
|
* @return 时间(秒) 返回0代表为永久有效
|
||||||
|
*/
|
||||||
|
public long getExpire(Object key) {
|
||||||
|
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找匹配key
|
||||||
|
*
|
||||||
|
* @param pattern key
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public List<String> scan(String pattern) {
|
||||||
|
ScanOptions options = ScanOptions.scanOptions().match(pattern).build();
|
||||||
|
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
|
||||||
|
RedisConnection rc = Objects.requireNonNull(factory).getConnection();
|
||||||
|
Cursor<byte[]> cursor = rc.scan(options);
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
result.add(new String(cursor.next()));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RedisConnectionUtils.releaseConnection(rc, factory);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询 key
|
||||||
|
*
|
||||||
|
* @param patternKey key
|
||||||
|
* @param page 页码
|
||||||
|
* @param size 每页数目
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public List<String> findKeysForPage(String patternKey, int page, int size) {
|
||||||
|
ScanOptions options = ScanOptions.scanOptions().match(patternKey).build();
|
||||||
|
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
|
||||||
|
RedisConnection rc = Objects.requireNonNull(factory).getConnection();
|
||||||
|
Cursor<byte[]> cursor = rc.scan(options);
|
||||||
|
List<String> result = new ArrayList<>(size);
|
||||||
|
int tmpIndex = 0;
|
||||||
|
int fromIndex = page * size;
|
||||||
|
int toIndex = page * size + size;
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
if (tmpIndex >= fromIndex && tmpIndex < toIndex) {
|
||||||
|
result.add(new String(cursor.next()));
|
||||||
|
tmpIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 获取到满足条件的数据后,就可以退出了
|
||||||
|
if (tmpIndex >= toIndex) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tmpIndex++;
|
||||||
|
cursor.next();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
RedisConnectionUtils.releaseConnection(rc, factory);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断key是否存在
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return true 存在 false不存在
|
||||||
|
*/
|
||||||
|
public boolean hasKey(String key) {
|
||||||
|
try {
|
||||||
|
return redisTemplate.hasKey(key);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除缓存
|
||||||
|
*
|
||||||
|
* @param key 可以传一个值 或多个
|
||||||
|
*/
|
||||||
|
public void del(String... keys) {
|
||||||
|
if (keys != null && keys.length > 0) {
|
||||||
|
if (keys.length == 1) {
|
||||||
|
boolean result = redisTemplate.delete(keys[0]);
|
||||||
|
log.debug("--------------------------------------------");
|
||||||
|
log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(",结果:").append(result).toString());
|
||||||
|
log.debug("--------------------------------------------");
|
||||||
|
} else {
|
||||||
|
Set<Object> keySet = new HashSet<>();
|
||||||
|
for (String key : keys) {
|
||||||
|
keySet.addAll(redisTemplate.keys(key));
|
||||||
|
}
|
||||||
|
long count = redisTemplate.delete(keySet);
|
||||||
|
log.debug("--------------------------------------------");
|
||||||
|
log.debug("成功删除缓存:" + keySet.toString());
|
||||||
|
log.debug("缓存删除数量:" + count + "个");
|
||||||
|
log.debug("--------------------------------------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================String=============================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通缓存获取
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return 值
|
||||||
|
*/
|
||||||
|
public Object get(String key) {
|
||||||
|
return key == null ? null : redisTemplate.opsForValue().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量获取
|
||||||
|
*
|
||||||
|
* @param keys
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Object> multiGet(List<String> keys) {
|
||||||
|
List list = redisTemplate.opsForValue().multiGet(Sets.newHashSet(keys));
|
||||||
|
List resultList = Lists.newArrayList();
|
||||||
|
Optional.ofNullable(list).ifPresent(e-> list.forEach(ele-> Optional.ofNullable(ele).ifPresent(resultList::add)));
|
||||||
|
return resultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通缓存放入
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @return true成功 false失败
|
||||||
|
*/
|
||||||
|
public boolean set(String key, Object value) {
|
||||||
|
try {
|
||||||
|
redisTemplate.opsForValue().set(key, value);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通缓存放入并设置时间
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
|
||||||
|
* @return true成功 false 失败
|
||||||
|
*/
|
||||||
|
public boolean set(String key, Object value, long time) {
|
||||||
|
try {
|
||||||
|
if (time > 0) {
|
||||||
|
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
|
||||||
|
} else {
|
||||||
|
set(key, value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 普通缓存放入并设置时间
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @param time 时间
|
||||||
|
* @param timeUnit 类型
|
||||||
|
* @return true成功 false 失败
|
||||||
|
*/
|
||||||
|
public boolean set(String key, Object value, long time, TimeUnit timeUnit) {
|
||||||
|
try {
|
||||||
|
if (time > 0) {
|
||||||
|
redisTemplate.opsForValue().set(key, value, time, timeUnit);
|
||||||
|
} else {
|
||||||
|
set(key, value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================Map=================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HashGet
|
||||||
|
*
|
||||||
|
* @param key 键 不能为null
|
||||||
|
* @param item 项 不能为null
|
||||||
|
* @return 值
|
||||||
|
*/
|
||||||
|
public Object hget(String key, String item) {
|
||||||
|
return redisTemplate.opsForHash().get(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取hashKey对应的所有键值
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return 对应的多个键值
|
||||||
|
*/
|
||||||
|
public Map<Object, Object> hmget(String key) {
|
||||||
|
return redisTemplate.opsForHash().entries(key);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HashSet
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param map 对应多个键值
|
||||||
|
* @return true 成功 false 失败
|
||||||
|
*/
|
||||||
|
public boolean hmset(String key, Map<String, Object> map) {
|
||||||
|
try {
|
||||||
|
redisTemplate.opsForHash().putAll(key, map);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HashSet 并设置时间
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param map 对应多个键值
|
||||||
|
* @param time 时间(秒)
|
||||||
|
* @return true成功 false失败
|
||||||
|
*/
|
||||||
|
public boolean hmset(String key, Map<String, Object> map, long time) {
|
||||||
|
try {
|
||||||
|
redisTemplate.opsForHash().putAll(key, map);
|
||||||
|
if (time > 0) {
|
||||||
|
expire(key, time);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向一张hash表中放入数据,如果不存在将创建
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param item 项
|
||||||
|
* @param value 值
|
||||||
|
* @return true 成功 false失败
|
||||||
|
*/
|
||||||
|
public boolean hset(String key, String item, Object value) {
|
||||||
|
try {
|
||||||
|
redisTemplate.opsForHash().put(key, item, value);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向一张hash表中放入数据,如果不存在将创建
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param item 项
|
||||||
|
* @param value 值
|
||||||
|
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
|
||||||
|
* @return true 成功 false失败
|
||||||
|
*/
|
||||||
|
public boolean hset(String key, String item, Object value, long time) {
|
||||||
|
try {
|
||||||
|
redisTemplate.opsForHash().put(key, item, value);
|
||||||
|
if (time > 0) {
|
||||||
|
expire(key, time);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除hash表中的值
|
||||||
|
*
|
||||||
|
* @param key 键 不能为null
|
||||||
|
* @param item 项 可以使多个 不能为null
|
||||||
|
*/
|
||||||
|
public void hdel(String key, Object... item) {
|
||||||
|
redisTemplate.opsForHash().delete(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断hash表中是否有该项的值
|
||||||
|
*
|
||||||
|
* @param key 键 不能为null
|
||||||
|
* @param item 项 不能为null
|
||||||
|
* @return true 存在 false不存在
|
||||||
|
*/
|
||||||
|
public boolean hHasKey(String key, String item) {
|
||||||
|
return redisTemplate.opsForHash().hasKey(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param item 项
|
||||||
|
* @param by 要增加几(大于0)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public double hincr(String key, String item, double by) {
|
||||||
|
return redisTemplate.opsForHash().increment(key, item, by);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hash递减
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param item 项
|
||||||
|
* @param by 要减少记(小于0)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public double hdecr(String key, String item, double by) {
|
||||||
|
return redisTemplate.opsForHash().increment(key, item, -by);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================set=============================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据key获取Set中的所有值
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Set<Object> sGet(String key) {
|
||||||
|
try {
|
||||||
|
return redisTemplate.opsForSet().members(key);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据value从一个set中查询,是否存在
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @return true 存在 false不存在
|
||||||
|
*/
|
||||||
|
public boolean sHasKey(String key, Object value) {
|
||||||
|
try {
|
||||||
|
return redisTemplate.opsForSet().isMember(key, value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将数据放入set缓存
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param values 值 可以是多个
|
||||||
|
* @return 成功个数
|
||||||
|
*/
|
||||||
|
public long sSet(String key, Object... values) {
|
||||||
|
try {
|
||||||
|
return redisTemplate.opsForSet().add(key, values);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将set数据放入缓存
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param time 时间(秒)
|
||||||
|
* @param values 值 可以是多个
|
||||||
|
* @return 成功个数
|
||||||
|
*/
|
||||||
|
public long sSetAndTime(String key, long time, Object... values) {
|
||||||
|
try {
|
||||||
|
Long count = redisTemplate.opsForSet().add(key, values);
|
||||||
|
if (time > 0) {
|
||||||
|
expire(key, time);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取set缓存的长度
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public 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 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 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 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 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 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 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 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 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 索引
|
||||||
|
* @param value 值
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public boolean lUpdateIndex(String key, long index, Object value) {
|
||||||
|
try {
|
||||||
|
redisTemplate.opsForList().set(key, index, value);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 移除N个值为value
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param count 移除多少个
|
||||||
|
* @param value 值
|
||||||
|
* @return 移除的个数
|
||||||
|
*/
|
||||||
|
public long lRemove(String key, long count, Object value) {
|
||||||
|
try {
|
||||||
|
return redisTemplate.opsForList().remove(key, count, value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prefix 前缀
|
||||||
|
* @param ids id
|
||||||
|
*/
|
||||||
|
public void delByKeys(String prefix, Set<Long> ids) {
|
||||||
|
Set<Object> keys = new HashSet<>();
|
||||||
|
for (Long id : ids) {
|
||||||
|
keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString()));
|
||||||
|
}
|
||||||
|
long count = redisTemplate.delete(keys);
|
||||||
|
// 此处提示可自行删除
|
||||||
|
log.debug("--------------------------------------------");
|
||||||
|
log.debug("成功删除缓存:" + keys.toString());
|
||||||
|
log.debug("缓存删除数量:" + count + "个");
|
||||||
|
log.debug("--------------------------------------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 HttpServletRequest
|
||||||
|
*
|
||||||
|
* 2018-11-24
|
||||||
|
*/
|
||||||
|
public class RequestHolder {
|
||||||
|
|
||||||
|
public static HttpServletRequest getHttpServletRequest() {
|
||||||
|
return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.interfaces.RSAPrivateKey;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author https://www.cnblogs.com/nihaorz/p/10690643.html
|
||||||
|
* @description Rsa 工具类,公钥私钥生成,加解密
|
||||||
|
* 2020-05-18
|
||||||
|
**/
|
||||||
|
public class RsaUtils {
|
||||||
|
|
||||||
|
private static final String SRC = "123456";
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
System.out.println("\n");
|
||||||
|
RsaKeyPair keyPair = generateKeyPair();
|
||||||
|
System.out.println("公钥:" + keyPair.getPublicKey());
|
||||||
|
System.out.println("私钥:" + keyPair.getPrivateKey());
|
||||||
|
System.out.println("\n");
|
||||||
|
test1(keyPair);
|
||||||
|
System.out.println("\n");
|
||||||
|
test2(keyPair);
|
||||||
|
System.out.println("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥加密私钥解密
|
||||||
|
*/
|
||||||
|
private static void test1(RsaKeyPair keyPair) throws Exception {
|
||||||
|
System.out.println("***************** 公钥加密私钥解密开始 *****************");
|
||||||
|
String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC);
|
||||||
|
String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);
|
||||||
|
System.out.println("加密前:" + RsaUtils.SRC);
|
||||||
|
System.out.println("加密后:" + text1);
|
||||||
|
System.out.println("解密后:" + text2);
|
||||||
|
if (RsaUtils.SRC.equals(text2)) {
|
||||||
|
System.out.println("解密字符串和原始字符串一致,解密成功");
|
||||||
|
} else {
|
||||||
|
System.out.println("解密字符串和原始字符串不一致,解密失败");
|
||||||
|
}
|
||||||
|
System.out.println("***************** 公钥加密私钥解密结束 *****************");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥加密公钥解密
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
private static void test2(RsaKeyPair keyPair) throws Exception {
|
||||||
|
System.out.println("***************** 私钥加密公钥解密开始 *****************");
|
||||||
|
String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC);
|
||||||
|
String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);
|
||||||
|
System.out.println("加密前:" + RsaUtils.SRC);
|
||||||
|
System.out.println("加密后:" + text1);
|
||||||
|
System.out.println("解密后:" + text2);
|
||||||
|
if (RsaUtils.SRC.equals(text2)) {
|
||||||
|
System.out.println("解密字符串和原始字符串一致,解密成功");
|
||||||
|
} else {
|
||||||
|
System.out.println("解密字符串和原始字符串不一致,解密失败");
|
||||||
|
}
|
||||||
|
System.out.println("***************** 私钥加密公钥解密结束 *****************");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥解密
|
||||||
|
*
|
||||||
|
* @param publicKeyText 公钥
|
||||||
|
* @param text 待解密的信息
|
||||||
|
* @return /
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {
|
||||||
|
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||||
|
byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text));
|
||||||
|
return new String(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥加密
|
||||||
|
*
|
||||||
|
* @param privateKeyText 私钥
|
||||||
|
* @param text 待加密的信息
|
||||||
|
* @return /
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {
|
||||||
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||||
|
byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes());
|
||||||
|
return Base64.encodeBase64String(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私钥解密
|
||||||
|
*
|
||||||
|
* @param privateKeyText 私钥
|
||||||
|
* @param text 待解密的文本
|
||||||
|
* @return /
|
||||||
|
* @throws Exception /
|
||||||
|
*/
|
||||||
|
public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
|
||||||
|
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text));
|
||||||
|
return new String(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥加密
|
||||||
|
*
|
||||||
|
* @param publicKeyText 公钥
|
||||||
|
* @param text 待加密的文本
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {
|
||||||
|
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
|
||||||
|
Cipher cipher = Cipher.getInstance("RSA");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes());
|
||||||
|
return Base64.encodeBase64String(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] doLongerCipherFinal(int opMode,Cipher cipher, byte[] source) throws Exception {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
if (opMode == Cipher.DECRYPT_MODE) {
|
||||||
|
out.write(cipher.doFinal(source));
|
||||||
|
} else {
|
||||||
|
int offset = 0;
|
||||||
|
int totalSize = source.length;
|
||||||
|
while (totalSize - offset > 0) {
|
||||||
|
int size = Math.min(cipher.getOutputSize(0) - 11, totalSize - offset);
|
||||||
|
out.write(cipher.doFinal(source, offset, size));
|
||||||
|
offset += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建RSA密钥对
|
||||||
|
*
|
||||||
|
* @return /
|
||||||
|
* @throws NoSuchAlgorithmException /
|
||||||
|
*/
|
||||||
|
public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException {
|
||||||
|
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||||
|
keyPairGenerator.initialize(1024);
|
||||||
|
KeyPair keyPair = keyPairGenerator.generateKeyPair();
|
||||||
|
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
|
||||||
|
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
|
||||||
|
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
|
||||||
|
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
|
||||||
|
return new RsaKeyPair(publicKeyString, privateKeyString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA密钥对对象
|
||||||
|
*/
|
||||||
|
public static class RsaKeyPair {
|
||||||
|
|
||||||
|
private final String publicKey;
|
||||||
|
private final String privateKey;
|
||||||
|
|
||||||
|
public RsaKeyPair(String publicKey, String privateKey) {
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPublicKey() {
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrivateKey() {
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONArray;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.example.utils.enums.DataScopeEnum;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import com.example.exception.BadRequestException;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前登录的用户
|
||||||
|
*
|
||||||
|
* 2019-01-17
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class SecurityUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前登录的用户
|
||||||
|
* @return UserDetails
|
||||||
|
*/
|
||||||
|
public static UserDetails getCurrentUser() {
|
||||||
|
UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class);
|
||||||
|
return userDetailsService.loadUserByUsername(getCurrentUsername());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取系统用户名称
|
||||||
|
*
|
||||||
|
* @return 系统用户名称
|
||||||
|
*/
|
||||||
|
public static String getCurrentUsername() {
|
||||||
|
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
if (authentication == null) {
|
||||||
|
throw new BadRequestException(HttpStatus.UNAUTHORIZED, "当前登录状态过期");
|
||||||
|
}
|
||||||
|
if (authentication.getPrincipal() instanceof UserDetails) {
|
||||||
|
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||||
|
return userDetails.getUsername();
|
||||||
|
}
|
||||||
|
throw new BadRequestException(HttpStatus.UNAUTHORIZED, "找不到当前登录的信息");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取系统用户ID
|
||||||
|
* @return 系统用户ID
|
||||||
|
*/
|
||||||
|
public static Long getCurrentUserId() {
|
||||||
|
UserDetails userDetails = getCurrentUser();
|
||||||
|
return new JSONObject(new JSONObject(userDetails).get("user")).get("id", Long.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前用户的数据权限
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static List<Long> getCurrentUserDataScope(){
|
||||||
|
UserDetails userDetails = getCurrentUser();
|
||||||
|
JSONArray array = JSONUtil.parseArray(new JSONObject(userDetails).get("dataScopes"));
|
||||||
|
return JSONUtil.toList(array,Long.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据权限级别
|
||||||
|
* @return 级别
|
||||||
|
*/
|
||||||
|
public static String getDataScopeType() {
|
||||||
|
List<Long> dataScopes = getCurrentUserDataScope();
|
||||||
|
if(dataScopes.size() != 0){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return DataScopeEnum.ALL.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jie
|
||||||
|
* 2019-01-07
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
|
||||||
|
|
||||||
|
private static ApplicationContext applicationContext = null;
|
||||||
|
private static final List<CallBack> CALL_BACKS = new ArrayList<>();
|
||||||
|
private static boolean addCallback = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对 某些初始化方法,在SpringContextHolder 未初始化时 提交回调方法。
|
||||||
|
* 在SpringContextHolder 初始化后,进行回调使用
|
||||||
|
*
|
||||||
|
* @param callBack 回调函数
|
||||||
|
*/
|
||||||
|
public synchronized static void addCallBacks(CallBack callBack) {
|
||||||
|
if (addCallback) {
|
||||||
|
SpringContextHolder.CALL_BACKS.add(callBack);
|
||||||
|
} else {
|
||||||
|
log.warn("CallBack:{} 已无法添加!立即执行", callBack.getCallBackName());
|
||||||
|
callBack.executor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T> T getBean(String name) {
|
||||||
|
assertContextInjected();
|
||||||
|
return (T) applicationContext.getBean(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
|
||||||
|
*/
|
||||||
|
public static <T> T getBean(Class<T> requiredType) {
|
||||||
|
assertContextInjected();
|
||||||
|
return applicationContext.getBean(requiredType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取SpringBoot 配置信息
|
||||||
|
*
|
||||||
|
* @param property 属性key
|
||||||
|
* @param defaultValue 默认值
|
||||||
|
* @param requiredType 返回类型
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static <T> T getProperties(String property, T defaultValue, Class<T> requiredType) {
|
||||||
|
T result = defaultValue;
|
||||||
|
try {
|
||||||
|
result = getBean(Environment.class).getProperty(property, requiredType);
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取SpringBoot 配置信息
|
||||||
|
*
|
||||||
|
* @param property 属性key
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static String getProperties(String property) {
|
||||||
|
return getProperties(property, null, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取SpringBoot 配置信息
|
||||||
|
*
|
||||||
|
* @param property 属性key
|
||||||
|
* @param requiredType 返回类型
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static <T> T getProperties(String property, Class<T> requiredType) {
|
||||||
|
return getProperties(property, null, requiredType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查ApplicationContext不为空.
|
||||||
|
*/
|
||||||
|
private static void assertContextInjected() {
|
||||||
|
if (applicationContext == null) {
|
||||||
|
throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" +
|
||||||
|
".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除SpringContextHolder中的ApplicationContext为Null.
|
||||||
|
*/
|
||||||
|
private static void clearHolder() {
|
||||||
|
log.debug("清除SpringContextHolder中的ApplicationContext:"
|
||||||
|
+ applicationContext);
|
||||||
|
applicationContext = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
SpringContextHolder.clearHolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
if (SpringContextHolder.applicationContext != null) {
|
||||||
|
log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext);
|
||||||
|
}
|
||||||
|
SpringContextHolder.applicationContext = applicationContext;
|
||||||
|
if (addCallback) {
|
||||||
|
for (CallBack callBack : SpringContextHolder.CALL_BACKS) {
|
||||||
|
callBack.executor();
|
||||||
|
}
|
||||||
|
CALL_BACKS.clear();
|
||||||
|
}
|
||||||
|
SpringContextHolder.addCallback = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import com.example.config.ElAdminProperties;
|
||||||
|
import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
|
||||||
|
import net.dreamlu.mica.ip2region.core.IpInfo;
|
||||||
|
import nl.basjes.parse.useragent.UserAgent;
|
||||||
|
import nl.basjes.parse.useragent.UserAgentAnalyzer;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||||
|
|
||||||
|
private static final char SEPARATOR = '_';
|
||||||
|
private static final String UNKNOWN = "unknown";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入bean
|
||||||
|
*/
|
||||||
|
private final static Ip2regionSearcher IP_SEARCHER = SpringContextHolder.getBean(Ip2regionSearcher.class);
|
||||||
|
|
||||||
|
|
||||||
|
private static final UserAgentAnalyzer USER_AGENT_ANALYZER = UserAgentAnalyzer
|
||||||
|
.newBuilder()
|
||||||
|
.hideMatcherLoadStats()
|
||||||
|
.withCache(10000)
|
||||||
|
.withField(UserAgent.AGENT_NAME_VERSION)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 驼峰命名法工具
|
||||||
|
*
|
||||||
|
* @return toCamelCase(" hello_world ") == "helloWorld"
|
||||||
|
* toCapitalizeCamelCase("hello_world") == "HelloWorld"
|
||||||
|
* toUnderScoreCase("helloWorld") = "hello_world"
|
||||||
|
*/
|
||||||
|
public static String toCamelCase(String s) {
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = s.toLowerCase();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(s.length());
|
||||||
|
boolean upperCase = false;
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
char c = s.charAt(i);
|
||||||
|
|
||||||
|
if (c == SEPARATOR) {
|
||||||
|
upperCase = true;
|
||||||
|
} else if (upperCase) {
|
||||||
|
sb.append(Character.toUpperCase(c));
|
||||||
|
upperCase = false;
|
||||||
|
} else {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 驼峰命名法工具
|
||||||
|
*
|
||||||
|
* @return toCamelCase(" hello_world ") == "helloWorld"
|
||||||
|
* toCapitalizeCamelCase("hello_world") == "HelloWorld"
|
||||||
|
* toUnderScoreCase("helloWorld") = "hello_world"
|
||||||
|
*/
|
||||||
|
public static String toCapitalizeCamelCase(String s) {
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
s = toCamelCase(s);
|
||||||
|
return s.substring(0, 1).toUpperCase() + s.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 驼峰命名法工具
|
||||||
|
*
|
||||||
|
* @return toCamelCase(" hello_world ") == "helloWorld"
|
||||||
|
* toCapitalizeCamelCase("hello_world") == "HelloWorld"
|
||||||
|
* toUnderScoreCase("helloWorld") = "hello_world"
|
||||||
|
*/
|
||||||
|
static String toUnderScoreCase(String s) {
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
boolean upperCase = false;
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
char c = s.charAt(i);
|
||||||
|
|
||||||
|
boolean nextUpperCase = true;
|
||||||
|
|
||||||
|
if (i < (s.length() - 1)) {
|
||||||
|
nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i > 0) && Character.isUpperCase(c)) {
|
||||||
|
if (!upperCase || !nextUpperCase) {
|
||||||
|
sb.append(SEPARATOR);
|
||||||
|
}
|
||||||
|
upperCase = true;
|
||||||
|
} else {
|
||||||
|
upperCase = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(Character.toLowerCase(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取ip地址
|
||||||
|
*/
|
||||||
|
public static String getIp(HttpServletRequest request) {
|
||||||
|
String ip = request.getHeader("x-forwarded-for");
|
||||||
|
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getHeader("WL-Proxy-Client-IP");
|
||||||
|
}
|
||||||
|
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
|
||||||
|
ip = request.getRemoteAddr();
|
||||||
|
}
|
||||||
|
String comma = ",";
|
||||||
|
String localhost = "127.0.0.1";
|
||||||
|
if (ip.contains(comma)) {
|
||||||
|
ip = ip.split(",")[0];
|
||||||
|
}
|
||||||
|
if (localhost.equals(ip)) {
|
||||||
|
// 获取本机真正的ip地址
|
||||||
|
try {
|
||||||
|
ip = InetAddress.getLocalHost().getHostAddress();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ip获取详细地址
|
||||||
|
*/
|
||||||
|
public static String getCityInfo(String ip) {
|
||||||
|
if (ElAdminProperties.ipLocal) {
|
||||||
|
return getLocalCityInfo(ip);
|
||||||
|
} else {
|
||||||
|
return getHttpCityInfo(ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ip获取详细地址
|
||||||
|
*/
|
||||||
|
public static String getHttpCityInfo(String ip) {
|
||||||
|
String api = String.format(ElAdminConstant.Url.IP_URL, ip);
|
||||||
|
JSONObject object = JSONUtil.parseObj(HttpUtil.get(api));
|
||||||
|
return object.get("addr", String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据ip获取详细地址
|
||||||
|
*/
|
||||||
|
public static String getLocalCityInfo(String ip) {
|
||||||
|
IpInfo ipInfo = IP_SEARCHER.memorySearch(ip);
|
||||||
|
if(ipInfo != null){
|
||||||
|
return ipInfo.getAddress();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getBrowser(HttpServletRequest request) {
|
||||||
|
UserAgent.ImmutableUserAgent userAgent = USER_AGENT_ANALYZER.parse(request.getHeader("User-Agent"));
|
||||||
|
return userAgent.get(UserAgent.AGENT_NAME_VERSION).getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得当天是周几
|
||||||
|
*/
|
||||||
|
public static String getWeekDay() {
|
||||||
|
String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(new Date());
|
||||||
|
|
||||||
|
int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
|
||||||
|
if (w < 0) {
|
||||||
|
w = 0;
|
||||||
|
}
|
||||||
|
return weekDays[w];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前机器的IP
|
||||||
|
*
|
||||||
|
* @return /
|
||||||
|
*/
|
||||||
|
public static String getLocalIp() {
|
||||||
|
try {
|
||||||
|
InetAddress candidateAddress = null;
|
||||||
|
// 遍历所有的网络接口
|
||||||
|
for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) {
|
||||||
|
NetworkInterface anInterface = interfaces.nextElement();
|
||||||
|
// 在所有的接口下再遍历IP
|
||||||
|
for (Enumeration<InetAddress> inetAddresses = anInterface.getInetAddresses(); inetAddresses.hasMoreElements();) {
|
||||||
|
InetAddress inetAddr = inetAddresses.nextElement();
|
||||||
|
// 排除loopback类型地址
|
||||||
|
if (!inetAddr.isLoopbackAddress()) {
|
||||||
|
if (inetAddr.isSiteLocalAddress()) {
|
||||||
|
// 如果是site-local地址,就是它了
|
||||||
|
return inetAddr.getHostAddress();
|
||||||
|
} else if (candidateAddress == null) {
|
||||||
|
// site-local类型的地址未被发现,先记录候选地址
|
||||||
|
candidateAddress = inetAddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (candidateAddress != null) {
|
||||||
|
return candidateAddress.getHostAddress();
|
||||||
|
}
|
||||||
|
// 如果没有发现 non-loopback地址.只能用最次选的方案
|
||||||
|
InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
|
||||||
|
if (jdkSuppliedAddress == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return jdkSuppliedAddress.getHostAddress();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异常工具 2019-01-06
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ThrowableUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取堆栈信息
|
||||||
|
*/
|
||||||
|
public static String getStackTrace(Throwable throwable){
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
try (PrintWriter pw = new PrintWriter(sw)) {
|
||||||
|
throwable.printStackTrace(pw);
|
||||||
|
return sw.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONArray;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 翻译工具类
|
||||||
|
*/
|
||||||
|
public class TranslatorUtil {
|
||||||
|
|
||||||
|
public static String translate(String word){
|
||||||
|
try {
|
||||||
|
String url = "https://translate.googleapis.com/translate_a/single?" +
|
||||||
|
"client=gtx&" +
|
||||||
|
"sl=en" +
|
||||||
|
"&tl=zh-CN" +
|
||||||
|
"&dt=t&q=" + URLEncoder.encode(word, "UTF-8");
|
||||||
|
|
||||||
|
URL obj = new URL(url);
|
||||||
|
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||||
|
con.setRequestProperty("User-Agent", "Mozilla/5.0");
|
||||||
|
|
||||||
|
BufferedReader in = new BufferedReader(
|
||||||
|
new InputStreamReader(con.getInputStream()));
|
||||||
|
String inputLine;
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
|
||||||
|
while ((inputLine = in.readLine()) != null) {
|
||||||
|
response.append(inputLine);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
return parseResult(response.toString());
|
||||||
|
}catch (Exception e){
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String parseResult(String inputJson){
|
||||||
|
JSONArray jsonArray2 = (JSONArray) new JSONArray(inputJson).get(0);
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (Object o : jsonArray2) {
|
||||||
|
result.append(((JSONArray) o).get(0).toString());
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.example.exception.BadRequestException;
|
||||||
|
import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证工具
|
||||||
|
*
|
||||||
|
* 2018-11-23
|
||||||
|
*/
|
||||||
|
public class ValidationUtil{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证空
|
||||||
|
*/
|
||||||
|
public static void isNull(Object obj, String entity, String parameter , Object value){
|
||||||
|
if(ObjectUtil.isNull(obj)){
|
||||||
|
String msg = entity + " 不存在: "+ parameter +" is "+ value;
|
||||||
|
throw new BadRequestException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证是否为邮箱
|
||||||
|
*/
|
||||||
|
public static boolean isEmail(String email) {
|
||||||
|
return new EmailValidator().isValid(email, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 验证码业务场景
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* 2020-05-02
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum CodeBiEnum {
|
||||||
|
|
||||||
|
/* 旧邮箱修改邮箱 */
|
||||||
|
ONE(1, "旧邮箱修改邮箱"),
|
||||||
|
|
||||||
|
/* 通过邮箱修改密码 */
|
||||||
|
TWO(2, "通过邮箱修改密码");
|
||||||
|
|
||||||
|
private final Integer code;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
public static CodeBiEnum find(Integer code) {
|
||||||
|
for (CodeBiEnum value : CodeBiEnum.values()) {
|
||||||
|
if (value.getCode().equals(code)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 验证码业务场景对应的 Redis 中的 key
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* 2020-05-02
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum CodeEnum {
|
||||||
|
|
||||||
|
/* 通过手机号码重置邮箱 */
|
||||||
|
PHONE_RESET_EMAIL_CODE("phone_reset_email_code_", "通过手机号码重置邮箱"),
|
||||||
|
|
||||||
|
/* 通过旧邮箱重置邮箱 */
|
||||||
|
EMAIL_RESET_EMAIL_CODE("email_reset_email_code_", "通过旧邮箱重置邮箱"),
|
||||||
|
|
||||||
|
/* 通过手机号码重置密码 */
|
||||||
|
PHONE_RESET_PWD_CODE("phone_reset_pwd_code_", "通过手机号码重置密码"),
|
||||||
|
|
||||||
|
/* 通过邮箱重置密码 */
|
||||||
|
EMAIL_RESET_PWD_CODE("email_reset_pwd_code_", "通过邮箱重置密码");
|
||||||
|
|
||||||
|
private final String key;
|
||||||
|
private final String description;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 数据权限枚举
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* 2020-05-07
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum DataScopeEnum {
|
||||||
|
|
||||||
|
/* 全部的数据权限 */
|
||||||
|
ALL("全部", "全部的数据权限"),
|
||||||
|
|
||||||
|
/* 自己部门的数据权限 */
|
||||||
|
THIS_LEVEL("本级", "自己部门的数据权限"),
|
||||||
|
|
||||||
|
/* 自定义的数据权限 */
|
||||||
|
CUSTOMIZE("自定义", "自定义的数据权限");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
public static DataScopeEnum find(String val) {
|
||||||
|
for (DataScopeEnum dataScopeEnum : DataScopeEnum.values()) {
|
||||||
|
if (dataScopeEnum.getValue().equals(val)) {
|
||||||
|
return dataScopeEnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019-2020 Zheng Jie
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.example.utils.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @website https://el-admin.vip
|
||||||
|
* @description
|
||||||
|
* 2020-06-10
|
||||||
|
**/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum RequestMethodEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜寻 @AnonymousGetMapping
|
||||||
|
*/
|
||||||
|
GET("GET"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜寻 @AnonymousPostMapping
|
||||||
|
*/
|
||||||
|
POST("POST"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜寻 @AnonymousPutMapping
|
||||||
|
*/
|
||||||
|
PUT("PUT"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜寻 @AnonymousPatchMapping
|
||||||
|
*/
|
||||||
|
PATCH("PATCH"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜寻 @AnonymousDeleteMapping
|
||||||
|
*/
|
||||||
|
DELETE("DELETE"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 否则就是所有 Request 接口都放行
|
||||||
|
*/
|
||||||
|
ALL("All");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request 类型
|
||||||
|
*/
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
public static RequestMethodEnum find(String type) {
|
||||||
|
for (RequestMethodEnum value : RequestMethodEnum.values()) {
|
||||||
|
if (value.getType().equals(type)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/**
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.example.utils.page;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页工具类
|
||||||
|
*
|
||||||
|
* @author Mark sunlightcs@gmail.com
|
||||||
|
*/
|
||||||
|
public class PageUtils implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
/**
|
||||||
|
* 总记录数
|
||||||
|
*/
|
||||||
|
private int total;
|
||||||
|
/**
|
||||||
|
* 每页记录数
|
||||||
|
*/
|
||||||
|
private int size;
|
||||||
|
/**
|
||||||
|
* 总页数
|
||||||
|
*/
|
||||||
|
private int pages;
|
||||||
|
/**
|
||||||
|
* 当前页数
|
||||||
|
*/
|
||||||
|
private int page;
|
||||||
|
/**
|
||||||
|
* 列表数据
|
||||||
|
*/
|
||||||
|
private List<?> list;
|
||||||
|
|
||||||
|
private double totalTime;
|
||||||
|
|
||||||
|
private Object independentIpNum;
|
||||||
|
|
||||||
|
private int resultTotal;
|
||||||
|
|
||||||
|
public int getResultTotal() {
|
||||||
|
return resultTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResultTotal(int resultTotal) {
|
||||||
|
this.resultTotal = resultTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页
|
||||||
|
* @param list 列表数据
|
||||||
|
* @param total 总记录数
|
||||||
|
* @param size 每页记录数
|
||||||
|
* @param page 当前页数
|
||||||
|
*/
|
||||||
|
public PageUtils(List<?> list, int total, int size, int page ,double totalTime,int independentIpNum ,int resultTotal) {
|
||||||
|
this.list = list;
|
||||||
|
this.total = total;
|
||||||
|
this.size = size;
|
||||||
|
this.page = page;
|
||||||
|
this.totalTime = totalTime;
|
||||||
|
this.independentIpNum = independentIpNum;
|
||||||
|
this.resultTotal = resultTotal;
|
||||||
|
this.pages = (int)Math.ceil((double)total/size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页
|
||||||
|
*/
|
||||||
|
public PageUtils(IPage<?> page) {
|
||||||
|
this.list = page.getRecords();
|
||||||
|
this.total = (int)page.getTotal();
|
||||||
|
this.size = (int)page.getSize();
|
||||||
|
this.page = (int)page.getCurrent();
|
||||||
|
this.pages = (int)page.getPages();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Object getIndependentIpNum() {
|
||||||
|
return independentIpNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndependentIpNum(Object independentIpNum) {
|
||||||
|
this.independentIpNum = independentIpNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotal() {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal(int total) {
|
||||||
|
this.total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSize(int size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPages() {
|
||||||
|
return pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPages(int pages) {
|
||||||
|
this.pages = pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPage() {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getTotalTime() {
|
||||||
|
return totalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotalTime(double totalTime) {
|
||||||
|
this.totalTime = totalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPage(int page) {
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<?> getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setList(List<?> list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package com.example.utils.page;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询参数
|
||||||
|
*/
|
||||||
|
public class Query {
|
||||||
|
|
||||||
|
private Class clz;
|
||||||
|
|
||||||
|
public Class<? extends Object> getClz() {
|
||||||
|
return clz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClz(Class clz) {
|
||||||
|
this.clz = clz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Query(Class clz) {
|
||||||
|
this.clz = clz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPage getPage(Map<String, Object> params) {
|
||||||
|
return this.getPage(params, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IPage getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
|
||||||
|
//分页参数
|
||||||
|
long curPage = 1;
|
||||||
|
long limit = 10;
|
||||||
|
|
||||||
|
if(params.get("page") != null && !"".equals(params.get("page"))){
|
||||||
|
curPage = Long.parseLong((String)params.get("page"));
|
||||||
|
}
|
||||||
|
if(params.get("size") != null && !"".equals(params.get("size"))){
|
||||||
|
limit = Long.parseLong((String)params.get("size"));
|
||||||
|
if(limit == -1){
|
||||||
|
limit = Long.MAX_VALUE;
|
||||||
|
curPage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//分页对象
|
||||||
|
Page page = new Page(curPage, limit);
|
||||||
|
|
||||||
|
//分页参数
|
||||||
|
params.put("page", page);
|
||||||
|
|
||||||
|
|
||||||
|
// 默认排序
|
||||||
|
if(isAsc) {
|
||||||
|
page.setAsc(defaultOrderField);
|
||||||
|
}else {
|
||||||
|
page.setDesc(defaultOrderField);
|
||||||
|
}
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.example.utils.page;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class R extends HashMap<String, Object> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public R() {
|
||||||
|
put("status", 200);
|
||||||
|
put("message", "success");
|
||||||
|
put("timestamp", new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static R ok(String message) {
|
||||||
|
R r = new R();
|
||||||
|
r.put("message", message);
|
||||||
|
r.put("timestamp", new Date());
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static R ok() {
|
||||||
|
return new R();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static R ok(Object data) {
|
||||||
|
R r = new R();
|
||||||
|
r.put("data", data);
|
||||||
|
r.put("timestamp", new Date());
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user