SpringBoot与VUE前后端分离最佳实践

前后端分离的开发模式大家都很清楚了,甚是麻烦:

  • 前端启动webpack-dev-server
  • 后端启动接口服务
  • 开启代理服务器,前端通过代理服务器请求后端接口(解决跨域问题)

但是这些东西对于后端来说,太麻烦了,直接把前端打包好的dist文件丢到后端静态服务器里面就好了。
至于前端的webpack-dev-server热部署特性,改完前端代码立即在浏览器生效,对于后端来说有什么用呢?

  • 配置前端项目打包Task
  • 配置后端项目启动Task(执行前端编译、拷贝编译后的静态文件、启动后端)
  • 一键启动

Kotlin杀手级特性-空安全

Kotlin相对于Java来说,有一个显著的特点,就是它致力于消除空引用所带来的危险,在Java中,为了避免NullPointerException的出现,我们需要不厌其烦的使用if (value != null) {}来处理这种问题(虽然在JDK8之后有了更好的方式)

在Kotlin中很好解决了这个问题,下面来看看它是如何做到的。

Golang-HTTP请求限流

在高并发应用场景中,为保证业务高峰期系统的稳定性或抵御CC攻击,最有效的方案为(缓存、降级、限流)
本文以限流为例,在Golang中示例如何通过中间件实现httpserver限流。

依赖

首先安装一个基本的限流算法包,然后为了方便,直接使用gin作为httprouter(后面会用到它的中间件)

1
2
3
$ go get -u golang.org/x/time/rate

$ go get -u github.com/gin-gonic/gin

JDK#UUID 简单优化

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
public class UuidUtil {
private final static char[] DIGITS_ARRAY = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
// 支持的最小进制数
private static final int MIN_RADIX = 2;
// 支持的最大进制数
private static final int MAX_RADIX = DIGITS_ARRAY.length;

public static String randomUuid() {
// 产生UUID
UUID uuid = UUID.randomUUID();

// 分区转换(19位) + 当前时间戳(13位)
return new StringBuffer()//
.append(digits(uuid.getMostSignificantBits() >> 32, 8))//
.append(digits(uuid.getMostSignificantBits() >> 16, 4))//
.append(digits(uuid.getMostSignificantBits(), 4))//
.append(digits(uuid.getLeastSignificantBits() >> 48, 4))//
.append(digits(uuid.getLeastSignificantBits(), 12))//
.append(System.currentTimeMillis()).toString();
}

/**
* Test: 模拟并发场景下的UUID效率,唯一性。
*
* @param args
*/
public static void main(String[] args) {
final long begin = System.currentTimeMillis();
final int threadCount = 100;
final int uuidCountPerThread = 10000;

final ExecutorService executor = Executors.newCachedThreadPool();
final Set<String> uuidSet = new ConcurrentSkipListSet<String>();

for (int i = 0; i < threadCount; ++i) {
executor.submit(new Runnable() {
@Override
public void run() {
for (int j = 0; j < uuidCountPerThread; ++j) {
uuidSet.add(randomUuid());
}
}
});
}
executor.shutdown();
while (true) {
if (executor.isTerminated()) {
int forecastSum = (threadCount * uuidCountPerThread);
int actualSum = uuidSet.size();
System.out.println(String.format("预计生成%d个,实际生成%d个,重复个数:%d, 耗时:%d",//
forecastSum, actualSum, forecastSum - actualSum, (System.currentTimeMillis() - begin) / 1000L));
break;
}
}
}

private static String digits(long val, int digits) {
long hi = 1L << (digits * 4);
return toString(hi | (val & (hi - 1)), DIGITS_ARRAY.length).substring(1);
}

private static String toString(long i, int radix) {
if (radix < MIN_RADIX || radix > MAX_RADIX) {
radix = 10;
}
if (radix == 10) {
return Long.toString(i);
}

final int size = 65;
int charPos = 64;
char[] buf = new char[size];
boolean negative = (i < 0);
if (!negative) {
i = -i;
}
while (i <= -radix) {
buf[charPos--] = DIGITS_ARRAY[(int) (-(i % radix))];
i = i / radix;
}
buf[charPos] = DIGITS_ARRAY[(int) (-i)];
if (negative) {
buf[--charPos] = '-';
}

return new String(buf, charPos, (size - charPos));
}
}

image.png

macOS效率神器-Hammerspoon

Hammerspoon 是 macOS 上一个强大的自动化工具,是一款开源软件,但安装之后 Hammerspoon 默认什么功能也没有,所有的功能都在 Lua 脚本中,需要用户自己编写。Hammerspoon 可以让用户通过 Lua 脚本直接调用 macOS 提供的 API,能做的事情既有自定义快捷键这种简单操作,也能实现连上家里 Wi-Fi 后自动打开某视频网站、到办公室后自动静音等复杂功能。官方提供的 API 已经非常丰富,包括管理应用程序、管理系统音频设备、画图、网格化窗口、控制系统电源状态、操纵显示屏、控制鼠标、执行HTTP请求、HTTP服务器、执行shell/applescript/javascript代码等等。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×