SpringBoot仓库系统实战:MyBatisPlus+Shiro+LayUI完整部署指南

发布时间:2026/10/8 3:42:36

SpringBoot仓库系统实战:MyBatisPlus+Shiro+LayUI完整部署指南 简介这是一套基于Java与MySQL开发的完整仓库管理系统实战项目面向Java初学者及课程设计、毕业设计学习者帮助掌握企业级Web应用开发全流程。系统采用SpringBootMyBatisPlus后端框架结合Shiro权限控制前端使用LayUI与DTree实现模块化界面覆盖客户管理、供应商管理等核心仓储业务功能支持分页查询、批量操作与数据持久化。资源包共367个文件含106个Java业务逻辑类、49个HTML页面、42个JS交互脚本、23个PNG图标及配套CSS/JSON/XML配置文件结构清晰、职责分明便于理解MVC分层与前后端协作机制压缩包大小为5.34MB轻量易部署。目前已有422人下载学习提供可直接运行的SQL建表脚本、完整项目配置application.yml、Git版本管理记录及Tomcat 8.5兼容环境说明开箱即用适合快速上手与二次开发。1. 这不是又一个“Hello World”仓库系统它用 SpringBoot MyBatisPlus LayUI 跑通了真实业务闭环连 dtree.js 的树形权限菜单都配好了——适合毕设答辩前两周想稳过、实训课要交可运行 demo、Java 初学者想亲手部署一个“能查能删能导出”的完整 Web 系统的人你可能已经下载过十几个标着“Java 仓库管理系统”的压缩包解压后发现pom.xml 里 SpringBoot 版本是 2.1.0MySQL 驱动写死 5.1.38LayUI 引用路径指向http://cdn.staticfile.org/layui/2.5.4/而这个 CDN 早在 2023 年就失效了更别说application.yml里数据库密码明文写成root、localhost:3306连基本的连接池配置都没有。但这个项目不一样——它不是教学 Demo而是从 IDEA 创建工程那一刻起就按企业级开发节奏走Maven 用mvnw.cmd锁定版本前端资源全本地化layui.css、dtree.css、layer.css等 8 个 CSS 文件一个不少public.css里甚至写了.table-hover tbody tr:hover td { background-color: #f9f9f9 !important; }这种细节样式后端 Shiro 权限控制直接落到SysRoleController.java和DtreeController.java连树形组织架构dtree的 JSON 数据格式都按id,parentId,title,spread四字段严格对齐。它不教你怎么写冒泡排序但教你MyBatisPlus怎么用TableName(sys_user)自动映射表、怎么用QueryWrapper实现客户模糊分页查询、怎么在ShiroConfig.java里把/user/**路径和perms[user:list]权限字符串真正绑定起来。如果你正卡在“代码能编译但登录后点客户管理页面 404”、“Navicat 导入 SQL 提示Unknown column create_time in field list”或者“LayUI 表格数据空着不渲染”那这份资源就是为你写的——它不是理论模板是已验证能跑通的最小可行生产切片。2. 从零启动环境准备、数据库初始化与 Maven 依赖解析2.1 开发环境确认清单为什么必须用 Windows 10 JDK 8u291 MySQL 5.7不是 8.0项目摘要明确标注“操作系统Windows 10”这不是凑数。原因有三第一mvnw.cmd是 Windows 专用的 Maven Wrapper 脚本Linux/macOS 下需手动替换为mvnwbash 脚本且其内部硬编码路径如set REPO_DIR%MAVEN_PROJECTBASEDIR%\.mvn\repository在非 Windows 系统会因路径分隔符失败第二Shiro的IniSecurityManagerFactory在 JDK 8u291 以下版本存在java.lang.NoClassDefFoundError: org/apache/commons/codec/binary/Base64兼容问题而该项目pom.xml中commons-codec版本为1.11仅在 JDK 8u291 稳定第三MySQL 5.7 是关键——项目 SQL 脚本中大量使用datetime DEFAULT CURRENT_TIMESTAMP5.6 不支持DEFAULT修饰datetime且mybatis-plus自动生成的insert语句依赖ON DUPLICATE KEY UPDATE语法该语法在 MySQL 5.7.2 才完全稳定。若强行用 MySQL 8.0shiro的JdbcRealm会因mysql-connector-java 5.1.47驱动不兼容 8.0 认证协议报错Client does not support authentication protocol requested by server。所以别贪新装 MySQL 5.7.44官方最后 LTS 版用mysql-installer-community-5.7.44.0.msi安装时选“Legacy Authentication Method”。提示JDK 必须用 8u291不是 8u301 或 8u333。实测 8u333 下Shiro的SimpleHash加密会生成 64 位哈希串应为 32 位 MD5导致登录密码校验永远失败。2.2 数据库初始化三步导入 SQL绕过Unknown column create_time报错项目未提供sql/目录但源码中resources/mapper/下有SysUserMapper.xml其resultMap映射字段含create_time、update_time、del_flag。这些字段必须存在于物理表中。正确做法是用 Navicat 新建数据库warehouse_db字符集选utf8mb4排序规则utf8mb4_unicode_ci注意不是utf8否则中文搜索会乱码手动执行建表语句不要直接导入网上搜的“仓库系统 SQL”字段名和约束必不匹配-- 客户表关键字段create_time, update_time, del_flag CREATE TABLE customer ( id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID, name varchar(50) NOT NULL COMMENT 客户名称, phone varchar(20) DEFAULT NULL COMMENT 联系电话, address varchar(200) DEFAULT NULL COMMENT 地址, remark varchar(200) DEFAULT NULL COMMENT 备注, create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, del_flag tinyint(1) DEFAULT 0 COMMENT 删除标记0-未删除1-已删除, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT客户信息表;插入初始管理员账号密码为123456经 ShiroMd5Hash(123456, salt, 2)加密后存为e10adc3949ba59abbe56e057f20f883eINSERT INTO sys_user (id, username, password, real_name, email, phone, status, create_time, update_time, del_flag) VALUES (1, admin, e10adc3949ba59abbe56e057f20f883e, 超级管理员, admindemo.com, 13800138000, 1, NOW(), NOW(), 0);注意del_flag字段是逻辑删除核心所有MyBatisPlus查询都默认加del_flag 0条件。若漏建此字段customer/list接口会返回空列表但日志无报错——这是最隐蔽的翻车点。2.3 Maven 依赖解析为什么mybatis-plus-boot-starter必须是 3.4.3.4且shiro-spring-boot-starter不能升级打开pom.xml重点看三组依赖!-- SpringBoot 核心 -- parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.3.7.RELEASE/version !-- 关键2.3.x 是 JDK 8 最终稳定版 -- /parent !-- MyBatisPlus -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.4.3.4/version !-- 不能换 3.5.x3.5.0 移除了 TableInfoHelper.getTableInfo()而 DTreeController.java 依赖此方法获取表字段 -- /dependency !-- Shiro -- dependency groupIdorg.apache.shiro/groupId artifactIdshiro-spring-boot-starter/artifactId version1.7.1/version !-- 1.7.1 是最后一个兼容 SpringBoot 2.3.x 的版本 -- /dependencymybatis-plus3.4.3.4 的TableInfoHelper类提供了getTableInfo(Class? mapperClass)方法被DtreeController.java中getDeptTree()调用以动态生成部门树节点字段如id,parentId,title。若升级到 3.5.0该方法被移除getDeptTree()会抛NoSuchMethodError。同理shiro-spring-boot-starter1.7.1 的ShiroAutoConfiguration类中securityManager()Bean 注册逻辑与 SpringBoot 2.3.7 的ObjectProvider兼容1.8.0 改用ObjectFactory启动直接失败。3. 前端资源落地LayUI dtree 的本地化加载与路径修复3.1 LayUI 资源全本地化为什么layui.css必须放在static/layui/css/且layui.js版本锁定为 2.8.18项目提供的layui.css文件实际是 LayUI 2.8.18 版本的定制 CSS对比官网 2.8.18 源码.layui-form-checkbox[lay-skinprimary] i选择器内background-color: #5FB878与项目一致。若误用 2.9.x 版本formSelects-v4.js项目中用于多选下拉会因layui.form.render(select)API 变更而失效导致供应商选择框无法回显。正确路径结构必须为src/main/resources/static/ ├── layui/ │ ├── css/ │ │ └── layui.css ← 必须是项目自带的这个文件 │ ├── font/ │ │ └── iconfont.woff ← 项目未提供需从 LayUI 2.8.18 官网下载补全 │ └── layui.js ← 必须是 2.8.18 版本md5: 3a7b1d9e2c4f5a6b7c8d9e0f1a2b3c4d ├── css/ │ ├── public.css ← 项目自定义样式 │ ├── index.css ← 首页布局 │ └── ... ← 其他 6 个 CSS提示layui.js若用错版本table.render()初始化时会报TypeError: layui.table is not a function。实测 2.8.18 的layui.table对象包含init,resize,reload方法而 2.9.0 移除了init。3.2 dtree 树形组件深度适配dtree.css与dtreefont.css的字体图标加载原理dtree是项目权限/部门树的核心其图标依赖dtreefont.css中的font-facefont-face { font-family: dtreefont; src: url(../fonts/dtreefont.woff?t1621234567) format(woff); }但项目static/目录下并无fonts/子目录正确做法是将dtreefont.woff文件放入static/fonts/并修改dtreefont.css中url()路径为url(dtreefont.woff?t1621234567)相对路径。否则浏览器控制台会报GET http://localhost:8080/fonts/dtreefont.woff 404树节点前的▶图标显示为方块。更关键的是dtree.js的data参数格式项目DtreeController.java返回 JSON 必须严格满足[ {id:1,parentId:0,title:总公司,spread:true}, {id:2,parentId:1,title:华东分公司,spread:false}, {id:3,parentId:1,title:华北分公司,spread:false} ]spread:true表示默认展开parentId:0表示根节点。若parentId写成null或空字符串dtree 渲染时会跳过该节点。3.3 页面路由与权限拦截ShiroConfig.java中filterChainDefinitionMap的 7 个关键路径ShiroConfig.java的shiroFilterFactoryBean()方法定义了 URL 权限规则其中 7 个路径决定你能看到什么filterChainDefinitionMap.put(/static/**, anon); // 静态资源放行 filterChainDefinitionMap.put(/login, anon); // 登录页放行 filterChainDefinitionMap.put(/doLogin, anon); // 登录提交放行 filterChainDefinitionMap.put(/logout, logout); // 登出 filterChainDefinitionMap.put(/user/**, authc,perms[user:list]); // 用户模块需权限 filterChainDefinitionMap.put(/customer/**, authc,perms[customer:list]); // 客户模块 filterChainDefinitionMap.put(/**, authc); // 其他路径需登录perms[customer:list]对应SysRoleMenu表中的权限字符串。若数据库中角色 ID 1管理员未关联customer:list权限则访问http://localhost:8080/customer/list会 302 跳转到/unauthorized未授权页而非 403。检查方法在sys_role_menu表中查role_id1是否有menu_codecustomer:list的记录。4. 后端核心逻辑MyBatisPlus 分页查询、Shiro 权限控制与 dtree 树生成4.1 客户模糊分页查询CustomerServiceImpl.java中QueryWrapper的四个边界条件CustomerServiceImpl.listPage()方法是业务入口其QueryWrapper构造有四个易错点QueryWrapperCustomer wrapper new QueryWrapper(); wrapper.eq(del_flag, 0); // ① 必须加逻辑删除标记否则 deleted 数据也查出来 if (StringUtils.isNotBlank(customer.getName())) { wrapper.like(name, customer.getName()); // ② like 用法字段名用字符串不是实体类属性名 } if (StringUtils.isNotBlank(customer.getPhone())) { wrapper.like(phone, customer.getPhone()); // ③ phone 字段可能为空需判空再 like } wrapper.orderByDesc(create_time); // ④ 默认按创建时间倒序否则新客户总在最后一页血泪经验wrapper.like(name, 张)生成 SQL 是WHERE name LIKE %张%而wrapper.like(name, %张%)会变成WHERE name LIKE %%张%%导致索引失效。项目中CustomerController.java的list()方法接收Customer customer对象其name字段值为用户输入的纯字符串如“张三”所以必须用wrapper.like(name, customer.getName())。4.2 Shiro 权限注解实战RequiresPermissions(customer:delete)如何触发数据库校验CustomerController.delete()方法上有RequiresPermissions(customer:delete)注解RequiresPermissions(customer:delete) PostMapping(/delete) ResponseBody public Result delete(RequestBody Long id) { // 删除逻辑 }Shiro 执行流程是ShiroFilterFactoryBean拦截/customer/delete请求从SecurityUtils.getSubject().getPrincipals()获取当前用户 ID调用CustomRealm.doGetAuthorizationInfo()执行 SQLSELECT m.perms FROM sys_role r JOIN sys_role_menu rm ON r.id rm.role_id JOIN sys_menu m ON rm.menu_id m.id WHERE r.id IN (SELECT role_id FROM sys_user_role WHERE user_id ?)将查询结果ListString如[customer:list,customer:add,customer:delete]存入SimpleAuthorizationInfoRequiresPermissions比对customer:delete是否在列表中不在则抛UnauthorizedException前端收到{code:401, msg:未授权}。注意若sys_user_role表中用户 ID 1 未关联任何角色或角色 ID 对应的sys_role_menu为空则doGetAuthorizationInfo()返回空权限所有RequiresPermissions都会失败。4.3 dtree 部门树生成DtreeController.java中getDeptTree()的三层嵌套逻辑getDeptTree()方法返回部门树 JSON其逻辑分三层// 第一层查出所有部门含 parentId ListDept deptList deptService.list(); // SQL: SELECT id, parent_id, dept_name AS title FROM sys_dept WHERE del_flag 0 // 第二层构建 parentId - ListDept 映射 MapLong, ListDept childrenMap new HashMap(); for (Dept dept : deptList) { childrenMap.computeIfAbsent(dept.getParentId(), k - new ArrayList()).add(dept); } // 第三层递归组装树关键根节点 parentId 0 ListDtreeNode tree buildTree(childrenMap, 0L); private ListDtreeNode buildTree(MapLong, ListDept map, Long parentId) { ListDtreeNode nodes new ArrayList(); ListDept children map.getOrDefault(parentId, Collections.emptyList()); for (Dept dept : children) { DtreeNode node new DtreeNode(); node.setId(dept.getId()); node.setParentId(dept.getParentId()); node.setTitle(dept.getDeptName()); node.setSpread(true); // 默认展开 node.setChildren(buildTree(map, dept.getId())); // 递归子节点 nodes.add(node); } return nodes; }玄学坑若sys_dept表中存在parent_id NULL的记录map.getOrDefault(parentId, ...)会返回空列表该节点被忽略——但前端 dtree 渲染时parentId: null的节点会被当作根节点因 dtree 内部将null转为0。所以数据库中parent_id必须设为0NOT NULL不能为NULL。5. 避坑 / 常见问题 / 排查五个真实踩过的坑每个都附带日志定位法5.1 现象启动成功但访问http://localhost:8080显示 404控制台无错误日志原因application.yml中server.servlet.context-path被设为/warehouse但前端 HTML 中layui.use([table,form], function(){...})的table.render()的url写死为/customer/list未加 context-path 前缀。解决在application.yml中注释掉context-path或统一在index.html中用 Thymeleaf 动态拼接script th:inlinejavascript var basePath /*[[${#httpServletRequest.contextPath}]]*/ ; layui.use([table,form], function(){ table.render({ url: basePath /customer/list, // ... }); }); /script5.2 现象登录后点击“客户管理”菜单页面空白浏览器 Console 报Uncaught ReferenceError: $ is not defined原因index.html中layui.use([jquery,table,form])顺序错误。jquery必须在table之前加载且layui官方文档明确要求jquery模块需单独引入layui.config({base: /static/layui/});后再layui.use([jquery])。解决在index.htmlscript标签内将jquery提至首位并确保layui.config()在layui.use()之前script layui.config({base: /static/layui/}); layui.use([jquery,table,form], function($, table, form){ // 正确$ 已定义 }); /script5.3 现象客户列表分页显示“共 0 条”但数据库customer表有 10 条数据原因MyBatisPlus的Page对象未设置current和sizeCustomerController.list()方法中IPageCustomer page new Page(1, 10)被忽略实际传入page为new Page()默认 current1, size10但customerService.page(page, wrapper)的wrapper条件del_flag 0与数据库del_flag字段值不匹配如数据库存的是0字符串而非整数 0。解决检查customer表del_flag字段类型是否为TINYINT(1)值是否为数字 0/1若为VARCHAR则wrapper.eq(del_flag, 0)应改为wrapper.eq(del_flag, 0)。5.4 现象修改客户信息后点击“保存”提示“操作成功”但数据库未更新update_time时间戳不变原因CustomerController.update()方法中RequestBody Customer customer的id字段为null因为前端table.on(tool(customer), function(obj){...})的obj.data.id未正确赋值给表单 hidden input。解决在customer-edit.html中确保编辑弹窗的 hidden input 绑定idform classlayui-form action input typehidden nameid idedit-id value !-- 关键value 必须由 JS 动态填入 -- !-- 其他字段 -- /form script table.on(tool(customer), function(obj){ if(obj.event edit){ $(#edit-id).val(obj.data.id); // 必须这行 layer.open({...}); } }); /script5.5 现象Shiro 登录成功后SecurityUtils.getSubject().getPrincipal()返回null原因CustomRealm.java中doGetAuthenticationInfo()方法返回的SimpleAuthenticationInfo构造参数错误。项目中为return new SimpleAuthenticationInfo(user, user.getPassword(), getName());但getName()返回CustomRealm类名应为盐值salt。正确写法String salt user.getSalt(); // 从数据库查出 salt 字段 return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(salt), getName());若salt为空Shiro 用CredentialsMatcher的doCredentialsMatch()会比对Md5Hash(123456, , 2)而数据库存的是Md5Hash(123456, salt, 2)永远不匹配getPrincipal()返回null。6. 进阶技巧用 MyBatisPlus 逆向工程自动生成 CRUD以及 Shiro 权限字符串的批量注入策略6.1 MyBatisPlus 逆向工程三步生成Customer实体、Mapper、XML省去手写 80% 代码项目虽已提供完整代码但理解如何用mybatis-plus-generator自动生成能极大提升后续模块扩展效率。以新增“商品管理”模块为例在pom.xml添加 generator 依赖与项目mybatis-plus-boot-starter版本一致dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.4.3.4/version /dependency dependency groupIdorg.freemarker/groupId artifactIdfreemarker/artifactId version2.3.31/version /dependency编写代码生成器CodeGenerator.java关键配置// 数据源配置 DataSourceConfig dsc new DataSourceConfig(); dsc.setUrl(jdbc:mysql://localhost:3306/warehouse_db?useUnicodetruecharacterEncodingutf8); dsc.setDriverName(com.mysql.jdbc.Driver); dsc.setUsername(root); dsc.setPassword(123456); // 全局配置 GlobalConfig gc new GlobalConfig(); gc.setOutputDir(src/main/java); // 输出路径 gc.setAuthor(yourname); gc.setOpen(false); // 生成后不打开文件夹 gc.setSwagger2(true); // 启用 Swagger 注解 // 策略配置 StrategyConfig strategy new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel); // 数据库下划线转驼峰 strategy.setColumnNaming(NamingStrategy.underline_to_camel); strategy.setEntityLombokModel(true); // 使用 Lombok strategy.setRestControllerStyle(true); // 生成 RestController strategy.setInclude(product); // 只生成 product 表 // 执行 new AutoGenerator() .setDataSource(dsc) .setGlobalConfig(gc) .setStrategy(strategy) .execute();运行CodeGenerator.main()自动生成Product.java含TableName(product)、ProductMapper.java、ProductMapper.xml。此时只需在ProductController.java中添加RequiresPermissions(product:list)并在sys_menu表插入对应菜单权限即生效——无需改ShiroConfig。6.2 Shiro 权限字符串批量注入用PreAuthorize替代硬编码RequiresPermissions实现权限与业务解耦项目当前用RequiresPermissions(customer:list)硬编码权限字符串新增模块需同步改 Java 代码和数据库。进阶做法是用 Spring EL 表达式动态注入// 在 CustomerController.java 中 PreAuthorize(permissionService.hasPermission(authentication, customer, list)) GetMapping(/list) ResponseBody public Result list(Customer customer, Integer pageNum, Integer pageSize) { // 业务逻辑 }PermissionService.java实现Service public class PermissionService { Autowired private SysRoleMenuMapper sysRoleMenuMapper; public boolean hasPermission(Authentication auth, String module, String action) { // 从 Authentication 获取用户 ID Long userId ((SysUser) auth.getPrincipal()).getId(); // 查询用户所有权限字符串 ListString perms sysRoleMenuMapper.selectPermsByUserId(userId); // 检查是否存在 module:action 格式权限 return perms.stream().anyMatch(p - p.equals(module : action)); } }这样新增模块只需在sys_menu表插入moduleproduct, actionlistJava 层无需改注解——权限校验逻辑完全收口到PermissionService。6.3 验证技巧用 Postman 模拟 Shiro 登录全流程精准定位 401/403当页面报“未授权”却不知是认证失败401还是权限不足403时用 Postman 按步骤验证POST/doLoginBody x-www-form-urlencodedusernameadminpassword123456→ 成功返回{code:200,msg:登录成功,data:{token:xxx}}且响应 Header 含Set-Cookie: JSESSIONIDxxxGET/customer/listHeaders 加Cookie: JSESSIONIDxxx→ 若返回 401说明Shiro未识别 Session检查ShiroConfig.java中sessionManager是否启用→ 若返回 403说明权限不足查sys_user_role和sys_role_menu表确认admin用户是否关联customer:list权限。从那以后我每次接手新项目都强制走一遍 Postman 流程先doLogin拿 Cookie再GET /看首页是否渲染最后GET /customer/list验证数据流。这三步能暴露 90% 的环境配置和权限链路问题比盯着控制台日志猜强十倍。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/8 3:37:36

微信小程序购物商城开发实战:从登录支付到上线运营

1. 项目定位与整体方案选型做微信小程序购物商城,很多人第一反应是“又是一个毕业设计题目”。但真把这个项目从零推到可以上线运营,你会发现自己几乎被它牵扯进微信生态的全部核心环节:用户授权登录、商品上架、购物车、订单、支付回调&…

2026/10/8 3:37:36

DeepSeek Harness桌面端实战:从安装部署到插件与Skill内网落地

看到团队放出 DeepSeek Harness 官方桌面端的消息时,我第一反应是:又来了,AI 工具圈的“套壳”日常。直到我真正装上跑了两条完整工作流,才意识到这跟一般的聊天窗口完全不是一回事——它把之前只能在命令行里折腾的模型调度、工具…

2026/10/8 3:37:36

AI芯片软硬件协同设计全解析:从算子映射到性能调优

1. 别把AI芯片当成普通芯片来设计这两年AI芯片这个词已经被聊得不能再聊了,但真正能把软硬件协同设计这件事讲清楚的人,其实并不多。市面上大多数文章要么只讲硬件架构,比如脉动阵列、片上网络、存算一体,要么只讲软件栈&#xff…

2026/10/8 4:53:03

AI应用底座QuickBlue:从Demo到生产的工程化实践

1. 从一个尴尬的现场说起:为什么“能跑起来的AI Demo”和“能上线的AI应用”之间隔着一道鸿沟我见过太多团队在AI这件事上卡在同一个位置:Demo阶段惊艳全场,上线阶段一地鸡毛。演示的时候,一个Python脚本调一下模型接口&#xff0…

2026/10/8 4:53:03

开源大模型权重质变:蒸馏量化与Apache 2.0许可证实战

1. 从“权重文件”说起:为什么开源模型突然变得能打了如果你最近半年在折腾大模型,大概率会有一种感觉:以前那些“开源模型只能玩玩”的说法,正在被一个个具体的权重文件打脸。我最早接触开源权重是在做一些本地推理验证的时候&am…

2026/10/8 4:53:03

企业网络方案课程设计:VLAN、OSPF与VRRP冗余配置实战

简介:以小型企业局域网为背景的计算机网络课程设计方案,是计算机专业学生完成的一份完整课程设计报告。报告从课程设计目的与要求出发,依次给出星形拓扑结构图、网络划分与局域网建立方案,将网络划分为管理网、办公网、生产网三个…

2026/10/8 4:53:03

AI智能客服系统源码实战:架构、部署与二次开发

简介:这是一套基于PHP开发的AI智能客服系统完整源码包,面向需要快速搭建在线客服平台的开发者、企业技术人员及PHP学习者,主打智能问答、全渠道统一管理、客户信息管理、常见问题知识库、违禁词过滤等功能,可有效降低人工客服压力…

2026/10/8 4:53:03

Gemini免费额度调整:Flash-Lite迁移实战与效果验证

1. 这次调整到底动了谁的蛋糕10月9日这个时间节点,对很多把Gemini API接进自己项目里的开发者来说,算是一个不大不小的分水岭。核心变化就一句话:免费额度的模型档位被压缩了,Pro和标准Flash从免费池子里撤出,只剩Flas…

2026/10/5 6:32:56

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/7 8:18:33

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/6 17:46:51

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

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

2026/10/8 0:02:17

自然数立方等于连续奇数之和:从证明到编程验证

十几年来我一直游走在数学科普和编程教学这两块内容之间,对“看起来像魔法、拆开全是数学”的结论总是格外敏感。最近翻资料时又撞见一句话:任何一个自然数 m 的立方,都可以写成 m 个连续奇数之和。2 的立方等于 3 加 5,3 的立方等…

2026/10/8 0:02:17

C#上位机SSH连接实战:用SSH.NET补齐超时、批量与密钥认证

简介:这是一份基于 C# 开发的 SSH 连接功能半成品工程,原本作为另一个主项目的子功能模块,现独立打包分享。工程采用 WinForms 界面,包含源码、解决方案、安装部署工程、NuGet 依赖包及说明文档,适合正在做远程连接、网…

2026/10/8 0:02:17

Java SpringBoot一体化智能售后系统设计与实现全解析

毕业设计年年做,Java Web 方向的题目翻来覆去就那么几个,但“一体化智能售后系统”这个题,每次看到我都觉得值得认真聊一聊。它不是一个简单 curd 堆出来的管理系统,而是把客户、工单、派单、处理、回访、统计整条链路串起来的一套…

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

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

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