【博客系统】博客系统第十一弹:从零开始在 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

注意:

  • 此处安装的是 OpenJDK,OpenJDK 是一个开源版本的 JDK,和 Oracle 官方的 JDK 略有差别。此处我们就使用 OpenJDK 即可。安装 Oracle JDK 比较麻烦。
  • 使用 java -version 验证是否安装成功。
  • 如果提示 “java 命令找不到” 则说明安装失败。

image-20250529160653334


3. 卸载 OpenJDK


  1. 检查安装的是哪个 OpenJDK

    dpkg --list | grep -i jdk
    
  2. 移除 OpenJDK 包

    apt-get purge openjdk*
    
  3. 卸载 OpenJDK 相关包

    apt-get purge icedtea-* openjdk-*
    
  4. 检查所有 OpenJDK 包是否都已卸载完毕

    dpkg --list | grep -i jdk
    

MySQL


使用 apt 安装 MySQL


  1. 查找安装包

    apt list | grep "mysql-server"
    
  2. 安装 MySQL

    sudo apt install mysql-server
    

查看 MySQL 状态


sudo systemctl status mysql

image-20250529161153518


MySQL 安装安全设置


默认的 MySQL 设置是不安全的,MySQL 安装提供了一个安全脚本,用于解决不太安全的默认选项。


运行以下命令:

sudo mysql_secure_installation #安装安全设置

执行过程:

  1. 是否设置验证密码组件:

    Press y|Y for Yes, any other key for No: Y #是否设置验证密码组件
    
  2. 密码强度设置:

    Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2 #设置密码强度
    
  3. 删除匿名用户:

    Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y #默认情况下,MySQL安装有一个匿名用户, 允许任何人登录MySQL. 是否删除匿名用户?
    
  4. 禁止 root 用户远程登录:

    Disallow root login remotely? (Press y|Y for Yes, any other key for No) : Y #仅应允许root从'localhost'连接
    
  5. 删除 test 数据库:

    Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y #默认情况下, MySQL带有⼀个test数据库, 是否删除?
    
  6. 重新加载权限表:

    Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y #是否现在加载配置, 使刚才的修改生效?
    
  7. 完成:

    All done!
    

通过以上步骤,MySQL 的安全设置已经完成,确保了数据库的安全性。设置密码


连接 MySQL 服务器


sudo mysql

使用 ALTER USER 命令修改密码


ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'BITE@yyds.666';

退出 MySQL


exit

image-20250529164241001


再次登录输入:

mysql -uroot -p   #  密码: BITE@yyds.666

卸载 MySQL


  1. 停止 MySQL
sudo systemctl stop mysql

  1. 卸载 MySQL
sudo apt-get remove --purge mysql-server mysql-client mysql-common

  1. 删除 MySQL 配置文件和数据
sudo rm -rf /etc/mysql /var/lib/mysql

  1. 清理残留文件和目录
sudo apt-get autoremove
sudo apt-get autoclean

  1. 验证卸载结果
mysql --version

部署 Web 项目到 Linux


环境配置


确保程序正常运行需完成以下配置:

  1. 数据库准备

    • 执行提供的建表脚本,确保表结构与服务器一致
  2. 多环境配置

    • 按环境创建配置文件(如开发/测试/生产环境)
    • 命名格式:application-XXX.ymlapplication-XXX.properties
    • 差异化配置项示例:MySQL账号密码、服务端口等

关键点:通过文件命名区分环境,避免硬编码敏感信息。


以下以application-XXX.yml为例:

application-dev.yml: 开发环境配置

image-20250529175414319

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: 生产环境配置

image-20250529175444889

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.ymlapplication-dev.yml)生效,需要在主配置文件application.yml中进行相应的配置。具体步骤如下:

  1. 删除主配置文件中的数据库相关配置: 在application.yml中删除与数据库相关的配置项,以避免冲突。
  2. 指定生效的配置文件: 在application.yml中添加配置,指定使用application-prod.ymlapplication-dev.yml作为生效的配置文件。

image-20250529175812878

在Spring框架中,spring.profiles.active属性用于指定激活的配置文件,application.yml 二选一即可:

spring:profiles:active: prod    
spring:profiles:active: dev

这里的active属性值填的是配置文件名的一部分(如devprod等),而不是完整的文件名(如application-prod.ymlapplication-dev.yml)。


启动程序:

image-20250530103902446


测试接口:

image-20250529182232839


当前配置文件中的数据库密码是按照 Linux 系统的设置来配置的,与 Windows 系统的数据库密码不一致,从而导致接口访问失败:

image-20250529182539655


在不同环境之间来回切换时,需要频繁修改配置文件中的active值。在多人协作的场景下,很容易出现忘记修改active值的情况,从而导致配置错误。

为了避免这种情况,我们可以通过从 Maven 中读取环境配置变量来为active赋值:

image-20250529184152481

<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@

image-20250529185215864


勾选好 profile 后,刷新 maven,重新运行程序:

image-20250529185507098


测试接口,此时接口访问成功:

image-20250529184623409


构建项目并打包


在本地使用 Maven 进行打包:

  1. 如果 Test 代码中有与环境配置相关的操作(比如数据库相关的操作),打包会失败,可以跳过测试。
  2. 点击 clean -> package

dev 切换成 prod,刷新 maven 并打包:

image-20250529190134939


因为这个项目使用的是 mybatis-plus ,所以不需要写 mybatis 的测试用例,所以打包成功

image-20250529192016934

  • 如果使用的是 MyBatis 而非 MyBatis-Plus,就需要在单元测试中编写 MyBatis 的接口测试代码

  • Maven 的配置文件中,如果选择了prod环境配置并刷新了 Maven,然后按照生命周期package命令进行打包,那么 Maven 会依次执行clean、validate、compile、test、package阶段:image-20250529191432762

  • 在 Maven 的 test 阶段运行单元测试时,由于配置的数据库密码与 Windows 系统的数据库密码不一致,导致 MyBatis 无法连接到数据库,从而使得单元测试失败

  • 单元测试失败会中断 Maven 的打包过程,导致打包失败

  • 解决方案:在打包前,设置去掉 test 阶段,避免打包过程因为 test 的问题导致打包过程被打断:image-20250529191733447

接下来,根据日志路径,在本地找到打好的 Jar 包:

image-20250529192828340


上传 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);

image-20250529193626767


直接拖动打好的 Jar 包到 Xshell 窗口即可完成文件的上传。

image-20250529194002503

Xshell 可以直接拖动文件到窗口,达到上传文件的目的。如果使用其他客户端,不支持文件的上传,需要借助 lrzsz 命令;


借助 mv 改一下 jar 包名:

image-20250529194152710


2. 运行程序


接下来,在 linux 上运行该 jar 包:

java -jar blog.jar

image-20250529194511729

部署程序后,日志输出可能会非常频繁。如果使用以下命令启动程序:

java -jar blog.jar

那么在按下Ctrl+C停止日志输出时,程序也会随之停止运行,导致服务无法继续提供。为了避免这种情况,应使用以下命令启动程序:

nohup java -jar blog.jar &

nohup 命令详细介绍

这样,即使关闭终端或退出当前会话,程序仍能在后台 持续运行,不会因Ctrl+C操作而中断,从而确保服务的稳定性。


开放端口号


如果外网需要访问该服务,需要先服务器防火墙开放对应的端口号。

本着服务器安全的原则,云服务器上的端口非必要不开启。比如常见端口号:数据库 3306、Redis 6379,尽可能避免开放,而是采用其他方式来连接,比如配置隧道的方式。

image-20250529204038344


image-20250529204120904


确保列表中有添加的规则:

image-20250529204159836


验证程序


  1. 访问项目:http://IP:Port/blog_login.html

    • IP 改为云服务器的 IP,Port 改为项目的端口号。
  2. 按照项目功能进行验证:

    • 验证账号注册登录。image-20250529204225810

    • 验证展示博客列表。image-20250529204310510

    • 验证博客编辑功能image-20250529204430024

    • 验证新增博客。image-20250529204506265

    • 验证展示博客内容。image-20250529204453371

      image-20250530104741094


跟踪日志


实时追踪日志


tail -f [日志文件名]

image-20250530112349734


此时再访问接口,就会出现相关的日志:

image-20250530112514553


过滤日志


我们关注的重点是 ERROR 级别的日志,而非 INFO 级别的日志。因此,可以使用以下命令来跟踪日志,直接过滤出 ERROR 级别的日志内容:

tail -f nohup.out | grep "ERROR"

如果需要停止当前的日志跟踪,可以按 Ctrl+C,然后重新输入上述命令以继续跟踪。


过滤日志后,INFO级别的日志不在显示,只显示 ERROR级别的日志:

image-20250530113205342


使用重定向将日志输出到自定义文件


如果想将输出的日志存储到自定义文件中,可以使用重定向操作

nohup java -jar blog.jar >指定文件路径 2>&1 &
  • >:将标准输出(日志信息)重定向到指定文件
  • 2>&1:将标准错误也重定向到指定文件,确保所有输出都写入同一文件
  • &将命令在后台运行,避免阻塞终端

例如:

nohup java -jar blog.jar >aa.log &more aa.log | grep "ERROR"

在 Linux 中,>操作符可以将命令的输出内容写入指定文件,这种操作称为“重定向”


配置日志存储文件


我们没有看见 jar 包同目录下,生成对应存储日志的 spring-blog.log 文件,但是我们配置文件中配置了:

image-20250530115314750


后续发现,日志的格式配置错误了,纠正配置文件的 log 配置格式后,clean一下,重新上传并运行新的 Jar 包。:

image-20250530114205753


此时,在对应 Jar 包目录下,除了nohup.out,还会生成一个名为spring-blog.log的文件,专门用于存储服务生成的日志:

image-20250530115540628

在程序启动前,日志默认存储在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 查看程序是否在运行。
    • 使用 curl http://127.0.0.1:8080/blog_login.html 看下是否有返回 HTML 页面。如果有返回,说明程序启动成功了,考虑端口未开放。
    • 如果未启动成功,需要查看对应的日志,根据原因来分析:
      • 数据库不存在。
      • 表不存在(区分大小写)。
      • 数据库密码不正确。
      • JDK 安装版本不对,或者未安装。
      • MySQL 未设置密码。
  2. HTTP 端口未开放

    • 检查云服务器防火墙/安全组是否开放相应端口(如 8080)

杀掉进程


如果我们需要重启服务,或者重新部署等,都需要先停止之前的服务。

(1) 查看当前服务的进程

ps -ef | grep java

image-20250530130621426

上图中的 35104 就是该服务的进程。


(2) 杀掉进程

kill -9 PID

image-20250530130854027


杀掉服务对应正在运行的进程,服务此时就不能再访问了:

image-20250530131532681


再次运行 Jar 包:

image-20250530131508349


总结


  1. 连接 Linux 服务器的方式有很多,Xshell 只是其中一种。Xshell 是一个客户端,而非服务器
  2. Ubuntu 软件管理工具是 apt,其他的 Linux 发行版本软件包管理工具不同,比如 CentOS 是使用 yum 来管理软件的。
  3. Spring Boot 可以使用多个配置文件来完成不同平台的配置。
  4. 在 Windows 上可以运行成功的代码,在 Linux 上不一定能运行成功。
  5. 启动程序需要使用 nohup 后台运行,需要停止服务时,使用 kill 命令。

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/84971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能外呼系统中 NLP 意图理解的工作原理与技术实现

智能外呼系统通过整合语音识别&#xff08;ASR&#xff09;、自然语言处理&#xff08;NLP&#xff09;和语音合成&#xff08;TTS&#xff09;等技术&#xff0c;实现了自动化的电话交互。其中&#xff0c;NLP 意图理解是核心模块&#xff0c;负责解析用户话语中的语义和意图&…

Sigma-Aldrich胰蛋白酶细胞解离方案速览

Sigma-Aldrich_胰蛋白酶用于细胞培养 细胞解离是细胞传代过程中的一个步骤&#xff0c;即细胞从预处理表面分离&#xff0c;形成悬浮液。这些悬浮液对于传代培养重新接种、细胞计数分析和细胞增殖非常重要。有多种蛋白水解酶可用来从粘附基质上脱离细胞&#xff0c;胰蛋白酶就…

宝塔安装WordPress程序

宝塔安装WordPress程序 一、提前准备1&#xff0c;下载WordPress2&#xff0c;在宝塔创建站点 二、部署项目1&#xff0c;上传下载的wordpress压缩包至创建的项目根目录下并解压 三、wordpress安装1&#xff0c;在浏览器打开创建的网站2&#xff0c;开始按照流程安装配置数据库…

【LangChain】框架解析

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1fa79; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f9e0; 一、技术原理剖析&#x1f4ca; 核心架构图解&#x1f4a1; 核心作用讲解&#x1f527; 关键技术模块说明⚖️ 技术选…

百度之星2024 初赛第一场 补给

百度之星2024 初赛第一场 补给 题干描述问题分析&#xff1a;C代码Java代码&#xff1a;Python代码补充说明&#xff1a; 题干描述 参考自马蹄集OJ&#xff0c;原文链接1 可怕的战争发生了&#xff0c;小度作为后勤保障工作人员&#xff0c;也要为了保卫国家而努力。 现在有 …

JavaScripts console.log和console.dir区别

console.log 和 console.dir 都是 JavaScript 中用于在浏览器控制台打印信息的方法 &#xff0c;二者主要有以下区别&#xff1a; 输出内容和格式 console.log&#xff1a;主要用于输出简单的日志信息&#xff0c;直接打印数据的字符串表示 。对于对象、数组等引用类型&#…

uniapp 开发企业微信小程序时,如何在当前页面真正销毁前或者关闭小程序前调用一个api接口

在 UniApp 开发企业微信小程序时&#xff0c;若需在页面销毁或小程序关闭前调用 API 接口&#xff0c;需结合页面生命周期和应用生命周期实现。以下是具体实现方案及注意事项&#xff1a; 一、在页面销毁前调用 API&#xff08;页面级&#xff09; 通过页面生命周期钩子 onUnl…

聊聊 Metasploit 免杀

各位小伙伴们&#xff0c;晚上好&#xff01; 咱们今天打开宵夜“安全食材箱”&#xff0c;聊聊渗透测试绕过杀毒&#xff08;免杀&#xff09;的那些门道。你可以把免杀理解为——深夜做宵夜时&#xff0c;家里有人睡觉&#xff0c;但你非得去厨房整点美食&#xff0c;还不能…

Android高级开发第二篇 - JNI 参数传递与 Java → C → Java 双向调用

文章目录 Android高级开发第二篇 - JNI 参数传递与 Java → C → Java 双向调用引言JNI基础回顾JNI中的参数传递基本数据类型传递字符串传递数组传递对象传递 Java → C → Java 双向调用从C/C调用Java方法实现一个完整的回调机制 内存管理与注意事项性能优化提示结论参考资源 …

2025-05-28 Python深度学习8——优化器

文章目录 1 工作原理2 常见优化器2.1 SGD2.2 Adam 3 优化器参数4 学习率5 使用最佳实践 本文环境&#xff1a; Pycharm 2025.1Python 3.12.9Pytorch 2.6.0cu124 ​ 优化器 (Optimizer) 是深度学习中的核心组件&#xff0c;负责根据损失函数的梯度来更新模型的参数&#xff0c;使…

Web攻防-SQL注入增删改查HTTP头UAXFFRefererCookie无回显报错

知识点&#xff1a; 1、Web攻防-SQL注入-操作方法&增删改查 2、Web攻防-SQL注入-HTTP头&UA&Cookie 3、Web攻防-SQL注入-HTTP头&XFF&Referer 案例说明&#xff1a; 在应用中&#xff0c;存在增删改查数据的操作&#xff0c;其中SQL语句结构不一导致注入语句…

Windows MongoDB C++驱动安装

MongoDB驱动下载 MongoDB 官网MongoDB C驱动程序入门MongoDB C驱动程序入门 安装环境 安装CMAKE安装Visual Studio 编译MongoDB C驱动 C驱动依赖C驱动&#xff0c;需要先编译C驱动 下载MongoDB C驱动源码 打开CMAKE(cmake-gui) 选择源码及输出路径,然后点击configure …

使用 C/C++ 和 OpenCV 调用摄像头

使用 C/C 和 OpenCV 调用摄像头 &#x1f4f8; OpenCV 是一个强大的计算机视觉库&#xff0c;它使得从摄像头捕获和处理视频流变得非常简单。本文将指导你如何使用 C/C 和 OpenCV 来调用摄像头、读取视频帧并进行显示。 准备工作 在开始之前&#xff0c;请确保你已经正确安装…

使用微软最近开源的WSL在Windows上优雅的运行Linux

install wsl https://github.com/microsoft/WSL/releases/download/2.4.13/wsl.2.4.13.0.x64.msi install any distribution from microsoft store, such as kali-linux from Kali office website list of distribution PS C:\Users\50240> wsl -l -o 以下是可安装的有…

Win11安装Dify

1、打开Virtual Machine Platform功能 电脑系统为&#xff1a;Windows 11 家庭中文版24H2版本。 打开控制面板&#xff0c;点击“程序”&#xff0c;点击“启用或关闭Windows功能”。 下图标记的“Virtual Machine Platform”、“适用于 Linux 的 Windows 子系统”、“Windows…

C++模板类深度解析与气象领域应用指南

支持开源&#xff0c;为了更好的后来者 ————————————————————————————————————————————————————By 我说的 C模板类深度解析与气象领域应用指南 一、模板类核心概念 1.1 模板类定义 模板类是C泛型编程的核心机制&#x…

MongoDB(七) - MongoDB副本集安装与配置

文章目录 前言一、下载MongoDB1. 下载MongoDB2. 上传安装包3. 创建相关目录 二、安装配置MongoDB1. 解压MongoDB安装包2. 重命名MongoDB文件夹名称3. 修改配置文件4. 分发MongoDB文件夹5. 配置环境变量6. 启动副本集7. 进入MongoDB客户端8. 初始化副本集8.1 初始化副本集8.2 添…

mac笔记本如何快捷键截图后自动复制到粘贴板

前提&#xff1a;之前只会进行部分区域截图操作&#xff08;commandshift4&#xff09;操作&#xff0c;截图后发现未自动保存在剪贴板&#xff0c;还要进行一步手动复制到剪贴板的操作。 mac笔记本如何快捷键截图后自动复制到粘贴板 截取 Mac 屏幕的一部分并将其自动复制到剪…

WPF 按钮点击音效实现

WPF 按钮点击音效实现 下面我将为您提供一个完整的 WPF 按钮点击音效实现方案&#xff0c;包含多种实现方式和高级功能&#xff1a; 完整实现方案 MainWindow.xaml <Window x:Class"ButtonClickSound.MainWindow"xmlns"http://schemas.microsoft.com/win…

C++ list基础概念、list初始化、list赋值操作、list大小操作、list数据插入

list基础概念&#xff1a;list中的每一部分是一个Node&#xff0c;由三部分组成&#xff1a;val、next、prev&#xff08;指向上一个节点的指针&#xff09; list初始化的代码&#xff0c;见下 #include<iostream> #include<list>using namespace std;void printL…