【博客系统】博客系统第十一弹:从零开始在 Linux 系统上搭建 Java 部署环境并部署 Web 项目
搭建 Java 部署环境
JDK
1. 更新软件包
apt 命令详细介绍
sudo apt-get update
2. 安装 OpenJDK
查找 JDK 包
apt list | grep "jdk"
安装 JDK
sudo apt install openjdk-17-jdk
注意:
- 使用
java -version
验证是否安装成功。 - 如果提示 “java 命令找不到” 则说明安装失败。
3. 卸载 OpenJDK
-
检查安装的是哪个 OpenJDK
dpkg --list | grep -i jdk
-
移除 OpenJDK 包
apt-get purge openjdk*
-
卸载 OpenJDK 相关包
apt-get purge icedtea-* openjdk-*
-
检查所有 OpenJDK 包是否都已卸载完毕
dpkg --list | grep -i jdk
MySQL
使用 apt 安装 MySQL
-
查找安装包
apt list | grep "mysql-server"
-
安装 MySQL
sudo apt install mysql-server
查看 MySQL 状态
sudo systemctl status mysql
MySQL 安装安全设置
默认的 MySQL 设置是不安全的,MySQL 安装提供了一个安全脚本,用于解决不太安全的默认选项。
运行以下命令:
sudo mysql_secure_installation #安装安全设置
执行过程:
-
是否设置验证密码组件:
Press y|Y for Yes, any other key for No: Y #是否设置验证密码组件
-
密码强度设置:
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2 #设置密码强度
-
删除匿名用户:
Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y #默认情况下,MySQL安装有一个匿名用户, 允许任何人登录MySQL. 是否删除匿名用户?
-
禁止 root 用户远程登录:
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : Y #仅应允许root从'localhost'连接
-
删除 test 数据库:
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y #默认情况下, MySQL带有⼀个test数据库, 是否删除?
-
重新加载权限表:
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y #是否现在加载配置, 使刚才的修改生效?
-
完成:
All done!
通过以上步骤,MySQL 的安全设置已经完成,确保了数据库的安全性。设置密码
连接 MySQL 服务器
sudo mysql
使用 ALTER USER
命令修改密码
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'BITE@yyds.666';
退出 MySQL
exit
再次登录输入:
mysql -uroot -p # 密码: BITE@yyds.666
卸载 MySQL
- 停止 MySQL
sudo systemctl stop mysql
- 卸载 MySQL
sudo apt-get remove --purge mysql-server mysql-client mysql-common
- 删除 MySQL 配置文件和数据
sudo rm -rf /etc/mysql /var/lib/mysql
- 清理残留文件和目录
sudo apt-get autoremove
sudo apt-get autoclean
- 验证卸载结果
mysql --version
部署 Web 项目到 Linux
环境配置
确保程序正常运行需完成以下配置:
-
数据库准备
- 执行提供的建表脚本,确保表结构与服务器一致
-
多环境配置
- 按环境创建配置文件(如开发/测试/生产环境)
- 命名格式:
application-XXX.yml
或application-XXX.properties
- 差异化配置项示例:MySQL账号密码、服务端口等
关键点:通过文件命名
区分环境,避免硬编码敏感信息。
以下以application-XXX.yml
为例:
application-dev.yml: 开发环境配置
server:port: 8080spring:datasource:url: jdbc:mysql://127.0.0.1:3306/java_blog_spring?characterEncoding=utf8&useSSL=falseusername: rootpassword: 123456 # windows 数据库密码driver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:configuration:map-underscore-to-camel-case: true
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # linux 服务器没必要打日志, 打日志也会影响性能
logging:file:name: spring-blog.log
application-prod.yml: 生产环境配置
:
server:port: 8080spring:datasource:url: jdbc:mysql://127.0.0.1:3306/java_blog_spring?characterEncoding=utf8&useSSL=falseusername: rootpassword: BITE@yyds.666driver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:configuration:map-underscore-to-camel-case: true
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
logging:file:name: spring-blog.log
如果同时有三个yml
文件,通常只有主配置文件application.yml
会自动生效。为了使其他配置文件(如application-prod.yml
或application-dev.yml
)生效,需要在主配置文件application.yml
中进行相应的配置。具体步骤如下:
删除主配置文件中的数据库相关配置
: 在application.yml
中删除与数据库相关的配置项,以避免冲突。指定生效的配置文件
: 在application.yml
中添加配置,指定使用application-prod.yml
或application-dev.yml
作为生效的配置文件。
在Spring框架中,spring.profiles.active
属性用于指定激活的配置文件,application.yml
二选一即可:
spring:profiles:active: prod
spring:profiles:active: dev
这里的active
属性值填的是配置文件名的一部分
(如dev
、prod
等),而不是完整的文件名(如application-prod.yml
或application-dev.yml
)。
启动程序:
测试接口:
当前配置文件中的数据库密码是按照 Linux 系统的设置来配置的,与 Windows 系统的数据库密码不一致,从而导致接口访问失败:
在不同环境之间来回切换时,需要频繁修改配置文件中的active
值。在多人协作的场景下,很容易出现忘记修改active
值的情况,从而导致配置错误。
为了避免这种情况,我们可以通过从 Maven 中读取环境配置变量来为active
赋值:
<profiles><profile><id>dev</id><properties><profile.name>dev</profile.name></properties></profile><profile><id>prod</id><activation><activeByDefault>true</activeByDefault></activation><properties><profile.name>prod</profile.name></properties></profile>
</profiles>
注意,每次勾选新的 profile 都需要刷新 maven
修改 application.yml
spring:profiles:active: @profile.name@
勾选好 profile
后,刷新 maven,重新运行程序:
测试接口,此时接口访问成功:
构建项目并打包
在本地使用 Maven 进行打包:
- 如果 Test 代码中有与环境配置相关的操作(比如数据库相关的操作),打包会失败,可以跳过测试。
- 点击
clean -> package
。
将 dev
切换成 prod
,刷新 maven 并打包:
因为这个项目使用的是 mybatis-plus ,所以不需要写 mybatis 的测试用例,所以打包成功
:
如果使用的是
MyBatis
而非MyBatis-Plus
,就需要在单元测试
中编写 MyBatis 的接口测试代码
。在
Maven
的配置文件中,如果选择了prod
环境配置并刷新了 Maven
,然后按照生命周期
的package
命令进行打包,那么 Maven 会依次执行clean、validate、compile、test、package
阶段:在 Maven 的
test 阶段运行单元测试
时,由于配置的数据库密码与 Windows 系统的数据库密码不一致,导致 MyBatis 无法连接到数据库,从而使得单元测试失败
。
单元测试失败会中断 Maven 的打包过程,导致打包失败
。解决方案:在打包前,设置去掉 test 阶段,避免打包过程因为 test 的问题导致打包过程被打断:
接下来,根据日志路径,在本地找到打好的 Jar 包:
或者通过下面这个方法,找到在本地中打好的 Jar 包:
上传 Jar 包到服务器并运行
1. 上传 Jar 包
在 linux 系统中,创建和 windows 对应数据库及数据表
-- 建表 SQL
create database if not exists java_blog_spring charset utf8mb4;use java_blog_spring;-- 用户表
DROP TABLE IF EXISTS java_blog_spring.user_info;
CREATE TABLE java_blog_spring.user_info(
`id` INT NOT NULL AUTO_INCREMENT,
`user_name` VARCHAR (128) NOT NULL,
`password` VARCHAR (128) NOT NULL,
`github_url` VARCHAR (128) NULL,
`delete_flag` TINYINT (4) NULL DEFAULT 0,
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY (id),
UNIQUE INDEX user_name_UNIQUE (user_name ASC)) ENGINE = INNODB DEFAULT CHARACTER SET = utf8mb4 COMMENT = '用户表';-- 博客表
drop table if exists java_blog_spring.blog_info;
CREATE TABLE java_blog_spring.blog_info (
`id` INT NOT NULL AUTO_INCREMENT,
`title` VARCHAR(200) NULL,
`content` TEXT NULL,
`user_id` INT(11) NULL,
`delete_flag` TINYINT(4) NULL DEFAULT 0,
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY (id))
ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表';-- 新增用户信息
insert into java_blog_spring.user_info (user_name, password, github_url) values("zhangsan", "123456", "https://gitee.com/bubblefish666/class-java45");
insert into java_blog_spring.user_info (user_name, password, github_url) values("lisi", "123456", "https://gitee.com/bubblefish666/class-java45");insert into java_blog_spring.blog_info (title, content, user_id) values("第一篇博客", "111我是博客正文我是博客正文我是博客正文", 1);
insert into java_blog_spring.blog_info (title, content, user_id) values("第二篇博客", "222我是博客正文我是博客正文我是博客正文", 2);
为了能通过加密、加盐功能的密码校验,更新 linux 数据库表中,用户的密码:
update user_info set password= 'e5bf3de57e3243ab9d94b59b379a0a640f967f2e3ae738c2f5474ab0fe46389b' where id in(1,2);
直接拖动打好的 Jar 包到 Xshell 窗口即可完成文件的上传。
Xshell 可以直接拖动文件到窗口,达到上传文件的目的。如果使用其他客户端,不支持文件的上传,需要借助 lrzsz
命令;
借助 mv 改一下 jar 包名:
2. 运行程序
接下来,在 linux 上运行该 jar 包:
java -jar blog.jar
部署程序后,日志输出可能会非常频繁。如果使用以下命令启动程序:
java -jar blog.jar
那么在按下Ctrl+C
停止日志输出时,程序也会随之停止运行,导致服务无法继续提供
。为了避免这种情况,应使用以下命令启动程序:
nohup java -jar blog.jar &
nohup 命令详细介绍
这样,即使关闭终端或退出当前会话,程序仍能在后台 持续运行
,不会因Ctrl+C
操作而中断,从而确保服务的稳定性。
开放端口号
如果外网需要访问该服务,需要先服务器防火墙开放对应的端口号。
本着服务器安全的原则,云服务器上的端口非必要不开启
。比如常见端口号:数据库 3306、Redis 6379,尽可能避免开放,而是采用其他方式来连接,比如配置隧道
的方式。
确保列表中有添加的规则:
验证程序
-
访问项目:
http://IP:Port/blog_login.html
- 将
IP
改为云服务器的主机 IP
,Port
改为项目的端口号
。
- 将
-
按照项目功能进行验证:
-
验证账号注册登录。
-
验证展示博客列表。
-
验证博客编辑功能
-
验证新增博客。
-
验证展示博客内容。
-
…
-
跟踪日志
实时追踪日志
tail -f [日志文件名]
特性 | tail | tail -f |
---|---|---|
功能 | 显示文件的最后几行(默认10行) | 实时显示文件的最后几行,并持续更新 |
用途 | 用于查看文件的尾部内容 | 用于实时监控文件的动态更新 ,常用于日志文件 |
输出行为 | 输出文件的最后几行后即结束 | 输出文件的最后几行后,持续监控文件的新内容并实时显示 |
适用场景 | 查看静态文件的尾部内容 | 监控动态更新的日志文件 ,如服务器日志 |
命令格式 | tail [文件名] | tail -f [文件名] |
示例 | tail nohup.out | tail -f nohup.out |
是否实时 | 不实时 ,仅显示当前内容 | 实时 ,持续更新文件的新内容 |
退出方式 | 命令执行后自动退出 | 需手动按 Ctrl+C 退出 |
tail
:用于查看文件的最后几行,适合查看静态文件的内容。tail -f
:用于实时监控文件的更新
,适合查看动态更新
的日志文件,如服务器日志。
此时再访问接口,就会出现相关的日志:
过滤日志
我们关注的重点是 ERROR
级别的日志,而非 INFO
级别的日志。因此,可以使用以下命令来跟踪日志,直接过滤出 ERROR
级别的日志内容:
tail -f nohup.out | grep "ERROR"
如果需要停止当前的日志跟踪,可以按 Ctrl+C
,然后重新输入上述命令以继续跟踪。
过滤日志后,INFO
级别的日志不在显示,只显示 ERROR
级别的日志:
如果我们想看更具体的 ERROR
级别的日志,比如错误日志连带着的堆栈信息,可以使用如下命令:
tail -f nohup.out | grep -A 10 "ERROR"
# 看带有 ERROR 日志往下的十条信息
-A
查看后 n 行-B
查看前 n 行-C
查看前后 n 行
使用重定向将日志输出到自定义文件
如果想将输出的日志存储到自定义文件中,可以使用重定向操作
。
nohup java -jar blog.jar >指定文件路径 2>&1 &
例如:
nohup java -jar blog.jar >aa.log &more aa.log | grep "ERROR"
>
:将标准输出(日志信息)
重定向到指定文件
。2>&1
:将标准错误
也重定向到指定文件,确保所有输出都写入同一文件
。&
:将命令在后台运行,避免阻塞终端
。
在 Linux 中,>
操作符可以将命令的输出内容写入指定文件,这种操作称为“重定向”
配置日志存储文件
我们没有看见 jar 包同目录下,生成对应存储日志的 spring-blog.log
文件,但是我们配置文件中配置了:
后续发现,日志的格式配置错误了,纠正配置文件的 log 配置格式后,clean
一下,重新上传并运行新的 Jar 包。:
此时,在对应 Jar 包目录下,除了nohup.out
,还会生成一个名为spring-blog.log
的文件,专门用于存储服务生成的日志:
在程序启动前,日志默认存储在
nohup.out
文件中。一旦程序启动,根据配置文件的指定
,日志将存储到spring-blog.log
文件中。
因此,若要追踪日志
,应使用以下命令:
tail -f spring-blog.log | grep "ERROR"
而不是:
tail -f nohup.out | grep "ERROR"
常见问题
一个程序的正常运行,需要程序的正确
和环境的正确
。
同样的代码在 Windows 上可以运行成功,不一定在 Linux 上运行成功。不同的系统对代码的理解和支持是不同的。比如 Windows 系统对 MySQL 不区分大小写,Linux 区分大小写。
服务不能正常访问的原因有很多,主要分以下几个方面:
-
服务未启动
- 使用
ps -ef | grep java
查看程序是否在运行。 - 使用
curl http://127.0.0.1:8080/blog_login.html
看下是否有返回 HTML 页面。如果有返回,说明程序启动成功了,考虑端口未开放
。 - 如果未启动成功,需要查看对应的日志,根据原因来分析:
- 数据库不存在。
- 表不存在(区分大小写)。
- 数据库密码不正确。
- JDK 安装版本不对,或者未安装。
- MySQL 未设置密码。
- …
- 使用
-
HTTP 端口未开放
检查云服务器防火墙/安全组是否开放相应端口(如 8080)
。
杀掉进程
如果我们需要重启服务,或者重新部署等,都需要先停止之前的服务。
(1) 查看当前服务的进程
ps -ef | grep java
上图中的 35104
就是该服务的进程。
也可以在启动程序后,输入如下命令
curl http://127.0.0.1:8080/blog_login.html
(2) 杀掉进程
kill -9 PID
杀掉服务对应正在运行的进程,服务此时就不能再访问了:
再次运行 Jar 包:
总结
- 连接 Linux 服务器的方式有很多,Xshell 只是其中一种。
Xshell 是一个客户端,而非服务器
。 - Ubuntu 软件管理工具是
apt
,其他的 Linux 发行版本软件包管理工具不同,比如 CentOS 是使用yum
来管理软件的。 - Spring Boot 可以使用多个配置文件来完成不同平台的配置。
- 在 Windows 上可以运行成功的代码,在 Linux 上不一定能运行成功。
- 启动程序需要使用
nohup
后台运行,需要停止服务时,使用kill
命令。