目录结构
一、项目说明
该项目是基于React+SpringBoot的一个分离项目。前端使用UmiJS来构建,使用了Ant Design Pro的组件库。后端是基于SpringBoot框架搭建的Java项目。
二、前端React打包
(一)使用WebStorm打包
-
使用 yarn build 命令打包前端项目,然后会在根目录下生成dist文件夹。这就是我们前端的包。如下图所示:
-
通过配置config.js去设置hash。详细参考UmiJS官网相关配置
-
可以在plugin.config.js覆盖原本的一些打包配置。可以详细参考这个大佬的博文去自定义构建打包配置https://blog.csdn.net/liusaint1992/article/details/83717444
到此为止,前端的打包完成。
三、后端Springboot项目打包
(一)使用IDEA打 .war包
- maven的多环境打包构建需要在pom.xml配置一个新的
<profile>
。配置后,勾选配置,dev举例,根据application-dev.yml配置打包。 - 选中test,点击右上方小闪电图标,禁掉test。
- 点击clean,删除上一次的target。
- 点击package,打包。
(二)使用命令打多环境配置的包
使用以下命令,根据对应的环境配置文件打包。一步到位
mvnw -Psit clean package -Dmaven.test.skip=true
打包成功后,如图,会在target下出来两个发布包。.war
包内置了tomcat,可以直接启动。下面的是不带tomcat的,我们需要把这个包放到容器下启动。(本文使用的包为.original
)
四、前端包发布Nginx服务器
(一)Linux上安装Nginx
- 下载解压Nginx
- 进入/usr/local文件夹,我们一般把自己安装的应用放在该文件夹中,可以理解为 C:/Progrem Files/。
cd /usr/local
- 创建nginx文件夹。
mkdir nginx
- 下载nginx安装包,我下载的是1.13.7版本的。
cd nginx
wget http://nginx.org/download/nginx-1.13.7.tar.gz
- 下载完成后,解压安装包。
sudo tar -xvf nginx-1.13.7.tar.gz
- 编译nginx
- 进入nginx目录
cd /usr/local/nginx/nginx-1.13.7
- 执行命令
./configure
- 执行make命令
apt-get install make
make
- 执行make install命令
make install
- 启动测试nginx
- 进入nginx启动目录
cd /usr/local/nginx/sbin
- 启动nginx
./nginx
-
完成后,访问服务器的80端口,查看是否出来Nginx的欢迎界面。
-
附注一张安装目录结构示意图
(二)修改nginx.config
根据下图,配置项目端口与ip地址,
server {
listen 80;
server_name localhost 192.168.0.100;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
# 配置前台包文件的路径
root html/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
proxy_read_timeout 1200;
}
# 配置反向代理
location /api/ {
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://192.168.0.100:8080/newcomp/api/;
index index.html index.htm;
proxy_read_timeout 1200;
client_max_body_size 100m;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
配置完成后,进入sbin目录下,重启nginx服务。
cd /usr/local/sbin
./nginx -s reload
可以使用以下命令,查询nginx进程,如图示:
ps -ef|grep nginx
(三)使用工具filezilla上传打包文件
使用文件传输工具,将我们本地打好的前端dist包上传至nginx的html文件夹下,nginx会自动热部署相应的文件。
五、后端包发布Tomcat服务器
(一)Linux安装JDK1.8
- oracle官网下载压缩包https://www.oracle.com/java/technologies/javase-jdk8-downloads.html。
- 将压缩包放在/usr/local/java下,解压
tar -zxvf jdk-8u231-linux-x64.tar.gz
- 设置环境变量
vim /etc/profile
在文件末尾加入
export JAVA_HOME=/usr/local/java/jdk1.8.0_231
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=.:${JAVA_HOME}/bin:$PATH
如果显示无法保存修改命令(说明该文件只有读权限,所以要添加写权限,或者用root权限改)
sudo vim /etc/profile
- 使配置生效
source /etc/profile
- 检查是否生效
java -version
(二)Linux上安装Tomcat
- 进入官网,选择你需要的tomcat版本,下载对应的tar.gz版本。
- 下载完成后,登录你的Linux系统,通过命令行,输入
rz
,打开文件传输窗口,将你本地的Tomcat安装包上传至你的/usr/local
目录下。也可以通过工具上传,亦可以直接在Linux上使用wget
命令下载。
cd /usr/local
ll
rz
打开如下:
- 解压
sudo tar -zxvf apache-tomcat-8.5.47.tar.gz
解压后
安装完毕。
(三)修改server.xml、startup.sh等配置文件
- server.xml
这个配置文件,如果不需要自定义配置的话,可以不修改,只要将发布包放在webapps下,就能解析到8080端口。
但是我们在服务器上,可能存在多个Tomcat容器,所以,简单介绍下该server.xml的一些自定义配置。
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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.
-->
<!-- Note: A "Server" is not itself a "Container", so you may not
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
-->
<!-- 8005 为当执行shutdown.sh关闭tomcat时就是连接8005端口执行“SHUTDOWN”命令,多个tomcat同时启动时,需要自行修改-->
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- A "Service" is a collection of one or more "Connectors" that share
a single "Container" Note: A "Service" is not itself a "Container",
so you may not define subcomponents such as "Valves" at this level.
Documentation at /docs/config/service.html
-->
<Service name="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools-->
<!--
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
-->
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
-->
<!-- 8080 不用说,http监听端口;8443是https的监听端口 -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- A "Connector" using the shared thread pool-->
<!--
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-->
<!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443
This connector uses the NIO implementation. The default
SSLImplementation will depend on the presence of the APR/native
library and the useOpenSSL attribute of the
AprLifecycleListener.
Either JSSE or OpenSSL style configuration may be used regardless of
the SSLImplementation selected. JSSE style configuration is used below.
-->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
type="RSA" />
</SSLHostConfig>
</Connector>
-->
<!-- Define an SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
This connector uses the APR/native implementation which always uses
OpenSSL for TLS.
Either JSSE or OpenSSL style configuration may be used. OpenSSL style
configuration is used below.
-->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
certificateChainFile="conf/localhost-rsa-chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
-->
<!-- Define an AJP 1.3 Connector on port 8009 -->
<!-- 8009--httpd等反向代理tomcat时就可以使用使用ajp协议反向代理到该端口。虽然我们经常都是使用http反向代理到8080端口,但由于ajp建立tcp连接后一般长时间保持,从而减少了http反复进行tcp连接和断开的开销,所以反向代理中ajp是比http高效的。 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host).
Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
<Engine name="Catalina" defaultHost="localhost">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false"
>
<!-- 这个可以配置项目启动后访问路径,就不要加项目名称就能访问了-->
<!-- <Context path="" docBase ="/newcomp/"/> -->
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
- startup.sh
要想使用./startup
命令启动项目,需要在/bin
目录下修改该启动文件。在末尾添加如下内容,需要对应之前我们的各种配置路径。
#set java environment
export JAVA_HOME=/usr/java/jdk1.8.0_231
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:%{JAVA_HOME}/lib:%{JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
#tomcat
export TOMCAT_HOME=/usr/local/apache-tomcat-8.5.47
exec "$PRGDIR"/"$EXECUTABLE" start "$@"
- shutdown.sh
同理
#set java environment
export JAVA_HOME=/usr/java/jdk1.8.0_231
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:%{JAVA_HOME}/lib:%{JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
#tomcat
export TOMCAT_HOME=/usr/local/apache-tomcat-8.5.47
exec "$PRGDIR"/"$EXECUTABLE" stop "$@"
在使用./shutdown.sh
可能会出现,停止服务了,但是查询该tomcat进程还是存在的情况。我们可以使用kill
命令将该tomcat进程手动杀掉。但是总归不方便,我们下面还会继续说明这个问题。
(四)启动Tomcat
进入bin
目录下,使用命令 ./startup.sh
启动Tomcat。
访问http://IP地址:8080
查看Tomcat能否正常显示初始化页面。
(五)发布后台
将我们之前打的original包,上传至tomcat下的webapps目录下,修改名称,去掉后缀。(在测试Tomcat能否正常工作后,将之前webapps下,默认的文件都删除)重新启动Tomcat就可以了。
六、编写shell脚本,简化发布流程
以上讲解了我们打包发布的场景。但是命令太多,操作繁琐。那么我们可以写一个shell脚本,来简化我们的后续发布流程。
我们一般会把我们自定义的脚本,放在/usr/local/sbin
目录下,方便我们以及他人统一管理脚本文件。
我们只需要把我们的前后台包,传到指定的位置,修改好对应的名称,然后执行一下我们编写的shell脚本,就可以完成发布了。
大家可以参考:
#! /bin/bash
## author:qiuyu
## 2020-10-26
## dev apache-tomcat-8.5.47测试发布 shell
date
echo 'Redeploy 192.168.0.100:8081'
## 前端文件,热部署
rm -rf /usr/local/nginx/html/dist
cp -r /home/sinosoft/fbb/newcompqiantai/dist /usr/local/nginx/html
echo 'Nginx hot-loading successful'
## 后台
sh /usr/local/apache-tomcat-8.5.47/bin/shutdown.sh
cp /home/sinosoft/fbb/newcomphoutai/newcomp.war /usr/local/apache-tomcat-8.5.47/webapps/
sh /usr/local/apache-tomcat-8.5.47/bin/startup.sh
echo 'Tomcat run successful'
echo 'Please view log ---> tail -f /usr/local/apache-tomcat-8.5.47/logs/catalina.out'
编写好我们的shell脚本后,后缀名称为.sh
.通过chmod +x 脚本名称.sh
命令添加脚本的执行权限。对了,大家最好要在linux环境下编写脚本。本人在windows下编写好上传后,执行时出现问题,后来发现是windows系统和linux系统下的空格是不一样的,这就很尴尬。。。
上面存留了一个问题,Tomcat下bin的./shutdown.sh
命令出现Tomcat进程杀不掉的情况,通过ps -ef|grep tomcat
查询仍然可以看到进程存在。我们可以通过如下步骤去解决:
- vim修改tomcat下
bin/catalina.sh
文件,添加点东西,主要是在启动时,记录tomcat启动的pid,如下:
#设置记录CATALINA_PID。
#该设置会在启动时候bin下新建一个CATALINA_PID文件
#关闭时候从CATALINA_PID文件找到pid,kill。。。同时删除 CATALINA_PID文件
在 PRGDIR=dirname "$PRG"
后面加上(大概文件第139行左右):
if [ -z "$CATALINA_PID" ]; then
CATALINA_PID=$PRGDIR/CATALINA_PID
cat $CATALINA_PID
fi
- vim tomcat的shutdown.sh文件,在最后一行加上 -force:
exec "$PRGDIR"/"$EXECUTABLE" stop -force "$@"
然后再使用shutdown.sh脚本时,就能把tomcat进程也杀掉了。
本文只是个人在学习时总结的一些东西,涉及纰漏,还望指出。