尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Spring Boot + MyBatis + JSP图书管理系统实战:从搭环境到避坑全攻略
简介一套基于SpringBootMyBatisJSP实现的图书管理系统完整项目面向Java Web学习者、课程设计及毕业设计人群。系统包含图书增删改查、分类管理、借阅归还、分页展示等核心功能并整合了权限控制能够帮助读者理解SpringBoot自动配置、MyBatis持久层映射、JSP视图渲染以及MVC分层协作的典型流程。压缩包共1192个文件大小95.3MB其中648个class文件为编译产物173个JSP页面负责前端展示148个XML文件用于MyBatis映射与工程配置65个jar为第三方依赖另有Java源码、图片、CSS与JavaScript等辅助资源覆盖了从源码到可运行部署的完整工程。已有2207人学习读者可通过本项目快速掌握前后端联动、数据库CRUD与分页查询的实现思路也可将其作为实训或毕业设计的参考基础并根据需要做二次扩展。1. 从空目录到能跑通的图书管理系统网上搜“图书管理系统”翻来覆去就是 springboot mybatis jsp 三件套。看着像旧技术可每年靠它毕业的人一点没少。这个组合能同时解决三件事给学生一个能讲清楚每个环节的完整 Java Web 项目给刚转后端的程序员一套看得懂的 MVC 全链路给公司一个不用引入前端工程构建链的轻量后台。它把 Spring Boot 的自动装配、MyBatis 的 SQL 映射、JSP 的服务端渲染摊在明面上翻车点集中排查路径短。新人照着走能跑通熟练的人能看清边界这套方案适合中小型管理系统不适合高并发和复杂交互前端。下面把它从建工程到做熟讲透。2. 搭建工程骨架Spring Boot 2.7 MyBatis Starter JSP 的启动组合2.1 三个依赖必须按这个姿势配否则一启动就 500JSP 在 Spring Boot 里属于“二等技术支持”官方文档不推荐但也不砍掉所以依赖要自己手动补全。先锁定 Spring Boot 版本 2.7.18这是 2.x 系列的最后一个稳定版本也是目前做 JSP 项目最省心的版本。为什么不用 3.x第 5 章单独讲这里先把最稳的组合立住。parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.2/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency dependency groupIdorg.apache.tomcat.embed/groupId artifactIdtomcat-embed-jasper/artifactId scopeprovided/scope /dependency dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId version1.2/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-devtools/artifactId scoperuntime/scope optionaltrue/optional /dependency /dependencies这段配置有三个关键点。第一spring-boot-starter-web自带内嵌 Tomcat但它不包含 JSP 编译器所以必须单独引tomcat-embed-jasperscope 用provided是因为部署到外部 Tomcat 时容器自己带这个库避免两套 Jasper 打架。第二jstl是 JSP 页面里c:forEach、c:if这些标签的来源不引的话标签会原样输出到页面上。第三mybatis-spring-boot-starter2.3.2 对应 MyBatis 3.5.x和 Spring Boot 2.7 是官方测过的配对别随手升到 3.x。2.2 springboot项目结构JSP 不能放 templates必须放 webapp/WEB-INF很多新手在这里栽跟头在src/main/resources/templates下建了bookList.jsp启动后访问永远 404。原因在于 Spring Boot 的模板自动配置只认 Thymeleaf、Freemarker 这类模板引擎JSP 不归它管。JSP 由InternalResourceViewResolver通过 Servlet 容器直接编译文件必须放在src/main/webapp下。src/main/java/com/example/library/ ├── LibraryApplication.java ├── controller/ │ └── BookController.java ├── service/ │ ├── BookService.java │ └── BookServiceImpl.java ├── mapper/ │ └── BookMapper.java └── entity/ ├── Book.java └── BorrowRecord.java src/main/resources/ ├── application.yml └── mapper/ └── BookMapper.xml src/main/webapp/WEB-INF/jsp/ ├── bookList.jsp ├── bookAdd.jsp └── login.jsp我一般会把 JSP 放webapp/WEB-INF/jsp而不是webapp/jsp。区别在于 WEB-INF 目录对浏览器不可见用户没法通过 URL 直接访问.jsp源码文件只能由 Controller forward 转发过去等于白送一层安全防护。另外启动类LibraryApplication.java的包名必须覆盖controller/service/mapper这些子包SpringBootApplication默认扫描的是它所在包及以下如果启动类放错包Mapper 接口注册不上运行时就会报Invalid bound statement。2.3 application.yml 三项配置决定页面能不能被找到JSP 项目里 application.yml 的内容比普通 REST 项目多三样东西视图解析器前缀后缀、MyBatis 映射文件位置、驼峰映射开关。server: port: 8080 servlet: context-path: / spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/library?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: root mvc: view: prefix: /WEB-INF/jsp/ suffix: .jsp mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.library.entity configuration: map-underscore-to-camel-case: truespring.mvc.view.prefix和suffix是视图解析器的核心参数。Controller 里写return bookList解析器会拼成/WEB-INF/jsp/bookList.jsp交给容器渲染这俩配置少一个页面就找不到。mybatis.mapper-locations指定 XML 映射文件的位置classpath:mapper/*.xml对应src/main/resources/mapper目录。map-underscore-to-camel-case打开后数据库的create_time自动映射到实体类的createTime不用手写一堆resultMap。连接串里的serverTimezoneAsia/Shanghai不加的话MySQL 8 驱动会直接报时区异常。2.4 建表图书、用户、借阅记录三张表一次性到位图书管理系统的数据模型不复杂三张表足够覆盖核心业务。下面是完整的建表脚本字段类型和注释直接决定了后面 MyBatis 映射的写法。CREATE DATABASE IF NOT EXISTS library DEFAULT CHARACTER SET utf8mb4; USE library; CREATE TABLE book ( id BIGINT AUTO_INCREMENT PRIMARY KEY, isbn VARCHAR(20) NOT NULL UNIQUE, title VARCHAR(100) NOT NULL, author VARCHAR(50), stock INT NOT NULL DEFAULT 0, state TINYINT NOT NULL DEFAULT 1 COMMENT 1可借 0下架, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE user ( id BIGINT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, real_name VARCHAR(50) ); CREATE TABLE borrow_record ( id BIGINT AUTO_INCREMENT PRIMARY KEY, book_id BIGINT NOT NULL, user_id BIGINT NOT NULL, borrow_time DATETIME DEFAULT CURRENT_TIMESTAMP, return_time DATETIME, status TINYINT NOT NULL DEFAULT 0 COMMENT 0借出 1已还 );字符集选 utf8mb4 而不是 utf8因为 ISBN 里可能有特殊字符用户名也可能有中文和生僻字utf8mb4 是 MySQL 8 的默认字符集能覆盖四字节 Unicode。book.state用TINYINT而不是VARCHAR这样在 MyBatis 的if判断里可以直接用Integer精确匹配避开 OGNL 字符串比较的坑这个坑第 4 章会详细讲。borrow_record.status是借还流水的状态位0 表示借出未还1 表示已还后面做超期提醒全靠它。3. 实现最小闭环图书列表、新增和借阅的完整代码怎么写3.1 BookMapper 的 XML 和注解怎么选实体类字段直接对应数据库列MyBatis 开启驼峰映射后下划线命名自动转驼峰实体里不需要额外加注解。public class Book { private Long id; private String isbn; private String title; private String author; private Integer stock; private Integer state; private LocalDateTime createTime; // getter / setter 省略实际代码里要补齐 }为什么要写Integer而不是int因为 MyBatis 的if teststate ! null判断依赖包装类型int默认值是 0永远不为 null条件判断会失效。接下来是 Mapper 接口只定义方法签名SQL 写在 XML 里。Mapper public interface BookMapper { ListBook selectList(Book query); Book selectById(Long id); int insertBook(Book book); int updateStock(Param(id) Long id, Param(stock) Integer stock); }Mapper注解是关键它让 mybatis-spring-boot-starter 启动时自动扫描并注册这个接口的代理实现。条件查询selectList接收一个Book对象作为查询条件标题、状态都可以塞进去动态拼 SQL。?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.example.library.mapper.BookMapper select idselectList resultTypeBook SELECT * FROM book where if testtitle ! null and title ! AND title LIKE CONCAT(%, #{title}, %) /if if teststate ! null AND state #{state} /if /where ORDER BY create_time DESC /select insert idinsertBook parameterTypeBook useGeneratedKeystrue keyPropertyid INSERT INTO book(isbn, title, author, stock, state) VALUES(#{isbn}, #{title}, #{author}, #{stock}, #{state}) /insert update idupdateStock UPDATE book SET stock stock - 1 WHERE id #{id} AND stock 0 /update /mapperselectList里where标签会自动去掉多余的AND这是 MyBatis 动态 SQL 最常用的写法。CONCAT(%, #{title}, %)这里有个细节#{title}是预编译参数不能直接在占位符里写%title%因为占位符只绑定值LIKE的模糊匹配符要拼在 SQL 文本里。updateStock这行 SQL 是整个借阅流程最关键的操作AND stock 0条件不满足时影响行数为 0Service 层根据返回的行数就能判断库存是否充足这是避免超卖最简单的做法。这里顺带说下 MyBatis 缓存。一级缓存默认开着作用范围是同一个 SqlSessionWeb 项目里每次请求都会新建 SqlSession所以平时感受不到。真正要留意的是二级缓存mybatis 二级缓存实现跨 SqlSession 共享默认不开。图书库存是实时性要求很高的数据这张表不要开二级缓存否则别的模块改了库存你这边 SessionFactory 级别还缓存着旧值。3.2 Service 层借书那天你迟早会为事务买单Service 层是事务的边界Controller 里不要写业务逻辑这是这套架构的规矩。借书操作涉及两张表扣减库存、插入借阅记录任何一个失败都得回滚。Service Transactional(rollbackFor Exception.class) public class BookServiceImpl implements BookService { Resource private BookMapper bookMapper; Resource private BorrowRecordMapper borrowRecordMapper; Override public void borrowBook(Long bookId, Long userId) { // 返回 0 说明库存不足或书不存在直接抛业务异常 int rows bookMapper.updateStock(bookId, 1); if (rows 0) { throw new BizException(库存不足); } BorrowRecord record new BorrowRecord(); record.setBookId(bookId); record.setUserId(userId); record.setStatus(0); borrowRecordMapper.insertRecord(record); } }Transactional(rollbackFor Exception.class)里的rollbackFor必须显式写这是血泪经验。Spring 的默认行为是只对RuntimeException回滚你自己定义的BizException如果继承的是Exception不加 rollbackFor 就永远不回滚库存照样扣记录照样插两边数据就错乱了。Spring Boot 2.x 默认用 CGLIB 代理基于类而不是接口做代理所以事务方法不能用private修饰且不能通过同类内部this调用绕过代理这个坑第 4 章展开说。3.3 Controller、JSP 和 JSTL三个文件拼出一个列表页Controller 返回字符串由视图解析器拼成 JSP 路径这个字符串是逻辑视图名不是物理路径。Controller RequestMapping(/book) public class BookController { Resource private BookService bookService; GetMapping(/list) public String list(Book query, Model model) { model.addAttribute(books, bookService.listBooks(query)); return bookList; } GetMapping(/add) public String addPage() { return bookAdd; } PostMapping(/add) public String add(Book book) { bookService.addBook(book); return redirect:/book/list; } }这里最容易犯的错是把Controller写成RestController。RestController会把返回值当 JSON 输出浏览器里看到的是一串字符串而不是页面。redirect:/book/list是 Post/Redirect/Get 模式表单提交后重定向到列表页用户按 F5 刷新不会重复提交表单。如果这里直接return bookList刷新一次就会插入一条重复数据。JSP 页面里用 JSTL 标签遍历集合这是 JSP 和纯 HTML 最大的区别。% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html head title图书列表/title /head body table border1 trth书名/thth作者/thth库存/thth操作/th/tr c:forEach items${books} varb tr td${b.title}/td td${b.author}/td td${b.stock}/td tda href/book/borrow?id${b.id}借阅/a/td /tr /c:forEach /table /body /html页面第一行的page指令必须写contentTypetext/html;charsetUTF-8保证中文不乱码。taglib指令引入 JSTL 核心标签库不引的话c:forEach会被当普通文本输出。${b.title}走的是 EL 表达式底层调getTitle()。这套写法扩展性很强后面要做 jsp 个人信息展示页面、借阅记录列表复制一个 JSP 改字段就行。4. 四个让图书管理系统翻车的坑每个都是我先踩过的4.1 500 白屏 日志只有两行tomcat-embed-jasper 没加现象项目启动正常访问/book/list直接报 HTTP 500控制台只有两行 INFO 日志看不到完整堆栈。浏览器显示 WhiteLabel Error Page什么有效信息都没有。原因spring-boot-starter-web虽然内嵌了 Tomcat但不包含 JSP 编译引擎。JSP 文件第一次被访问时需要 Jasper 把.jsp编译成.java再编成.class缺了tomcat-embed-jasper这一步直接失败。更隐蔽的是 Spring Boot 3.x 下即使加了 jasper 也会报错因为命名空间从javax.servlet换成了jakarta.servletJSP 的编译 API 全部不兼容。解决回到 Spring Boot 2.7.18按第 2 章的 pom 配置完整引入tomcat-embed-jasperscope 为 provided和jstl1.2。如果团队已经锁了 Boot 3.xJSP 这条路基本没有后悔药最务实的方案是换 Thymeleaf标签写法和 JSTL 接近迁移成本比死磕 jakarta 兼容低得多。4.2 页面出来了但 CSS/JS 全 404静态资源放错目录现象JSP 页面里的表格和文字能显示但样式完全没有浏览器 F12 里一堆红色 404请求路径是/static/css/style.css。原因Spring Boot 的默认静态资源映射是/**自动从classpath:/static、classpath:/public、classpath:/resources这些目录找资源。很多从 Spring MVC 时代过来的人习惯在src/main/webapp/static下建资源目录这个位置在 Spring Boot 内嵌容器里不在默认查找列表内所以全 404。解决把 CSS、JS、图片放到src/main/resources/static/css、static/js下页面引用路径改成/css/style.css不要写/static前缀。如果你想保留/static/**这种 URL 风格可以在 application.yml 加spring.mvc.static-path-pattern: /static/**然后资源还是放classpath:/static下。JSP 在 WEB-INF 下不能被浏览器直接访问但静态资源不用藏放 classpath 下既能被容器加载又不会被 JSP 编译流程干扰。4.3 MyBatis条件不生效OGNL 表达式别用 比较字符串现象列表页加了一个分类筛选下拉框前端传了state1结果 SQL 里没有拼接这个条件查询结果始终是全部数据。这种问题在排查时容易怀疑是参数没传进来实际上参数是对的是if标签里的表达式出了问题。原因MyBatis 的if teststate 1里走的是 OGNL 表达式单引号包住的1会被解析成 Character 字符而state是 String 类型String 和 Character 用比较永远返回 false条件被跳过。这个细节在 Java 代码里写1.equals(state)习惯了根本注意不到但在 OGNL 里语法规则完全不同是 MyBatis 条件不生效最常见的原因。解决双引号才是字符串把if teststate 1换成if teststate 1。更稳妥的写法是转成 toString 比较if teststate ! null and state 1.toString()。最省心的方案是在实体类里把state定义成IntegerXML 里只用if teststate ! null判空既避开 OGNL 字符串陷阱也贴合数据库TINYINT字段类型。4.4 借阅成功但库存没扣事务被同类自调用吃掉现象borrow_record表插入了借阅记录但book.stock没扣减两边数据对不上。日志里没有异常看起来一切都正常。原因事务注解没生效。Spring 的事务是 AOP 代理实现的只有从外部进入被代理对象的方法事务切面才会执行。如果你在BookServiceImpl内部写了一个方法调用this.borrowBook()这个调用发生在代理对象内部直接绕过切面Transactional形同虚设。另外一个近亲病因是业务方法里try-catch捕获了异常并打了一行日志异常被吞掉后事务管理器根本感知不到业务失败自然不会回滚。解决事务方法调用一律通过注入的 Service 对象进行不要用this调内部方法。异常的准则很简单业务代码不做 catch 吞异常如果有需要catch 之后必须重新抛出RuntimeException。借书这种写操作场景看一眼.intValue()或row 0的判断结果确认影响行数符合预期再继续后续操作。5. 版本锁死Spring Boot 2.7.18 和 mybatis starter 2.3.2 是这套组合的甜点参数5.1 为什么卡在 2.7.18javax 和 jakarta 的分界线搜索引擎里“springboot版本太高”这类问题一大半都出在 Spring Boot 3.x 的命名空间迁移上。Spring Boot 3.0 起整个 Java EE 规范从javax.*迁移到jakarta.*涉及 Servlet、JSP、JSTL 等所有 Web 底层 API。这不仅仅是换个 import 路径的问题Tomcat、Jasper 编译器的实现也跟着变了。组件Spring Boot 2.7.xSpring Boot 3.xServlet 命名空间javax.servletjakarta.servlettomcat-embed-jasper完全兼容不兼容mybatis-spring-boot-starter2.3.x 稳定需 3.0.4JSTL 依赖javax.servlet:jstl:1.2jakarta.servlet.jsp.jstl:3.0做 JSP 项目的工程结论是非要用 JSP就锁 Spring Boot 2.7.18配套 mybatis-spring-boot-starter 2.3.2这是经过大量项目验证的甜点参数组合。2.7.x 是 2.x 系列的终点官方持续修复安全漏洞适合中小系统。如果公司新项目硬性要求 Boot 3.x就把 JSP 换成 Thymeleaf模板引擎能力更强页面标签风格和 JSTL 接近迁移成本在可控范围内。5.2 MyBatis 自动配置的黑匣子拆开看一眼mybatis-spring-boot-starter 启动时做了什么这是面试必问点也是排查问题的底层知识。很多人把 MyBatis 初始化当成黑匣子出了问题只会重启其实整个流程可以简化成四步。1. starter 读取 application.yml 里 mybatis.* 配置项 2. XMLConfigBuilder 解析 Configuration对应源码里的 XMLConfigBuilder 类 3. SqlSessionFactoryBean 持有 Configuration构建 SqlSessionFactory 4. MapperScannerRegistrar 扫描 Mapper 接口注册代理对象Spring Boot 整合 MyBatis 后开发人员写 Mapper 接口和 XML容器帮你完成注册和代理。理解这个过程的价值在于当你需要自定义 Configuration 行为比如修改默认缓存策略、增加拦截器插件时你知道该在哪个环节介入。下面是排查 SQL 问题最实用的配置mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true cache-enabled: false log-impl: org.apache.ibatis.logging.stdout.StdOutImpllog-impl是 MyBatis 配置打印 SQL 的开关StdOutImpl 会把执行的 SQL 语句和参数直接打到控制台排查动态 SQL 拼接问题几乎靠它。cache-enabled控制二级缓存false表示关闭。前面说过的一级缓存和二级缓存实现差异很大一级缓存是 SqlSession 级别Web 请求每次新建会话天然隔离二级缓存跨 SqlSession 甚至跨事务网上搜 mybatis 二级缓存实现能搜到一堆但图书库存这种频繁更新的数据开二级缓存就是在给自己埋雷。5.3 换 MyBatis 版本时的依赖树排查套路升级 MyBatis 或者 Spring Boot 之前先看依赖树这是最省时间的排查方式。mybatis-spring-boot-starter 自己拉了特定版本的 mybatis 和 mybatis-spring它们和 Spring Boot 版本有固定配对关系乱升版本最常见的结果就是启动时ClassNotFoundException或者NoSuchMethodError。mvn dependency:tree -Dincludesorg.mybatis:*这个命令只过滤 mybatis 相关的依赖。在 mybatis-spring-boot-starter 2.3.2 下你会看到 mybatis 3.5.13、mybatis-spring 2.1.2 这些版本和 Spring Boot 2.7 的兼容性是有保障的。如果换成 mybatis-spring-boot-starter 3.0.4它的依赖是 jakarta 版本必须同步升级 Spring Boot 3.x否则 javax 包冲突会让整个容器起不来。换版本前先跑这个命令比启动后看红屏日志快得多。6. 做熟之后这套图书管理系统还能往哪里长6.1 登录拦截器闭环的最后一块拼图图书管理系统的功能做完整后还差一个登录拦截器把管理界面保护起来。不加拦截器任何人都能直接访问/book/list管理系统的意义就没了。一个简单的HandlerInterceptor足够public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (request.getSession().getAttribute(loginUser) null) { response.sendRedirect(/login); return false; } return true; } }注册时要把登录页和静态资源放行否则会死循环重定向Configuration public class WebConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns(/**) .excludePathPatterns(/login, /css/**, /js/**); } }登录成功后把用户信息塞进 session后面做超期提醒、借阅记录就能绑定到具体读者jsp 个人信息展示页面也就有了真正的用户态数据。6.2 借阅超期提醒这个功能让系统真正“能用”只把 CRUD 做完系统还停留在演示层面。加一个每天定时跑的还书提醒任务立刻有了运维味。Spring Boot 的Scheduled一行注解就能搞定Component public class BorrowRemindTask { Resource private BorrowRecordMapper borrowRecordMapper; Scheduled(cron 0 0 8 * * ?) public void remind() { ListBorrowRecord records borrowRecordMapper.selectExpiring(); records.forEach(r - System.out.println(提醒还书 r.getBookId())); } }cron 0 0 8 * * ?表示每天上午 8 点触发。别忘了在启动类加EnableScheduling否则这个任务根本不会被执行。selectExpiring对应的 SQL 查询status 0 AND return_time NOW()就能查出超期未还的记录实际系统里把这个输出换成站内信或邮件即可。6.3 收个尾说点实战习惯把这套项目完整做完后我的习惯是在 README 里固定写四件事启动命令、数据库初始化脚本、默认账号密码、要求的 Java 版本。JSP 项目在 IDEA 里直接 run 和打包成java -jar跑行为会有细微差别尤其是静态资源路径和 webapp 的加载时机。所以每次改完代码我都会打一次包用命令跑一遍验证这个习惯帮我拦下过很多“本地好好的部署就挂”的尴尬。这套 springboot mybatis jsp 的实践链路值得完整走一遍希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

ST语言数据类型选型指南:从BOOL到LREAL的精度避坑实践

ST语言数据类型选型指南:从BOOL到LREAL的精度避坑实践

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

📅 2026/10/28 18:20:53
汽车电子四大核心芯片协同设计与选型实战指南

汽车电子四大核心芯片协同设计与选型实战指南

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

📅 2026/10/28 18:20:53
在 .NET 4.0 与 VS2010 的 WinForm 中集成 CefSharp Chromium

在 .NET 4.0 与 VS2010 的 WinForm 中集成 CefSharp Chromium

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

📅 2026/10/28 18:20:53
MORE NEWS

更多资讯

📰

智能从来不是工具,是结构:Copilot 救不了组织

WGA 在 2026 年 10 月发布的一份组织设计报告里引过一项覆盖 5179 名客服的研究:AI 辅助让人均处理量涨了 14%,新手和低技能员工涨了 34%。WGA 据此判断,工作流、排队、升级路径与汇报线,四样一样没碰。 人更快了,组织…

📰

2026日语能力考试N1、N2、N3、N4、N5历年真题及答案合集PDF(2010-2026年)

2026年7月日本语能力测试(JLPT)考试公告2026年度12月日本语能力测试(JLPT)N1–N5级别考试定于12月6日举行。备考资源汇总为协助考生系统备考,现提供以下历年真题资料:资源类型内容说明格式说明真题试卷2010…

📰

CAN 位时序与 500kbps 参数推导:HAL 里看不到 0x001A0005,但它就在那

做车载 ECU 诊断工具链,第一步绕不过去的是把 CAN 波特率配准。我用的是STM32F407ZGT6最小系统板, 它的 CAN_BTR 寄存器有 0x001A0005这个值,要把它从 42MHz 推导出来,才敢说"会 CAN"。一、先确认你的时钟到底是多少CAN 挂在 APB1 …

📰

门店上 AI 项目怎么立项排期?6 个阶段、8 到 12 周参考周期与 3 个最容易返工的节点

门店 AI 项目从立项到上线,中小连锁的参考周期是 8—12 周,其中约 6 周花在数据和评测上。大量项目返工不是因为模型不行,而是立项时把排期压得太紧、数据接入和验收指标没有提前定义清楚。 这篇笔记给一份可直接套用的立项排期表&#xff1a…

📰

2026 AI 全栈开发面试题:前端、后端、模型、部署一篇打通

✍️ 作者:王文峰(外号:神秘小峯 / 山峯)|中国国学、传统文化与代码爱好者的程序人生,期待你的关注和支持! 2026 AI 全栈开发面试题:四层考点全解析 一、AI 全栈 = 四层能力模型 二、交互层:流式是 AI 应用的门面 考点 1:流式输出选 SSE 还是 WebSocket? 考点 2:最…

📰

结合第三方视觉平台开发基本视觉应用,是机器视觉工程师的核心能力之一

结合第三方视觉平台开发基本视觉应用,是机器视觉工程师的核心能力之一。下面从平台选型、典型应用开发流程、关键技能点三个维度展开,帮你梳理一条可落地的路径。一、第三方视觉平台选型 不同平台定位差异较大,选型要看项目规模、预算和团队技…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬