【博客系统】博客系统第十一弹:从零开始在 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: 8080 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/java_blog_spring?characterEncoding=utf8&useSSL=false username: root password: 123456 # windows 数据库密码 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-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: 8080 spring: datasource: url: jdbc:mysql://127.0.0.1:3306/java_blog_spring?characterEncoding=utf8&useSSL=false username: root password: BITE@yyds.666 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-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赋值:
dev dev prod true prod
注意,每次勾选新的 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
跟踪日志
实时追踪日志
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 区分大小写。
服务不能正常访问的原因有很多,主要分以下几个方面:
-
服务未启动
杀掉进程
如果我们需要重启服务,或者重新部署等,都需要先停止之前的服务。
(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 命令。
-
-
-