JSP+Servlet+数据库实现库存商品管理系统完整教程

发布时间:2026/9/9 11:03:27

JSP+Servlet+数据库实现库存商品管理系统完整教程 简介这是一份基于JSPServlet数据库技术栈的简易库存商品管理系统完整项目源码面向正在学习Java Web开发的学生、需要完成课程设计的同学以及希望快速了解传统服务端渲染与JDBC交互的初级开发者。压缩包内含38个文件核心包括9个Java类源文件、6个JSP页面、2个SQL建表脚本另有配置文件与项目说明文档包体积仅148KB属于轻量级教学型项目。系统已覆盖管理员登录校验、商品列表展示、增删改操作、删除二次确认、库存不足10件红色告警、全字段必填校验以及同名同规格商品库存自动累加等实用功能并附带项目.doc说明文档与SQL脚本方便导入MyEclipse后一键部署运行。目前已有1488人学习下载学习曲线平缓非常适合作为Java Web课程设计模板或Servlet/JSP入门实践项目。1. 项目概述与需求分析前一阵子和几个做课程设计的同学聊到JavaWeb练手项目发现很多人卡在同一个问题上选题容易真正落地难。网上也有一堆现成的“XX管理系统”但多半是Spring Boot全家桶代码量不小看起来很高端却很难短时间吃透。更常见的是讲原理的文章一大把可真要动手写一个能跑的JSPServlet数据库项目又不知道从哪下手。这个“简易的库存商品管理系统使用JSPServlet数据库.zip”的标题其实点明了几个关键信息技术栈固定为JSP、Servlet、数据库应用场景是库存商品管理定位是“简易”。这套组合恰恰是JavaWeb最经典、最基础的一环非常适合课程设计、毕业设计选题或者想搞懂Web开发底层原理的初学者。它不像Spring Boot那样把很多东西都封装好了你反而能看到一个Http请求从浏览器进入Servlet、再操作数据库、最终返回页面的完整链路。从功能上看一个库存系统要解决的核心痛点无非三个商品信息如何录入和维护也就是增删改查库存数量怎么管理入库、出库之后数字要跟着变日常操作时怎么快速找到某个商品统计当前库存状态。围绕这三个点项目可以拆成商品管理模块、库存变更模块和系统登录模块。再配合JSP编写界面、Servlet处理请求、数据库存储数据一个基础但五脏俱全的JavaWeb项目框架就出来了。这篇文章我会把这套项目的核心逻辑拆开来讲包括数据库表怎么设计、DAO层怎么写、Servlet和JSP怎么配合、以及打包部署成war包跑在Tomcat上的完整过程。如果你正在做类似的课程设计或者想补齐JavaWeb基础这篇文章可以作为你的“参考模板”。我尽量把每一步都讲透也会把实际编码中容易踩的坑标出来。2. 技术选型与项目环境搭建2.1 为什么选JSPServlet这个组合现在再提JSP可能会让人觉得“过时了”但我不这么看。只要是科班出身老师多半都会让你用这个组合完成一次课设目的不是让你造火箭而是让你理解Web开发最内核的东西HTTP协议、请求响应模型、Session机制、数据库连接以及前后端数据交互的方式。这些基础搞懂了后面学Spring MVC、MyBatis都是事半功倍。更重要的是这个组合的项目量级刚刚好。一个库存商品管理系统表单提交、列表展示、分页查询、登录校验这些都是JSPServlet能优雅完成的典型场景。不会像纯Servlet写页面那么痛苦也不会像Spring Boot那样把细节藏得太深。写完之后你能清楚地说出每一行代码“为什么写在这里”这对答辩和面试都是加分项。2.2 开发环境与版本选择先列一份我实际使用的环境清单你可以直接照着准备JDK: 1.8稳定和Tomcat兼容性好服务器: Tomcat 8.5 或 9.0适配Servlet 3.1/4.0规范数据库: MySQL 5.7 或 8.0本文示例用MySQL 5.7IDE: Eclipse for Java EE 或 IntelliJ IDEA任意数据库客户端: Navicat 或 MySQL Workbench这些软件装起来不难但有几个细节值得注意。首先是Tomcat版本和JDK的匹配问题如果你是JDK1.8建议选Tomcat 8.5这样不会出现版本不兼容的怪事。其次是数据库的编码问题建库时务必将字符集设置成utf8mb4否则后面页面显示中文可能就是一片问号。CREATE DATABASE stock_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;另外如果你是第一次用IDEA开发Web项目建议先在Project Structure里检查一下Artifacts确认导出的WAR包包含了web.xml和lib目录。这个坑我在第5章单独讲。3. 数据库设计与核心表结构3.1 库存系统的实体关系库存商品管理系统的核心实体其实不多我按最简化的方式设计了三张表管理员表admin、商品分类表category、商品表goods。为什么要有分类表呢因为如果你只有一个商品表每次录入商品都要重复输入分类名称容易出错也难维护。把分类抽出来单独存商品表里存分类ID查询时再关联设计上更规范。一张ER图能帮你在答辩时加分不少。你需要画清楚的关联是分类表与商品表是一对多关系一个分类下可以挂多个商品管理员表独立存在和商品表没有直接关联它只管登录校验。3.2 建表SQL与关键字段说明我给出完整的建表语句你可以直接复制执行。-- 管理员表 CREATE TABLE admin ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL ); -- 商品分类表 CREATE TABLE category ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL ); -- 商品表 CREATE TABLE goods ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL, category_id INT, price DECIMAL(10,2) DEFAULT 0, stock INT DEFAULT 0, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_goods_category FOREIGN KEY (category_id) REFERENCES category(id) ); -- 初始化数据 INSERT INTO admin (username, password) VALUES (admin, 123456); INSERT INTO category (name) VALUES (日用品), (数码产品), (办公用品);这里有两个细节需要特别说明。第一是price字段一定要用DECIMAL不要用FLOAT或DOUBLE因为浮点数在金额计算时会有精度丢失。第二是stock字段默认值设为0这样新增商品时就算忘了填库存数据库层也不会报错。商品表的category_id是个外键设计时保留外键约束是为了保证引用完整性。不过实际开发中有些团队出于性能考虑会去掉物理外键只在代码层面做逻辑校验。对于课程设计来说保留物理外键是稳妥的做法数据不容易乱。3.3 JDBC连接数据库的封装数据库连接代码每个DAO里都要用所以最好抽成一个工具类。网上很多教程把连接信息直接硬编码在Java类里这样改起来很麻烦。我建议写一个db.properties配置文件然后用静态代码块加载更加灵活。public class DBUtil { private static String url; private static String user; private static String password; static { try { Class.forName(com.mysql.jdbc.Driver); // 如果用的是MySQL 8.x驱动类要改成 com.mysql.cj.jdbc.Driver // url后面最好加上?useSSLfalseserverTimezoneAsia/Shanghai url jdbc:mysql://localhost:3306/stock_db?useSSLfalsecharacterEncodingutf8; user root; password 你的密码; } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } public static void close(Connection conn, Statement st, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (st ! null) { try { st.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn ! null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } }提示MySQL 8.x的驱动类名和连接URL都变了如果你下载的是mysql-connector-java 8.0以上版本仍然写com.mysql.jdbc.Driver会直接报ClassNotFoundException。这个坑很常见第6章会再提。4. 核心功能实现从登录到商品增删改查4.1 项目目录结构与分层设计开始写代码之前先把包结构规划好。我习惯这么分src/ com.stock.filter/ // 登录过滤器 com.stock.servlet/ // Servlet控制层 com.stock.dao/ // 数据库访问层 com.stock.entity/ // 实体类 com.stock.util/ // 工具类 WebContent/ WEB-INF/ lib/ // 依赖jar包 web.xml css/ // 静态资源 jsp/ // JSP页面这样的分层直白地体现了MVC思想JSP负责视图Servlet负责控制DAO负责数据访问实体类负责封装数据。有些课设会再加一个Service层对于商品库存这种小项目来说不是必须的加了反而让源码显得繁琐。如果你想在答辩时多讲一点设计思想可以提你借鉴了MVC模式。4.2 登录模块与Session校验登录是所有管理系统的第一道门。它实现起来并不复杂前端提交表单Servlet接收用户名和密码调用DAO查询admin表比对成功后把user对象放进Session。这里的关键点是后续的每个操作都要校验Session中有没有这个用户也就是请求是否“已登录”。每个Servlet里都写一遍Session校验很啰嗦我推荐用Filter统一处理。WebFilter(/*) public class LoginFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; String uri req.getRequestURI(); // 放行登录接口和静态资源 if (uri.endsWith(login.jsp) || uri.endsWith(LoginServlet) || uri.endsWith(.css) || uri.endsWith(.js)) { chain.doFilter(request, response); return; } // 其他请求必须要有session if (req.getSession().getAttribute(user) null) { resp.sendRedirect(jsp/login.jsp); return; } chain.doFilter(request, response); } }第一次做这个模块时最容易忽略静态资源放行的问题。如果不加uri.endsWith(.css)这类判断你会发现登录页面能打开但样式全部丢失因为浏览器请求CSS文件时也会被Filter拦下来触发跳转。解决的办法就是上面的放行逻辑页面、CSS、JS、图片等路径统统放行。4.3 商品管理DAO层与Servlet控制层商品模块是整个项目的重头戏基本就是教科书级别的CRUD。实体类Goods没什么好说的几个字段对应表的列就行。DAO层需要提供的接口有这几个查询所有商品、根据ID查询、新增商品、修改商品、删除商品以及分页模糊搜索。我挑两个稍有点难度的来写。分页查询核心是SQL的LIMIT关键字和总记录数的统计。public ListGoods findByPage(String keyword, int pageNo, int pageSize) { ListGoods list new ArrayList(); String sql SELECT g.*, c.name AS categoryName FROM goods g LEFT JOIN category c ON g.category_id c.id WHERE g.name LIKE ? LIMIT ?, ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); ps.setInt(2, (pageNo - 1) * pageSize); ps.setInt(3, pageSize); ResultSet rs ps.executeQuery(); while (rs.next()) { Goods g new Goods(); g.setId(rs.getInt(id)); g.setName(rs.getString(name)); g.setCategoryName(rs.getString(categoryName)); g.setPrice(rs.getBigDecimal(price)); g.setStock(rs.getInt(stock)); list.add(g); } } catch (SQLException e) { e.printStackTrace(); } return list; }这里有两个容易出错的地方。第一LIMIT的偏移量计算是(pageNo - 1) * pageSize很多新手写成pageNo * pageSize结果第一页直接跳过前面几条数据。第二关联查询时商品表有name分类表也有name列名冲突了所以在SELECT里用别名c.name AS categoryName区分实体类里也要有对应的categoryName字段。Servlet层的逻辑则是接收页面参数调用DAO最后决定跳转到哪个JSP。WebServlet(/GoodsServlet) public class GoodsServlet extends HttpServlet { private GoodsDAO goodsDAO new GoodsDAO(); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action request.getParameter(action); if (delete.equals(action)) { int id Integer.parseInt(request.getParameter(id)); goodsDAO.deleteById(id); response.sendRedirect(GoodsServlet?actionlist); } else if (edit.equals(action)) { int id Integer.parseInt(request.getParameter(id)); request.setAttribute(goods, goodsDAO.findById(id)); request.getRequestDispatcher(jsp/goods-edit.jsp).forward(request, response); } else { listWithPage(request, response); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String action request.getParameter(action); if (add.equals(action)) { String name request.getParameter(name); int categoryId Integer.parseInt(request.getParameter(categoryId)); BigDecimal price new BigDecimal(request.getParameter(price)); Integer stock Integer.valueOf(request.getParameter(stock)); goodsDAO.insert(new Goods(0, name, categoryId, price, stock)); response.sendRedirect(GoodsServlet?actionlist); } else if (update.equals(action)) { int id Integer.parseInt(request.getParameter(id)); // 其他字段类似调用goodsDAO.update(goods) } } }这段代码比较“原始”但逻辑就是正常的Servlet写法doGet用于查、删、跳转编辑页doPost用于新增和修改。一个Servlet类干完crud的所有活这在小型项目里没问题也算是一种方便的写法。等你理解了再拆分成多个Servlet也不难。在doPost的开头加request.setCharacterEncoding(UTF-8)是很关键的不加的话提交中文表单时后端接收到的就是乱码。这个方法只对POST请求生效GET请求的参数编码要在Tomcat的server.xml连接器里配置URIEncoding。4.4 前端列表页面与分页条的实现JSP页面建议用JSTL标签库配合EL表达式这样页面里不会有大量散落的Java代码片段。你需要在WEB-INF/lib中放入jstl-1.2.jar和standard.jar加载成功后就可以在页面顶部加% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %。商品列表页的核心部分是表格和分页条表格内容用c:forEach循环输出分页条则是计算总页数后动态生成链接。table border1 tr thID/th th商品名称/th th分类/th th单价/th th库存/th th操作/th /tr c:forEach items${goodsList} varg tr td${g.id}/td td${g.name}/td td${g.categoryName}/td td${g.price}/td td${g.stock}/td td a hrefGoodsServlet?actioneditid${g.id}编辑/a a hrefGoodsServlet?actiondeleteid${g.id} onclickreturn confirm(确定删除该商品吗)删除/a /td /tr /c:forEach /table注意操作列里的删除链接onclickreturn confirm(...)是后端删除操作的最后一道确认关卡防止误点。这个细节虽然简单但在实际使用中确实能救回不少被误删的数据。分页条的写法比较固定前提是Servlet里往request里放了pageNo、totalPage、keyword这几个属性。div 共${totalCount}件商品 a hrefGoodsServlet?actionlistpageNo1keyword${keyword}首页/a a hrefGoodsServlet?actionlistpageNo${pageNo-1}keyword${keyword}上一页/a 第${pageNo}/${totalPage}页 a hrefGoodsServlet?actionlistpageNo${pageNo1}keyword${keyword}下一页/a a hrefGoodsServlet?actionlistpageNo${totalPage}keyword${keyword}末页/a /div4.5 库存数量变化与数据导出功能如果你不想只停留在“增删改查”的层面想给系统加点亮点那可以考虑两个扩展功能入库出库操作和数据导出。入库出库功能并不复杂本质上就是对stock字段做加减法。新增一个入库记录表或者在商品表旁边加一个stock_log日志表每次操作记录数量变化和操作时间。页面里放两个输入框提交后Servlet根据inbound/outbound参数来决定是加还是减。这个功能的价值在于它能直观地反映库存变动的历史也对得上“库存商品管理系统”这七个字。数据导出的话网上讨论比较多的方案是用POI导出为.xlsx但对这个项目来说杀鸡用牛刀了。最简单的实现是直接在Servlet里设置响应头为CSV格式把商品列表的数据用逗号拼接输出浏览器就会自动下载一个csv文件Excel也能正常打开。代码核心就是response.setContentType(text/csv;charsetUTF-8); response.setHeader(Content-Disposition, attachment;filenamegoods.csv); PrintWriter out response.getWriter(); out.println(\ufeff ID,名称,分类,价格,库存); // BOM解决中文乱码 for (Goods g : goodsList) { out.println(g.getId() , g.getName() , g.getCategoryName() , g.getPrice() , g.getStock()); }注意输出CSV时给文件加一个UTF-8 BOM头\ufeffExcel打开才不会出现中文乱码这个小技巧很多教程不会写。5. 项目部署与打包发布5.1 将项目导出为WAR包本地能跑通之后很多课设还要求演示部署或者要交一个可运行的文件这时导出WAR包就是必须的操作。IDEA里的路径是Build - Build Artifacts - 选择你配置好的war包 - BuildEclipse里是右键项目 - Export - WAR file。这里有一个很常见的坑导出的WAR包放到Tomcat后访问却提示404。八成是你配置Artifacts时没有把lib目录打进去导致Tomcat运行时找不到MySQL驱动类。检查方法是解压WAR包看WEB-INF/lib下是否有mysql-connector-java的jar包没有的话就回去重新配置Artifacts手动把依赖库添加进去。5.2 部署到Tomcat并启动项目把stock.war复制到Tomcat的webapps目录下进入bin目录Windows下双击startup.batLinux/Mac下执行startup.sh。Tomcat会自动解压war包然后就能通过地址访问了http://localhost:8080/stock/需要注意的是项目的访问路径默认是WAR包名比如stock.war访问根路径就是/stock/。如果你嫌上下文路径太长可以把它改名为ROOT.war这样直接访问http://localhost:8080/就能进系统。这个方法在部署给老师演示时特别实用少输一层路径。部署成功后启动Tomcat看控制台日志只要没有SEVERE异常说明项目起来了。然后用admin账号登录依次测试新增商品、编辑、删除、分页搜索确认功能都正常。6. 常见问题与排查技巧实录6.1 高频问题速查我把自己在开发和辅导过程中遇到的典型问题整理成了表格方便你对照排查症状可能原因解决办法启动Tomcat报端口被占用8080端口被其他进程占用修改server.xml的port或关闭占用进程ClassNotFoundException: com.mysql.jdbc.Driver驱动jar没有放到WEB-INF/lib添加mysql-connector-java jar包并重新部署访问Servlet报404Servlet注解配置错误或包名路径错检查WebServlet(/XXX)和请求路径是否完全一致JSP页面上中文乱码页面编码、请求编码、数据库编码不一致统一设置为UTF-8检查JSP的pageEncoding表单提交后数据乱码未设置request编码在Servlet doPost开头加入request.setCharacterEncoding(UTF-8)分页页码不准确总页数计算错误总页数 (totalCount pageSize - 1) / pageSize修改完JSP页面不生效Idea/Tomcat未重新编译部署重新build项目或重启Tomcat6.2 排查思路与避坑指南上面那个表格是结果但排查过程我得更正一点遇到问题千万别先怀疑代码逻辑先看Tomcat控制台日志。日志里的异常信息是整个问题排查的第一手线索比如ClassNotFoundException说明缺了jar包SQLException: Unknown database说明数据库名字写错了The server time zone value说明连接URL里少了serverTimezone参数。有两个问题值得展开说。第一个是MySQL 8.x连接报错的问题。旧版驱动com.mysql.jdbc.Driver在新版本中已经弃用了如果你用的连接驱动包是8.0以上驱动类要改成com.mysql.cj.jdbc.DriverURL后面还要拼接?serverTimezoneAsia/ShanghaiuseSSLfalse。这个问题在IDEA和Eclipse里都出现过通常报错信息里会直接提示”The server time zone value”。解决思路很简单要么换用5.1.x版本的驱动要么改连接配置。两种方式我都试过建议用第二种毕竟8.x驱动在性能和加密通信上都更完善。第二个是JSP修改后“不生效”的现象。很多人改了页面代码刷新浏览器还是老样子于是怀疑Tomcat缓存。实际上Tomcat默认在开发模式下会对JSP做增量检查但IDE如果没有把修改后的文件同步到部署目录那当然看不到效果。IDEA里要执行Build - Recompile或者干脆点Rebuild Project。如果你发现改了Java方法也没反应检查一下是不是没有redeploy尤其是在用外部Tomcat时热部署往往不被默认启动而是需要在运行配置里指定On frame deactivation: Update classes and resources。6.3 提升答辩印象分的细节代码能跑只是一个基础分想在答辩时有更亮眼的表现你还可以加一些小功能库存预警列表页对低于某个阈值的商品用红色字体标出来用一个colspan判断即可通用下拉框分类查询下拉框的值从数据库动态读取不要写死在页面上日志记录简单记录登录IP和操作时间但要注意隐私合规别过度记录代码结构把DAO层的方法名起的语义清晰比如findByPage、insert、updateById答辩时可以说“我这里的DAO层我感觉接口设计得比较清晰”。实操过程与经验总结到这里整套项目的骨架和血和肉都讲得差不多了数据库的设计、Filter登录校验、Servlet从接收请求到跳转页面的完整链路、JSP展示的细节、WAR包的部署还有我在写代码过程中实打实踩到的坑。说句实在话这套技术栈看起来“老”但它解决了教学中最核心的问题让你亲手写完一个Web系统的未来。现在很多人一上来就学Spring BootCRUD写完却对底层机制糊里糊涂连Servlet和JSP都分不清这样反而不利于成长。我之前带过几个新人凡是能把基于Servlet的项目自己撸一遍的后面接触Spring MVC和MyBatis的适应速度明显快一大截面试时聊HTTP请求、Session原理也能说得有底气。最后再分享一个小技巧开发过程中善用浏览器的“开发者工具”——按F12打开Network面板可以清晰地看到每一次请求的状态码、请求参数、响应时间。比如页面提交失败时它会明明白白显示是404路径写错、500代码异常还是302被过滤器跳转。当你把调试习惯培养起来以后就会觉得JavaWeb开发也没有那么玄乎问题总能一步一步定位。如果你打算把这个项目再做深一点试试加上库存变更记录表或者用ECharts画一个简单的销售趋势图。技术都是旧技术但你能在旧框架里用出新的思路这比单纯追求新框架名号要有意义得多。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/9/9 11:03:27

SD8227竖屏车机刷机实测:精简ROOT+蝰蛇音效,从卡顿到流畅

简介:一份面向掌讯竖屏设备(SD8227/SD8219、768x1024分辨率)的定制系统固件包,版本为 v15ROOT,已完成精简去冗余和预授权 ROOT,适合对设备进行深度自定义、去除预装应用并提升运行流畅度的玩家或维修人员使…

2026/9/9 11:03:27

outskirts和suburb区别:从边缘位置到功能社区,一文讲透

先说结论:outskirts 和 suburb 虽然中文里都能翻译成“郊区”,但它们在英文里的使用场景、语义边界和语感完全不是一回事。你拿“suburbs”去描述一个荒凉的公路边缘地带,或者在正式文书里用“outskirts”指代一个成熟的居住社区,…

2026/9/9 11:03:27

magnitude:面向CLI场景的轻量级本地模型推理运行时

1. 项目概述:magnitude 不是“大小”,而是本地模型推理的底层基石 最近在多个技术社区和开源项目讨论区里,“magnitude”这个词频繁出现在 CLI 工具链、本地大模型服务、Agent 架构设计的上下文中——但它既不是数学里的模长,也不…

2026/9/9 12:18:42

RabbitMQ安装与基本操作

RabbitMQ基本操作: https://blog.csdn.net/Michael_lcf/article/details/124677268 RabbitMQ的5大核心概念: https://blog.csdn.net/Michael_lcf/article/details/126435452 RabbitMQ的队列模式:https://blog.csdn.net/Michael_lcf/article/details/139362674 Rabbi…

2026/9/9 12:18:42

基于Python的中医藏象辨证量化诊断系统的设计与实现

包含:lunwen开题报告开题答辩PPT毕业答辩PPT项目源码 摘 要 目的:本设计旨在深入研究深度学习、集成学习等机器学习理论,并应用相关算法开展中医藏象辨证量化诊断的创新研究和应用,在设计和实现AdaBoost、随机森林、卷积神经网络和…

2026/9/9 12:18:42

Visual Studio高级保存选项:彻底解决编码乱码与换行符问题

如果你经常用 Visual Studio 写代码,大概率碰到过这种场景:明明是一份正常的 C# 工程,从某个仓库 clone 下来之后,所有中文注释全部变成“锟斤拷”;或者辛辛苦苦在 Windows 上改好的 .py 文件,提交到 Linux…

2026/9/9 12:18:42

浅谈Thumbnails压缩gif图片质量的实现方式

Thumbnails是一个比较大众的图片处理工具,类似的工具还有hutool,可以对图片进行裁剪、缩放、旋转、格式转换、水印等。然而它只提供单张图片的压缩,对于gif的压缩,却是需要我们自己去处理。 下面是一段压缩图片质量的代码&#xf…

2026/9/9 12:18:42

工业读码器选型实战指南:从场景到参数全面解析

1. 选型真不是看参数表那么简单,先理清应用场景再谈方案能提出“工业扫码器设备前期选型可以提供方案吗”这个问题的人,多半已经被市面上五花八门的读码器型号搞得有点晕了。我接触过不少做自动化集成的朋友,他们经常拿着一个需求跑来问我&am…

2026/9/9 12:13:41

基于NSGA-II的峰谷电价下电动汽车充电负荷多目标优化实践

这两年做电动汽车充电负荷优化,和电网侧、用户侧的人聊了不少,发现大家不约而同盯上了同一个问题:电动车越来越多,大家下班回家就充电,高峰和高峰撞在一起,变压器扛不住,电费也难看。单纯靠电网…

2026/9/8 7:15:10

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/8 7:15:10

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/9 0:00:48

MHS模型硬件标准:让大模型像调用软件一样控制物理设备

让Claude真正看着显微镜说“这个细胞形态不太对”,或者让大模型自己调一版机械臂的运动轨迹,这事儿听上去已经很接近科幻片了。但你真上手试一次就会发现,模型不缺智商,缺的是一个能插进显微镜、机械臂、激光控制器里的“通用插座…

2026/9/9 0:00:48

AI五大核心方向详解:从机器学习到大模型,零基础转行选哪条?

会有人告诉我,他想转行学AI,但打开招聘网站一看直接傻眼:机器学习、深度学习、自然语言处理、计算机视觉、大模型应用……满屏都是这些词,好像每个都会一点,又好像每个都离自己很远。还有人上来就问“学Python还是学Ja…

2026/9/9 0:00:49

从50行最小循环到生产级AI引擎:工程化改造全解析

直接说干货。这一章我写的不是那种"hello world跑通某个模型"的教程,而是把AI引擎当做一个真正要上线、要被人调用、要扛流量的系统来聊。从最初只有50行的最小循环,到能够承载生产流量的AI引擎,中间差的不是代码量,而是…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/9 10:21:54

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码