JoyLau's Blog

JoyLau 的技术学习与思考

背景

以前博客多多少少写个一些常用工具的代理设置,这里做一个汇总, 以后有更多工具使用代理直接在此处记录了

说明

如果代理有用户名密码的话, 使用

1
2
3
http://username:password@127.0.0.1:1087
# 或者
sockts5://username:password@127.0.0.1:1087

Mac 终端代理设置

export HTTP_PROXY=http://127.0.0.1:1087

export SOCKS5_PROXY=socks5://127.0.0.1:1086

export ALL_PROXY=socks5://127.0.0.1:1086

我一般直接使用最后一种方式,简单粗暴

HomeBrew 代理设置

同上, 因为 brew 走的 curl,代理设置通用

Git 代理配置

需要全局 git 都走代理

git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'

取消

git config --global --unset http.proxy
git config --global --unset https.proxy

但是有时候我们并不需要所有的 git 仓库都走代理,可以去掉上述的命令中的 –global,然后到你需要走代理的那个 git 仓库下执行命令,或者添加配置:

单独配置 git 走代理
在 .git => config 文件中加入配置

1
2
3
4
[https]
proxy = socks5://127.0.0.1:1080
[http]
proxy = socks5://127.0.0.1:1080

配置仅 Github 走代理

1
git config --global http.https://github.com.proxy http://127.0.0.1:7890

注意这里不需要配置 https, 配置 http 就可以生效了

Linux 终端代理

Mac 终端代理设置

Ubuntu 桌面版使用全局代理

以前我使用的是: http://blog.joylau.cn/2018/08/08/Git-Proxy-And-Ubuntu-Global-Proxy/
现在我使用的是: Clash

Gradle 配置代理

配置 gradle.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
## http
systemProp.http.proxyHost=www.somehost.org
systemProp.http.proxyPort=8080
systemProp.http.proxyUser=userid
systemProp.http.proxyPassword=password
systemProp.http.nonProxyHosts=*.nonproxyrepos.com|localhost

## https
systemProp.https.proxyHost=www.somehost.org
systemProp.https.proxyPort=8080
systemProp.https.proxyUser=userid
systemProp.https.proxyPassword=password
systemProp.https.nonProxyHosts=*.nonproxyrepos.com|localhost

另一种快速的方法是使用阿里云的 maven 仓库
配置如下:
在用户目录下的 .gradle 的目录下新建文件 init.gradle

1
2
3
4
5
6
7
8
9
allprojects {
repositories {
mavenLocal()
maven {
url "http://maven.aliyun.com/nexus/content/groups/public"
}
mavenCentral()
}
}

Docker 配置代理

在命令行使用 export HTTP_PROXY=xxxx:xx , 命令行里绝大部分命令都可以使用此代理联网,但是安装的 docker 不行,无法 pull 下来镜像文件,想要 pull 使用代理的话,需要添加代理的变量
vim /usr/lib/systemd/system/docker.service
添加

Environment=HTTP_PROXY=http://xxxx:xxx
Environment=HTTPS_PROXY=http://xxxx:xxx

保存

systemctl deamon-reload
systemctl restart docker

npm 使用代理

npm 支持 http 代理,但是不支持 socks 代理

1
2
npm config set proxy "http://localhost:1087"
npm config set https-proxy "http://localhost:1087"

该设置方式是永久的,全局的,想要取消的话,使用

删除代理

1
2
npm config delete proxy
npm config delete https-proxy

apt-get 使用代理

使用参数 -o Acquire

1
sudo apt-get -o Acquire::http::proxy="http://host:port" update/install ...

该代理是一次性的,关闭 shell 即失效

JVM 使用代理配置

1
-DsocksProxyHost=172.16.1.201 -DsocksProxyPort=60798

在该代理基础上需要排除一些不需要使用代理的, 需要再加上

1
-Dhttp.nonProxyHosts="192.168.1.*|172.16.*.*" -DsocksNonProxyHosts="192.168.1.*|172.16.*.*"

Postman 使用 socks5 代理

默认的 Postman 不支持使用 socks5 代理,支持 http和 https 代理, 需要转换下即可
使用方法:

  1. 安装 http-proxy-to-socks npm install -g http-proxy-to-socks
  2. 开启转发 hpts -s 172.16.1.200:60798 -p 7951 本地的 7951 端口转发到远程的 60798 端口
  3. 之后正常设置 http 代理即可

何为

以前我都是服务器上执行定时任务,在凌晨的时候 pull 博客仓库在 hexo 编译, 在上传到 github 静态资源库, 在 pull 静态资源库到 nginx 目录下,这样实现个人博客的发布

真: 放弃定时任务, 采用 github 的钩子, 在博客仓库有 push 行为时,立马执行上述操作, 以前直接在服务器上写的脚本来执行,这次决定将这些操作打包成一个 docker 镜像, 随时随地可部署

避免了部署还需要配置定时任务和写一批脚本的问题.

环境准备

  1. 以 Ubuntu 18.04 为基础镜像,进行镜像的制作
  2. docker run -it -name blog-auto-publish ubuntu:18.04 /bin/bash
  3. apt update
  4. apt install git
  5. apt install vim
  6. rm -rf /etc/apt/sources.list
  7. vim /etc/apt/sources.list
script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse

deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse

  1. apt update
  2. apt install curl
  3. curl -sL https://deb.nodesource.com/setup_13.x | bash
  4. apt-get install -y nodejs
  5. npm install hexo -g
  6. apt install nginx
  7. apt install fcgiwrap

新建目录

mkdir /my-blog
mkdir -p /my-blog/bash
mkdir -p /my-blog/logs

克隆仓库

git clone https://github.com/JoyLau/blog.git

cd blog

npm install

建立命令

vim /my-blog/bash/init.sh

vim init.sh

1
2
3
#!/usr/bin/env bash
chown -R www-data:www-data /my-blog/* && service fcgiwrap start && service nginx start && tail -f -n 500 /my-blog/logs/publish.log

vim /my-blog/bash/pull-deploy.sh

1
2
3
4
5
6
7
8
9
10
11
#! /usr/bin/env bash
cd /my-blog/blog && \
## git checkout -- _config.yml && \
git pull && \
echo `pwd` && \
## update config
## sed -i "s/https:\/\/name:password@github.com\/JoyLau\/blog-public.git/https:\/\/$GITHUB_REPO_USERNAME:$GITHUB_REPO_PASSWORD@github.com\/$GITHUB_REPO_USERNAME\/$GITHUB_REPO_NAME.git/g" _config.yml && \
## hexo clean && \
hexo g
## hexo d

vim /my-blog/bash/publish.sh

1
2
3
4
5
6
#!/bin/bash
echo "Content-Type:text/html"
echo ""
echo "ok"
/my-blog/bash/pull-deploy.sh>/my-blog/logs/publish.log

注意: 前 2 行是必须的.这样发出请求会有返回

配置 nginx

vim /etc/nginx/sites-available/default

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
server {
listen 80 default_server;
listen [::]:80 default_server;

index index.html index.htm index.nginx-debian.html;

server_name _;

location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}

}

server {
listen 8080 default_server;
listen [::]:8080 default_server;

root /my-blog/bash;

server_name _;

location ~ ^/.*\.sh {
gzip off;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}


nginx -t 检查错误

注意

  1. fcgiwrap 不能以 root 组或者 root 用户运行, 这点在配置文件 /etc/init.d/fcgiwrap 可以配置,默认为 www-data, 因此 nginx 的用户也设置为 www-data,同时设置 /my-blog 目录下所属者为 www-data

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
FROM nas.joylau.cn:5007/joy/blog.joylau.cn:1.0

LABEL maintainer="blog.joylau.cn"

ENV GITHUB_REPO_USERNAME ""
ENV GITHUB_REPO_PASSWORD ""
ENV GITHUB_REPO_NAME ""
ENV REPO_INFO ""

EXPOSE 80

EXPOSE 8080

CMD ["sh", "/my-blog/bash/init.sh"]

打包镜像:
docker build -t nas.joylau.cn:5007/joy/blog.joylau.cn:1.0 .

打包后镜像大小为: 294 MB

使用

docker run -p 8081:80 -p 8082:8080 -d –name blog.joylau.cn nas.joylau.cn:5007/joy/blog.joylau.cn:1.0

备注

  1. 80 端口提供的服务为 blog 页面
  2. 8080 端口提供的服务为执行 shell 命令
  3. 提供 webhook 为 http://host:port/publish.sh ,通过请求这个请求来更新博客
  4. 查看日志文件有 /my-blog/logs/publish.log 和 nginx 的日志文件 /var/log/nginx/error.log

后续优化备忘

  1. 删除原来的 /var/log/nginx/error.log 日志里的错误信息,现有的错误信息是是测试使用产生的
  2. 在镜像里就执行一遍 chown -R www-data:www-data /my-blog/* , 否则的话容器刚启动的时候会很慢, 可以不执行 hexo g ,使用 hexo g –watch 实时监听文件变化,也不需要 nginx 了,直接使用 hexo-server ,开启 –debug 参数打印详细日志信息
  3. 考虑将 publish.sh 的最后一行命令不等待执行完就返回,现在的情况是部署到配置较低的机器上执行很慢,会导致请求超时,虽然不影响执行结果
  4. 配置好容器内的时区,使得日志的时间戳更明显

优化更新记录 [2020-04-01]

  1. 设置时区:
1
2
3
4
apt-get install tzdata
然后依次选择 6 , 70 即可

使用 dpkg-reconfigure tzdata 来重写选择
  1. 清空 nginx 日志文件
1
2
echo "" > /var/log/nginx/error.log 
echo "" > /var/log/nginx/access.log
  1. webhooks 不等待执行完就返回
    vim /my-blog/bash/publish.sh
1
2
3
4
5
#!/bin/bash
echo "Content-Type:text/html"
echo ""
echo "ok"
/my-blog/bash/pull-deploy.sh>/my-blog/logs/publish.log 2>&1 &
  1. 实时监听文件变化
    vim /my-bog/bash/init.sh
1
2
3
4
5
#!/usr/bin/env bash
service fcgiwrap start
service nginx start
cd /my-blog/blog/ && nohup hexo g --watch >/my-blog/logs/hexo-generate.log 2>&1 &
tail -f -n 500 /my-blog/logs/publish.log /my-blog/logs/hexo-generate.log /var/log/nginx/error.log /var/log/nginx/access.log
  1. 不使用 dockerfile 来构建,直接使用 docker commit
1
docker commit -c 'CMD ["sh", "/my-blog/bash/init.sh"]' -c "EXPOSE 80" -c "EXPOSE 8080" -a "JoyLau" -m "JoyLau's Blog Docker Image"  blog nas.joylau.cn:5007/joy/blog.joylau.cn:2.1

优化更新记录 [2020-04-02]

更新脚本:

  1. init.sh
1
2
3
4
5
6
7
8
#!/usr/bin/env bash
echo "Hello! log file in /my-blog/logs/publish.log"
service fcgiwrap start
service nginx start
su - www-data -c "cd /my-blog/blog/ && git pull"
cd /my-blog/blog/
hexo g --watch | tee -a /my-blog/logs/publish.log

  1. publish.sh
1
2
3
4
5
#!/bin/bash
echo "Content-Type:text/html"
echo ""
echo "ok\r\n"
/my-blog/bash/pull-deploy.sh | tee -a /my-blog/logs/publish.log
  1. pull-deploy.sh
1
2
3
4
5
#! /usr/bin/env bash
echo "Prepare to update Blog Posts....."
cd /my-blog/blog/
git pull

优化更新记录 [2020-04-07]

新增 republish.sh

1
2
3
4
#!/usr/bin/env bash
echo "prepare republish......"
cd /my-blog/blog/
hexo clean && hexo g

修改 init.sh

1
2
3
4
5
#!/usr/bin/env bash
echo "Hello! log file in /my-blog/logs/publish.log"
service fcgiwrap start
service nginx start
su - www-data -c "cd /my-blog/blog/ && git pull && hexo g --watch | tee -a /my-blog/logs/publish.log"

使用 Dockerfile 构建 [2020-04-21 更新]

在容器里各种操作是在是太黑箱了,日后极难维护,这里我编写 Dockerfile 来构建镜像

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
FROM node:latest
MAINTAINER joylau 2587038142.liu@gmail.com
LABEL Descripttion="This image is JoyLau's Bolg"
ENV GIT_REPO="https://github.com/JoyLau/blog.git"
ENV BRANCH master
EXPOSE 80 8081
ADD sources.list /etc/apt/sources.list
RUN apt-get update &&\
apt-get install -y gosu nginx git fcgiwrap &&\
npm install hexo -g &&\
npm install -g cnpm --registry=https://registry.npm.taobao.org
COPY nginx.default.conf /etc/nginx/sites-available/default
RUN mkdir -p /my-blog/bash /my-blog/logs
COPY *.sh /my-blog/bash/
RUN chown -R www-data:www-data /my-blog &&\
chmod -R 777 /var/www &&\
chmod +x /my-blog/bash/*.sh
ENTRYPOINT ["/my-blog/bash/docker-entrypoint.sh"]
CMD ["/my-blog/bash/init.sh"]

docker-entrypoint.sh

1
2
3
4
5
6
7
8
9
#!/bin/bash
set -e
if [ "$1" = '/my-blog/bash/init.sh' -a "$(id -u)" = '0' ]; then
service nginx start
service fcgiwrap start
echo "☆☆☆☆☆ base service has started. ☆☆☆☆☆"
exec gosu www-data "$0" "$@"
fi
exec "$@"

init.sh

1
2
3
4
5
6
7
#! /bin/bash
cd /my-blog
echo "☆☆☆☆☆ your git repo is [$GIT_REPO] ; branch is [$BRANCH]. ☆☆☆☆☆"
git clone -b $BRANCH --progress $GIT_REPO blog
cd blog
cnpm install -d
hexo g --watch --debug | tee -a /my-blog/logs/genrate.log

nginx.default.conf

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
server {
listen 80 default_server;
listen [::]:80 default_server;

index index.html index.htm index.nginx-debian.html;

server_name _;

root /my-blog/blog/public;

location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}

}

server {
listen 8081 default_server;
listen [::]:8080 default_server;

root /my-blog/bash;

server_name _;

location ~ ^/.*\.sh {
gzip off;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}

publish.sh

1
2
3
4
5
6
7
#!/bin/bash
echo "Content-Type:text/html"
echo ""
echo "<h1>ok</h1>"
echo "<h3>Prepare to update Blog Posts.....</h3>"
cd /my-blog/blog/
git pull

republish.sh

1
2
3
4
5
6
7
#!/bin/bash
echo "Content-Type:text/html"
echo ""
echo "<h1>ok</h1>"
echo "<h3>republish blog.....</h3>"
cd /my-blog/blog
hexo g --force

sources.list

1
2
3
4
5
6
7
8
9
deb http://mirrors.163.com/debian/ stretch main non-free contrib
deb http://mirrors.163.com/debian/ stretch-updates main non-free contrib
deb http://mirrors.163.com/debian/ stretch-backports main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch-updates main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch-backports main non-free contrib
deb http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib
deb-src http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib

启动

1
docker run -d --restart always --name blog -p 8001:80 -p 8002:8081 nas.joylau.cn:5007/joy/blog.joylau.cn:3.0

加入代理 [2020-04-28更新]

遇到初始化容器很慢的情况, 原因是 git clone 很慢
本次在 init.sh 脚本里加入了 git 代理设置, 有代理的条件的可以设置代理
快速启动容器

问题

brew update 遇到错误, 错误信息如下:

script
1
2
3
4
5
6
7
Updating Homebrew...
Warning: You are using macOS 10.15.
We do not provide support for this pre-release version.
You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub,
Discourse, Twitter or IRC. You are responsible for resolving any issues you
experience, as you are running this pre-release version.

解决方式

  1. brew doctor

运行后发现源为科大的源, 于是切换回原来的官方的 brew 源

script
1
2
cd "$(brew --repo)"
git remote set-url origin https://github.com/Homebrew/brew.git

有其他问题,建议按照提示一一解决掉

  1. brew update

更新成功

  1. brew config

查看配置

错误

MacOS 升级到 10.15 版本时,预览文件出现下面的提示

qlPlugin-not-work

解决方式 1

删除 ~/Library/QuickLook 目录下的隔离属性 (quarantine attribute)

运行下面命令查看属性:

script
1
xattr -r ~/Library/QuickLook

运行下列命令移除这些属性:

script
1
xattr -d -r com.apple.quarantine ~/Library/QuickLook

解决方式 2

  1. 空格预览文件出现下列提示,点击 取消
qlPlugin-not-work
  1. 转到系统设置里
qlPlugin-solution-1

点击 “Allow Anyway”

  1. 使用下列命令打开刚才需要预览的文件
script
1
qlmanage -p /path/to/any/file.js
  1. 此时弹出提示,点击 “open”
qlPlugin-solution-2
  1. 然后就可以预览该后缀名的所有文件了
qlPlugin-solution-3
  1. 如果需要预览其他类型的文件,则将上述步骤重新操作一遍, 换个后缀名即可

最后推荐

推荐下自己使用的预览插件

script
1
brew cask reinstall qlcolorcode qlstephen qlmarkdown quicklook-json qlimagesize suspicious-package quicklookase qlvideo

需要注意的是 qlcolorcode 需要 highlight 库来显示高亮效果, 需要安装: brew install highlight

背景

在一次生产环境部署 elasticsearch 节点时 docker 容器设置了 –restart always,
此时 elasticsearch 的一个节点发生了 java.lang.OutOfMemoryError: Java heap space
容器并没有重启

elasticsearch 已经设置了 -Xms -Xmx

解释

JVM堆内存超出xmx限制,并抛java.lang.OutOfMemoryError: Java heap space异常。堆内存爆了之后,JVM和java进程会继续运行,并不会crash

解决

当JVM出现 OutOfMemoryError,要让 JVM 自行退出, 这样容器就会触发重启

添加新的 jvm 配置: ExitOnOutOfMemoryError and CrashOnOutOfMemoryError

该配置支持 jdk8u92 版本及其之后的版本

地址: https://www.oracle.com/technetwork/java/javase/8u92-relnotes-2949471.html

oracle 官网的原话:

New JVM Options added: ExitOnOutOfMemoryError and CrashOnOutOfMemoryError
Two new JVM flags have been added:

ExitOnOutOfMemoryError - When you enable this option, the JVM exits on the first occurrence of an out-of-memory error. It can be used if you prefer restarting an instance of the JVM rather than handling out of memory errors.

CrashOnOutOfMemoryError - If this option is enabled, when an out-of-memory error occurs, the JVM crashes and produces text and binary crash files (if core files are enabled).

ExitOnOutOfMemoryError: 启用此选项时,JVM在第一次出现内存不足错误时退出。如果您希望重新启动JVM实例而不是处理内存不足错误,则可以使用它。
CrashOnOutOfMemoryError: 如果启用此选项,则在发生内存不足错误时,JVM崩溃并生成文本和二进制崩溃文件(如果启用了核心文件)。

加上配置

ES_JAVA_OPTS = “-XX:+ExitOnOutOfMemoryError”

git 命令显示中文

直接在终端中执行下面的命令
git config –global core.quotepath false

文件回滚

  1. 工作区尚未暂存的文件: git checkout – 文件名
  2. 已添加到暂存区: git reset HEAD 文件名 && git checkout – 文件名
  3. 已提交到本地库, 想要撤销提交,并恢复到之前的文件内容: git reset –hard HEAD^

其中:
git reset 有三种参数:

  • Soft:这个模式仅仅撤销 commit 记录而已,不影响本地的任何文件,即本地修改的文件内容还会存在,也不影响(index)缓存区的任何文件。
  • Hard:不仅撤销 commit 记录,还将本地的文件指向 commit 前的版本,同时 index 也会指向 commit 前的版本。
  • Mixed:回滚 index ,其余的保持不变。

另外 HEAD 后面加上 ~1 代表回滚一次 commit 记录, HEAD^ 代表全部 commit 记录

git fetch 和 git pull

  1. git fetch : 将本地仓库指向的 remote 提交记录更新为和远端一致,即最新,其他的不做任何改变
  2. git pull : 将本地仓库和将本地仓库指向的 remote 都更新为最新, 相当于 fetch + merge

参看: https://blog.csdn.net/qq_37420939/article/details/89736567

git merge 和 git rebase

merge 和 rebase 都是 git pull 时的策略

git rebase 有以下几种使用场景:

  1. 合并本地的多次提交记录

合并最近的 4 次提交纪录

1
2

git rebase -i HEAD~4

在 idea 中可以在 Version Control 中选择最早时间的提交记录, 然后选择 Interactively Rebase from Here
然后除了第一个为pick外,其他选择squash,点击start rebasing,接着输入提交信息就可以把多次commit合并为一次了

  1. 分支合并,可以把本地未push的分叉提交历史整理成直线

将提交合并到其他分支上

有时候我们在某一个分支上提交了一些代码, 需要将这次提交合并到其他分支上, 这时的做法是:

这当前分支上使用 git log 查看需要进行合并的提交记录的 ID

切换到需要合并的分支上: git checkout 分支名

进行合并: git cherry-pick commitId

推送到到上游分支: git push

spring boot 后台的配置

这里记录一些坑
使用 gradle 配置, 其中移除了 Tomcat , 使用的是 Undertow
先引入依赖

implementation ('org.springframework.boot:spring-boot-starter-websocket')

提示报错 web 容器没有实现 JSR356
undertow 肯定是实现了 JSR356, 在 undertow-websockets-jsr 这个依赖里
判断肯定是由于移除 Tomcat 的问题,查看依赖发现 spring-boot-starter-websocket 依赖了 web , 而 web 默认使用的就是 Tomcat
于是移除 web 依赖即可

1
2
3
implementation ('org.springframework.boot:spring-boot-starter-websocket'){
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-web'
}

代码部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// config.enableSimpleBroker("/topic");
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("*")
.withSockJS();
}

}

注意在启动类上加入: @EnableWebSocketMessageBroker

这里使用的是 stomp 协议, 于是也要前端使用 stomp 配合

发送消息可以加入 @SendTo 注解, 还有一种方式, 就是使用 SimpMessagingTemplate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
@RequestMapping("ws")
public class PushMessage {

private final SimpMessagingTemplate template;

public PushMessage(SimpMessagingTemplate template) {
this.template = template;
}

@GetMapping("/config")
public void configMessage() {
template.convertAndSend("/topic/public", MessageBody.success());
}
}

React 配置

安装组件 npm install react-stomp
自行封装一个组件,如下:

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
import React, {Component} from 'react';
import SockJsClient from "react-stomp";
import {message} from "antd";

class Websocket extends Component {

render() {
return (
<div>
<SockJsClient
url={'ws'}
topics={[]}
onMessage={(payload) => {
console.info(payload)
}}
onConnect={() => {
console.info("websocket connect success")
}}
onConnectFailure={() => {
message.error("websocket 连接失败!")
}}
onDisconnect={() => {
console.info("websocket disconnect")
}}
debug={false}
{...this.props}
/>
</div>
);
}
}

export default Websocket;

子组件使用:

1
2
3
4
5
6
7
<Websocket
topics={['/topic/public']}
debug={false}
onMessage={(payload) => {
// do somthing
}}
/>

遇坑解决

以上方式看起来使用没有问题,但是现实情况往往开发时前后端分离,请求后端接口往往在 node 项目里配置代理, 这里涉及到 websocket 的代理

之前的配置都是在 package.json 配置, 比如:

1
"proxy": "http://localhost:8098"

但是这种方式对 websocket 的代理失败,会发现 websocket 连接不上

解决方式:
在新版的 customize-cra 的使用方式里:
先安装 http-proxy-middleware : npm install http-proxy-middleware
在 src 目录下新建文件 setupProxy.js, 名字不可改,一定要是这个文件名

1
2
3
4
5
6
7
8
9
10
11
12
const proxy = require("http-proxy-middleware");
const pck = require('../package');

module.exports = app => {
app.use(
proxy("/ws",
{
target: pck.proxy,
ws: true
})
)
};

这里开启 ws: true 即可完成 websocket 的代理.

添加多页面配置

之前写过一篇 npm eject 之后的多页面配置,可以往前翻阅 , 现在不想 eject, 该怎么配置多页面?

  1. npm install react-app-rewire-multiple-entry –save-dev

  2. 在 config-overrides.js 中添加配置
    现在 public 里复制一个 html 页面, 在 src 目录下再新增一个目录,里面的文件拷贝 index 的稍微改动下,
    大致目录如下:

-serviceWorker.js
-metadata.js
-metadata.css
-logo.svg
-App.test.js
-App.js
-App.css

基本使用:

1
2
3
4
5
6
7
8
9
10
11
12
const multipleEntry = require('react-app-rewire-multiple-entry')([{
entry: 'src/metadata/metadata.js',
template: 'public/metadata.html',
outPath: '/metadata',
}]);

module.exports = {
webpack: function(config, env) {
multipleEntry.addMultiEntry(config);
return config;
}
};

在 customize-cra 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const multipleEntry = require('react-app-rewire-multiple-entry')([
{
entry: 'src/entry/landing.js',
template: 'public/landing.html',
outPath: '/landing.html'
}
]);

const {
override,
overrideDevServer
} = require('customize-cra');

module.exports = {
webpack: override(
multipleEntry.addMultiEntry
)
};

结合 ant-design 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const {override, fixBabelImports, addLessLoader} = require('customize-cra');

const multipleEntry = require('react-app-rewire-multiple-entry')([{
entry: 'src/metadata/metadata.js',
template: 'public/metadata.html',
outPath: '/metadata',
}]);


module.exports = override(
multipleEntry.addMultiEntry,
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true,
}),
addLessLoader({
javascriptEnabled: true,
modifyVars: { '@primary-color': '#1890ff' },
}),
);

注意,这样配置的话, 请求的 uri 是 /metadata, 在 build 后会生成 metadata 文件, 将打包后的文件拷贝到服务器上运行效果不好
一般我都注释掉 template, 再将 outPath 写成 /metadata.html

打包不生成 source-map 文件

在 配置文件 config-overrides.js 添加 process.env.GENERATE_SOURCEMAP = "false";
或者

在项目更目录下创建文件 .env, 写入: GENERATE_SOURCEMAP=false 即可.

0%