decodeURIComponent出现Uncaught URIError URI malformed错误

最近使用showdoc编辑表格后突然数据丢失,研究源码发现是在解析时出现错误导致渲染失败

url加密传参有时候会出现Uncaught URIError: URI malformed的错误,这是因为你的url中包含了“%”字符,浏览器在对“%”执行decodeURIComponent时报错,正确的解决是将%全部替换为%25再进行传输:
urlStr.replace(/%/g, ‘%25’);

lombok plugin插件

Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。 —-百度百科

使用步骤

  1. 添加lombok plugin插件
    lombok.jpeg

2.添加lombok依赖,依赖的版本要跟加入插件的版本一致

1
2
3
4
5
6
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
  1. 启用配置
    lombok2.jpeg
    lombok3.jpeg

4.代码中使用

1
2
3
4
5
6
//使用该注解就可以省略 get set toString啦
@Data
public class{
private String name;
private ing age;
}

日志

1 使用
包名:

1
import lombok.extern.log4j.Log4j2;

注解:

1
@Log4j2

使用

1
log.info("log日志打印")

2. 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
application.yml的配置:
#debug: true
logging:
level:
#指定包,指定类,或者直接root
#root: debug
com.cobra.logdemo.controller: debug
#日志输出配置二选一,只有两个都配置,只有一个生效,
#区别是path默认生成的是spring.log文件,而path生成的是直接命名的文件,
可以是相对路径也可以是绝对路径
file: var/my.log
#path: var/my.log
# pattern:
#控制台日志输出格式配置,仅对控制台有效
#console: "%d -%msg%n"

采用配置文件形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
log配置之二,新建logback-spring.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!--输出日志格式-->
<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>
%d - %msg%n
</pattern>
</layout>
</appender>
<!--只保存info日志-->
<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>
%d - %msg%n
</pattern>
</encoder>
<!--滚动输出策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>d:/logtest/info/info.%d.log</fileNamePattern>
</rollingPolicy>
</appender>

<!--只保存warn日志-->
<appender name="fileWarnLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>
%d - %msg%n
</pattern>
</encoder>
<!--滚动输出策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>d:/logtest/warn/warn.%d.log</fileNamePattern>
</rollingPolicy>
</appender>

<!--只保存error日志-->
<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<encoder>
<pattern>
%d - %msg%n
</pattern>
</encoder>
<!--滚动输出策略-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--路径-->
<fileNamePattern>d:/logtest/error/error.%d.log</fileNamePattern>
</rollingPolicy>
</appender>

<root level="info">
<appender-ref ref="consoleLog"/>
<appender-ref ref="fileInfoLog"/>
<appender-ref ref="fileWarnLog"/>
<appender-ref ref="fileErrorLog"/>
</root>

</configuration>

链接

lombok官网

jrebel启动报错:找不到口令文件

错误信息

1
错误: 找不到口令文件: C:\Users\hstech\AppData\Local\JetBrains\IntelliJIdea2020.2\tomcat\δ????_TEMP\jmxremote.password

解决方法

方法一

访问这个路径发现乱码部分前面有个未命名,这个是之前用的是2019版本,现在升级2020后使用了汉化包导致

1
2
3
4
## 之前
Unnamed_temp
## 汉化后
未命名_temp

解决方案

我把这个勾取消了,关于上面的前缀还没找到在哪设置

image-20200917134329853

在这里添加这条语句好像可以运行了

1
JAVA_OPTS   -Dfile.encoding\\=UTF-8

方法二

因为我的项目名是中文,导致路径也是中文。idea中正常启动是可以的,只是控制台中文会乱码,当用jrebel启动的时候,直接报错。

参考其他人博客在jrebel的环境变量里加 JAVA_OPTS,确实不报错,但debug加了断点不进!

解决方法
1、img

2、增加

1
2
-Dfile.encoding=UTF-8
-Dsun.jnu.encoding=UTF-8

然后重启idea

img

3、tomcat中加 -Dfile.encoding=UTF-8

img

最后启动就ok了

链接

jrebel启动报错:找不到口令文件

NTP服务器 - 时间同步

最近在研究集群的时候发现基本都有一项设置,那就是配置ntp服务器

为什么要配置ntp服务器呢?

我们先看看什么是NTP

NTP是用于同步网络中计算机时间的协议,全称为网络时间协议(Network Time Protocol)。

那有什么用呢,我们看看腾讯云对他的介绍

网络时间协议(Network Time Protocol,NTP),用于同步网络中各个计算机的时间的协议。其用途是将计算机的时钟同步到世界协调时 UTC。在 NTP 设计时考虑到了各种网络延迟,当您通过公共网络同步时,误差可以降低到10毫秒以内;当您通过本地网络同步时,误差可以降低到1毫秒。

总体就是说,为了保证时区和时间一致性以免影响到业务,这里可以看看阿里云怎么说。

时区和时间一致性对于云服务器ECS非常重要,有时会直接影响到任务执行的结果,例如,您在更新数据库或者分析日志时,时间顺序对结果有很大影响。为避免在实例上运行业务时出现逻辑混乱和网络请求错误等问题,您需要统一相关实例的时区设置。另外,您还可以通过NTP服务同步网络中所有服务器的本地时间。

下面介绍下国内的一些网络授时服务器

国家科学院国家授时中心

1
ntp.ntsc.ac.cn

阿里云

1
ntp.cloud.aliyuncs.com

腾讯云

1
2
3
4
5
time1.cloud.tencent.com
time2.cloud.tencent.com
time3.cloud.tencent.com
time4.cloud.tencent.com
time5.cloud.tencent.com

华为云

1
2
3
4
5
6
华北区 ntp.myhuaweicloud.com
华东区 ntp.myhuaweicloud.com
华南区 ntp.myhuaweicloud.com
东北区 ntp.myhuaweicloud.com
亚太-香港 ntp.myhuaweicloud.com
亚太-曼谷 ntp.myhuaweicloud.com

安装

Linux 实例设置 NTP 服务

Windows 实例设置 NTP 服务

参考

中科院 - 关于“网络授时域名”全面试运行测试的公告

阿里云NTP服务器

腾讯云NTP 服务概述

华为云有没有提供NTP服务器,怎样安装?

Ant Design of Vue 表格内使用按钮代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

<template>
<div>
<a-table :columns="columns" :dataSource="data" bordered rowKey="guid">
<span slot="action" slot-scope="text, record">
<a-button type="primary" @click="show(record.id)">查看</a-button>
<a-divider type="vertical" />
<a-button type="success" @click="edit(record.id)">修改</a-button>
<a-divider type="vertical" />
<a-button type="danger" @click="del(record.id)">删除</a-button>
</span>
</a-table>
</div>
</template>

<script>
const columns = [
{
title: '服务名',
dataIndex: 'name',
scopedSlots: { customRender: 'name' }
},
{
title: '激活状态',
dataIndex: 'isEnabled',
customRender: function(text, record, index) {
return record.isEnabled ? '激活' : '禁用';
}
},
{
title: '描述',
dataIndex: 'description'
},
{
title: '操作',
dataIndex: 'operation',
fixed: 'right',
width: 260,
scopedSlots: { customRender: 'action' }
}
];
export default {
data() {
return {
pluginId: '',
pluginName: '',
// 表格显示
data: [],
// 表格标题
columns,
targetId: ''
};
},
watch: {
$route(to, from) {
//监听路由是否变化
if (to.query.id != from.query.id) {
this.id = to.query.id;
this.pluginName = this.$route.query.name;
this.init(); //重新加载数据
}
}
},
mounted() {
this.pluginId = this.$route.query.id;
this.pluginName = this.$route.query.name;
this.init();
},
methods: {
init() {
this.$http.get('service/plugins/services').then(res => {
var arr = [];
let name = this.pluginName;
for (let i = 0; i < res.services.length; i++) {
if (res.services[i].type == name) {
arr.push(res.services[i]);
}
}
this.data = arr;
});
},
// 根据id获取服务信息
getInfoById(id) {
for (let i = 0; i < this.data.length; i++) {
if (this.data[i].id == id) {
return this.data[i];
}
}
},
show(id) {
console.log(id);
},
edit(id) {
console.log(id);
},
del(id) {
var info = this.getInfoById(id);
this.ModalText = '您确定要删除 ' + info.name + ' 吗?';
this.visible = true;
this.targetId = id;
}
}
};
</script>

<style scoped="scoped">
</style>

一个java工具包 - Hutool

简介

Hutool是Hu + tool的自造词,前者致敬我的“前任公司”,后者为工具之意,谐音“糊涂”,寓意追求“万事都作糊涂观,无所谓失,无所谓得”的境界。
Hutool是一个Java工具包,也只是一个工具包,它帮助我们简化每一行代码,减少每一个方法,让Java语言也可以“甜甜的”。Hutool最初是我项目中“util”包的一个整理,后来慢慢积累并加入更多非业务相关功能,并广泛学习其它开源项目精髓,经过自己整理修改,最终形成丰富的开源工具集。

Hutool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类

依赖

依赖可以导入所有或者按需引用

全部

1
2
3
4
5
6
<!--  全部  -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.0.7</version>
</dependency>

按需引用

Maven中搜索hutool

相关功能

模块 介绍
hutool-aop JDK动态代理封装,提供非IOC下的切面支持
hutool-bloomFilter 布隆过滤,提供一些Hash算法的布隆过滤
hutool-cache 简单缓存实现
hutool-core 核心,包括Bean操作、日期、各种Util等
hutool-cron 定时任务模块,提供类Crontab表达式的定时任务
hutool-crypto 加密解密模块,提供对称、非对称和摘要算法封装
hutool-db JDBC封装后的数据操作,基于ActiveRecord思想
hutool-dfa 基于DFA模型的多关键字查找
hutool-extra 扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等)
hutool-http 基于HttpUrlConnection的Http客户端封装
hutool-log 自动识别日志实现的日志门面
hutool-script 脚本执行封装,例如Javascript
hutool-setting 功能更强大的Setting配置文件和Properties封装
hutool-system 系统参数调用封装(JVM信息等)
hutool-json JSON实现
hutool-captcha 图片验证码实现
hutool-poi 针对POI中Excel的封装
hutool-socket 基于Java的NIO和AIO的Socket封装

注意
阿里Maven的public库没有对应依赖,需要使用central库。

1
2
3
4
5
6
<mirror>
<id>aliyun-central</id>
<mirrorOf>*</mirrorOf>
<name>aliyun central</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>

参考

Hutool官网

参考文档

Api文档

分享一个js工具包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* 获取cookie
* @param {string} key cookie键
*/
function getCookie(key) {
var e = key;
for (var t = e + "=", n = document.cookie.split(";"), o = 0; o < n.length; o++) {
for (var i = n[o]; " " == i.charAt(0);)
i = i.substring(1, i.length);
if (0 == i.indexOf(t))
return unescape(i.substring(t.length, i.length))
}
return "";
}

/**
* 删除指定cookie
* @param {string} key cookie键
*/
function clearCookie(key) {
var e = key;
setCookie(e, "", -1);
}

/**
* 设置cookie
* @param {string} key cookie键
* @param {string} value cookie值
* @param {number} time cookie过期时间
*/
function setCookie(key, value, time) {
var e = key, t = value, n = time;
n = n || 0;
var o = "";
if (0 != n) {
var i = new Date;
i.setTime(i.getTime() + 1e3 * n), o = "; expires=" + i.toGMTString()
}
document.cookie = e + "=" + escape(t) + o + "; path=/";
}

/**
* 清除所有cookie
*/
function clearAllCookie() {
var keys = document.cookie.match(/[^ =;]+(?=\=)/g);
if (keys) {
for (var i = keys.length; i--;)
document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString()
}
}

随机数

1
2
3
4
5
6
7
8
9
10
11
/**
* 生成最小值和最大值之间的随机数(包含最小值最大值)
* @param {number} min 最小值
* @param {number} max 最大值
* @param {boolean} isDecimal 是否是小数,默认生成整数
*/
function randomNum(min, max, isDecimal) {
var num = Math.random() * (max - min + 1) + min;
if (isDecimal === true) { return num; }
return parseInt(num, 10);
}

时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
* 时间戳转换为时间字符串
* @param {object} timestamp 时间戳
*/
function formatDate(timestamp) {
function add0(m) {
m = parseInt(m);
return ((m < 10) ? ('0' + m) : m);
}
function format(shijianchuo) {

if ((typeof shijianchuo) !== "number") {
shijianchuo = parseInt(shijianchuo);
}

if (Date.prototype.getTimezoneOffset.call(new Date) === 0) {
//如果是UTC时间,代表用户可能没设置时区,则转换为北京时间。如果不需要请去除该if
shijianchuo += (8 * 60 * 60 * 1000);
}

var time = new Date(shijianchuo);
var y = time.getFullYear();
var m = time.getMonth() + 1;
var d = time.getDate();
var h = time.getHours();
var mm = time.getMinutes();
var s = time.getSeconds();
return y + '-' + add0(m) + '-' + add0(d) + ' ' + add0(h) + ':' + add0(mm) + ':' + add0(s);
}
return format(timestamp);
}

MD5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/**
* MD5加密
* @param {string} string 要加密的字符串
*/
function createMD5(string) {

function RotateLeft(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
}

function AddUnsigned(lX, lY) {
var lX4, lY4, lX8, lY8, lResult;
lX8 = (lX & 0x80000000);
lY8 = (lY & 0x80000000);
lX4 = (lX & 0x40000000);
lY4 = (lY & 0x40000000);
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
if (lX4 & lY4) {
return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
}
if (lX4 | lY4) {
if (lResult & 0x40000000) {
return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
} else {
return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
}
} else {
return (lResult ^ lX8 ^ lY8);
}
}

function F(x, y, z) { return (x & y) | ((~x) & z); }
function G(x, y, z) { return (x & z) | (y & (~z)); }
function H(x, y, z) { return (x ^ y ^ z); }
function I(x, y, z) { return (y ^ (x | (~z))); }

function FF(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};

function GG(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};

function HH(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};

function II(a, b, c, d, x, s, ac) {
a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
return AddUnsigned(RotateLeft(a, s), b);
};

function ConvertToWordArray(string) {
var lWordCount;
var lMessageLength = string.length;
var lNumberOfWords_temp1 = lMessageLength + 8;
var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
var lWordArray = Array(lNumberOfWords - 1);
var lBytePosition = 0;
var lByteCount = 0;
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
lByteCount++;
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4;
lBytePosition = (lByteCount % 4) * 8;
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
return lWordArray;
};

function WordToHex(lValue) {
var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount;
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255;
WordToHexValue_temp = "0" + lByte.toString(16);
WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
}
return WordToHexValue;
};

function Utf8Encode(string) {
string = string.replace(/\r\n/g, "\n");
var utftext = "";

for (var n = 0; n < string.length; n++) {

var c = string.charCodeAt(n);

if (c < 128) {
utftext += String.fromCharCode(c);
}
else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}

}

return utftext;
};

var x = Array();
var k, AA, BB, CC, DD, a, b, c, d;
var S11 = 7, S12 = 12, S13 = 17, S14 = 22;
var S21 = 5, S22 = 9, S23 = 14, S24 = 20;
var S31 = 4, S32 = 11, S33 = 16, S34 = 23;
var S41 = 6, S42 = 10, S43 = 15, S44 = 21;

string = Utf8Encode(string);

x = ConvertToWordArray(string);

a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;

for (k = 0; k < x.length; k += 16) {
AA = a; BB = b; CC = c; DD = d;
a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
a = AddUnsigned(a, AA);
b = AddUnsigned(b, BB);
c = AddUnsigned(c, CC);
d = AddUnsigned(d, DD);
}

var temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);

return temp.toLowerCase();
}

Guid

1
2
3
4
5
6
7
8
9
/**
* 生成Guid
*/
function createGuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}

base64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* base64加密
* @param {any} string
*/
function base64Encode(string) {
var Base64 = { _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", encode: function (e) { var t = ""; var n, r, i, s, o, u, a; var f = 0; e = Base64._utf8_encode(e); while (f < e.length) { n = e.charCodeAt(f++); r = e.charCodeAt(f++); i = e.charCodeAt(f++); s = n >> 2; o = (n & 3) << 4 | r >> 4; u = (r & 15) << 2 | i >> 6; a = i & 63; if (isNaN(r)) { u = a = 64 } else if (isNaN(i)) { a = 64 } t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a) } return t }, _utf8_encode: function (e) { e = e.replace(/rn/g, "n"); var t = ""; for (var n = 0; n < e.length; n++) { var r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r) } else if (r > 127 && r < 2048) { t += String.fromCharCode(r >> 6 | 192); t += String.fromCharCode(r & 63 | 128) } else { t += String.fromCharCode(r >> 12 | 224); t += String.fromCharCode(r >> 6 & 63 | 128); t += String.fromCharCode(r & 63 | 128) } } return t } }
return Base64.encode(string);
}

/**
* base64解密
* @param {any} string
*/
function base64Decode(string) {
var Base64 = { _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", decode: function (e) { var t = ""; var n, r, i; var s, o, u, a; var f = 0; e = e.replace(/[^A-Za-z0-9+/=]/g, ""); while (f < e.length) { s = this._keyStr.indexOf(e.charAt(f++)); o = this._keyStr.indexOf(e.charAt(f++)); u = this._keyStr.indexOf(e.charAt(f++)); a = this._keyStr.indexOf(e.charAt(f++)); n = s << 2 | o >> 4; r = (o & 15) << 4 | u >> 2; i = (u & 3) << 6 | a; t = t + String.fromCharCode(n); if (u != 64) { t = t + String.fromCharCode(r) } if (a != 64) { t = t + String.fromCharCode(i) } } t = Base64._utf8_decode(t); return t }, _utf8_decode: function (e) { var t = ""; var n = 0; var r = c1 = c2 = 0; while (n < e.length) { r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r); n++ } else if (r > 191 && r < 224) { c2 = e.charCodeAt(n + 1); t += String.fromCharCode((r & 31) << 6 | c2 & 63); n += 2 } else { c2 = e.charCodeAt(n + 1); c3 = e.charCodeAt(n + 2); t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63); n += 3 } } return t } }
return Base64.decode(string);
}

文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 下载文件
* @param {any} url 要下载的地址
* @param {any} saveName 文件保存的名字 可选参数
*/
function openDownloadDialog(url, saveName) {
//url = ((window.location.href.toLowerCase().indexOf('probation') == -1) ? '' : '/probation') + url;
if (typeof url == 'object' && url instanceof Blob) {
url = URL.createObjectURL(url); // 创建blob地址
}
var aLink = document.createElement('a');
aLink.target = "_blank";
aLink.href = url;
aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
aLink.dispatchEvent(event);
}

页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* 网页全屏
*/
function fullscreen() {
var docElm = document.documentElement;
if (docElm.requestFullscreen) {
docElm.requestFullscreen();
} else if (docElm.mozRequestFullScreen) {
docElm.mozRequestFullScreen();
} else if (docElm.webkitRequestFullScreen) {
docElm.webkitRequestFullScreen();
} else if (docElm.msRequestFullscreen) {
docElm.msRequestFullscreen();
}
}

/**
* 退出全屏
*/
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}

/**
* 让页面始终显示在最最上层,而不是在iframe中
*/
function pageKeepTop() {
if (window && top) {
//如果window和top对象存在,但是他们不相等
if (window !== top) {
//把当前页面显示在最外面
top.location.href = window.location.href;
}
}
}

/**
* 获取是否在web环境中。是为true,否为false。
*/
function getIsWeb() {
if (window) {
return ((window.location.href).indexOf('file:') === -1);
} else {
return false;
}
}

分页插件pagehelper使用

分页插件pagehelperjar包

1
2
3
4
5
6
<!--分页插件 begin-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>

代码

1
2
3
4
//设置分页属性
PageHelper.startPage(recordQuery.getPageNum(), recordQuery.getPageSize());
List<RecordVo> list = recordService.findRecord(recordQuery);
PageInfo<RecordVo> pageInfo = new PageInfo<>(list);

微服务架构和单体架构

一、微服务架构和单体架构

微服务架构

什么是微服务

微服务架构的系统是一个分布式的系统,按业务进行划分为独立的服务单元,解决单体系统的不足,同时也满足越来越复杂的业务需求。

微服务架构就是将单一程序开发成一个微服务,每个微服务运行在自己的进程中,并使用轻量级的机制通信,通常是HTTP RESTFUL API。这些服务围绕业务能力来划分,并通过自动化部署机制来独立部署。这些服务可以使用不同的编程语言,不同数据库,以保证最低限度的集中式管理。

总结起来微服务就是将一个单体架构的应用按业务划分为一个个的独立运行的程序即服务,它们之间通过HTTP协议进行通信(也可以采用消息队列来通信,如RoocketMQ,Kafaka等),可以采用不同的编程语言,使用不同的存储技术,自动化部署(如Jenkins)减少人为控制,降低出错概率。服务数量越多,管理起来越复杂,因此采用集中化管理。例如Eureka,Zookeeper等都是比较常见的服务集中化管理框架。

clipboard.png

优势

  1. 轻巧

    将复杂的业务拆分成多个小的业务,每个业务拆分成一个服务,将复杂的问题简单化。利于分工,降低新人的学习成本。

  2. 细分业务

    微服务系统是分布式系统,业务与业务之间完全解耦,随着业务的增加可以根据业务再拆分,具有极强的横向扩展能力。面对搞并发的场景可以将服务集群化部署,加强系统负载能力。

  3. 功能独立

    服务间采用HTTP协议通信,服务与服务之间完全独立。每个服务可以根据业务场景选取合适的编程语言和数据库。

  4. 不影响其他功能

    微服务每个服务都是独立部署的,每个服务的修改和部署对其他服务没有影响。

  5. 不受技术限制

    在微服务中,我们可以结合项目业务及团队的特点,合理地选择技术栈

微服务设计要点

  1. AKF拆分原则
  2. 前后端分离
  3. 无状态服务
  4. Restful通信风格

传统单体架构

什么是单体架构

在软件设计的时候经常提到和使用经典的3层模型,即表现层,业务逻辑层,数据访问层。虽然在软件设计中划分了3层模型,但是对业务场景没有划分,一个典型的单体架构就是将所有的业务场景的表现层,业务逻辑层,数据访问层放在一个工程中最终经过编译,打包,部署在一台服务器上。此时服务架构如图:

clipboard 1.png

一个归档包(例如war格式)包含了应用所有功能的应用程序,我们通常称之为单体应用。架构单体应用的方法论,我们称之为单体应用架构。

单体架构的优点

  1. 结构简单,容易理解

    对于开发人员而言,这是非常重要的一点。经典的分层架构已经相对比较成熟,更容易被更多的开发人员所理解和接受,学习成本也相对比较低,对团队本身的要求也不是特别高。这不仅使得系统的设计和开发都相对比较容易,而且出错的几率会相对低一些。用现在时髦的词语说,就是“坑相对较少”,开发实现都可以“踩在踩坑人的背上前进”

  2. 实现数据一致性相对比较容易

    通过本地事务或者分布式事务可以方便有效地保证数据一致性

  3. 部署简单方便

    可以方便快速地打包成WAR包,部署到Jetty或者Tomcat容器中。一次部署完成即可运行整个应用程序

总结起来,这种架构大致可以使用下图表示,各层组件可以通过相互引用进行相互调用,也可以通过IoC/DI实现解耦,进而实现应用程序“一体化”,这也是“单体架构”一词的由来:

单体架构存在的问题

  1. 系统仍然为单体应用

    大量的业务必然会有大量的代码,代码的可读性和可维护性依然很差。

  2. 存在瓶颈

    面对海量的用户,数据库将会成为瓶颈,解决方案将使用分布式数据库,也就是将数据库进行分库分表。

  3. 持续交付能力差

    业务越复杂,代码越多,修改代码和添加代码所需的时间越长。新人熟悉代码的时间长、成本高。

参考资料

漫谈单体架构与微服务架构(上):单体架构

微服务设计、拆分原则

时间差计算代码演示

java - 时间差计算代码演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 获取两个日期的时间差
* @param endDate 结束时间
* @param currentDate 当前时间
* @return
*/
public static long getTimeDifference(String endDate ,String currentDate){

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date end = df.parse(endDate);
Date current = df.parse(currentDate);
long diff = end.getTime() - current.getTime();
long days = diff / (1000 * 60 * 60 * 24);
return days;
} catch (Exception e) {
System.out.println("算时间差错误"+e);
}
return 0;
}