咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

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
import android.util.Log;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

public class UDPSearch{

private final String TAG = this.getClass().getSimpleName();
private final Object mLock;
private DatagramSocket socket = null;
private UDPCallback callback;
private Thread threadReceive,threadSend;

public UDPSearch(UDPCallback callback) {
this.callback = callback;
this.mLock = new Object();
}


public void start(){

threadReceive = new Thread(new UDPReceive());
threadSend = new Thread(new UDPSend());

threadReceive.start();
threadSend.start();
}
public void stop(){

if(threadSend != null){
threadSend.interrupt();
threadSend = null;
}
if(threadReceive != null){
threadReceive.interrupt();
threadReceive = null;
}
}


class UDPSend implements Runnable{

private final String TAG = this.getClass().getSimpleName();
private final int BROADCAST_PORT = 6666;
private final String BROADCAST_HOST = "255.255.255.255";
private final byte[] broadcastData = new byte[]{ 0x01 ,0x02, 0x03 ,0x04 };

@Override
public void run() {

Log.i(TAG,"run start");

try {

TimeUnit.SECONDS.sleep(2);
InetAddress inetAddress = InetAddress.getByName(BROADCAST_HOST);
socket = new DatagramSocket();
socket.setBroadcast(true);

Log.d(TAG, "create udp socket target port:" + socket.getPort() + " and local port : " + socket.getLocalPort());
//socket已创建,通知线程接收数据
synchronized (mLock){
mLock.notify();
Log.i(TAG, "notify create socket ok");
}
while (!Thread.currentThread().isInterrupted()) {
Log.d(TAG,"send udp broadcast target port: " + BROADCAST_PORT);
try{
socket.send(new DatagramPacket(broadcastData, broadcastData.length,
inetAddress, BROADCAST_PORT));
}catch (IOException io){
// 这种错误不应该结束发送广播,系统网络关闭可以复现。
// java.io.IOException: sendto failed: ENETUNREACH (Network is unreachable)
// Caused by: android.system.ErrnoException: sendto failed: ENETUNREACH (Network is unreachable)
io.printStackTrace();
}
TimeUnit.SECONDS.sleep(2);
}
} catch (InterruptedException | UnknownHostException | SocketException e) {
e.printStackTrace();
}finally {
Log.i(TAG,"socket close");
if(socket != null){
socket.close();
socket = null;
}
}
Log.i(TAG,"stop");
}
}


class UDPReceive implements Runnable{

private final String TAG = this.getClass().getSimpleName();

@Override
public void run() {

Log.i(TAG,"run start");
if(socket == null){
try {
Log.w(TAG,"socket not init, wait mLock.");
synchronized (mLock){
mLock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i(TAG, "stop wait mLock");
while (socket != null && !Thread.currentThread().isInterrupted()) {
try {
final int len = 256;
DatagramPacket datagramPacket = new DatagramPacket(new byte[len], len);
Log.i(TAG, "receive data block");
socket.receive(datagramPacket);
Log.i(TAG, "receive data size = " + datagramPacket.getLength());
callback.onReceivePacket(datagramPacket.getData(), datagramPacket.getLength());
} catch (IOException e) {
e.printStackTrace();
}
}
Log.i(TAG,"stop");
}
}


}

1
2
3
public interface UDPCallback {
void onReceivePacket(byte[] data, int len);
}

签名的指纹在对接一些平台会用到,如微信,高德等。

很久没用,忘记了,这里记录一下,方便以后使用

命令

1
$ keytool -list -v -keystore 签名文件

Debug默认的签名

阅读全文 »

为了方便复习redis的数据类型,根据网络文章整理一份。

一、Redis 字符串(String)

字符串类型是最基础的类型,在redis里面字符串可以存储3中类型的值,字节串、整数、浮点数。
这里整数或者浮点数是可以执行自增或自减的。
使用场景:

  1. 计数
  2. 分布式锁
  3. 缓存数据

二、Redis 列表(List)

阅读全文 »

Spring3支持JSR-303验证框架,JSR-303 是Java EE 6 中的一项子规范,叫做BeanValidation,官方参考实现是hibernate Validator(与Hibernate ORM 没有关系),JSR 303 用于对Java Bean 中的字段的值进行验证。

1. 表单属性

1
2
3
4
5
6
@Data
public class User {

@NotBlank(message = "name不能为空")
private String name;
}

2. Controller中开启验证

1
2
3
4
5
6
7
import org.springframework.validation.annotation.Validated;

@PostMapping("/register")
public ResponseEntity<Void> register(@Validated User user) {

return ResponseEntity.noContent().build();
}
阅读全文 »

在VM虚拟机中NAT网络转为桥接,客户机CentOS则要改为静态IP,下面是操作日志。

ens33是默认的网卡,我们就修改这个网卡。
修改内容

  1. 设置一个静态IP、网关
  2. 启动IPV4,关闭IPV6
1
2
3
4
5
6
7
# 图形编辑
$ nmtui edit ens33

# 等同于编辑文件
$ vi /etc/sysconfig/network-scripts/ifcfg-ens33

$ service network restart

nmtui edit ens33

阅读全文 »

卸载

CentOS会自带OpenJDK,卸载自带的OpenJDK,再安装我们需要的版本

1
2
3
4
5
6
7
8
9
$ rpm -qa | grep jdk

java-11-openjdk-headless-11.0.4.11-1.el7_7.x86_64
java-1.8.0-openjdk-headless-1.8.0.222.b10-0.el7_6.x86_64
copy-jdk-configs-3.3-10.el7_5.noarch

$ rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0.222.b10-0.el7_6.x86_64
$ rpm -e --nodeps java-11-openjdk-headless-11.0.4.11-1.el7_7.x86_64
$ rpm -e --nodeps copy-jdk-configs-3.3-10.el7_5.noarch

搜索

1
$ yum search openjdk | grep -i --color openjdk
阅读全文 »

Ubuntu 默认的Gnome桌面有很酷炫的动画,在GUI没有找到关闭动画的设置。

为了省资源,可以通过以下指令控制桌面动画的开关。

1
$ gsettings set org.gnome.desktop.interface enable-animations false

Ubuntu默认安装的Nodejs版本都是比较低的(差很多),无法编译Vue,所以要安装最新版本。
思路是先安装旧版本,再升级到最新版本。

安装(失效)

网络原因,无法安装。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 先安装旧版
$ sudo apt install -y nodejs npm
# 2. 换源
$ sudo npm config set registry https://registry.npm.taobao.org (已停用)
$ sudo npm config set registry https://registry.npmmirror.com

# 注意:n方式安装,网络不通,装不了
# 3. 安装工具 n (管理 node 版本)
$ sudo npm install n -g
# 4. node升级安装最新版本
$ sudo n stable
# 5. npm升级安装最新版本(要先升级node再升级npm)
$ sudo npm install -g npm

安装(推荐)

阅读全文 »

安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

$ sudo add-apt-repository ppa:openjdk-r/ppa

$ sudp apt-get update

# 安装java8
$ sudo apt-get install openjdk-8-jdk

# 安装java11
$ sudo apt-get install openjdk-11-jdk

$ java -version
openjdk version "11.0.8" 2020-07-14
OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1, mixed mode, sharing)

Ubuntu默认安装的PostgreSQL版本都是比较低的(差很多),通过官方源来安装最新的版本。

一、安装

参考【Linux downloads (Ubuntu) 】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get -y install postgresql
$ sudo service postgresql status
● postgresql.service - PostgreSQL RDBMS
Loaded: loaded (/lib/systemd/system/postgresql.service; enabled; vendor preset: enabled)
Active: active (exited) since Wed 2022-05-25 10:18:58 CST; 18min ago
Main PID: 4020835 (code=exited, status=0/SUCCESS)
Tasks: 0 (limit: 4578)
Memory: 0B
CGroup: /system.slice/postgresql.service

May 25 10:18:58 cnubuntu systemd[1]: Starting PostgreSQL RDBMS...
May 25 10:18:58 cnubuntu systemd[1]: Finished PostgreSQL RDBMS.

二、查看版本

阅读全文 »

gradle在中国有cdn了:

修改 gradle-wrapper.properties 中的

services.gradle.orgdownloads.gradle-dn.com

【参考】

1. 简单

1
$ sudo docker run -p 8080:8080 -p 50000:50000 -u 0 jenkins/jenkins:lts

-u 0 :表示已root账号启动镜像(镜像内部使用的用户是 jenkins )

2. 带jenkins_home

阅读全文 »

2019年09月17日 JDK 13 发布,非 LTS 版本。

新特性: http://openjdk.java.net/projects/jdk/13/

  • 350: Dynamic CDS Archives
  • 351: ZGC: Uncommit Unused Memory ZGC优化
  • 353: Reimplement the Legacy Socket API Socket的底层实现优化
  • 354: Switch Expressions (Preview) switch表达式增加yield关键字用于返回结果,作用类似于return
  • 355: Text Blocks (Preview) 使用 “”” 三个双引号表示文本块

中文

  • 350: 对 Java 10 中引入的 应用程序类数据共享进行了进一步的简化、改进和扩展
  • 351: ZGC优化
  • 353: Socket的底层实现优化
  • 354: switch表达式增加yield关键字用于返回结果,作用类似于return
  • 355: 使用 “”” 三个双引号表示文本块
阅读全文 »

部署的相当多坑的,如果顺利,按照上面的资料走,基本不会有问题。下面记录一些坑位。

我是在VMWare虚拟机上做的测试,需要两台Windows服务器。

坑位

  1. 系统版本,windows server 2012,安装域控制和office online一直有未知错误。
  2. 安装好系统之后,不要激活,不要安装更新补丁,建议马上拍一个快照。
阅读全文 »

更新: “USB 启动盘” 推荐 rufusventoy

背景

2014年买的老笔记本想要重装系统,老硬件不想装Win10,用U盘装了个 微PE(不建议使用,有软件捆绑) 安装了原版sp1,装完之后,硬盘原本挺好的四个分区盘符全乱了,一般的盘符可以修改过来,但系统盘变成了D盘,改不过来。

于是想再次重装,顺便对硬盘重新分一下区,分两个区就足够。

Ghost

阅读全文 »

Win8、Win10对技术更新了不少,现在的购买的机器都是预装Win10,如果想要降级为Win7,那么如果想简单的重装系统,会发现装不了。

原因

  1. 新的机器都是采用 UEFI BIOS 启动方式 ,它具有启动速度快、安全性高和支持大容量硬盘的特点。
  2. Win10的硬盘分区采用 GUID 格式

修改

如果要降级重装 Win7,修改这两个东西:

阅读全文 »

故障

一台 Thinkpad E431 (装的Win7系统)半年没开过机,拿出来时,开机停留在“Windows启动管理器”,不会自动进入系统,并且 Enter 键失效了,无法进入系统。

后来通过乱按左边的键才能进一次系统,在系统里发现 BackspaceShift 键也失效了(可以下载 键盘检测 软件来检查)。

初步怀疑是放置时间太久导致COMS没电,主板的一些配置信息丢失了。F1 进去看了一遍BIOS,没找到什么改的,而且 Enter 失效,通过外接键盘才能改BIOS信息。

意外解决问题

阅读全文 »

断点下载HTTP协议中有支持,一般的Web服务器都会支持,如 nginx

HTTP 协议范围请求允许服务器只发送 HTTP 消息的一部分到客户端。范围请求在传送大的媒体文件,或者与文件下载的断点续传功能搭配使用时非常有用。

应用场景

  • 断点下载,下载大文件可以暂停。
  • 多任务/多线程下载大文件(类似迅雷软件)

一、检查服务器是否支持断点续传

阅读全文 »

切片上传一般用在大文件上传,防止上传过程中网络断开重头开始,但在HTTP协议里面并没有,所以实现要使用自定义一下方法。

网上很多资料,大概实现的原理:

  1. 客户端将大文件切为X份,每份切片都做md5校验。
  2. 按顺序一次上传一片,同时前后端做md5校验。
  3. 切片上传过程中可以暂停,并且在发生网络异常时,只是某切片上传失败。
  4. 上传所有切片之后,请求合并文件,后端将所有切片合并,前后端再次对大文件进行md5校验。

js本地文件切片

1
let blob = file.slice(start, end,file.type);
阅读全文 »