news 2026/10/5 3:45:08

JavaWeb医药管理系统:Servlet+JSP+JDBC分层设计与答辩要点

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaWeb医药管理系统:Servlet+JSP+JDBC分层设计与答辩要点

简介:一套面向计算机专业学生的JavaWeb医药管理系统期末大作业项目包,适合正在做课程设计、毕业设计以及希望进行JavaWeb实战练习的学习者。项目采用典型分层结构,Controller、Dao、JSP页面职责清晰,覆盖客户管理、代理商管理、药品管理与购买管理等核心业务;源码中能看到控制层与数据访问层的完整实现与调用关系,有助于理解JDBC操作、DAO封装和业务层协作方式。源码已经本地编译并运行验证过,附带SQL数据库脚本,导入后可完整复现项目环境,还配有Markdown说明与界面预览截图,便于阅读和二次开发。压缩包共119个文件,包含33个Java源文件、33个class编译文件、30个JSP页面,以及XML配置、JAR依赖、项目配置、数据库脚本等关键文件;源码和编译产物同时提供,既可直接部署运行,也便于对照学习,整包约3.01MB,目录结构清晰,可按模块逐一学习。目前已有94人学习使用过,适合想要获得高分项目参考、快速理解完整Web项目组织方式的学生。

1. JavaWeb医药管理系统:期末大作业拿高分的关键在代码结构

如果你正在为JavaWeb期末大作业发愁,这套医药管理系统值得你花十分钟认真看看。它不是一个花哨的框架项目,而是一个把Servlet + JSP + JDBC这套传统JavaWeb技术栈完整落地的业务系统,覆盖了客户管理、医药公司管理、药品管理、采购下单四大核心模块。项目里Controller、Dao、DaoImpl的类名是真真切切能对应到代码文件的,评审分98分意味着它在功能完整度、代码规范性和演示流畅度上都经得起验收。对正在做课程设计、需要一份"能跑、能讲、能改"的参考源码的同学来说,这个项目的难度适中——既不会像SSM整合那样一堆配置劝退新手,又比单纯的CRUD练习多了业务关联和分层设计,能让你在答辩时讲出东西。

2. 项目结构与本地运行:先把JavaWeb骨架搭起来

拿到压缩包后第一件事不是急着看代码,而是把文件结构和运行方式理清楚。很多同学期末翻车不是因为代码写不出来,而是项目在别人机器上能跑、在自己机器上死活起不来。这个医药管理系统的源代码和数据库是配套的,本地编译可运行,但你需要按它的技术栈去准备环境。

2.1 源码文件拆解:Controller与DaoImpl的角色分工

从项目文件清单来看,这套系统的结构很清晰,是标准的JavaWeb分层写法。Controller类负责接收HTTP请求、解析参数、调用DAO层并返回页面跳转,Dao接口定义数据访问方法,DaoImpl实现具体的SQL操作,Seetable是一个工具类,从名字推测是统一查询或分页展示的辅助组件。

文件类别具体类职责说明
控制层ClientController、AgencyController、MedicineController、BuyController对应客户、医药公司、药品、采购四个模块的请求入口
工具类Seetable通用查询辅助,负责结果集封装或分页处理
DAO基类BaseDao抽取JDBC公共操作,如获取连接、关闭资源、通用增删改
DAO实现ClientDaoImpl、AgencyDaoImpl、MedicineDaoImpl、BuyDaoImpl各业务模块的SQL执行与结果映射

这种结构的价值在于,你答辩被问"你的项目是怎么分层的"时,能很自然地讲清楚:页面请求打到Controller,Controller不直接写SQL,而是调DaoImpl,DaoImpl通过BaseDao拿到数据库连接再执行具体语句。Controller和DaoImpl一一对应的关系也让你加新功能时有明确的落笔位置——新增一个订单模块,就建OrderController和OrderDaoImpl,照着Buy模块的写法复制改造即可。我一般会建议先用五分钟把每个类打开扫一遍,从Controller的方法签名就能看出系统支持哪些操作,这比对着PPT背功能清单靠谱得多。

2.2 IDEA里本地跑起来:Tomcat配置与部署路径

这个项目既然标注了"本地编译过可运行",说明它大概率是一个可以在IDEA里直接导入的Web工程。技术栈是Servlet + JSP + JDBC的情况下,你需要准备:JDK 8或11、Tomcat 8.5或9、MySQL 5.7或8.0、IDEA Ultimate版。

打开项目的操作路径是:IDEA中选择File → Open,选中包含pom.xml或src目录的根文件夹。如果项目是Maven结构,IDEA会自动下载依赖;如果是传统Web工程(没有pom.xml),需要右键项目选择Add Framework Support补上Web能力。接着配置Tomcat:Run → Edit Configurations → 点加号选Tomcat Server → Local,在Deployment选项卡里把项目的war包或exploded版本添加进去,Application context建议填/medicine。

# 典型部署步骤(IDEA菜单路径) 1. File -> Project Structure -> Artifacts -> 点+ -> Web Application: Exploded 2. Run -> Edit Configurations -> 添加 Tomcat Server -> Local 3. Deployment 页签 -> 点+ -> Artifact -> 选择刚才配置的 exploded 包 4. Server 页签 -> 修改 Tomcat 端口(默认8080,如果被占用改成8081) 5. 启动前确认:项目右键 -> Open Module Settings -> Dependencies 里有 Tomcat 依赖

这里的逻辑是:Artifacts配置决定IDEA把项目编译后以什么形式发布给Tomcat,Deployment决定Tomcat启动后加载哪个产物。第一次跑项目报ClassNotFoundException多半是第三步没做,Tomcat找不到Web应用的类文件。Application context填/medicine是为了让访问路径变成http://localhost:8080/medicine/login.jsp,避免直接用根路径时和其它项目冲突。

2.3 数据库初始化:SQL脚本导入与连接配置

数据库文件是这套资源里的核心资产,没有它,代码跑起来也只能看到报错页面。把压缩包里的.sql文件用Navicat或命令行导入MySQL后,库里应该能看到客户表、医药公司表、药品表、采购记录表这几张业务表。表之间有关联关系,比如药品表通过company_id关联医药公司表,采购表通过medicine_id和client_id关联药品与客户——这是期末大作业的加分点,能体现外键设计和业务逻辑,而不是各表孤立存在。

-- 典型的连接配置写法(db.properties 或 JDBC 工具类中) jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/medicine_db?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8 jdbc.username=root jdbc.password=你的数据库密码

连接配置有几点容易卡住新手的细节。MySQL 8.x要求驱动类名写com.mysql.cj.jdbc.Driver,而5.x写com.mysql.jdbc.Driver,版本写错直接报ClassNotFoundException。URL里的serverTimezone=Asia/Shanghai不加上会在连接时报时区错误,characterEncoding=utf8不加乱码。我习惯把数据库密码单独拎出来检查——很多项目源码里的密码和本机不一致,跑不通的第一反应不该是怀疑代码,而是先看这个properties文件。

提示:导入SQL前先确认数据库字符集是utf8mb4,不然药品名称里的生僻字或特殊符号可能存不进去,连带查询展示时出现问号。

3. 从BaseDao到业务模块:JDBC封装的三个细节

用户提到这套项目的DAO层是学习重点,这是大实话。JavaWeb期末项目最容易被问崩溃的地方就在数据访问层——面试或答辩老师不会满足于你"能查出来数据",他们会问PreparedStatement和Statement的区别、连接资源什么时候关闭、SQL注入怎么防。这套系统的BaseDao + DaoImpl结构正好是回答这些问题的现成案例。

3.1 BaseDao的抽取逻辑:连接、增删改、资源关闭三板斧

BaseDao是整套DAO层的底座。虽然源码里没有展开,但从JavaWeb项目的常见写法可以还原它的骨架:一个获取Connection的方法、一个通用的增删改方法、一个关闭资源的close方法。核心价值是把"拿连接、执行SQL、关资源"这三个动作固定下来,让每个DaoImpl不用重复写七行垃圾代码。

// 典型的BaseDao抽象形态(参考此类项目最常见写法) public class BaseDao { // 获取连接:从配置文件读驱动和URL,Class.forName只需要执行一次 protected Connection getConnection() throws SQLException { return DriverManager.getConnection(url, username, password); } // 通用增删改:传入SQL和可变参数,内部统一走PreparedStatement protected int executeUpdate(String sql, Object... params) { try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { for (int i = 0; i < params.length; i++) { ps.setObject(i + 1, params[i]); } return ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); return 0; } } }

这套写法的关键点有三个。第一,用try-with-resources自动关连接和PreparedStatement,避免手动close时忘记处理,Java 7以后的标配;第二,可变参数Object... params让子类调用时传参很方便,传几个都行,不用写重载方法;第三,setObject省去了按类型手动调setString、setInt的麻烦,代码量少一半。对于期末项目来说,这种封装已经足够体现你对JDBC的理解,而且面试追问"你的项目怎么管理数据库资源"时,你可以直接说"所有资源统一在BaseDao的模板方法里关闭"。

3.2 ClientDaoImpl与MedicineDaoImpl:增删改查的标准姿势

DaoImpl的作用是为每个业务表提供具体的SQL操作。拿客户管理模块举例,ClientDaoImpl里应该有按ID查询客户、查询全部客户列表、新增客户、修改客户信息、删除客户这五个最基础的方法。而MedicineDaoImpl除了基础CRUD,通常多一个按关键字模糊搜索药品的方法,因为药品列表页一般带搜索框。

// MedicineDaoImpl中按名称模糊查询的典型实现 public List<Medicine> findByName(String keyword) { String sql = "SELECT * FROM medicine WHERE name LIKE ?"; List<Medicine> list = new ArrayList<>(); try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setString(1, "%" + keyword + "%"); ResultSet rs = ps.executeQuery(); while (rs.next()) { Medicine m = new Medicine(); m.setId(rs.getInt("id")); m.setName(rs.getString("name")); m.setPrice(rs.getBigDecimal("price")); m.setStock(rs.getInt("stock")); m.setCompanyId(rs.getInt("company_id")); list.add(m); } return list; } catch (SQLException e) { e.printStackTrace(); return list; } }

这段代码里值得细说的是LIKE模糊查询和结果集映射。LIKE ?配合"%" + keyword + "%"是JDBC里做搜索的标准做法,注意这里的百分号是拼在参数里的,而不是拼在SQL模板里——如果拼在SQL里写成WHERE name LIKE '%?%'就会报SQL语法错误,这是新手特别喜欢踩的坑。结果集映射这段,每张表的字段和JavaBean的setter一一对应,看着繁琐,但你可以在Seetable这个工具类里做一次封装,把这种"遍历ResultSet然后set值"的重复劳动收敛起来。

3.3 PreparedStatement参数绑定引发的三个改写症状

PreparedStatement是这层代码的绝对主角。它比起直接拼接SQL字符串,至少带来三个质变:第一,SQL结构预编译,数据库能复用执行计划,高频查询的性能更稳定;第二,参数通过setObject绑定,不需要手动处理引号转义——直接拼字符串的时候,用户输入一个' or '1'='1就能把查询条件改写成恒真,预编译后这个输入只被当作普通字符处理;第三,可读性更好,SQL模板和参数值分离,代码评审时一眼能看到查询条件是什么。

// 正确写法:模板和参数分离 SELECT * FROM client WHERE name = ? // 错误写法:直接拼接(存在SQL注入风险) SELECT * FROM client WHERE name = '" + name + "'

在这个资源里检查你自己的理解是否到位,有个自测方法:打开任意一个DaoImpl,看SQL语句里面有没有出现+号拼接变量。如果出现了,说明这个位置有SQL注入风险,也说明写代码的人对PreparedStatement的理解还停在表面。这套源码既然是98分项目,大概率不会出现这种写法,但你把代码改造成自己的过程需要留意——很多同学为了给查询条件加动态排序,不小心就把原来安全的写法改成了拼接。

4. 控制层流转:Servlet怎么把页面、请求和DAO串起来

如果说DAO层是项目的心脏,那Controller层就是项目的神经系统。所有用户操作——点登录、查药品、下单采购——都是先经过Controller,再被翻译成DAO调用。这一章重点拆四个Controller的职责边界,以及一次完整请求从浏览器到数据库再返回页面的路径。

4.1 四类Controller的请求分发逻辑

从类名就能看出这个项目的模块划分:ClientController管客户档案,AgencyController管医药公司资料,MedicineController管药品目录,BuyController管采购业务。每个Controller内部最稳定的结构是一个doGet或doPost方法,里面用action参数做分支判断——这是传统JavaWeb项目最常见的写法,不依赖SpringMVC的注解路由,但也因此更容易被答辩老师追着问"你的请求是怎么路由过来的"。

// 典型请求路径设计(以药品管理为例) POST /medicine/medicineController?action=add -> 新增药品 POST /medicine/medicineController?action=update -> 修改药品 GET /medicine/medicineController?action=delete&id=5 -> 删除ID为5的药品 GET /medicine/medicineController?action=list -> 查询全部药品 GET /medicine/medicineController?action=search&keyword=感冒 -> 模糊搜索

每个action对应一个独立方法,方法内部做三件事:从request取参数、调DaoImpl执行、把结果放进request作用域然后转发到JSP页面。这种设计的优点是扩展新功能不需要改框架,在Controller里加一个else if分支就能完成。缺点也有——当分支超过八个,代码会变得很臃肿,但这属于面试时可以聊的"技术债务"话题,期末项目完全够用。

4.2 一次完整下单流程的链路追踪

BuyController是这个系统里最有业务含量的一块,因为它不只是一个表的操作,而是多个表的联动。假设用户在页面上提交一笔采购单,BuyController大概要执行这样的流程:先接收药品ID、客户ID、采购数量这些参数,调用MedicineDaoImpl查一下当前库存够不够,如果库存不足返回提示,如果够就调BuyDaoImpl插入采购记录,同时更新药品表的库存数字。

// BuyController中下单逻辑的伪代码拆解 public void doBuy(HttpServletRequest request, HttpServletResponse response) { int medicineId = Integer.parseInt(request.getParameter("medicineId")); int clientId = Integer.parseInt(request.getParameter("clientId")); int quantity = Integer.parseInt(request.getParameter("quantity")); // 第一步:查当前库存 Medicine m = medicineDao.findById(medicineId); if (m.getStock() < quantity) { request.setAttribute("errorMsg", "库存不足,当前仅剩" + m.getStock()); request.getRequestDispatcher("/buy/error.jsp").forward(request, response); return; } // 第二步:插入采购记录 int rows = buyDao.insert(new BuyRecord(medicineId, clientId, quantity)); // 第三步:扣减库存成功才继续 if (rows > 0) { medicineDao.decreaseStock(medicineId, quantity); response.sendRedirect("buyController?action=list"); } }

这个流程里的业务逻辑值得跟答辩老师讲清楚:库存校验和扣减不是一个原子操作,如果在真实生产环境会出现超卖风险,需要加事务或锁。期末项目不要求你做成分布式事务,但你主动说出"这里是简化处理,实际生产需要考虑同步问题",评分老师会觉得你是真的做过思考而不是在背代码。参数转换这里也有个扎实的小细节——Integer.parseInt如果用户传了非数字字符会抛NumberFormatException,你可以在catch里做容错处理,这是代码健壮性加分的点。

4.3 页面与后端数据的对接方式

这套系统是JSP页面配合后端渲染,不是前后端分离。页面里的表单submit到Controller,Controller处理完用request.setAttribute塞数据,再用request.getRequestDispatcher().forward()跳转到指定的JSP页面。JSP里用<c:forEach>或<%= %>把数据渲染成表格。

<!-- 药品列表页的核心渲染片段 --> <table border="1"> <tr> <th>药品编号</th> <th>药品名称</th> <th>单价</th> <th>库存</th> <th>所属公司</th> <th>操作</th> </tr> <c:forEach items="${requestScope.medicineList}" var="m"> <tr> <td>${m.id}</td> <td>${m.name}</td> <td>${m.price}</td> <td>${m.stock}</td> <td>${m.companyName}</td> <td> <a href="medicineController?action=edit&id=${m.id}">编辑</a> <a href="medicineController?action=delete&id=${m.id}" onclick="return confirm('确认删除?')">删除</a> </td> </tr> </c:forEach> </table>

JSP页面的数据绑定有几个常见的坑,这里提前点一下。items="${requestScope.medicineList}"里的属性名必须和Controller里setAttribute的名字完全一致,大小写都不能差,否则页面上表格是空的。药品所属公司这一列在数据库里存的是company_id,页面上直接显示ID肯定不行,需要在Service层或Dao层做一次关联查询,把公司名称带出来——这个细节能做到位,说明你的连表查询是过关的。删除操作上的onclick="return confirm(...)"是前端二次确认的常规写法,能防止误删,也显得你考虑了用户体验。

5. 复现与排查:JavaWeb项目最常见的五个坑及处理方法

再好的源码,拿到自己机器上也可能因环境差异翻车。这章整理的是我在复现同类JavaWeb项目时踩过的坑,每一条都按现象、原因、解决的顺序来写,基本都是你实际操作时会遇到的。

5.1 Tomcat启动后访问403或直接404

现象:Tomcat启动日志没有报错,浏览器访问http://localhost:8080/能看到Tomcat主页,但输入项目的访问路径就404。

原因:大多数情况是IDEA部署时Application context和实际项目路径不一致。比如你配置了/medicine但访问时写的是/Medicine(大小写不匹配),或者Deployment里根本没添加Artifact,Tomcat只是个空壳启动。

解决:打开Run → Edit Configurations,进Deployment页签确认Artifact已经添加,把Application context改成/medicine,然后在Tomcat的Server页签点"Update resources"或重启项目。改完后直接访问http://localhost:8080/medicine/看能不能跳转到登录页,如果还不行就打开Tomcat的本地日志看有没有加载到这个Web应用。

5.2 数据库连接报错:Public Key Retrieval is not allowed

现象:启动项目后第一个请求数据库的操作就报错,错误信息里有Public Key Retrieval is not allowed。

原因:这是MySQL 8.x的驱动安全策略导致的。MySQL 8默认使用caching_sha2_password认证,JDBC连接时如果没有明确允许获取公钥,驱动会拒绝连接。

解决:在数据库连接URL上加参数allowPublicKeyRetrieval=true。完整的URL类似jdbc:mysql://localhost:3306/medicine_db?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8。建议这四个参数写全,能一次性把公钥、SSL、时区、编码四个隐患全部规避掉。

5.3 JSP页面中文全是问号或乱码

现象:数据库里的中文数据显示正常,但JSP页面上显示成???,或者表单提交的中文到数据库里变成乱码。

原因:乱码问题的根源是"三端编码不一致"——JSP文件本身的编码、HTTP请求的编码、数据库连接的编码。JSP头部没写<%@ page contentType="text/html;charset=UTF-8" %>,或者Servlet里接收请求时没有调用request.setCharacterEncoding("UTF-8"),就会导致乱码。

解决:在每个JSP页面顶部强制加上<%@ page contentType="text/html;charset=UTF-8" language="java" %>;在所有Controller处理POST请求的第一步加request.setCharacterEncoding("UTF-8");确认数据库连接URL里有characterEncoding=utf8。三条同时满足,乱码九成能解决,剩下的可能是数据库表本身不是utf8字符集,需要ALTER TABLE改一下。

5.4 部署时疯狂报ClassNotFoundException

现象:Tomcat启动后页面能打开,但访问某个功能时报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver或找不到项目里的某个类。

原因:核心原因是Tomcat运行时找不到编译产物或依赖的jar包。MySQL驱动jar包没有添加到WEB-INF/lib下,或者IDEA的Artifacts输出目录和实际编译目录不一致——代码改了一部分,但Tomcat加载的还是旧的class文件。

解决:确认mysql-connector-java的jar包已经复制到WEB-INF/lib目录;在IDEA里执行Build → Rebuild Project,把class文件全部重新编译;查看Project Structure → Artifacts的输出目录是否指向了target/classes或out/artifacts下的正确路径。我一般遇到这种问题直接换个干净路径重新部署一遍,比在日志里猜原因快得多。

5.5 页面能显示但点按钮就500:参数空指针

现象:列表页打开正常,但点击编辑或删除按钮时直接报500错误,日志显示NullPointerException。

原因:Controller从request里取参数时,拿到的值是null,然后直接用这个null去调数据库或做类型转换。常见场景是跳转编辑页时URL写的是action=edit&id=${m.id},但JSP里这个${m.id}的变量名不对,拼出来的URL里就没有id参数。

解决:先在Controller入口打印每个参数的取值,用System.out.println或浏览器URL里直接看参数是否存在。如果确认URL没带参数,就检查JSP里EL表达式的变量名是否和DaoImpl返回的JavaBean属性名一致。另外养成习惯:request.getParameter返回的String,转int之前先判空,一段代码里做三步——取参、判空、转换,能让这类500错误几乎绝迹。

6. 把Seetable用活:你的项目演示比别人的多一个亮点

Seetable这个类在文件清单里存在,但在很多同学手里会被忽略——因为Controller和DaoImpl已经能跑通功能了,工具类看起来就是个不起眼的辅助角色。但我在拆这个项目时发现,Seetable恰恰是能在答辩演示和功能扩展时打出差异化的位置。

这个类从命名推测,大概率是把ResultSet封装成表格数据的工具,可能是按页查询,也可能是把查询结果统一转成List<Map<String, Object>>方便JSP页面用<c:forEach>渲染。不管具体实现是哪一种,你在理解源码后可以做一件事:给它增加一个"动态查询"能力,让Seetable接收表名、条件字段、排序字段三个参数,自动拼接SQL并返回结果集。

// 给Seatable扩展一个通用分页查询方法(改造思路示例) public List<Map<String, Object>> queryByPage(String tableName, int pageNum, int pageSize) { int offset = (pageNum - 1) * pageSize; String sql = "SELECT * FROM " + tableName + " LIMIT ? OFFSET ?"; List<Map<String, Object>> result = new ArrayList<>(); try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) { ps.setInt(1, pageSize); ps.setInt(2, offset); ResultSet rs = ps.executeQuery(); ResultSetMetaData meta = rs.getMetaData(); while (rs.next()) { Map<String, Object> row = new LinkedHashMap<>(); for (int i = 1; i <= meta.getColumnCount(); i++) { row.put(meta.getColumnLabel(i), rs.getObject(i)); } result.add(row); } } catch (SQLException e) { e.printStackTrace(); } return result; }

用了LIMIT ? OFFSET ?做分页,是MySQL里最高效的翻页方式;通过ResultSetMetaData动态获取列名,就不需要为每张表单独写结果集映射了。这段代码你自己实现一遍后,能明显感受到工具类的价值——药品列表加个分页、客户列表加个分页,只需要一行调用搞定,不用在每个DaoImpl里复制粘贴不同的分页SQL。

答辩演示时我的习惯是先把系统完整跑一遍业务流程,然后当场展示这个通工具类支持的表名列表,演示给不同报表切换的灵活性。这个技巧不算难,但很多同学不会往这个方向想,属于成本低、收益高的加分项。答辩那天的血泪经验告诉我:能快速演示"新表接入"要比反复演示增删改查更能让评委记住你的项目。从那以后我每次拿到一个新项目源码,都会先找工具类文件改造一遍再谈其它——把公共能力抽出来、把演示效果做足,这既是对原作者代码的理解,也是项目能力最好的证明。希望帮到你,祝你期末顺利拿下高分。

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

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

大模型上下文管理实战:从Context Mode到对话式AI记忆体系

"我刚才说的那个方案&#xff0c;你直接给个结论吧。"用户这句话发过来的时候&#xff0c;我盯着后台日志看了半天。AI助手回复的是&#xff1a;"请问您指的是哪一个方案&#xff1f;我还需要更多上下文。"那一刻我就知道&#xff0c;这个助手又"失忆…

作者头像 李华
网站建设 2026/10/5 3:44:23

四足机器人机械结构设计全攻略:从构型选材到装配调试

做四足机器人&#xff0c;最难的不是算法&#xff0c;不是电机&#xff0c;而是你画出来的第一版结构能不能在第三次调试的时候不断腿。我见过太多人把精力全堆在步态和强化学习上&#xff0c;结果机械结构一塌糊涂&#xff0c;走着走着关节嘎吱响&#xff0c;跑两步大腿直接断…

作者头像 李华
网站建设 2026/10/5 3:44:22

OpenShell:用注册表为cmd窗口添加毛玻璃圆角效果

你把系统自带的命令提示符窗口玩出过花吗&#xff1f;我指的不是换字体、改配色这种小儿科&#xff0c;而是像终端工具那样给cmd加上毛玻璃模糊、圆角边框、标签页、甚至让窗口半透明置顶。以前这活得靠ConEmu、Windows Terminal这类独立工具才能干&#xff0c;但如果你用的是W…

作者头像 李华
网站建设 2026/10/5 3:44:13

从零设计四足机器人:机械结构选型、自由度分配与调试实战

开这次从零设计一台小型四足机器人&#xff0c;我先画了两个星期的机械结构图&#xff0c;而不是急着买电机。原因很简单&#xff1a;四足机器人是个强耦合系统&#xff0c;机械结构决定了运动学模型的精度、控制算法的余量&#xff0c;甚至整机成本的上限。很多人最后跑不直、…

作者头像 李华
网站建设 2026/10/5 3:44:04

插件加载与激活机制全解析:从failed to load plugins到排查实战

先说实话&#xff0c;插件&#xff08;plugins&#xff09;大概是软件工程里被提及最多、却又最容易被误解的名词之一。前几天我处理一个故障&#xff0c;日志里就一行&#xff1a;failed to load plugins web boot: 2 entries did not activate linxin666/dsh-p&#xff0c;乍…

作者头像 李华
网站建设 2026/10/5 3:43:29

工业嵌入式MRAM存储方案:PIC24与MR25H40CDF SPI驱动实战

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

作者头像 李华