news 2026/10/17 2:54:12

JSP会议室预约系统实战:冲突检测与并发优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JSP会议室预约系统实战:冲突检测与并发优化

简介:这是一套面向Java Web初学者与课程设计开发者的会议室预约系统完整源码,基于JSP、Servlet与JavaBean技术构建,用于解决企业或组织内部会议室资源分配与冲突问题。系统区分管理员与员工两类角色:管理员负责部门、员工账户、会议室信息及公告的增删改查与权限分配,员工则可查看公告、按日期时间预订会议室并取消订单,覆盖用户管理、权限控制、数据库CRUD与前端表单验证等典型模块。压缩包共744个文件,约5.01MB,以gif、js、html、png、css等前端资源为主,另含jsp页面、jar依赖、sql脚本及少量java源码,便于直接部署到Tomcat运行。目前已有1657人学习下载,适合作为毕业设计、课程作业或JSP/Servlet入门练手项目,帮助读者快速理解MVC分层结构、session身份验证与数据库操作流程。

1. 从一张排班表说起:这个 JSP 会议室预约系统到底能干什么

如果你在行政或 IT 岗待过,一定见过这种场面:早上九点,三个人同时站在同一间会议室门口,手里都攥着打印出来的预约单,谁也不知道到底谁先约的。纸质登记本、Excel 共享表、群里喊一声“下午两点有人用吗”,这些办法在小团队里勉强能转,一旦楼层多、会议室多、参会人跨部门,立刻变成玄学。这套 JAVA JSP 会议室预约系统就是冲着这个场景来的——它把会议室资源、时间段、预约人三者用一张数据库表锁死,谁先提交谁占坑,后来的人只能看到“已被占用”。技术栈是经典的 JSP + Servlet + JDBC + MySQL,跑在 Tomcat 上,没有 Spring 那一套重框架,适合课程设计、小型企业内部工具,或者想拿一个完整 CRUD 项目练手 Java Web 的开发者。你拿到源码后,改改数据库连接就能跑,前端是 JSP 直出加少量 JavaScript 校验,后端 Servlet 处理请求,结构直白,没有黑匣子。

2. 技术选型与工程结构:为什么用 JSP 而不是前后端分离

2.1 这套组合的适用边界

先说实话,JSP 在今天不是主流选择,但它在这个项目里有明确的合理性。会议室预约的核心逻辑是“查空闲时段 → 插入预约记录 → 冲突检测”,业务简单、并发量低(几十人规模),用 JSP + Servlet 可以做到零前端构建、零 Node 环境,一个 Tomcat 加一个 MySQL 就能跑。对于要交课程设计或者给内部小团队快速搭工具的人来说,省掉 Webpack、Vue CLI 这些环节,反而降低了部署门槛。常见做法是把 JSP 当模板引擎用,页面里嵌 Java 代码片段做数据渲染,Servlet 负责接收表单和跳转,JDBC 直接操作数据库。这套东西的缺点是页面逻辑和业务逻辑容易混在一起,所以我在看这个项目时会重点关注它有没有把数据库操作抽到单独的 DAO 类里。

2.2 目录结构长什么样

一个典型的 JSP 会议室预约系统工程目录如下,你拿到源码后可以对照着看:

MeetingRoom/ ├── src/ │ └── com/ │ └── meeting/ │ ├── dao/ # 数据库操作层 │ │ ├── UserDao.java │ │ ├── RoomDao.java │ │ └── BookingDao.java │ ├── model/ # 实体类 │ │ ├── User.java │ │ ├── Room.java │ │ └── Booking.java │ ├── servlet/ # 控制器 │ │ ├── LoginServlet.java │ │ ├── RoomListServlet.java │ │ └── BookingServlet.java │ └── util/ │ └── DBUtil.java # 数据库连接工具 ├── WebContent/ │ ├── css/ │ │ └── style.css │ ├── js/ │ │ └── validate.js │ ├── login.jsp │ ├── room_list.jsp │ ├── booking_form.jsp │ ├── my_bookings.jsp │ └── WEB-INF/ │ ├── web.xml │ └── lib/ │ └── mysql-connector-java-8.0.xx.jar └── database.sql # 建表脚本

这个结构里,src下按 DAO、model、servlet、util 分包,是 Java Web 项目最常见的分层方式。WebContent放 JSP 页面和静态资源,WEB-INF/lib放 MySQL 驱动 jar 包,web.xml配置 Servlet 映射。database.sql是建表脚本,导入后就有初始数据。你如果用的是 Eclipse 或 IDEA,导入项目后需要把 jar 包加到 Build Path 里,否则会报ClassNotFoundException: com.mysql.cj.jdbc.Driver。

2.3 数据库表设计

会议室预约系统的核心表就三张:用户表、会议室表、预约记录表。建表 SQL 大致如下:

-- 用户表:存登录账号和角色 CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(50) NOT NULL, real_name VARCHAR(50), role INT DEFAULT 0 -- 0普通用户 1管理员 ); -- 会议室表:存会议室基本信息 CREATE TABLE t_room ( id INT PRIMARY KEY AUTO_INCREMENT, room_name VARCHAR(100) NOT NULL, capacity INT, location VARCHAR(200), status INT DEFAULT 1 -- 1可用 0停用 ); -- 预约记录表:核心表,存谁在什么时间约了哪间房 CREATE TABLE t_booking ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, room_id INT NOT NULL, booking_date DATE NOT NULL, start_time TIME NOT NULL, end_time TIME NOT NULL, purpose VARCHAR(500), status INT DEFAULT 1, -- 1有效 0已取消 create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES t_user(id), FOREIGN KEY (room_id) REFERENCES t_room(id) );

这里的关键字段是booking_date、start_time、end_time,冲突检测就是靠这三个字段做区间重叠判断。status字段用来做软删除,用户取消预约时把 status 置 0,而不是物理删除,方便管理员追溯。注意t_booking表没有加唯一约束来防重复预约,因为时间段重叠不是简单的唯一键能解决的,需要在业务层用 SQL 查询判断。

3. 核心模块拆解:从登录到预约提交的完整链路

3.1 数据库连接工具类

先看DBUtil.java,这是整个项目的地基。所有 DAO 都从这里拿连接:

package com.meeting.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DBUtil { // 数据库连接参数,部署时改这里 private static final String URL = "jdbc:mysql://localhost:3306/meeting_room?useSSL=false&serverTimezone=UTC&characterEncoding=utf8"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { // 加载驱动,MySQL 8.0 用 cj 包路径 Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 每次调用返回一个新连接,用完记得 close public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } // 关闭连接,防止连接泄漏 public static void close(Connection conn) { if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }

这段代码里,URL中的serverTimezone=UTC是 MySQL 8.0 必须带的参数,否则会报时区错误。characterEncoding=utf8防止中文乱码。Class.forName放在 static 块里只执行一次。注意这里没有用连接池,每次getConnection都新建连接,在几十人规模下够用,但如果要优化,可以换成 Druid 或 HikariCP,这是常见的改造点。

3.2 预约冲突检测逻辑

这是整个系统最核心的一段代码,在BookingDao.java里:

package com.meeting.dao; import com.meeting.util.DBUtil; import java.sql.*; public class BookingDao { /** * 检查指定会议室在指定时间段是否已被预约 * @param roomId 会议室ID * @param date 预约日期 * @param start 开始时间 * @param end 结束时间 * @return true表示有冲突,false表示可预约 */ public boolean isConflict(int roomId, String date, String start, String end) { String sql = "SELECT COUNT(*) FROM t_booking " + "WHERE room_id = ? AND booking_date = ? AND status = 1 " + "AND start_time < ? AND end_time > ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, roomId); ps.setString(2, date); ps.setString(3, end); // 已有预约的开始时间 < 新预约的结束时间 ps.setString(4, start); // 已有预约的结束时间 > 新预约的开始时间 try (ResultSet rs = ps.executeQuery()) { if (rs.next()) { return rs.getInt(1) > 0; } } } catch (SQLException e) { e.printStackTrace(); } return false; } /** * 插入预约记录 */ public boolean addBooking(int userId, int roomId, String date, String start, String end, String purpose) { // 先检测冲突,再插入 if (isConflict(roomId, date, start, end)) { return false; } String sql = "INSERT INTO t_booking(user_id, room_id, booking_date, " + "start_time, end_time, purpose) VALUES(?,?,?,?,?,?)"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, userId); ps.setInt(2, roomId); ps.setString(3, date); ps.setString(4, start); ps.setString(5, end); ps.setString(6, purpose); return ps.executeUpdate() > 0; } catch (SQLException e) { e.printStackTrace(); } return false; } }

冲突检测的 SQL 条件start_time < ? AND end_time > ?是区间重叠的标准判断:两个时间段重叠,当且仅当一个的开始时间早于另一个的结束时间,且一个的结束时间晚于另一个的开始时间。参数传入时注意顺序,第三个参数传新预约的end,第四个参数传新预约的start,这个顺序容易写反,写反了逻辑就完全错了。status = 1保证只检查有效预约,已取消的不算。addBooking里先查冲突再插入,但在并发场景下这个“查-插”不是原子的,两个人同时提交可能都查到无冲突然后都插入。常见做法是在t_booking上加一个基于room_id + booking_date + start_time的唯一索引,或者在插入时用INSERT ... SELECT ... WHERE NOT EXISTS来保证原子性。这个项目如果没做,就是你要改造的第一个点。

3.3 预约 Servlet 的请求处理

BookingServlet.java负责接收前端表单,调用 DAO,然后跳转结果页:

package com.meeting.servlet; import com.meeting.dao.BookingDao; import com.meeting.model.User; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import java.io.IOException; @WebServlet("/booking") public class BookingServlet extends HttpServlet { private BookingDao bookingDao = new BookingDao(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置编码,防止中文参数乱码 req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); // 从 session 拿当前登录用户 HttpSession session = req.getSession(); User user = (User) session.getAttribute("loginUser"); if (user == null) { resp.sendRedirect("login.jsp"); return; } // 接收表单参数 int roomId = Integer.parseInt(req.getParameter("roomId")); String date = req.getParameter("bookingDate"); String start = req.getParameter("startTime"); String end = req.getParameter("endTime"); String purpose = req.getParameter("purpose"); // 基本校验:结束时间必须晚于开始时间 if (start.compareTo(end) >= 0) { req.setAttribute("msg", "结束时间必须晚于开始时间"); req.getRequestDispatcher("booking_form.jsp").forward(req, resp); return; } // 调用 DAO 插入 boolean success = bookingDao.addBooking( user.getId(), roomId, date, start, end, purpose); if (success) { resp.sendRedirect("my_bookings.jsp"); } else { req.setAttribute("msg", "该时间段已被预约,请选择其他时间"); req.getRequestDispatcher("booking_form.jsp").forward(req, resp); } } }

这个 Servlet 用@WebServlet("/booking")注解配置映射,不需要在web.xml里再写一遍。req.setCharacterEncoding("UTF-8")必须在获取任何参数之前调用,否则中文参数会乱码。从 session 拿用户对象做登录校验,没登录就跳回登录页。时间格式校验用字符串比较compareTo,因为HH:mm格式的字符串比较结果和实际时间先后一致,这是个取巧但有效的做法。最后根据插入结果决定跳转到“我的预约”还是返回表单页并带错误提示。

3.4 JSP 页面如何渲染会议室列表

room_list.jsp是用户选择会议室的页面,核心是用 JSP 脚本片段遍历 DAO 查出来的列表:

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page import="java.util.List" %> <%@ page import="com.meeting.model.Room" %> <%@ page import="com.meeting.dao.RoomDao" %> <html> <head> <title>会议室列表</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <h2>可用会议室</h2> <table border="1"> <tr> <th>名称</th><th>容纳人数</th><th>位置</th><th>操作</th> </tr> <% // 页面里直接调 DAO,简单项目常见做法 RoomDao roomDao = new RoomDao(); List<Room> rooms = roomDao.getAllAvailable(); for (Room room : rooms) { %> <tr> <td><%= room.getRoomName() %></td> <td><%= room.getCapacity() %></td> <td><%= room.getLocation() %></td> <td> <a href="booking_form.jsp?roomId=<%= room.getId() %>">预约</a> </td> </tr> <% } %> </table> </body> </html>

这种在 JSP 里直接 new DAO 的写法,严格来说违反了 MVC 分层,但在这个规模的项目里很常见,优点是少写一个 Servlet。<% %>里写 Java 逻辑,<%= %>输出变量值。循环遍历rooms列表,每行生成一个预约链接,链接带上roomId参数,点击后跳到预约表单页。如果你要改造,可以把这段查询逻辑挪到RoomListServlet里,JSP 只负责渲染,这是标准的 MVC 做法。

4. 部署与运行:从零把项目跑起来

4.1 环境准备清单

跑这个项目需要以下环境,版本不用完全一致,但大版本要对:

组件推荐版本说明
JDK1.8 或 11JSP/Servlet 项目,1.8 最稳
Tomcat8.5 或 9.0支持 Servlet 3.1+ 注解
MySQL5.7 或 8.08.0 需要改驱动类名和 URL
IDEEclipse / IDEA需要支持 Dynamic Web Project
MySQL 驱动8.0.x jar放 WEB-INF/lib 下

JDK 建议用 1.8,因为很多老项目的 JSP 页面用了 Java 8 的语法,换高版本可能遇到模块化问题。Tomcat 8.5 和 9.0 都支持@WebServlet注解,选哪个都行。MySQL 8.0 的驱动类名是com.mysql.cj.jdbc.Driver,5.7 是com.mysql.jdbc.Driver,这个在DBUtil.java里要对应改。

4.2 数据库初始化步骤

第一步,登录 MySQL 创建数据库:

mysql -u root -p

输入密码后执行:

CREATE DATABASE meeting_room DEFAULT CHARACTER SET utf8mb4; USE meeting_room; SOURCE /path/to/database.sql;

SOURCE命令导入建表脚本,路径换成你实际存放database.sql的位置。导入完成后用SHOW TABLES;确认三张表都在。然后插入一条管理员账号:

INSERT INTO t_user(username, password, real_name, role) VALUES('admin', 'admin123', '管理员', 1);

密码是明文存储的,这在课程设计里常见,但生产环境必须加盐哈希,这是你要改造的点之一。

4.3 Tomcat 部署与访问

在 Eclipse 里导入项目后,右键项目 → Properties → Project Facets,确认 Dynamic Web Module 版本和 Java 版本匹配。然后把 MySQL 驱动 jar 复制到WebContent/WEB-INF/lib下,右键 Build Path → Add to Build Path。接着配置 Tomcat 服务器,把项目添加到服务器,启动。访问地址:

http://localhost:8080/MeetingRoom/login.jsp

用 admin/admin123 登录,进入会议室列表,点预约,选时间,提交。如果提交后跳转到“我的预约”页面并看到记录,说明整条链路通了。如果报 404,检查web.xml里的 welcome-file 配置或者直接访问具体 JSP 路径。如果报 500 且堆栈里有Access denied for user,说明DBUtil.java里的数据库账号密码不对。

5. 避坑与常见问题排查

5.1 中文乱码:POST 和 GET 要分开处理

现象:登录时输入中文用户名,后台收到的是????。原因:Tomcat 默认用 ISO-8859-1 解码请求参数。解决:POST 请求在 Servlet 第一行加req.setCharacterEncoding("UTF-8");GET 请求(比如 URL 带中文参数)需要在 Tomcat 的server.xml里给 Connector 加URIEncoding="UTF-8"。JSP 页面头部也要有<%@ page contentType="text/html;charset=UTF-8" %>。这三处缺一处都可能乱码,我一般三个地方都写上,省得来回查。

5.2 时间比较用字符串还是 Date

现象:预约 09:00 到 10:00,系统却提示冲突。原因:如果数据库里存的是TIME类型,JDBC 取出来是java.sql.Time,直接和字符串比较会出错。解决:统一在 DAO 层把时间转成HH:mm格式的字符串再比较,或者用java.sql.Time.valueOf("09:00:00")转成 Time 对象比较。这个项目里 SQL 的start_time < ?是让 MySQL 做比较,传入的字符串 MySQL 会自动转成 TIME,所以只要格式对(HH:mm或HH:mm:ss)就没问题。但如果格式写成9:00少个前导零,MySQL 可能解析失败,这是血泪经验。

5.3 连接泄漏导致 Tomcat 越跑越慢

现象:项目跑半天后,Tomcat 报Too many connections,MySQL 连接数打满。原因:DAO 里getConnection后没有在 finally 块里 close,异常时连接泄漏。解决:用 try-with-resources 语法,把Connection、PreparedStatement、ResultSet都放在 try 的括号里,Java 会自动关闭。上面BookingDao的代码已经用了这个写法。如果你拿到的是老版本代码,检查每个 DAO 方法,确保没有裸的conn.close()漏掉。

5.4 并发提交导致重复预约

现象:两个人同时点提交,系统都提示成功,但同一时间段出现了两条记录。原因:isConflict查询和addBooking插入之间有时间窗口,两个线程都查到无冲突。解决:在t_booking表上加唯一索引UNIQUE KEY uk_room_time (room_id, booking_date, start_time),这样第二个插入会抛DuplicateKeyException,在 Servlet 里捕获这个异常并提示“已被预约”。或者用INSERT INTO ... SELECT ... WHERE NOT EXISTS (SELECT 1 FROM t_booking WHERE ...)一条 SQL 搞定。这个改造不难,但能彻底解决并发问题。

5.5 JSP 页面直接调 DAO 导致报错难定位

现象:room_list.jsp报NullPointerException,但堆栈指向 JSP 生成的行号,看不出具体哪一步。原因:JSP 里嵌了太多 Java 逻辑,异常被 Tomcat 包装后行号对不上。解决:把 DAO 调用挪到 Servlet 里,Servlet 里 try-catch 打印完整堆栈,JSP 只做渲染。如果暂时不想大改,至少在 JSP 的脚本片段里加 try-catch,把异常信息输出到页面或日志。我一般会在 JSP 顶部加<%@ page isErrorPage="true" %>配合错误页,但治本还是分层。

6. 二次开发改造:从能跑到好用

6.1 加一个连接池,别再用 DriverManager

DBUtil每次新建连接,在几十人规模下勉强能用,但如果你想让它更接近生产,换成 Druid 连接池是成本最低的改造。引入druid-1.2.x.jar,改写DBUtil:

public class DBUtil { private static DataSource dataSource; static { try { Properties props = new Properties(); props.load(DBUtil.class.getClassLoader() .getResourceAsStream("druid.properties")); dataSource = DruidDataSourceFactory.createDataSource(props); } catch (Exception e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }

druid.properties里配url、username、password、initialSize=5、maxActive=20。这样连接复用,Tomcat 重启后不会有一堆 TIME_WAIT 连接。改造后 DAO 代码不用动,因为getConnection的签名没变。

6.2 把冲突检测做成原子操作

前面提过并发问题,具体改造是在addBooking里用一条 SQL 完成检测加插入:

INSERT INTO t_booking(user_id, room_id, booking_date, start_time, end_time, purpose) SELECT ?, ?, ?, ?, ?, ? FROM DUAL WHERE NOT EXISTS ( SELECT 1 FROM t_booking WHERE room_id = ? AND booking_date = ? AND status = 1 AND start_time < ? AND end_time > ? );

executeUpdate返回 0 表示有冲突,返回 1 表示插入成功。这样就不需要先查再插,一条 SQL 原子完成。注意 MySQL 里FROM DUAL可以省略,但写上兼容性更好。参数顺序要仔细对,SELECT后面六个是插入值,WHERE后面四个是冲突检测条件。

6.3 加一个“我的预约”取消功能

现在的my_bookings.jsp可能只展示列表,没有取消按钮。改造思路:在列表每行加一个“取消”链接,指向CancelServlet?id=xxx,Servlet 里把status置 0:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int id = Integer.parseInt(req.getParameter("id")); String sql = "UPDATE t_booking SET status = 0 WHERE id = ? AND user_id = ?"; try (Connection conn = DBUtil.getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, id); ps.setInt(2, ((User) req.getSession().getAttribute("loginUser")).getId()); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } resp.sendRedirect("my_bookings.jsp"); }

AND user_id = ?保证只能取消自己的预约,防止越权。这个改造涉及一个 Servlet 加一个 JSP 链接,半小时能搞定。

6.4 验证改造是否生效

改完之后怎么确认没翻车?我一般走这三步:第一,用两个浏览器(或一个正常窗口一个无痕窗口)登录不同账号,同时提交同一会议室同一时间段,看是否只有一个成功。第二,取消一条预约后,再用同一时间段预约,看是否能成功,确认status = 0的记录不参与冲突检测。第三,把 Tomcat 停掉再启动,连续提交二十次预约,看 MySQL 的Threads_connected是否稳定在连接池maxActive以内。这三步走完,基本能确认连接池和原子插入都生效了。

从那以后我每次拿到这种 JSP 老项目,都强制先跑一遍并发提交测试,再去看它的连接管理——这两个地方不出问题,剩下的都是页面改改的事。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 2:54:07

编译原理实验代码:从词法分析到目标代码生成的完整实现

简介&#xff1a;这份资源是电子科技大学编译原理课程的实验代码合集&#xff0c;面向正在学习编译原理、需要完成词法分析与语法分析实验的高校学生及自学者。包内共21个文件&#xff0c;以cpp与h源码为主&#xff0c;辅以pas示例、vcxproj与sln工程文件、docx运行说明及exe可…

作者头像 李华
网站建设 2026/10/17 2:52:46

Ionic+Cordova插件集成Unity:让AR功能成为原生模块

简介&#xff1a;UnityIonicIntegration 是一份针对 Unity 3D 内容与 Ionic 混合应用双向集成的实战指南&#xff0c;适合需要同时掌握 Android/iOS 端插件封装与原生通信的移动开发者。方案基于 Cordova 插件实现 Unity 与 Ionic 之间双向消息传递&#xff0c;并已在带 Vufori…

作者头像 李华
网站建设 2026/10/17 2:52:44

labelImg图像标注工具详解:VOC格式转YOLO的完整流程与避坑指南

简介&#xff1a;LabelImg 是一款开源的可视化图像标注工具&#xff0c;主要面向目标检测领域的数据集制作环节。使用者可以通过图形界面快速框选图像中的目标&#xff0c;并自动生成符合 PASCAL VOC 规范的 XML 标注文件&#xff0c;为 Faster R-CNN、YOLO、SSD 等主流检测网络…

作者头像 李华
网站建设 2026/10/17 2:52:33

OpenCV C/C++动态抠图源码实战:从背景建模到掩膜合成的完整链路

简介&#xff1a;本资源面向计算机视觉初学者与C/C开发者&#xff0c;提供基于OpenCV的动态扣图完整源代码&#xff0c;解决实时视频流或连续图像序列中前景目标提取的问题。代码围绕背景减除模型展开&#xff0c;涵盖BackgroundSubtractorMOG2与BackgroundSubtractorKNN两种主…

作者头像 李华
网站建设 2026/10/17 2:51:56

地球微观粒子不能推导出宇宙宏观| 赵杰 | 量子意识(第三卷)

作者&#xff1a;赵杰清华大学硕士、微美全息云科技&#xff08;NASDAQ&#xff1a;WIMI&#xff09;董事长、微算法科技&#xff08;NASDAQ&#xff1a;MLGO&#xff09;董事长、育杰奖学金创始人宇宙的尺度层级中&#xff0c;地球微观粒子的研究始终局限于 “局部可控的实验室…

作者头像 李华