智能教室云平台管理系统:基于Spring Boot、WebSocket与传感器的设计方案

news/2024/9/29 0:23:30/

一、项目概述

随着信息技术的迅猛发展,智能教室已成为现代教育的重要组成部分。智能教室云平台管理系统旨在通过集成多种智能硬件和云计算技术,实现对教室环境的实时监测与管理。系统通过人脸识别门禁控制、环境监测、语音交互等功能,提升教室的智能化水平,提高教学管理效率和学习体验。

技术栈关键词

  • 硬件平台: Raspberry Pi、STM32、LD3320语音模块、各类传感器(温湿度、光照、烟雾)、网络摄像头

  • 软件平台: Spring Boot、MySQL/MongoDB、RESTful API、Vue.js

  • 通信协议: MQTT、HTTP、WebSocket

二、系统架构

本系统采用分层架构设计,主要分为感知层、控制层、平台层和应用层。通过这样的结构设计,系统能够有效地管理和处理各类数据。

1. 系统架构设计

  • 感知层: 该层负责数据的采集,包括温湿度传感器、光照传感器、烟雾传感器及摄像头等设备。这些设备将环境数据和用户信息实时上传到控制层。

  • 控制层: 基于Raspberry Pi和STM32微控制器,这一层负责对采集到的数据进行处理和分析,同时实现控制逻辑,例如对环境设备的调节(如空调、灯光等)。

  • 平台层: 采用Spring Boot框架,构建云平台以实现数据的存储、用户管理、权限控制和业务逻辑处理。该层与数据库进行交互,确保数据的持久性和一致性。

  • 应用层: 提供用户界面及服务接口,用户可以通过Web或移动端进行操作和管理,实现对教室环境的实时监控和控制。

2. 选型及通信协议

  • 单片机选择: 选择Raspberry Pi作为主控板,负责处理复杂的数据运算和网络连接,STM32则用于实时控制各类传感器和执行器。

  • 传感器选择: 使用温湿度传感器(如DHT11)、光照传感器(如BH1750)、烟雾传感器等,以便实时监测教室内的环境情况。

  • 通信协议:

    • MQTT: 用于设备之间的轻量级消息传输,适合物联网环境。

    • HTTP: 用于前后端的数据交互,支持RESTful API设计。

数据采集
处理控制逻辑
数据存储与管理
用户交互
感知层
控制层
平台层
应用层

三、环境搭建和注意事项

在搭建智能教室云平台时,需要做好环境配置,以确保系统的稳定性和易用性。

1. 硬件环境

  • Raspberry Pi: 选择最新版本(如Raspberry Pi 4),确保具备较强的计算能力和网络连接。

  • STM32微控制器: 选择适合的型号(如STM32F103系列),以支持多种传感器的连接。

  • 传感器及模块: 确保选用的传感器能够与STM32和Raspberry Pi顺畅通信。

2. 软件环境

  • 开发环境:

    • 安装Java Development Kit (JDK) 和 Apache Maven,用于Spring Boot应用的开发和构建。

    • 配置MySQL或MongoDB数据库,创建必要的表结构以存储用户信息、环境数据和日志记录。

  • 前端开发环境:

    • 安装Node.js及对应的前端框架(如Vue.js)用于构建用户界面。

3. 网络配置

  • 确保Raspberry Pi能够连接到互联网,以便数据上传和远程访问。同时,注意网络安全,防止未授权访问。

四、代码实现过程

在本节中,我们将详细介绍智能教室云平台的各个功能模块的代码实现,包括硬件平台(Raspberry Pi、STM32、LD3320语音模块、各类传感器、网络摄像头)和软件平台(Spring Boot、MySQL/MongoDB、RESTful API、Vue.js)的集成。每个模块的实现流程将明确说明,并提供相应的代码示例。

1. 硬件平台

1.1 Raspberry Pi 设置

Raspberry Pi作为系统的核心控制单元,负责数据的处理和网络通信。

环境搭建步骤:

  1. 安装Raspberry Pi OS。

  2. 确保Raspberry Pi连接到网络,并更新软件包:

    sudo apt updatesudo apt upgrade
    
  3. 安装必要的Python库,用于与传感器和模块通信:

    pip install paho-mqtt
    pip install requests
    
1.2 STM32 设置

STM32微控制器用于控制传感器和执行器。

开发环境:

  • 使用Keil或STM32CubeIDE进行开发。

传感器示例代码(温湿度传感器 DHT11):

#include "dht11.h"void readDHT11() {DHT11_Data data;if (DHT11_Read(&data) == DHT11_OK) {printf("Temperature: %d, Humidity: %d\n", data.temperature, data.humidity);} else {printf("Failed to read from DHT11\n");}
}

1.3 LD3320 语音模块

LD3320模块用于接收和解析语音指令。通过串口与Raspberry Pi或STM32通信。

示例代码(Raspberry Pi与LD3320通信):

import serial
import time# 初始化串口
ser = serial.Serial('/dev/ttyS0', 9600)def read_voice_command():if ser.in_waiting > 0:command = ser.readline().decode('utf-8').strip()return commandreturn Nonewhile True:command = read_voice_command()if command:print(f"Received command: {command}")# 根据命令执行相关操作

1.4 传感器模块

温湿度传感器(DHT11)和光照传感器(BH1750)的数据通过Raspberry Pi采集并通过MQTT协议发送到云平台。

示例代码(温湿度传感器数据上传):

import paho.mqtt.client as mqtt
import dht11
import RPi.GPIO as GPIO
import time# MQTT配置
MQTT_BROKER = "mqtt.example.com"
MQTT_TOPIC = "classroom/environment"# 初始化DHT11
GPIO.setmode(GPIO.BCM)
dht_sensor = dht11.DHT11(pin=4)def publish_data():client = mqtt.Client()client.connect(MQTT_BROKER, 1883, 60)while True:result = dht_sensor.read()if result.is_valid():payload = {"temperature": result.temperature,"humidity": result.humidity}client.publish(MQTT_TOPIC, json.dumps(payload))print(f"Published: {payload}")time.sleep(10)publish_data()

2. 软件平台

2.1 Spring Boot 后端

Spring Boot用于构建后端服务,处理用户请求和数据存储。

项目结构:

src
└── main├── java│   └── com│       └── example│           ├── controller│           ├── service│           ├── model│           └── repository└── resources├── application.properties

application.properties 配置:

server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/classroom
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
2.2 用户管理模块

用户实体类:

@Entity
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String username;private String password;private String role; // 角色:管理员、教师、学生// Getters and Setters
}

用户注册和登录控制器:

@RestController
@RequestMapping("/api/user")
public class UserController {@Autowiredprivate UserService userService;@PostMapping("/register")public ResponseEntity<String> register(@RequestBody User user) {userService.register(user);return ResponseEntity.ok("用户注册成功");}@PostMapping("/login")public ResponseEntity<String> login(@RequestBody LoginRequest request) {String token = userService.login(request);return ResponseEntity.ok(token);}
}

用户服务层:

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;public void register(User user) {// 处理密码加密user.setPassword(passwordEncoder.encode(user.getPassword()));userRepository.save(user);}public String login(LoginRequest request) {User user = userRepository.findByUsername(request.getUsername());if (user != null && passwordEncoder.matches(request.getPassword(), user.getPassword())) {// 生成JWT Token(简化处理,实际应用中应使用安全库)return "token"; // 返回JWT Token}throw new RuntimeException("登录失败");}
}

2.3 门禁管理模块

门禁控制器:

@RestController
@RequestMapping("/api/access")
public class AccessController {@Autowiredprivate AccessService accessService;@PostMapping("/check")public ResponseEntity<String> checkAccess(@RequestBody UserFaceData faceData) {boolean accessGranted = accessService.checkFace(faceData);if (accessGranted) {return ResponseEntity.ok("门禁开启");} else {return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("未授权");}}
}

门禁服务层:

@Service
public class AccessService {public boolean checkFace(UserFaceData faceData) {// 人脸识别逻辑(调用外部人脸识别API或本地模型)// 假设使用某个人脸识别库进行处理return faceRecognitionService.isFaceRecognized(faceData);}
}

2.4 环境监测模块

环境监测控制器:

@RestController
@RequestMapping("/api/environment")
public class EnvironmentController {@Autowiredprivate EnvironmentService environmentService;@GetMapping("/current")public ResponseEntity<EnvironmentData> getCurrentData() {EnvironmentData currentData = environmentService.getCurrentData();return ResponseEntity.ok(currentData);}
}

环境服务层:

@Service
public class EnvironmentService {@Autowiredprivate EnvironmentRepository environmentRepository;public EnvironmentData getCurrentData() {// 从数据库或MQTT接收最新的环境数据return environmentRepository.findTopByOrderByTimestampDesc(); // 获取最新记录}
}

环境数据模型:

@Entity
public class EnvironmentData {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private float temperature;private float humidity;private float lightIntensity;private LocalDateTime timestamp;// Getters and Setters
}

2.5 语音控制模块

语音控制器:

@RestController
@RequestMapping("/api/voice")
public class VoiceController {@Autowiredprivate VoiceControlService voiceControlService;@PostMapping("/command")public ResponseEntity<String> executeCommand(@RequestBody String command) {String result = voiceControlService.processCommand(command);return ResponseEntity.ok(result);}
}

语音控制服务层:

@Service
public class VoiceControlService {public String processCommand(String command) {// 解析语音命令并执行相应操作switch (command.toLowerCase()) {case "开灯":// 调用灯光控制逻辑turnOnLight();return "灯光已开启";case "关灯":// 调用灯光控制逻辑turnOffLight();return "灯光已关闭";case "调节空调到22度":// 调用空调控制逻辑setAirConditioner(22);return "空调已调节到22度";default:return "无法识别的命令";}}private void turnOnLight() {// 通过MQTT或直接控制GPIO来打开灯光// 示例代码mqttClient.publish("classroom/control/light", "on");}private void turnOffLight() {// 通过MQTT或直接控制GPIO来关闭灯光mqttClient.publish("classroom/control/light", "off");}private void setAirConditioner(int temperature) {// 发送控制指令给空调设备mqttClient.publish("classroom/control/air_conditioner", String.valueOf(temperature));}
}

2.6 实时监控模块

实时监控控制器:

@RestController
@RequestMapping("/api/monitor")
public class MonitorController {@GetMapping("/live")public ResponseEntity<String> getLiveStream() {// 返回实时监控视频流的URLString videoStreamUrl = "/stream/live"; // 假设是通过某种方式提供的return ResponseEntity.ok(videoStreamUrl);}
}

前端集成:
在Vue.js前端中,可以使用 <video> 标签来显示实时视频流。

Vue.js 实时监控组件:

<template><div><h1>教室实时监控</h1><video width="600" controls autoplay><source :src="videoStreamUrl" type="video/mp4">Your browser does not support HTML5 video.</video></div>
</template><script>
export default {data() {return {videoStreamUrl: ''};},created() {this.fetchLiveStream();},methods: {fetchLiveStream() {fetch('/api/monitor/live').then(response => response.text()).then(url => {this.videoStreamUrl = url;}).catch(error => {console.error('Error fetching live stream:', error);});}}
};
</script>

3. 数据库设计

3.1 数据库表结构

用户表 (users):

CREATE TABLE users (id BIGINT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(255) NOT NULL UNIQUE,password VARCHAR(255) NOT NULL,role VARCHAR(50) NOT NULL
);

环境数据表 (environment_data):

CREATE TABLE environment_data (id BIGINT AUTO_INCREMENT PRIMARY KEY,temperature FLOAT NOT NULL,humidity FLOAT NOT NULL,light_intensity FLOAT NOT NULL,timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);

出入记录表 (access_logs):

CREATE TABLE environment_data (id BIGINT AUTO_INCREMENT PRIMARY KEY,temperature FLOAT NOT NULL,humidity FLOAT NOT NULL,light_intensity FLOAT NOT NULL,timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
);

4. 前端实现

4.1 Vue.js 前端项目设置

使用Vue CLI初始化前端项目。

vue create classroom-management
4.2 前端项目结构
src
├── components
│   ├── UserManagement.vue
│   ├── AccessControl.vue
│   ├── EnvironmentMonitor.vue
│   └── LiveMonitor.vue
├── App.vue
└── main.js
4.3 用户管理组件

用户管理组件 (UserManagement.vue):

<template><div><h2>用户管理</h2><form @submit.prevent="registerUser"><input v-model="username" placeholder="用户名" required /><input v-model="password" type="password" placeholder="密码" required /><button type="submit">注册用户</button></form><form @submit.prevent="loginUser"><input v-model="loginUsername" placeholder="用户名" required /><input v-model="loginPassword" type="password" placeholder="密码" required /><button type="submit">登录</button></form><div v-if="message">{{ message }}</div></div>
</template><script>
export default {data() {return {username: '',password: '',loginUsername: '',loginPassword: '',message: ''};},methods: {async registerUser() {try {const response = await fetch('/api/user/register', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ username: this.username, password: this.password })});if (response.ok) {this.message = '用户注册成功!';} else {this.message = '注册失败!';}} catch (error) {console.error('Error during registration:', error);this.message = '注册过程中出现错误!';}},async loginUser() {try {const response = await fetch('/api/user/login', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ username: this.loginUsername, password: this.loginPassword })});if (response.ok) {const token = await response.text();localStorage.setItem('token', token);this.message = '登录成功!';} else {this.message = '登录失败!';}} catch (error) {console.error('Error during login:', error);this.message = '登录过程中出现错误!';}}}
};
</script><style>
/* 添加样式 */
form {margin-bottom: 1rem;
}
</style>

4.4 门禁控制组件 (AccessControl.vue)

功能说明: 实现门禁控制功能,通过人脸识别进行访问控制。

<template><div><h2>门禁控制</h2><button @click="checkAccess">进入教室</button><div v-if="accessMessage">{{ accessMessage }}</div></div>
</template><script>
export default {data() {return {accessMessage: ''};},methods: {async checkAccess() {try {const response = await fetch('/api/access/check', {method: 'POST',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({ /* 这里填入人脸数据或ID */ })});if (response.ok) {this.accessMessage = await response.text();} else {this.accessMessage = '未授权访问!';}} catch (error) {console.error('Error during access check:', error);this.accessMessage = '门禁检查过程中出现错误!';}}}
};
</script>

4.5 环境监测组件 (EnvironmentMonitor.vue)

功能说明: 实时监控教室的环境数据(温度、湿度、光照等)。

<template><div><h2>环境监测</h2><div><p>当前温度: {{ environmentData.temperature }} °C</p><p>当前湿度: {{ environmentData.humidity }} %</p><p>当前光照强度: {{ environmentData.lightIntensity }} lx</p></div></div>
</template><script>
export default {data() {return {environmentData: {temperature: 0,humidity: 0,lightIntensity: 0}};},created() {this.fetchEnvironmentData();setInterval(this.fetchEnvironmentData, 5000); // 每5秒更新一次数据},methods: {async fetchEnvironmentData() {try {const response = await fetch('/api/environment/current');if (response.ok) {this.environmentData = await response.json();} else {console.error('Error fetching environment data:', response.statusText);}} catch (error) {console.error('Error during environment data fetch:', error);}}}
};
</script><style>
/* 添加样式 */
h2 {font-size: 1.5em;
}
div {margin-top: 10px;
}
</style>

4.6 实时监控组件 (LiveMonitor.vue)

功能说明: 显示教室内的实时监控视频流。

<template><div><h2>教室实时监控</h2><video width="600" controls autoplay><source :src="videoStreamUrl" type="video/mp4">Your browser does not support HTML5 video.    </video></div></template><script>export default {data() {return {videoStreamUrl: ''};},created() {this.fetchLiveStream();},methods: {async fetchLiveStream() {try {const response = await fetch('/api/monitor/live');if (response.ok) {this.videoStreamUrl = await response.text();} else {console.error('Error fetching live stream:', response.statusText);}} catch (error) {console.error('Error during live stream fetch:', error);}}}};</script><style>/* 添加样式 */video {border: 1px solid #ccc;margin-top: 10px;}</style>

5. 整合所有组件到主应用 (App.vue)

在主应用文件中整合所有组件,确保用户能够通过不同的模块进行操作。

<template><div id="app"><header><h1>智能教室云平台管理系统</h1></header><main><UserManagement /><AccessControl /><EnvironmentMonitor /><LiveMonitor /></main></div>
</template><script>
import UserManagement from './components/UserManagement.vue';
import AccessControl from './components/AccessControl.vue';
import EnvironmentMonitor from './components/EnvironmentMonitor.vue';
import LiveMonitor from './components/LiveMonitor.vue';export default {components: {UserManagement,AccessControl,EnvironmentMonitor,LiveMonitor}
};
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;text-align: center;color: #2c3e50;margin-top: 30px;
}
main {display: flex;flex-direction: column;align-items: center;
}
</style>

6. 部署与测试

6.1 后端部署
  1. 打包 Spring Boot 应用:

    mvn clean package
    

    生成的 JAR 文件在 target 目录下。

  2. 运行应用:

    java -jar target/classroom-management-0.0.1-SNAPSHOT.jar
    
  3. 确保数据库已创建并配置好:

    • 启动 MySQL 服务,并运行 SQL 文件创建表结构。
6.2 前端部署
  1. 构建 Vue.js 应用:

    npm run build
    

    生成的静态文件在 dist 目录下。

  2. 将静态文件部署到 Web 服务器(如 Nginx):

server {listen 80;server_name your_domain.com;location / {root /path/to/your/dist;index index.html;try_files $uri $uri/ /index.html;}location /api/ {proxy_pass http://localhost:8080;  # 代理到 Spring Boot 后端}
}
6.3 测试
  1. 功能测试: 确保所有功能模块正常运作,包括用户注册、登录、门禁控制、环境监测和实时监控。

  2. 性能测试: 使用工具(如 JMeter)对系统进行压力测试,确保系统在高并发情况下也能稳定运行。

  3. 安全性测试: 检查用户权限管理和数据加密是否符合预期,防止未授权访问。

用户 前端界面 用户管理控制器 门禁控制器 环境监测控制器 用户服务 门禁服务 语音控制服务 设备控制模块 日志数据库 环境数据数据库 填写注册信息 提交注册请求 处理注册逻辑 保存用户信息 返回保存结果 返回注册成功消息 返回注册结果 显示注册成功消息 填写登录信息 提交登录请求 验证用户信息 查询用户信息 返回用户数据 返回验证 用户 前端界面 用户管理控制器 门禁控制器 环境监测控制器 用户服务 门禁服务 语音控制服务 设备控制模块 日志数据库 环境数据数据库

五、项目总结

在本项目中,我们成功构建了一个智能教室云平台管理系统,通过集成多种硬件设备和软件技术,实现了对教室环境的智能化管理。项目的主要目标是提升教学管理效率,优化学习环境,增强师生的互动体验。以下是项目的主要功能、实现过程以及未来的展望。

1. 主要功能

  • 用户管理模块:实现了用户的注册、登录和权限管理功能,支持人脸识别登记,保证了教室的安全性。

  • 门禁控制模块:通过摄像头和人脸识别技术,自动控制教室的门禁,记录用户的出入信息,确保只有授权人员可以进入教室。

  • 环境监测模块:实时监测教室内的温湿度、光照等环境指标,并将数据存储到数据库中,支持历史数据查询,帮助管理人员了解教室的环境变化。

  • 语音控制模块:通过LD3320语音模块,用户可以通过语音指令控制设备,如开关灯、调节空调等,增强了教室的互动性。

  • 实时监控模块:提供教室内摄像头的实时监控功能,支持远程查看,确保教室的安全和管理的有效性。

2. 实现过程

整个项目的实现过程可以分为以下几个阶段:

  1. 需求分析:明确系统的功能需求,确定所需的硬件和软件技术栈。

  2. 系统设计:设计系统的架构,包括感知层、控制层、平台层和应用层。选择合适的硬件平台(Raspberry Pi、STM32等)和通信协议(MQTT、HTTP等)。

  3. 环境搭建:搭建硬件环境和软件环境,确保所有传感器、模块和服务器能够正常工作。

  4. 模块开发:

    • 使用Spring Boot开发后端服务,处理用户请求,管理数据。

    • 实现RESTful API,供前端进行数据交互。

    • 使用Vue.js开发前端界面,提供友好的用户体验。

  5. 测试与调试:对各个功能模块进行单元测试和集成测试,确保系统的稳定性和安全性。

  6. 部署:将后端服务部署到云服务器,前端静态文件部署到Web服务器,确保系统可访问。

3. 项目收获

通过本项目的开发,我们对智能教室的管理系统有了更深入的理解,掌握了以下技能和知识:

  • 硬件与软件集成:成功实现了各种传感器、摄像头和语音模块与后端系统的集成,提升了我们在物联网领域的实践能力。

  • 后端开发:通过使用Spring Boot构建RESTful API,提升了我们对Java后端开发的理解和应用能力。

  • 前端开发:通过Vue.js实现了动态用户界面,增强了我们在前端开发方面的技能。

  • 系统架构设计:加深了对分层架构设计的理解,能够更好地设计和实现复杂系统。


http://www.ppmy.cn/news/1531677.html

相关文章

《解锁高效流程设计:深度剖析责任链模式与实战应用》

《解锁高效流程设计&#xff1a;深度剖析责任链模式与实战应用》 责任链模式 是一种行为设计模式&#xff0c;它允许多个对象来处理请求&#xff0c;而不预先指定具体的处理者。多个处理对象被连接成一条链&#xff0c;沿着这条链传递请求&#xff0c;直到某个处理对象决定处理…

【计算机网络 - 基础问题】每日 3 题(二十四)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

《迁移学习》—— 将 ResNet18 模型迁移到食物分类项目中

文章目录 一、迁移学习的简单介绍1.迁移学习是什么&#xff1f;2.迁移学习的步骤 二、数据集介绍三、代码实现1. 步骤2.所用到方法介绍的文章链接3. 完整代码 一、迁移学习的简单介绍 1.迁移学习是什么&#xff1f; 迁移学习是指利用已经训练好的模型&#xff0c;在新的任务上…

QtCreator的界面

编辑 advanced Auto-indent Selection&#xff1a;自动缩进选择。将所选内容按照预设的缩进规则进行缩进。Rewrap Paragraph&#xff1a;重新换行段落。将一段文字根据指定宽度重新排版。Visualize Whitespace&#xff1a;可视化空白字符。显示通常不可见的空格、制表符等空白…

element ui 精确控制日期控件 date-picker

https://github.com/element-plus/element-plus/discussions/17378 -- 某组件 xxx.vue ... <el-date-pickerv-model"timeRange"type"daterange"range-separator"-"start-placeholder"开始日期"end-placeholder"结束日期"…

QTday1代码的形式实现登录框

代码注释 main.cpp #include "widget.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);//调用应用程序类的有参构造的实例化对象Widget w;//调用自定义的有参构造实例化的对象w.show();//调用该类的父类里的成员函数…

spring6启用Log4j2日志

pom文件 <!--log4j2的依赖--> <dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.23.1</version> </dependency> <dependency><groupId>org.apache…

C++入门编程题(力扣):字符串中最多数目的子序列

1.题目描述&#xff1a; 给你一个下标从0开始的字符串 text 和另一个下标从0开始且长度为 2 的字符串 pattern两者都只包含小写英文字母。 你可以在 text 中任意位置插入 一个 字符&#xff0c;这个插入的字符必须是 pattern[0]或者 pattern[1]。 注意&#xff0c;这个字符可以…