Docker Compose 部署若依前后端分离版

news2024/12/24 3:15:27

准备一台服务器

本次使用虚拟机,虚拟机系统 Ubuntu20.04,内存 4G,4核。
确保虚拟机能连接互联网。

Ubuntu20.04 安装 Docker

添加 Docker 的官方 GPG key:

sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

添加仓库到 apt 中:

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

  sudo apt-get update

安装最新版本的 Docker:

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

docker-compose-plugin 就是 Docker Compose,上面的命令就安装了 Docker Compose

配置 Docker 镜像仓库:

sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": ["https://mirror.baidubce.com"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

# 使用 Docker info 命令查看配置的加速仓库
docker info

启动一个 Hello World 容器测试 Docker 是否安装成功:

sudo docker run hello-world

看到如下内容就是安装成功:
image.png

使用如下命令查看 Docker 的版本以及 Docker Compose 的版本:

docker version
docker compose version

配置 Docker 命令可以使用非 Root 用户使用:

# 创建名为 docker 的用户组
sudo groupadd docker

# 将当前用户添加到 docker 用户组中
sudo usermod -aG docker $USER

# 激活
newgrp docker

# 验证非 Root 用户是否能使用 Docker 命令
docker run hello-world

配置 Docker 开机自启:

sudo systemctl enable docker.service
sudo systemctl enable containerd.service

# 关闭 Docker 开机自启
sudo systemctl disable docker.service
sudo systemctl disable containerd.service

打 ruoyi 后端的镜像

做必要的配置修改

image.png
image.png

master:
    url: jdbc:mysql://mysql-service:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&connectTimeout=1000&socketTimeout=30000&autoReconnect=true&failOverReadOnly=false
    username: ruoyi
    password: 123456

image.png

编写 Dockerfile 文件

# 使用官方的 OpenJDK 8 镜像作为基础镜像
FROM openjdk:8-jdk-alpine
# 创建存放上传文件的目录
RUN mkdir -p /opt/project/ruoyi/ruoyi-backend/upload-file-path
# 创建存放日志的目录
RUN mkdir -p /opt/project/ruoyi/ruoyi-backend/logs
# 安装字体文件
RUN mkdir -p /etc/apk/
RUN touch /etc/apk/repositories
RUN echo -e 'https://mirrors.aliyun.com/alpine/v3.6/main/\nhttps://mirrors.aliyun.com/alpine/v3.6/community/' > /etc/apk/repositories
RUN apk --no-cache add ttf-dejavu fontconfig
RUN set -xe && apk --no-cache add ttf-dejavu fontconfig
# 设置工作目录
WORKDIR /opt/project/ruoyi/ruoyi-backend
# 将构建好的 JAR 文件复制到容器中
COPY ./ruoyi-admin/target/ruoyi-admin.jar ruoyi-admin.jar
# 暴露应用程序端口
EXPOSE 8080
# 启动应用程序
CMD ["nohup","java","-jar","/opt/project/ruoyi/ruoyi-backend/ruoyi-admin.jar", ">", "/opt/project/ruoyi/ruoyi-backend/logs/nohup.log", "&"]

IDEA 连接虚拟机中的 Docker 并打镜像

首先,检查 IDEA 是否安装了 Docker 插件:
image.png
版本比较新的 IDEA 默认都安装了这个插件,如果没有安装,安装一下。
确保我们虚拟机上安装了 Docker 和 Docker-compose,并启动了 Docker。
找到 IDEA 下方的 Services tab 栏,按照如下操作新建一个 Docker 连接:
image.png
配置连接 Docker 的 SSH 连接:
image.png
如果按照下面通过 password 认证连接 docker,idea 会显示 “Only key-pair ssh auth type is supported for docker connectons”:
image.png

所以需要改为 key-pair 的认证方式:
image.png
点击 OK。
移除路径映射后点击 OK:
image.png
右键我们创建的 Docker 连接,点击 “connection”,就连接成功了:
image.png
找到我们的 Dockerfile,右键这个文件,点击"Modify Run Configuration":
image.png
这里我们只需要修改 Image tag,也就是镜像名称,再点击 OK:
image.png
在打镜像前将我们的项目打包:
image.png
image.png
在 Dockerfile 文件的头部左侧的箭头位置点击 “Build image for dockerfile”,就会自动按照 Dockerfile 为我们打镜像:
image.png
打镜像完成后,就可以看到我们打的镜像了:
image.png

打 ruoyi 前端的镜像

编写 Dockerfile

在项目的根目录下创建 nginx.conf 配置文件,这个配置文件会拷贝到 ruoyi 前端镜像中,作为 Nginx 的配置文件:

user root;
worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;

    server {
        listen 80;
        server_name 127.0.0.1;
        charset utf-8;

        location / {
            root /opt/project/ruoyi/ruoyi-front-code;
            try_files $uri $uri/ /index.html;
            index index.html index.htm;
        }

        location /prod-api/ {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header REMOTE-HOST $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://ruoyi-backend-service:8080/;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root html;
        }
    }
}
# 使用 Nginx 作为基础镜像
FROM nginx:1.12.2
# 将 nginx.conf 拷贝到容器中
COPY nginx.conf /etc/nginx/nginx.conf
# 创建存放前端编译后代码的目录
RUN mkdir -p /opt/project/ruoyi/ruoyi-front-code
# 将构建好的应用拷贝到 Nginx 的默认 web 目录
COPY dist /opt/project/ruoyi/ruoyi-front-code
# Expose 端口
EXPOSE 80
# 启动 Nginx 服务器
CMD ["nginx", "-g", "daemon off;"]

WebStorm 连接虚拟机中的 Docker 打镜像

连接和打包步骤和 IDEA 连接虚拟机 Docker 的步骤一模一样。

准备 docker compose 启动的所有容器需要的文件以及文件夹

准备 Redis 容器需要的配置文件

找到本次部署的 Redis 7.2.0 的 redis.conf 文件,编辑其中的以下内容:


# 修改连接 redis 的密码为 123456
requirepass 123456

# 注释掉 bind 127.0.0.1,bind 用于限制访问 Redis 的机器 ip,直接关掉
# bind 127.0.0.1

准备 MySQL 容器需要的初始化 SQL 文件

初始化的 SQL 文件在 Ruoyi 后端项目的如下位置:
image.png
容器首次启动的时候,我们需要执行这些初始化文件来建表、导入数据。
我们还需要一个创建数据库并创建一个用户的 sql 文件(create-database-user.sql):

-- 创建数据库
CREATE DATABASE  `ry-vue` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建普通用户
grant all PRIVILEGES on ry-vue.* to ruoyi@'%' identified by '123456';
flush privileges;
use ry-vue;

我们编写一个初始化的 sql 文件,在这个 sql 文件中再调用 create-database-user.sql、quartz.sql 和 ry_20231130.sql 这三个文件:

source /opt/mysql-service/create-database-user.sql;
use ry-vue;
source /opt/mysql-service/quartz.sql;
source /opt/mysql-service/ry_20231130.sql;

注意:这里的路径都是容器中的路径,就是容器首次启动时会调用这些命令

在宿主机中创建文件夹以及上传需要文件

/opt/project 目录的目录结构如下:

project/
└── ruoyi
    ├── docker-compose.yml -- 下面我们要编写的 docker-compose 文件
    ├── mysql-service -- 存放 mysql-service 相关文件的目录
    │   ├── other
    │   │   ├── children-sql -- 子 sql 文件存放目录
    │   │   │   ├── create-database-user.sql
    │   │   │   ├── quartz.sql
    │   │   │   └── ry_20231130.sql
    │   │   └── init -- mysql 初始化执行目录,会挂载到 docker-entrypoint-initdb.d
    │   │       └── arrange-sql.sql -- sql 编排文件,会依次调用 children-sql 文件夹中的 sql 文件
    │   └── volumes -- mysql-service 挂载的容器卷
    │       └── mysql
    └── redis-service
        └── volumes -- redis-service 挂载的容器卷
            └── redis.conf

准备 SQL 文件

quartz.sql 和 ry_20231130.sql 在 ruoyi 后端代码根目录的 sql 文件夹中就有,直接拷贝即可,但是,需要在这两个 SQL 文件的第一行添加一行使用指定数据库的 SQL 语句:

use ry-vue;

create-database-user.sql 负责创建用户、数据库和为用户赋权:

-- 创建数据库
CREATE DATABASE  `ry-vue` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 应先创建新用户
create user 'ruoyi'@'%' identified by '123456';
-- 执行授权
GRANT ALL PRIVILEGES ON `ry-vue`.* TO 'ruoyi'@'%';
-- 刷新
flush privileges;
-- 授权远程
ALTER USER 'ruoyi'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
-- 刷新
flush privileges;

arrange-sql.sql 负责调用其他 SQL 文件,起到对 SQL 文件进行编排的作用:

source /opt/mysql-service/create-database-user.sql;
SET NAMES utf8;
source /opt/mysql-service/quartz.sql;
source /opt/mysql-service/ry_20231130.sql;

编写 docker-compose.yml 文件

version: '3.8'
services:
  mysql-service:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 123456
    ports:
      - "3306:3306"
    volumes:
      - /opt/project/ruoyi/mysql-service/volumes/mysql:/var/lib/mysql
      - /opt/project/ruoyi/mysql-service/other/init:/docker-entrypoint-initdb.d/
      - /opt/project/ruoyi/mysql-service/other/children-sql:/opt/mysql-service/

  redis-service:
    image: redis:7.2.0-alpine3.18
    restart: always
    ports:
      - "6379:6379"
    volumes:
      - /opt/project/ruoyi/redis-service/volumes/redis.conf:/usr/local/etc/redis/redis.conf
    command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]

  ruoyi-backend-service:
    image: ruoyi-backend:1.0
    networks:
      - ruoyi-network
    ports:
      - "8080:8080"
    depends_on:
      - mysql-service
      - redis-service

  ruoyi-frontend-service:
    image: ruoyi-frontend:1.0
    networks:
      - ruoyi-network
    ports:
      - "80:80"
    depends_on:
      - ruoyi-backend-service

networks:
  ruoyi-network:
    driver: bridge

使用如下命令启动 docker-compose 文件中的容器:

docker compose up -d

遇到的问题

后端连接到 MySQL 错误

13:55:01.882 [main] ERROR c.a.d.p.DruidDataSource - [init,942] - init datasource error, url: jdbc:mysql://mysql-service:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT&connectTimeout=1000&socketTimeout=30000
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
        at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:175)
        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
        at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:825)
        at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:446)
        at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:239)
        at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:188)
        at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:118)
        at com.alibaba.druid.filter.stat.StatFilter.connection_connect(StatFilter.java:232)
        at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:112)
        at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1706)
        at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1801)
        at com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:938)
        at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1462)
        at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1458)
        at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:83)
        at org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.getConnection(AbstractRoutingDataSource.java:194)
        at org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:159)
        at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:117)
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80)
        at org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:80)
        at org.mybatis.spring.transaction.SpringManagedTransaction.getConnection(SpringManagedTransaction.java:67)
        at org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:345)
        at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:89)
        at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:64)
        at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:333)
        at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:158)
        at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:110)
        at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:90)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:154)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:142)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:425)
        at com.sun.proxy.$Proxy100.selectList(Unknown Source)
        at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224)
        at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147)
        at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80)
        at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:142)
        at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
        at com.sun.proxy.$Proxy101.selectConfigList(Unknown Source)
        at com.ruoyi.system.service.impl.SysConfigServiceImpl.loadingConfigCache(SysConfigServiceImpl.java:177)
        at com.ruoyi.system.service.impl.SysConfigServiceImpl.init(SysConfigServiceImpl.java:40)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
        at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
        at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:920)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:453)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:343)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1370)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1359)
        at com.ruoyi.RuoYiApplication.main(RuoYiApplication.java:18)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure

修改 application-durid.yml 中的如下配置:

url: jdbc:mysql://mysql-service:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT&connectTimeout=1000&socketTimeout=30000&autoReconnect=true&failOverReadOnly=false

testOnBorrow: true

开启代理软件会导致访问虚拟机前端页面出现问题

image.png

访问后端接口报错

image.png
后端的报错日志:

15:38:29.831 [http-nio-8080-exec-8] ERROR c.r.f.w.e.GlobalExceptionHandler - [handleRuntimeException,93] - 请求地址'/captchaImage',发生未知异常.
java.lang.NullPointerException: null
        at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
        at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219)
        at sun.awt.FontConfiguration.init(FontConfiguration.java:107)
        at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774)
        at sun.font.SunFontManager$2.run(SunFontManager.java:431)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.font.SunFontManager.<init>(SunFontManager.java:376)
        at sun.awt.FcFontManager.<init>(FcFontManager.java:35)
        at sun.awt.X11FontManager.<init>(X11FontManager.java:57)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at java.lang.Class.newInstance(Class.java:442)
        at sun.font.FontManagerFactory$1.run(FontManagerFactory.java:83)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74)
        at java.awt.Font.getFont2D(Font.java:491)
        at java.awt.Font.access$000(Font.java:224)
        at java.awt.Font$FontAccessImpl.getFont2D(Font.java:228)
        at sun.font.FontUtilities.getFont2D(FontUtilities.java:180)
        at sun.font.StandardGlyphVector.initFontData(StandardGlyphVector.java:1126)
        at sun.font.StandardGlyphVector.init(StandardGlyphVector.java:1115)
        at sun.font.StandardGlyphVector.<init>(StandardGlyphVector.java:167)
        at java.awt.Font.createGlyphVector(Font.java:2545)
        at com.google.code.kaptcha.text.impl.DefaultWordRenderer.renderWord(DefaultWordRenderer.java:67)
        at com.google.code.kaptcha.impl.DefaultKaptcha.createImage(DefaultKaptcha.java:43)
        at com.ruoyi.web.controller.common.CaptchaController.getCode(CaptchaController.java:70)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:111)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:111)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:114)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at com.ruoyi.common.filter.RepeatableFilter.doFilter(RepeatableFilter.java:39)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121)
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
        at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter.doFilterInternal(JwtAuthenticationTokenFilter.java:42)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:111)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
        at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:748)

http://doc.ruoyi.vip/ruoyi/other/faq.html#linux%E7%B3%BB%E7%BB%9F%E9%AA%8C%E8%AF%81%E7%A0%81%E4%B9%B1%E7%A0%81%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95

image.png

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

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

相关文章

Hibernate的QBC与HQL查询

目录 1、Hibernate的QBC查询 2、Hibernate的HQL查询 3、NatvieSQL原生查询 1、Hibernate的QBC查询 Hibernate具有一个直观的、可扩展的条件查询API public class Test { /** * param args */ public static void main(String[] args) { Session sessio…

【八股】AQS,ReentrantLock实现原理

AQS 概念 AQS 的全称是 AbstractQueuedSynchronized &#xff08;抽象队列同步器&#xff09;&#xff0c;在java.util.concurrent.locks包下面。 AQS是一个抽象类&#xff0c;主要用来构建锁和同步器&#xff0c;比如ReentrantLock, Semaphore, CountDownLatch&#xff0c;里…

安卓LayoutParams浅析

目录 前言一、使用 LayoutParams 设置宽高二、不设置 LayoutParams2.1 TextView 的 LayoutParams2.2 LinearLayout 的 LayoutParams 三、getLayoutParams 的使用四、setLayoutParams 的作用五、使用 setWidth/setHeight 设置宽高 前言 先来看一个简单的布局&#xff0c;先用 x…

Jackson-jr 对比 Jackson

关于Jackson-jr 对比 Jackson 的内容&#xff0c;有人在做了一张下面的图。 简单点来说就 Jackson-jr 是Jackson 的轻量级应用&#xff0c;因为我们在很多时候都用不到 Jackson 的很多复杂功能。 对很多应用来说&#xff0c;我们可能只需要使用简单的 JSON 读写即可。 如我们…

手撕spring框架(5)

手撕spring框架(5) 相关系列 手撕spring框架&#xff08;1&#xff09; 手撕spring框架&#xff08;2&#xff09; 手撕spring框架&#xff08;3&#xff09; 手撕spring框架&#xff08;4&#xff09; 这是本专题最后一节了&#xff0c;主要是讲述自定义一个注解&#xff0c;实…

QT中的容器

Qt中的容器 关于Qt中的容器类&#xff0c;下面我们来进行一个总结&#xff1a; Qt的容器类比标准模板库&#xff08;STL&#xff09;中的容器类更轻巧、安全和易于使用。这些容器类是隐式共享和可重入的&#xff0c;而且他们进行了速度和存储的优化&#xff0c;因此可以减少可…

HackTheBox_knote

前言 最近打算刷一些内核利用的 CTF 的题目~~~ 题目分析 内核版本&#xff1a;v5.8.3&#xff0c;但是没有开启 cg 隔离smap/smep/kpti/kaslr 全关&#xff0c;可以 ret2usr&#xff0c;所以应该是比较老的题目了&#xff08;&#xff1a;这里很奇怪的是就算设置 kaslr 但是…

虚拟化技术 使用Vsphere Client管理ESXi服务器系统

使用Vsphere Client管理ESXi服务器系统 一、实验目的与要求 1.掌握使用vSphere Client管理ESXi主机 2.掌握将CentOS的安装介质ISO上传到ESXi存储 3.掌握在VMware ESXi中创建虚拟机 4.掌握在所创建的虚拟机中安装CentOS6.5操作系统 5.掌握给CentOS6.5安装VMware Tools 6.掌…

RabbitMQ(Docker 单机部署)

序言 本文给大家介绍如何使用 Docker 单机部署 RabbitMQ 并与 SpringBoot 整合使用。 一、部署流程 拉取镜像 docker pull rabbitmq:3-management镜像拉取成功之后使用下面命令启动 rabbitmq 容器 docker run \# 指定用户名-e RABBITMQ_DEFAULT_USERusername \# 指定密码-e R…

python数据可视化:显示两个变量间的关系散点图scatterplot()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 python数据可视化&#xff1a; 显示两个变量间的关系 散点图 scatterplot() [太阳]选择题 请问关于以下代码表述错误的选项是&#xff1f; import seaborn as sns import matplotlib.pyplot …

EPAI手绘建模APP编辑模型2

⑩ 桥接&#xff0c;选择两个面。桥接完成后&#xff0c;在选择的两个面之间生成了一个边界放样模型&#xff0c;边界放样模型和原模型合并成一个新的模型。 图 213 桥接 ⑪ 移除特征&#xff0c;选择倒圆角面、倒直角面、挖孔面、凸起面&#xff0c;移除。移除特征后&#xff…

图像处理ASIC设计方法 笔记21 标记ASIC的顶层状态机

目录 (一)标记ASIC的工作流程1 ASIC首先从控制寄存器内读出待标记图像的基本参数2若写入了有效的启动命令,则进入下面一帧图像的标记过程。3 ASIC通过接口模块从FIFO1中读取待标记的图像4一帧图像初步标记完成后进行等价表的整理压缩5从临时标记存储器中读取临时标记送入标记…

【iOS】KVC

文章目录 前言一、KVC常用方法二、key与keypath区别key用法keypath用法 三、批量存值操作四、字典与模型相互转化五、KVC底层原理KVC设值底层原理KVC取值底层原理 前言 KVC的全称是Key-Value Coding&#xff0c;翻译成中文叫做键值编码 KVC提供了一种间接访问属性方法或成员变…

数据结构练习题---环形链表详解

链表成环&#xff0c;在力扣中有这样的两道题目 https://leetcode.cn/problems/linked-list-cycle/ https://leetcode.cn/problems/linked-list-cycle-ii/description/ 这道题的经典解法是利用快慢指针&#xff0c;如果链表是一个环形链表&#xff0c;那么快指针(fast)和慢指…

AI图书推荐:AI在语言学习教育领域的应用和挑战

这本书《AI在语言学习教育领域的应用和挑战》&#xff08;AI in Language Teaching, Learning, and Assessment&#xff09;由Fang Pan编辑&#xff0c;出版于IGI Global&#xff0c;主要探讨了人工智能&#xff08;AI&#xff09;在语言教育领域的应用、挑战以及潜在的益处。 …

【苍穹外卖】项目实战Day04

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;苍穹外卖项目实战 &#x1f320; 首发时间&#xff1a;2024年5月5日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e…

TwinCAT3 实时内核调度算法

前言 TwinCAT3 支持多核心CPU并行运行实时任务&#xff0c;根据官方网站的帮助信息“实时”定义取自DIN44300&#xff0c;而且实时任务的调度算法默认是 RMS算法&#xff08;速率单调调度算法&#xff09; RMS算法 来看一下百度百科的解释&#xff1a; RMS&#xff08;单调速…

探究Android的多分辨率支持以及各种类型图标尺寸大小

术语和概念 屏幕尺寸 屏幕的物理尺寸&#xff0c;以屏幕的对角线长度作为依据&#xff08;比如 2.8寸&#xff0c; 3.5寸&#xff09;。 简而言之&#xff0c; Android把所有的屏幕尺寸简化为三大类&#xff1a;大&#xff0c;正常&#xff0c;和小。 程序可以针对这三种尺寸…

大厂案例 - 通用的三方接口调用方案设计(中)

文章目录 Pre阿里云华为云【AK和SK生成方案】最佳实践1. 创建API密钥管理系统2. 生成AK和SK3. 存储和管理AK和SK4. 提供API密钥分发机制5. 安全性6. 其他注意事项 DB Model Design表结构Next考虑其他建议 API接口设计指导1. 使用POST作为接口请求方式2. 客户端IP白名单3. 单个接…

ROS服务器通信

目录 一、角色 二、流程 注意 三、例子描述 四、srv文件 编译配置文件 vscode配置 五、Server.cpp编写例子 编写CMakeList 六、观察server的效果 七、Client编写例子 编写CMakeList 八、观察Client的结果 九、Client优化&#xff08;动态输入&#xff09; 了解argc…