Spring Boot与Docker的完美融合:从开发到部署的实战

一、Spring Boot与Docker简介

Spring Boot框架特点与优势概述

Spring Boot 是一个由Pivotal团队开发的用于简化新Spring应用初始搭建以及开发过程的框架。它的核心特点和优势包括:

  1. 简化配置:Spring Boot采用约定优于配置的方式,减少了大量的XML配置工作,通过自动配置功能极大地加速了应用的初始化。

  2. 独立运行:通过内嵌的Tomcat、Jetty或Undertow服务器,Spring Boot应用可以被打包成单一可执行的jar或war文件,只需java -jar命令即可启动应用。

  3. 开箱即用:提供了众多starter模块,只需引入相应的starter依赖就能快速集成第三方库和服务,如数据库连接、模板引擎、安全框架等。

  4. 健康检查与监控:内置Actuator模块,提供了应用健康状况、度量指标等多种监控功能。

  5. 微服务友好:易于与其他Spring Cloud组件配合,支持微服务架构体系下的服务注册与发现、负载均衡等功能。

Docker容器技术的基本原理与应用场景

Docker 是一个开源的应用容器引擎,基于Go语言开发,它实现了操作系统级别的虚拟化,允许开发者打包应用及其依赖包到一个可移植的容器中。

        1、容器化原理:Docker通过namespace实现资源隔离,利用cgroups进行资源限制和调度,结合联合文件系统(UnionFS)实现容器镜像层叠存储,从而达到轻量级虚拟化效果。

        2、容器优点

               环境一致性:每个Docker容器都包含应用运行所需的所有依赖,确保在不同环境下表现一致。

                高效便捷:相较于传统的虚拟机技术,Docker容器启动速度快、占用资源少。

                可移植性:容器可以在任意支持Docker的平台上运行,无需关心底层基础设施的具体细节。

        3、应用场景

                持续集成/持续部署(CI/CD):在DevOps流程中,Docker容器作为标准化交付单元,便于代码构建、测试和部署。

                微服务架构:每个微服务都可以封装在单独的容器中运行,易于管理和扩展。

                跨环境部署:开发、测试、生产环境的一致性保证,避免了“在我机器上能运行”的问题。

Spring Boot应用与Docker容器化部署的价值体现

当Spring Boot应用与Docker容器技术相结合时,产生的价值体现在以下几个方面:

  1. 标准化交付:Spring Boot应用通过Docker容器化后,形成统一的部署单元,不受宿主机环境差异的影响,提升了应用发布的可靠性和可重复性。

  2. 敏捷开发与部署:开发人员能够在本地通过Docker快速模拟生产环境,加速迭代速度。运维人员则可以通过简单的命令行操作部署或更新应用。

  3. 资源利用率提高:多个Docker容器可以在一台物理机或虚拟机上高效共存,充分利用系统资源,降低运维成本。

  4. 弹性伸缩与扩展:在云环境下,基于Docker的Spring Boot应用可轻易地进行横向扩容和缩容,满足业务需求的变化。

二、搭建Spring Boot项目

创建并配置Spring Boot应用项目

        1、创建项目:首先,使用Spring Initializr在线工具或者IDEA、Eclipse等集成开发环境的插件创建一个新的Spring Boot项目,根据业务需求选择合适的依赖项,例如Web、Data JPA、Security等。

Shell

# 在线创建项目,生成对应Maven或Gradle构建脚本
https://start.spring.io/

        2、基础配置:在项目中编写主要的Java类和配置文件,例如主启动类、实体类、控制器、服务类等。同时,配置application.properties或application.yml文件,设定应用的基本属性,如服务器端口、数据库连接等。

应用配置与环境分离

为了使Spring Boot应用更好地适应Docker部署,我们需要将应用配置与环境分离,采用以下方式:

  1. 多环境配置:在src/main/resources目录下,根据不同的环境(如dev, test, prod)创建对应的配置文件,如application-dev.properties、application-prod.properties,分别存放各环境的特定配置。

  2. 环境变量注入:在Spring Boot中,可以通过@Value注解或@ConfigurationProperties绑定环境变量。在Docker部署时,可以将环境变量注入到容器中,覆盖默认配置。

Properties

# application.properties
server.port=${PORT:8080}

优化项目结构,确保其适合容器化部署

  1. 资源文件处理:将应用所需的静态资源如HTML、CSS、JavaScript等文件放在指定的resources目录下,确保在容器内部可以正确访问。

  2. 日志配置:调整日志输出路径,使其指向Docker容器内的某个目录,便于日志管理和收集。

  3. 排除不必要的依赖:对构建过程中不需要的依赖进行剔除或优化,减少最终Docker镜像的大小。

  4. 配置Dockerignore文件:类似于.gitignore,用于忽略在构建Docker镜像时不需要包含的项目文件和目录。

通过这些准备工作,我们不仅能够创建和配置好Spring Boot应用项目,还确保了项目结构的合理化,使之更加适合后续的Docker容器化部署。

四、构建Spring Boot应用的Docker镜像

编写Dockerfile自定义镜像构建

Dockerfile是一个文本文件,其中包含了构建Docker镜像所需要的指令集合。下面是一个典型的用于构建Spring Boot应用的Dockerfile示例:

Dockerfile

# 使用官方提供的OpenJDK基础镜像
FROM openjdk:11-jdk-slim as builder# 设置工作目录
WORKDIR /app# 将本地的.mvn和pom.xml文件复制到容器的工作目录
COPY .mvn .mvn
COPY pom.xml .# 使用Maven下载依赖,利用缓存提高构建效率
RUN mvn dependency:go-offline# 复制整个项目源代码到容器
COPY src src# 在容器内编译并打包Spring Boot应用
RUN mvn package -DskipTests# 创建新的生产镜像层
FROM openjdk:11-jre-slim# 设置容器启动时的工作目录
WORKDIR /opt/app# 从构建阶段复制编译好的JAR包到生产镜像
COPY --from=builder /app/target/my-spring-boot-app.jar ./app.jar# 暴露应用运行所需端口
EXPOSE 8080# 定义容器启动时执行的命令
ENTRYPOINT ["java", "-jar", "/opt/app/app.jar"]# 可选:设置环境变量,例如数据库连接、端口等
# ENV SPRING_DATASOURCE_URL=jdbc:mysql://dbhost:port/dbname
# ENV SERVER_PORT=8080

Dockerfile中的关键指令详解

  • FROM: 指定基础镜像,这里是使用官方的OpenJDK镜像作为构建的基础。

  • WORKDIR: 设置Docker容器内的工作目录。

  • COPY: 用来将宿主机上的文件或目录复制到容器内的指定位置。

  • RUN: 执行命令,在构建镜像的过程中运行命令,比如这里的RUN mvn命令是用来编译和打包Spring Boot应用。

  • CMD: 定义容器启动时运行的默认命令,这里是启动Spring Boot应用。

  • EXPOSE: 声明容器对外暴露的端口,但并不真正打开端口,实际运行时还需映射到宿主机端口。

  • ENV: 设置环境变量,可以在容器内部使用这些环境变量。

执行Dockerfile构建镜像命令

使用以下命令构建Docker镜像:

Bash

docker build -t your-image-name .

其中:

  • -t 参数用于指定新镜像的名字和标签,例如 your-image-name 可以替换为实际的镜像名,如 mycompany/myapp:latest
  • . 表示Dockerfile所在的目录,Docker会从当前目录下查找Dockerfile并开始构建过程。

推送镜像到Docker Hub或私有仓库

构建完成后,如果要将镜像推送到公共的Docker Hub或私有的Docker仓库,首先需要登录到相应的仓库:

Bash

docker login [registry-url]

然后,将本地镜像推送到仓库:

Bash

docker push your-image-name

如果是私有仓库,请将 your-image-name 替换为完整的镜像仓库地址,如 myregistry.com/myrepo/myimage:tag

五、Spring Boot应用的Docker部署实践

使用Docker运行Spring Boot应用容器

在构建完Spring Boot应用的Docker镜像后,可以使用Docker命令运行一个容器来部署应用。这里涉及的主要参数有:

  • -p (或--publish):端口映射,用于将容器内部的服务端口映射到宿主机的端口。例如,如果你的应用在容器内部监听8080端口,你可以这样映射到宿主机的80端口:

    Bash
    docker run -p 80:8080 -d your-image-name

    这样外部请求到宿主机的80端口会被转发到容器内部的8080端口。

  • -v (或--volume):数据卷挂载,用于将宿主机目录与容器内部的目录进行绑定,实现数据持久化。例如,将宿主机的/data/logs目录挂载到容器内的/logs路径:

    Bash
    docker run -v /data/logs:/logs -d your-image-name
  • -e (或--env):设置环境变量,可以将应用运行时需要的环境变量传递给容器。例如,设置Spring Boot应用的配置项:

    Bash
    docker run -e SPRING_DATASOURCE_URL=jdbc:mysql://db_host:3306/db_name -d your-image-name

启动Spring Boot应用容器的Docker命令示例

综合上述参数,一个完整的启动Spring Boot应用容器的命令可能如下所示:

Bash

docker run -d \-p 80:8080 \-v /data/config:/config \-v /data/logs:/var/logs \-e SPRING_PROFILES_ACTIVE=prod \-e SPRING_DATASOURCE_URL=jdbc:mysql://db_host:3306/db_name \--name my-spring-boot-container \your-image-name

Docker Compose多容器编排实践

在实际环境中,往往需要部署多个相互依赖的服务,此时可以使用Docker Compose进行编排。

编写docker-compose.yml文件

Yaml

version: '3'
services:app:build: .image: your-image-nameports:- "80:8080"volumes:- /data/config:/config- /data/logs:/var/logsenvironment:- SPRING_PROFILES_ACTIVE=prod- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/db_namedepends_on:- dbdb:image: mysql:5.7environment:- MYSQL_ROOT_PASSWORD=root_password- MYSQL_DATABASE=db_namevolumes:- /data/mysql:/var/lib/mysql
使用docker-compose up启动服务

保存上述docker-compose.yml文件后,你可以在项目根目录下运行以下命令来启动所有服务:

Bash

docker-compose up -d

这里的-d参数表示在后台守护模式下运行容器。运行后,Docker Compose会根据yml文件的内容构建镜像(如果未指定镜像),然后启动并编排所有定义的服务。在上面的例子中,除了Spring Boot应用外,还有一个名为db的MySQL服务。

六、Spring Boot应用的持续集成与持续部署(CI/CD)

结合Jenkins或GitHub Actions实现自动化构建Docker镜像

Jenkins方案:

  1. 安装配置Jenkins:在服务器上安装并配置Jenkins,安装必要的插件,如Docker Pipeline插件、Git插件等。
  2. 创建Pipeline:在Jenkins中创建一个Pipeline项目,配置项目的源码管理(如Git仓库),并添加Pipeline脚本。
  3. 编写Jenkinsfile:在Spring Boot项目的根目录下编写Jenkinsfile,定义构建、测试、打包Docker镜像以及推送镜像到仓库等步骤。

Groovy

pipeline {agent anystages {stage('Checkout') {steps {git 'https://github.com/your-repo/your-spring-boot-app.git'}}stage('Build and Package') {steps {sh 'mvn clean package'}}stage('Build Docker Image') {steps {script {def customImage = docker.build("your-docker-registry/your-image-name:${env.BUILD_NUMBER}")}}}stage('Push Docker Image') {steps {script {withCredentials([usernamePassword(credentialsId: 'dockerhub-creds', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS')]) {customImage.push("${env.BUILD_NUMBER}")customImage.push("latest")}}}}}
}

GitHub Actions方案:

  1. 配置GitHub Actions Workflow:在Spring Boot项目的根目录下创建.github/workflows/docker-publish.yml文件,定义一个workflow。
  2. 编写Workflow YAML文件:配置一系列jobs和steps,用于拉取代码、构建Docker镜像、并将镜像推送到Docker registry。

Yaml

name: Docker Image CI/CDon:push:branches:- masterjobs:build-and-push-image:runs-on: ubuntu-lateststeps:- name: Checkout repositoryuses: actions/checkout@v2- name: Set up JDKuses: actions/setup-java@v2with:java-version: '11'- name: Build and push Docker imageenv:DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}run: |# Build the Docker imagedocker build -t your-docker-registry/your-image-name:${{ github.sha }} .docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORDdocker push your-docker-registry/your-image-name:${{ github.sha }}docker push your-docker-registry/your-image-name:latest

使用Kubernetes进行Spring Boot应用的容器编排和部署

一旦Docker镜像构建完成并推送到镜像仓库,就可以在Kubernetes集群中进行部署:

        1、配置Kubernetes Deployment:编写Deployment YAML文件,描述Pod副本数量、容器镜像、端口映射、环境变量等配置信息。

Yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: spring-boot-app-deployment
spec:replicas: 3selector:matchLabels:app: spring-boot-apptemplate:metadata:labels:app: spring-boot-appspec:containers:- name: spring-boot-containerimage: your-docker-registry/your-image-name:latestports:- containerPort: 8080env:- name: SPRING_DATASOURCE_URLvalueFrom:secretKeyRef:name: database-credentialskey: url

        2、创建Kubernetes Service:定义Service以暴露Pods,并进行负载均衡和服务发现。

Yaml

apiVersion: v1
kind: Service
metadata:name: spring-boot-app-service
spec:selector:app: spring-boot-appports:- protocol: TCPport: 80targetPort: 8080type: LoadBalancer

        3、应用部署:使用kubectl命令或通过Kubernetes Dashboard将上述YAML文件应用到集群中。

Bash

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

通过这样的流程,每次向代码仓库提交新的变更,都会触发CI/CD流程,自动构建Docker镜像并将其部署到Kubernetes集群,实现高效的持续集成与持续部署。

七、案例实战与问题解决

分享实际Spring Boot项目Docker化部署的完整流程

  1. 项目准备

    • 确保Spring Boot项目已具备Docker化部署的条件,如将应用配置与环境分离,优化项目结构。
    • 编写Dockerfile,定义构建镜像所需的步骤,包括基础镜像选择、复制项目文件、运行构建命令、设置容器入口点等。
  2. 构建Docker镜像

    • 使用docker build -t your-image-name .命令根据Dockerfile构建镜像。
  3. 运行和验证Docker容器

    • 运行容器:docker run -p 8080:8080 -d your-image-name,确保容器成功启动并且应用可通过端口映射正常访问。
    • 检查日志输出以确认应用是否启动成功,必要时通过docker logs <container-id>查看容器日志。
  4. 部署到生产环境

    • 如果使用Kubernetes,编写Deployment和Service YAML文件,并使用kubectl apply -f <manifest-file>命令部署到集群。
    • 或者,使用Docker Compose在单个节点或多节点环境中进行部署。
  5. 配置和优化

    • 设置必要的环境变量,如数据库连接字符串、密钥等。
    • 配置日志收集器,如使用fluentd或logstash将容器内日志导出到集中式日志系统。
    • 设置健康检查,通过Liveness Probe和Readiness Probe确保应用状态被准确监控。

遇到的典型问题及解决方案探讨

日志收集

问题:容器内的日志不易于收集和管理。

解决方案:

  • 在Dockerfile中设置应用程序的日志输出到标准输出(stdout/stderr)。
  • 在Kubernetes中配置日志驱动,将容器日志自动发送到ELK stack(Elasticsearch, Logstash, Kibana)或类似日志管理系统。
  • 使用sidecar容器模式,与主应用容器共享卷,将日志文件同步到sidecar容器中,sidecar容器负责将日志上传到云端存储或日志服务。
健康检查

问题:Kubernetes无法准确判断容器内部应用是否已准备好接收流量。

解决方案:

  • 在Spring Boot应用中启用Actuator健康检查端点,并在Kubernetes的Deployment中配置Liveness Probe和Readiness Probe,设置合适的HTTP GET请求路径和超时时间,让Kubernetes可以根据应用健康状态动态管理Pod。
网络配置

问题:容器间通信或容器与外部世界的通信存在问题。

解决方案:

  • 在Kubernetes中,可以通过Services提供服务发现和负载均衡,确保Pod间的通信。
  • 使用Ingress Controller提供外部访问的路由规则,处理来自公网的请求。
  • 若需容器直接访问外部网络资源,可能需要配置正确的DNS解析机制或直接在Docker容器中配置网络代理。

通过以上实战案例和问题解决方法,我们可以深入了解Spring Boot应用在Docker化部署过程中可能会遇到的问题,并学习如何有效解决这些问题,从而实现应用的稳定、高效部署。

八、总结与展望

Spring Boot应用Docker化部署的关键环节和最佳实践总结

  1. 关键环节

    • 项目优化:确保Spring Boot项目结构简洁、配置分离、资源适配容器环境。
    • Dockerfile构建:精心编写Dockerfile,精简镜像体积,遵循分层构建原则,合理设置环境变量、端口映射和卷挂载。
    • 镜像发布:自动化构建并通过Docker Registry发布镜像,实现版本控制和回滚能力。
    • 容器化部署:利用Docker命令行或编排工具(如Docker Compose、Kubernetes)进行容器部署,设置健康检查、日志收集等运维策略。
    • CI/CD流程:结合Jenkins、GitHub Actions等工具,实现从代码提交到应用上线的全流程自动化。
  2. 最佳实践

    • 最小化镜像:仅包含运行应用所必需的组件,避免无谓的额外软件。
    • 环境无关性:通过环境变量传递配置,确保应用在任何环境下都能运行。
    • 日志管理:将日志输出到标准输出,方便通过Docker log驱动统一收集。
    • 滚动升级与蓝绿部署:利用Kubernetes的滚动更新策略和部署策略,保证应用更新过程中的服务连续性和高可用性。

探讨云原生时代下Spring Boot与Docker技术的进一步融合趋势

随着云原生技术的发展,Spring Boot与Docker的融合日益紧密,未来的趋势可能包括:

  1. 容器运行时标准化:Docker作为容器标准的一部分,将进一步推动与Kubernetes、Containerd等容器运行时环境的兼容性和互操作性,使得Spring Boot应用在不同平台上的部署更为便捷。

  2. Serverless架构:Spring Boot应用将更容易通过容器技术与无服务器架构(如Knative、AWS Lambda等)结合,实现按需自动扩缩容和成本优化。

  3. 服务网格与Sidecar模式:随着Istio、Linkerd等服务网格技术的发展,Spring Boot应用通过与Docker容器配合,将更有效地参与到服务治理、熔断限流、链路追踪等微服务场景中。

  4. 可观测性增强:Spring Boot应用借助容器环境,能够更好地集成Prometheus、Grafana等监控工具,提升系统的可观测性和故障排查能力。

  5. 持续优化与创新:随着Spring Boot生态与Docker生态系统持续演进,双方将在安全性、性能优化、资源管理等方面深化合作,共同推进云原生应用的成熟与发展。

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

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

相关文章

深度学习入门(3)

一、感知机 感知机接收多个输入信号&#xff0c;输出一个信号。这里所说的“信号”可以想象成电流或河流那样具备“流动性”的东西。 但是&#xff0c;和实际的电 流不同的是&#xff0c;感知机的信号只有“流 / 不流”&#xff08; 1 / 0 &#xff09;两种取值。在本书中&…

【研发日记】Matlab/Simulink软件优化(一)——动态内存负荷压缩

文章目录 背景介绍 初始代码 优化代码 分析和应用 总结 背景介绍 在一个嵌入式软件开发项目中&#xff0c;有一个使用MATLAB Function编写的算法模块&#xff0c;功能是从一个较大的数组中提取一段数据&#xff0c;然后求均值输出&#xff0c;示例如下&#xff1a; 初始代…

Python和Java哪个更适合后端开发?

Python和Java都是强大的后端开发语言&#xff0c;它们各自有鲜明的特点和适用场景。选择哪一个更适合后端开发&#xff0c;主要取决于具体的项目需求、团队技术栈、个人技能偏好以及长期发展考虑等因素。 下面是两者在后端开发中的优势和劣势&#xff1a; 「Python&#xff1…

Maven超详细使用

定义 是一款用于管理和构建java项目的工具 作用 1. 依赖管理 2. 统一项目结构 3. 项目构建 项目目录结构 POM 项目对象模型 (Project Object Model) POM (Project Object Model) &#xff1a;指的是项目对象模型&#xff0c;用来描述当前的maven项目。 仓库 本地仓库&#…

ElasticSearch nested 字段多关键字搜索,高亮全部匹配关键字的处理

ElasticSearch nested 字段多关键字搜索&#xff0c;高亮全部匹配关键字的处理 环境介绍 ElasticSearch 版本号: 6.7.0 需求说明 用户会传入多个关键字去ES查询ElasticSearch nested 字段 的多个字段&#xff0c;要求在返回的结果中被搜索的字段需要高亮所有匹配的关键字。…

银河麒麟高级服务器操作系统adb读写缓慢问题分析

1.问题环境 处理器&#xff1a; HUAWEI Kunpeng 920 5251K 内存&#xff1a; 512 GiB 整机类型/架构&#xff1a; TaiShan 200K (Model 2280K) BIOS版本&#xff1a; Byosoft Corp. 1.81.K 内核版本 4.19.90-23.15.v2101.ky10.aarch64 第三方应用 数据库 2.问题…

【脚本】JAVA 执行 阿里QLExpress 动态脚本 demo 进阶版 增加项目灵活性

【脚本】JAVA 执行 阿里QLExpress 脚本 demo 进阶版 测试demo import com.ql.util.express.DefaultContext;public class QlExpressTest {public static void main(String[] args) throws Exception {QLExpressManager qlExpressManager new QLExpressManager();DefaultConte…

苹果个人证书管理

根据近日工业和信息化部发布的《工业和信息化部关于开展移动互联网应用程序备案工作的通知》&#xff0c;相信不少要进行IOS平台App备案的朋友遇到了一个问题&#xff0c;就是apple不提供云管理式证书的下载&#xff0c;也就无法获取公钥及证书SHA-1指纹。 已经上架的应用不想重…

瑞芯微RK3568/RK3588+鸿蒙,矿鸿工控屏、矿鸿工控板、矿鸿网关,推动矿业数智化变革

4月10日至12日&#xff0c;以“绿色智能创新&#xff0c;携手共赢未来”为主题的第二届中国国际矿业装备与技术展览会在西安举行。信迈科技携矿鸿解决方案及产品亮相&#xff0c;赋能矿山行业数智化升级和国产化改造进程全面提速。 作为华为矿山军团矿鸿生态使能合作伙伴&#…

【位运算】3097. 或值至少为 K 的最短子数组 II

本文涉及知识点 位运算 LeetCode3097. 或值至少为 K 的最短子数组 II 给你一个 非负 整数数组 nums 和一个整数 k 。 如果一个数组中所有元素的按位或运算 OR 的值 至少 为 k &#xff0c;那么我们称这个数组是 特别的 。 请你返回 nums 中 最短特别非空 子数组 的长度&…

数据可视化-ECharts Html项目实战(10)

在之前的文章中&#xff0c;我们学习了如何在ECharts中编写雷达图&#xff0c;实现特殊效果的插入运用&#xff0c;函数的插入&#xff0c;以及多图表雷达图。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&…

国内免费中文版ChatGPT网站入口(2024/4/15)

首先向大家介绍一些基本信息&#xff1a;ChatGPT3.5在官方网站上是可以免费使用的&#xff0c;而ChatGPT4.0则采取按月收费的模式&#xff0c;价格为20美元&#xff08;约合140元人民币&#xff09;。因此&#xff0c;所谓的免费使用主要指的是GPT3.5。如果有人声称GPT4.0也是免…

vite+vue3+antDesignVue 记录-持续记录

记录学习过程 持续补充 每天的学习点滴 开始时间2024-04-12 1&#xff0c;报错记录 &#xff08;1&#xff09;env.d.ts文件 解决方法&#xff1a; 在env.d.ts文件中添加以下代码&#xff08;可以看一下B站尚硅谷的讲解视频&#xff09; declare module *.vue {import { Defi…

关于centos8自带的apache2.4开启https后,XP系统的IE8无法显示网页的问题

经检验&#xff0c;是因为系统的apache和openssl版本太高导致的。 禁用系统默认的apache2.4&#xff0c;自己重新源码编译安装一套openssl-1.0.1fapache2.2.23php7.1.2即可。跟update-crypto-policies没有关系&#xff0c;可保持默认的DEFAULT状态。 关于centos8自带的apache2…

数据结构从入门到实战——顺序表

目录 前言 一、顺序表的概念及结构 1.1 线性表 二、顺序表分类 三、动态顺序表的实现 3.1 顺序表结构的创建以及初始化 3.2 顺序表的销毁 3.3 顺序表的打印 3.4 尾插数据 ——最困难的 3.5 头插数据 3.6 尾删数据 3.7 头部删除数据 前言 在计算机科学和数据结…

不饱和脂肪酸的综述

1.概述 不饱和脂肪酸是一类脂肪酸&#xff0c;其碳链上存在双键&#xff08;不饱和键&#xff09;。根据双键的数量和位置&#xff0c;不饱和脂肪酸可以进一步分为以下两类&#xff1a; 单不饱和脂肪酸&#xff08;Monounsaturated fatty acids&#xff0c;简称MUFA&#xff0…

excel添加折线图,如何将日期作为横坐标?

就这么两列数据&#xff0c;想添加一个以日期为横坐标的折线图&#xff0c;但是出来的折线是这个样子&#xff0c;切换行/列也不行&#xff0c;怎么办呢&#xff1f; 实际上这个折线图中包括两条折线&#xff0c;蓝色的是日期的折线&#xff0c;橙色的是时间的折线&#xff0c;…

夜月一帘幽梦,春风十里“三指针法“ (链表面试题篇2)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能接…

第 6 章 URDF、Gazebo与Rviz综合应用(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 6.7 URDF、Gazebo与Rviz综合应用 关于URDF(Xacro)、Rviz 和 Gazebo 三者的关系&#xff0c;前面已有阐述&…

无人机三维建模对光伏测绘的影响有多大?

在光伏电站建设前期阶段&#xff0c;需要对选址地点进行测绘&#xff0c;人工测绘容易出现数据不准确、信息共享不畅等缺陷。随着科技的快速发展以及无人机技术的不断提升&#xff0c;许多光伏企业选择借助无人机进行测绘工作&#xff0c;快速生成三维建模&#xff0c;提高测绘…