news 2026/10/11 2:13:40

基于JavaEE的网上书店项目:课程设计、毕业设计与部署避坑全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于JavaEE的网上书店项目:课程设计、毕业设计与部署避坑全解析

简介:这是一份基于JavaEE的网上书店项目完整代码,专为高校学生的课程设计或毕业设计而准备,也适合入门Java Web开发的学习者研读。项目完整实现了用户注册登录与个人信息管理、图书信息展示与按书名或作者搜索、购物车增减与结算、订单生成与状态查看、管理员后台维护以及基础销售数据统计等功能,覆盖电商网站典型业务链。技术层面采用了Servlet处理请求、JSP生成动态页面、JPA操作数据库、EJB封装业务逻辑,并搭配MySQL作为数据存储,SQL文件包含建库建表及初始化数据,能够直接导入运行。压缩包内共88个文件,其中40个JSP页面用于前端展示,11个Java源文件和11个class文件承载后端逻辑,另有数据库SQL脚本、样式表、XML配置及示例图片等,整包大小约519KB,结构清晰便于查阅。目前已有3133人浏览学习,借助完整代码与配套数据库,读者可以透彻理解JavaEE分层架构、会话管理和持久化映射,为二次开发或毕业答辩提供扎实参考。

1. 基于JavaEE的网上书店项目:课程设计与毕业设计最直接的技术起点

课程设计选题里,基于JavaEE的网上书店项目一直是最常见的选项之一。做JavaEE+MySQL课程设计或毕业设计的同学,经常卡在三处:环境搭不起来、代码结构乱、SQL文件与程序字段对不上。我拆过不少这类项目,最想说的是——完整代码与SQL文件配套,比单看某个Servlet有价值得多。它意味着你导入数据库、部署Tomcat后,第一步就能看到一个真正能买书的页面;之后无论你要加购物车结算、订单状态流转还是后台管理,都有现成的数据和代码边界可以参考。这套项目代码功能上覆盖用户注册登录、图书浏览、分类检索、购物车、订单提交与后台管理,适合作为课程设计或毕业设计底子,在此基础上改样式、加模块、补测试都能行。

2. 技术栈选型与项目结构:为什么原生JavaEE仍是课程设计最稳的选择

2.1 三层架构与MVC:JSP+Servlet+DAO的分层骨架

课程设计评审老师最爱问的问题是“请求是怎么走的”。用Spring Boot开发,三分钟不一定能讲到Servlet和事务;但原生JavaEE的链路就是教科书模板:浏览器请求→Servlet(控制器)→Service(业务)→DAO(数据访问)→JSP(视图)。项目里合格的结构通常是这样的:

bookstore/ |-- src/ | |-- com/example/bookstore/ | | |-- controller/ # Servlet 控制器,接收请求并跳转页面 | | |-- service/ # 业务逻辑层,处理登录、下单等规则 | | |-- dao/ # JDBC 数据访问层 | | |-- model/ # User、Book、Order 实体类 | | `-- util/ # DBUtil、MD5Util 等工具类 |-- WebContent/ | |-- jsp/ # 视图页面 | |-- css/ js/ images/ # 静态资源 |-- sql/ | `-- bookstore.sql # 建库建表与初始化数据

这套结构的价值,是提前把“Controller怎么调Service、Service怎么抛业务异常、DAO怎么关闭资源”固定了下来。答辩现场你能一句话讲清:JSP只做展示,Servlet只做参数接收和页面跳转,业务规则在Service,SQL全在DAO。老师追问“为什么不在JSP里直接写JDBC”,你就回答职责分离、改动互不影响,这个答案基本不会扣分。

对刚接触JavaEE的同学,我不建议课设阶段把层与层抽象成接口和实现两套文件。一个Service类对应一个DAO类足够,抽接口会让代码量翻倍,答辩还容易被追问“接口只有一个实现类,抽象意义是什么”。同样的道理,model类直接用字段加getter/setter,不需要引入ORM框架;原生JavaEE的定位就是把Servlet生命周期、请求转发和JDBC这些底层机制暴露在明处,这正是课程设计想考察的点。

2.2 数据库设计:用户、图书、订单与订单项的表结构

网上书店的数据量不大,但实体关系非常适合做课设:用户、图书、分类、订单、订单项五张主表,另外购物车表在某些方案里需要。下面列出项目包中核心表的设计:

表名作用关键字段
user用户账户id、username、password、phone、create_time
category图书分类id、name、parent_id
book图书id、title、author、price、stock、sales、cover_image、category_id
order订单主表id、user_id、total_price、status、create_time
order_item订单明细id、order_id、book_id、book_name、price、quantity

注意order_item里面冗余了book_name和price。设计时很多人觉得这是多余的,但仔细想:图书价格和书名都会变,如果订单明细只存book_id,历史订单再查就会显示当下价格,对账直接错乱。快照字段是订单系统的经典做法。category表用parent_id实现树形分类,两级分类用自连接即可,不需要嵌套集模型,对课设来说反而好解释。

建表脚本里值得复用的写法是每张表都用InnoDB、utf8mb4、DATETIME默认当前时间:

CREATE TABLE book ( id INT PRIMARY KEY AUTO_INCREMENT, -- 主键自增,无业务含义 title VARCHAR(200) NOT NULL, -- 书名,列表页经常按此过滤 author VARCHAR(100) DEFAULT NULL, price DECIMAL(10,2) NOT NULL, -- 定点数,避免浮点误差 stock INT NOT NULL DEFAULT 0, -- 库存,下单时条件更新 sales INT NOT NULL DEFAULT 0, -- 销量 cover_image VARCHAR(255) DEFAULT NULL, category_id INT NOT NULL, -- 分类外键 create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_title (title), -- 书名检索索引 KEY idx_category_id (category_id), -- 分类列表索引 CONSTRAINT fk_book_category FOREIGN KEY (category_id) REFERENCES category (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

DECIMAL(10,2)避免FLOAT的浮点误差,价格和金额一律用定点数;stock、sales用INT;外键放在建表SQL底层保证完整性,实际项目有时会把外键去掉改成应用层保证,但课设保留外键更容易向老师解释表关系。索引方面,title加普通索引支撑搜索场景,category_id加索引支撑分类列表。

2.3 JDBC访问方式:裸JDBC与连接池的取舍

课程设计要不要用连接池?我的意见是尽量不引入。不是Druid不好,而是课设环境经常不稳定:连接池依赖包、配置文件、版本兼容,任何一环出问题都让你消耗大量时间在环境上,而课设的并发量通常个位数,裸JDBC完全能扛住。

项目的DBUtil是典型的DriverManager写法:

public class DBUtil { private static final String URL = "jdbc:mysql://localhost:3306/bookstore?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"; private static final String USER = "root"; private static final String PASSWORD = "123456"; static { try { Class.forName("com.mysql.jdbc.Driver"); // MySQL 5.7的驱动类 } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }

如果你本机装的是MySQL 8.0,把驱动类名改成com.mysql.cj.jdbc.Driver;URL里保留serverTimezone=Asia/Shanghai,否则8.0连接会报时区错误。这个切换细节在避坑章节还会展开。JDBC连接属于系统级资源,每用一次都要在finally里关闭;如果项目里出现“连接数太多”、“MySQL一直报too many connections”,多半是某个DAO的Connection没关。到了订单事务里,Connection必须在一个方法内传递复用,这一点第4章会详细讲。

3. 导入SQL与本地跑通:从命令行到浏览器呈现的完整步骤

3.1 环境版本匹配:JDK 8、Tomcat 9与MySQL 5.7组合

拿到项目后第一步不是看代码,而是把版本统一。项目里的Java代码按JDK 8语法编写,Tomcat建议用9.0(Servlet 4.0规范),MySQL优先5.7。我做过一个对照:

组件建议版本理由
JDK1.8与代码语法一致,配置JAVA_HOME后IDE可识别
Tomcat9.0.x支持Servlet 4.0,默认端口8080兼容课设环境
MySQL5.7.x对utf8mb4、DATETIME默认值支持好,导入脚本零报错
数据库IDENavicat / DataGrip只是执行脚本工具,命令行也可以

如果你的机器已经装了MySQL 8.0,不用卸载,把JDBC驱动换成mysql-connector-java 8.0.x,URL里加serverTimezone=Asia/Shanghai和allowPublicKeyRetrieval=true,也能跑通。但第一次复现不要两边同时换版本,出问题没人帮你分担排查负担。先按5.7组合跑通,再升级才有对比依据。

3.2 执行建库脚本:mysql命令与SQL文件导入

Windows下打开cmd,macOS/Linux打开终端,先以root登录MySQL:

# 先用账号密码登录MySQL,再执行source导入 mysql -uroot -p

登录后执行source命令导入项目里的bookstore.sql,注意路径分隔符在Windows里用斜杠或反斜杠都行,但不要包含中文与空格:

# 执行项目自带的建库建表脚本 source D:/course/bookstore/bookstore.sql;

完成后可以验证表是否创建成功:

SHOW DATABASES; USE bookstore; SHOW TABLES;

正常能看到user、category、book、order、order_item。如果报错,先看是不是重复导入导致“table already exists”,项目脚本通常会处理为先DROP DATABASE再CREATE DATABASE;如果报“Unknown collation”,多半是MySQL版本太老,把字符集改成utf8能临时跳过,但不建议长期用。

SQL脚本里一般包含建库、建表、外键、初始数据(管理员账号、分类样例、图书样例)。初始数据非常关键,有了它你一启动就有书可看,不用手工插数据。需要提醒的是,脚本里的DROP DATABASE语句杀伤力很大,它不经过二次确认,如果bookstore这个库名在本地已有其他用途,建议先把脚本备份再执行。

注意:导入前确认库里没有你自己维护的数据;DROP DATABASE不可回滚,没有后悔药。稳妥做法是导入前用mysqldump备份同名库。

3.3 部署到Tomcat:两种IDE的配置与首访验证

Eclipse JavaEE版的操作:File→Import→Existing Projects into Workspace,选中项目根目录;右键项目→Run As→Run on Server,选择本机Tomcat。Eclipse会自动把WebContent目录识别成Web应用根目录,启动后即使不开IDE,也可以直接访问。

IDEA的操作稍微多一步:Run→Edit Configurations→+→Tomcat Server→Local,在Deployment页点+,选择该项目,Application context填/bookstore。配置完成后重启,浏览器访问:

http://localhost:8080/bookstore/index.jsp

首访出现Tomcat默认首页或HTTP 404,按顺序排查三处:Tomcat是否在本机8080端口正常监听;项目是否真正部署到webapps(IDEA里的exploded方式是标记依赖一个输出目录,不等于拷贝文件);Application context填的是不是/bookstore。大多数新人把context写成/bookStore,Linux下大小写敏感,Windows虽然不区分,但代码里req.getContextPath()拼出来的路径不对一样会出问题。

另一个常见现象:修改了Java代码重启Tomcat后页面还是旧逻辑。根因是Eclipse或IDEA的增量发布没有把class文件同步,或者旧目录残留在webapps下。简单做法是先Clean Tomcat工作目录、Remove部署项,再重新Run on Server。Service层和DAO层的改动,热部署经常不生效,直接重启最省时间。

启动出错的日志位置也要知道:Tomcat/logs目录下catalina.日期.log记录启动过程,localhost.日期.log记录应用请求异常;控制台看不到完整堆栈时,先去看log文件。

4. 核心功能代码解析:登录、购物车与订单三块最能抄的部分

4.1 登录模块:验证码校验、MD5加密与Session管理顺序

登录是所有功能入口,答辩也往往从这里开始问。标准流程是:页面填用户名、密码、验证码,提交到LoginServlet,先校验验证码,再验证用户。代码骨架如下:

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); String username = req.getParameter("username"); String password = req.getParameter("password"); String captcha = req.getParameter("captcha"); HttpSession session = req.getSession(); String sessionCaptcha = (String) session.getAttribute("captcha"); // 验证码比较:忽略大小写,对用户更友好 if (sessionCaptcha == null || !captcha.equalsIgnoreCase(sessionCaptcha)) { req.setAttribute("msg", "验证码错误,请重新输入"); req.getRequestDispatcher("/login.jsp").forward(req, resp); return; } // 密码加盐后做MD5,避免直接使用原始散列 User user = userService.login(username, MD5Util.md5(password + username)); if (user == null) { req.setAttribute("msg", "用户名或密码错误"); req.getRequestDispatcher("/login.jsp").forward(req, resp); return; } session.setAttribute("loginUser", user); session.setMaxInactiveInterval(30 * 60); // 单位秒,30分钟不活动自动失效 resp.sendRedirect(req.getContextPath() + "/book/list"); }

几个关键参数说明如下:setCharacterEncoding必须在读取任何参数之前执行,否则中文用户名乱码;验证码比较用equalsIgnoreCase,避免用户混淆大小写;session.setMaxInactiveInterval(30 * 60)把会话有效期设为30分钟,单位是秒,别误写成30;登录成功后只放User对象,不要连密码都带进Session,后面其他页面通过session.getAttribute("loginUser")取用户信息。

MD5加密这里有个容易被批评的点:直接MD5受彩虹表威胁。课程设计阶段可以用MD5+盐值,比如MD5(password + username)再做一次,简单而且在答辩里说得通“加盐降低撞库风险”。如果想让代码更像工业实现,引入BCrypt也行,但会让依赖变多,看学校要求取舍。

4.2 购物车模块:Session购物车与数据库购物车的特性对比

购物车是网上书店交互最重的地方。两种方案我分开说。

Session购物车适合“游客可以加购、结算时再登录”的产品流程。实现方式是在Session里存一个Java对象Cart,里面用Map<Integer, CartItem>维护图书ID到购物车行的映射:

public class Cart { private Map<Integer, CartItem> items = new HashMap<>(); public void add(Book book, int quantity) { CartItem item = items.get(book.getId()); if (item == null) { // 第一次加入该图书,新建购物车行 items.put(book.getId(), new CartItem(book, quantity)); } else { // 已有同款图书,累加数量 item.setQuantity(item.getQuantity() + quantity); } } public void remove(Integer bookId) { items.remove(bookId); } public double getTotalPrice() { double sum = 0; for (CartItem item : items.values()) { sum += item.getPrice() * item.getQuantity(); } return sum; } }

CartItem里除了bookId、quantity,还应该有价格快照和书名,渲染列表就不用join数据库。getTotalPrice用item.getPrice()而不是重查book表的当下价格,这是故意为之的“价格快照”设计:用户加购时看到的价格就是结算时价格,避免结算时价格突变。真要实现“结账按最新价格”,需要在提交订单前给用户重新展示一次明细并确认。

Session购物车的缺点是:服务重启后Cart对象丢失,用户换浏览器也丢。如果产品要求“登录后购物车不丢”,就要用数据库购物车表。数据库方案加购时用INSERT...ON DUPLICATE KEY UPDATE,而不是先SELECT再INSERT两步,减少一次来回,也避免竞态。但从课设的评审目标看,Session购物车配合getTotalPrice快照已经能完整展示HashMap、对象设计、会话跟踪三个考点,做数据库购物车反而可能把课时耗在表设计上。

4.3 订单生成与库存扣减:事务是最后的防线

订单提交是网上书店里最容易出隐性Bug的地方。用户点击下单,系统要做四件事:插入order主表生成订单号、批量插入order_item明细、扣减book.stock、累加book.sales。这四个动作要么全成功,要么全失败。

我见过A同学的项目,下单成功后订单明细有、库存没减,排查到凌晨才发现写的是“每个DAO方法内部各自拿一个Connection”。数据库事务天然绑定连接,跨连接无法保证原子性。下面是正确的Service层写法:

public boolean createOrder(Long userId, Map<Integer, Integer> cartItems) { Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); // 关闭自动提交,事务边界开始 Order order = new Order(); order.setUserId(userId); Long orderId = orderDao.insert(conn, order); for (Map.Entry<Integer, Integer> entry : cartItems.entrySet()) { int bookId = entry.getKey(); int quantity = entry.getValue(); Book book = bookDao.getById(conn, bookId); if (book.getStock() < quantity) { throw new StockNotEnoughException("库存不足: " + book.getTitle()); } orderItemDao.insert(conn, orderId, book, quantity); bookDao.decreaseStock(conn, bookId, quantity); } conn.commit(); return true; } catch (Exception e) { rollback(conn); return false; } finally { DBUtil.close(conn); } }

每个DAO方法都显式接收Connection,保证所有SQL走同一个连接、同一个事务。setAutoCommit(false)之后,除了SELECT,所有写操作都要等commit才生效;任何一步抛异常,rollback把前面插入的订单和明细一起撤掉。库存判断这段,先查book再判断stock >= quantity,这其实是乐观检查;更稳的是下面这种条件更新,让数据库判断库存够不够:

-- 条件更新:库存足够才扣减,受影响行数为0说明库存不足 UPDATE book SET stock = stock - ? WHERE id = ? AND stock >= ?

受影响行数为0,说明库存不足,Service层抛异常回滚。这样就把“先查再改可能超卖”的窗口期问题交给数据库解决。课程设计评委问到“如何防止超卖”,你答出条件更新加事务回滚,已经超出基本预期。

5. 避坑指南:把网上书店跑通路上的五个高发问题

5.1 中文乱码:JSP、Servlet、JDBC三处编码必须统一

现象:注册中文用户名,提交后查询出来是“???”,或者页面上显示一堆菱形乱码。

原因:三处编码不一致。JSP页面声明用GBK,浏览器发送表单时编码却是UTF-8;Servlet没有在读取参数前指定字符集,MySQL连接串又没加characterEncoding;数据在写入时已经损坏,任何显示层修复都无效。

解决:JSP文件头部统一用contentType="text/html; charset=UTF-8"和pageEncoding="UTF-8";Servlet入口第一行加req.setCharacterEncoding("UTF-8");JDBC URL追加characterEncoding=UTF-8;建表时用utf8mb4。改完重启Tomcat再测,浏览器缓存也清一下。这是定位乱码最快的一组检查项,我每次帮人看课设问题都先问这三处。

5.2 数据库连接失败:MySQL 8.0的驱动类名和时区参数

现象:用MySQL 8.0启动项目,报Public Key Retrieval is not allowed,或者ClassNotFoundException: com.mysql.jdbc.Driver。

原因:MySQL 8.0的官方驱动把主类从com.mysql.jdbc.Driver改成了com.mysql.cj.jdbc.Driver,默认连接也不再用老旧的认证插件;连接串缺少serverTimezone时,驱动无法确定会话时区会直接抛SQLException。

解决:驱动Jar替换为8.x版本,驱动类名写成com.mysql.cj.jdbc.Driver,URL形如jdbc:mysql://localhost:3306/bookstore?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false。这里allowPublicKeyRetrieval=true是因为8.0默认的caching_sha2_password认证在非SSL连接下需要显式允许检索公钥;useSSL=false关闭SSL警告。逐个参数都能在答辩时解释,这本身就是加分项。

5.3 登录成功跳转404:Context Path与注解映射的叠加问题

现象:登录成功,地址栏显示/book/list,页面却是404;单独访问某个JSP可以,一到Servlet就找不到。

原因:路径不匹配。Servlet映射是/book/list,但web.xml里的url-pattern实际是/list;或者项目部署context是/bookstore,代码里跳转用了绝对路径/book/list,少了一层上下文。还有一个隐蔽问题:同时使用@WebServlet注解和web.xml配置同一个Servlet时,web.xml优先于注解,你改了注解路径但不改web.xml,新路径根本不生效。

解决:启动时先确认项目访问根路径;代码里跳转统一用req.getContextPath()拼接项目前缀;如果用了注解映射,检查web.xml里是否还残留同名servlet-mapping,删掉其中一套。排查404时,看Tomcat localhost日志比看浏览器控制台有用,日志里会明确写出请求对应的URI。

5.4 Session 丢失:Cookie的Path与服务器会话策略

现象:本地运行登录成功,跳转到另一个模块再回来就要求重新登录;同一浏览器换了电脑或清除数据后会话也失效。

原因:浏览器保存SessionId依赖Cookie,如果Cookie的Path设置得不合适,浏览器只在部分路径下携带JSESSIONID;另外,如果你的项目在多个端口部署,Cookie作用域名不匹配也会丢失。

解决:先开开发者工具看Application→Cookies,确认JSESSIONID的Path是否覆盖项目根路径。若手动写Cookie,要写Path=/,表示根路径下全部携带;不要设过期时间让Cookie变成会话级Cookie,否则关闭浏览器就丢。还有就是Tomcat的session-config里session-timeout单位是分钟,要明确知道改了哪个值,别把30分钟写成30秒。

5.5 上传图书封面无法显示:物理路径与虚拟路径没有对应

现象:后台能上传图片,数据库里也存了/images/upload/1.jpg,但前台img标签一直裂图,文件明明在服务器目录里。

原因:图片写到了服务器磁盘某个物理路径,而Web应用通过URL访问的资源根目录是WebContent或webapps下的应用目录;浏览器请求的/images/upload/1.jpg并不会自动落到物理路径上,除非你配置了路径映射。

解决:课设项目最简单的办法是把上传目录放在WebContent/upload,然后以相对路径访问,比如"upload/1.jpg"。如果老师要求目录不能随部署覆盖丢失,那就给Tomcat配置虚拟目录映射:

<!-- 将 /bookstore/images 请求映射到磁盘目录 /var/upload/images --> <Context path="/bookstore/images" docBase="/var/upload/images" />

加在Tomcat的conf/server.xml或应用META-INF/context.xml中,docBase指向系统实际存储目录。配置后,所有以/bookstore/images/开头的请求都会映射到物理目录。注意虚拟目录的上下文路径必须和项目context一致,否则仍然404。上传文件名也别直接拼接用户输入,统一用UUID重命名,既防路径穿越也避免中文文件名乱码。

6. 进阶技巧:把列表查询从“跑得动”改成“扛得住翻页”

6.1 深翻页性能分析与游标分页实测

课程设计做到列表分页后,很多人会写LIMIT 0, 10。这个写法在数据量小的时候没问题,但在后台管理页看第1000页商品时,数据库需要先扫描并丢弃前一万行,再返回目标页。更糟的是SELECT *的深翻页,每一行都要回表查询完整数据,开销成倍增长。

我的处理方式是区分两套分页写法。传统的页码分页保留给后台列表,但把SELECT *改成先查主键再回表:

-- 先拿主键,再按主键取完整行,避免大offset直接回表 SELECT * FROM book WHERE id IN ( SELECT id FROM book ORDER BY create_time DESC LIMIT 100000, 10 ) ORDER BY create_time DESC;

前台“上一页/下一页”则用游标分页,连偏移量都省掉:

SELECT id, title, author, price, stock FROM book WHERE create_time < ? ORDER BY create_time DESC LIMIT 10;

Java侧配合游标参数:

public List<Book> pageByCursor(String lastTime, int size) { String sql = "SELECT id, title, author, price, stock FROM book " + "WHERE create_time < ? ORDER BY create_time DESC LIMIT ?"; // lastTime 绑定上次返回的最后一条记录时间,size 固定为每页行数 }

不要直接拼表名和字段名,全走PreparedStatement参数绑定。注意create_time必须有索引,否则范围过滤也会全表扫。某个模拟项目X上,我用10万条数据做了对比:LIMIT 100000, 10执行时间接近800毫秒,游标分页稳定在30毫秒以内,差距在20倍以上。从那以后我每次接手带列表页的课设,都先强制走一遍EXPLAIN,看到Extra里出现Using filesort或Scan就停下来修索引,再继续写其他功能。希望帮到你。

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

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

VC6.0 CRT源码缺失真相与可调试环境重建指南

简介&#xff1a;本资源是针对 Visual C 6.0 开发环境缺失标准 C 运行时库源码问题的专项补全包&#xff0c;面向使用 VC6.0 进行底层开发、教学演示或源码级调试的 C/C 初中级开发者。VC6.0 安装后常缺少 VC98\CRT\SRC 目录&#xff0c;导致无法查看 printf、malloc、memcpy 等…

作者头像 李华
网站建设 2026/10/11 2:13:28

PJ85718DM+STM32F437ZG:HVAC高抗扰温度采集系统设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/11 2:13:14

ArcGIS SHP转TXT:精准控制坐标精度与几何结构的底层解析方案

简介&#xff1a;本资源是一套面向GIS从业者与空间数据处理初学者的ArcGIS实用工具包&#xff0c;聚焦Shapefile与文本格式间的双向转换需求&#xff0c;特别适用于土地利用分析、占补平衡核算及跨平台数据交换等实际业务场景。压缩包共11个文件&#xff0c;含1个核心ArcGIS工具…

作者头像 李华
网站建设 2026/10/11 2:12:11

华为鸿蒙免费外卖记录工具—小羊外卖

名字容易误会&#xff1a;小羊外卖不接单、不送餐&#xff0c;只帮你把点过的留下来。盼你装上&#xff0c;先记最近一顿——下次饭点纠结&#xff0c;可以从自己的味道里抽一家。先说重点① 纯净、无广告、不收费② 记餐厅、菜品、价钱、评分&#xff0c;还能拍小票、复制上次…

作者头像 李华
网站建设 2026/10/11 2:10:31

PSR开关电源EMC设计实战:干扰源抑制与PCB布局要点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/11 2:08:25

前缀和算法核心:8类高频题型与面试实战

前缀和这个东西&#xff0c;说穿了就是预处理一个累加数组&#xff0c;把一堆区间求和从 O(n) 变成 O(1)。我经常跟准备面试的朋友说&#xff0c;如果子数组求和、子矩阵求和这类题老是卡壳&#xff0c;八成是还没把前缀和这套思维真正装进脑子。这篇文章我直接把平时刷题、出题…

作者头像 李华