尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
JavaWeb过滤器Filter实战:统一处理编码、登录校验与日志记录
如果你一路跟着 JavaWeb 学到 Day13大概率已经写了不少 Servlet、天天和 Request、Response 打交道也可能在 JSP 里被各种数据展示折磨过。这个阶段你一定会冒出一种感觉太多重复代码了。每个 Servlet 都要手动设置编码每个需要登录的页面都得复制粘贴一段判断 Session 的代码想给系统加个访问日志却发现不知道该从哪个入口统一塞进去。Filter 过滤器就是来解决这类“横切关注点”问题的标准方案。它可以把编码处理、登录校验、日志记录这些和具体业务无关、但又躲不开的逻辑从业务代码里彻底抽出来做成统一拦截、统一处理的组件。这篇 Day13 学习笔记我按照“原理拆解 项目实战”的方式把 Filter 从入门到落地完整梳理了一遍适合已经掌握 Servlet 基础、正处于 JavaWeb 进阶阶段的同学直接抄作业。在本篇笔记里我不会只贴一堆配置代码而是把过滤器为什么这么设计、请求经过过滤器时底层到底发生了什么、多个过滤器以什么顺序执行这些关键问题全部用大白话讲清楚。最后还会带着你做一个贴近真实项目的综合案例统一编码处理、登录状态校验、访问日志记录三个过滤器一次到位。看完之后你不仅能应付作业和面试更重要的是能把“抽公共逻辑”这套思路内化成自己的设计习惯。1. 内容整体设计与思路拆解1.1 Day13 这个节点为什么先学过滤器学习 JavaWeb 有个很典型的“顿悟时刻”第一次发现所有 Servlet 里都在重复做同一件事。比如每个 doGet、doPost 方法第一行都是request.setCharacterEncoding(UTF-8)每个需要登录的页面都要先从 Session 里取用户对象取不到就response.sendRedirect(login.jsp)。一开始你还能忍受写着写着就烦了因为每新增一个页面这些代码就要再复制一遍改一个参数还要全局搜索替换。过滤器就是在这个痛点背景下出现的。它的设计初衷很简单在请求到达 Servlet 之前先把所有请求统一拦一道在 Servlet 返回响应之后再统一拦一道。你可以把过滤器理解成小区门口的保安亭所有进出的车都要在这里过一下保安可以做登记、查证件、查后备箱做完该做的事之后才放行。对应到代码里编码过滤器就是所有请求先过一遍“UTF-8 通道”登录过滤器就是“查证件”日志过滤器就是“登记进出记录”。这个阶段学 Filter 还有一个隐藏价值它是后面学习 SpringMVC 拦截器、AOP 思想的认知铺垫。JavaWeb 里的 Filter 把你带进“横切逻辑”这个思维方式SpringMVC 的 Interceptor 就是把同一套思路换了个更精细的包装。所以在 Day13 这个节点认真搞懂 Filter收益是全链路式的不只是单纯多学一个 API。1.2 过滤器核心原理一次请求的“蹲守点”从底层看过滤器要解决的问题是在不修改 Servlet 源码的前提下给一组 Servlet 增加通用能力。Servlet 规范里定义了javax.servlet.Filter接口Web 容器比如 Tomcat在启动时会创建 Filter 实例并且维护一张“过滤器链”的表。当请求进来时Tomcat 会按照顺序把请求依次交给每一个过滤器最后一个过滤器处理完才会调用真正的 Servlet。我把这个流程拆成几个关键节点帮助你记忆客户端发起请求Tomcat 接收到后根据请求 URL 匹配过滤器映射。命中第一个过滤器执行doFilter中chain.doFilter()之前的代码。chain.doFilter()的作用是把请求放行给下一个过滤器如果这是最后一个过滤器就放行给 Servlet。Servlet 处理完成后响应会沿着原来的链路“逆着”返回每个过滤器中chain.doFilter()之后的代码在此阶段执行。响应最终回到客户端。这里最容易被忽视的知识点是chain.doFilter()前后的代码并不是同时执行的而是“前半段在请求阶段执行后半段在响应阶段执行”。所以如果你想统计一次请求的总耗时就在 doFilter 调用前记一个开始时间调用之后再用当前时间减去开始时间。这个特性在后面实战的日志过滤器里会直接用到。1.3 过滤器的典型应用场景过滤器到底能干什么我在整理这张场景表时是按“请求前拦截、请求后处理、请求前后都处理”三类来归类的理解了分类面试时被问到就能马上举出例子。分类场景核心逻辑请求前拦截登录状态校验检查 Session 或 Token未登录直接跳转登录页请求前拦截权限控制判断当前用户角色是否能访问某 URL请求前拦截敏感词过滤在请求参数进入业务层之前做内容替换请求前拦截统一编码设置设置请求和响应的字符集避免中文乱码请求后处理响应压缩对响应内容做 Gzip 压缩再返回客户端请求前后都处理访问日志与耗时统计记录请求 URL、IP、处理时间请求前后都处理跨域处理在响应头写入 CORS 信息解决前后端分离跨域很多初学者一听到过滤器就只想到登录校验实际上它是 JavaWeb 里做“统一治理”的最好入口。开发里常见的 XSS 防护、SQL 注入拦截、接口幂等校验也都可以用过滤器做基础版本。学 Filter 时如果只看 API 不看场景很容易变成“背代码”所以我更建议你把这张场景表保存在笔记里遇到实际需求时一个一个对照。2. 核心细节解析与实操要点2.1 Filter 接口三大方法与生命周期过滤器接口的方法不多就三个但每个方法背后的生命周期问题都值得掰开讲。public interface Filter { default void init(FilterConfig filterConfig) throws ServletException {} void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; default void destroy() {} }init方法在 Web 应用启动时执行一次并且只执行一次。它拿到的是FilterConfig对象里面可以读取 web.xml 中配置的初始化参数。比如你可以在配置里指定“哪些路径不拦截”然后在这里读取成集合后续做白名单判断。我在实际项目里经常这么干灵活度明显比写死在代码里高。doFilter是每次请求都会执行的也是过滤器真正干活的入口。需要注意ServletRequest和ServletResponse是父接口如果要操作 Http 相关的 API比如获取 Session、设置状态码必须强转为HttpServletRequest和HttpServletResponse。destroy同样是应用卸载时执行一次做资源清理。多数项目里这个方法都是空的但你如果真的在init里开启了数据库连接池或者其他重量级资源记得在这里关闭。三个方法的执行时机用一句话记忆就是启动时 init 一次请求时 doFilter 无数次停止时 destroy 一次。这个生命周期和 Servlet 的 init/service/destroy 高度相似因为它们都是被 Web 容器管理的对象创建和销毁的主动权都在容器手里。2.2 配置方式与 URL 匹配规则过滤器有两种注册方式第一种是传统 web.xml 配置第二种是 Servlet 3.0 引入的WebFilter注解。我接触过不少新手在这两种方式之间“精神分裂”一会儿用注解一会儿用 XML出了问题不知道去哪里找。这里给一个明确建议新项目用注解老项目维护用 XML两者不建议混用。web.xml 里的配置长这样filter filter-nameencodingFilter/filter-name filter-classcom.example.filter.EncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping注解方式就简洁很多WebFilter(urlPatterns /*, initParams WebInitParam(name encoding, value UTF-8)) public class EncodingFilter implements Filter { // ... }关于 URL 匹配规则这个必须记牢因为很多过滤器“没生效”或“拦多了”都是在这里出问题的。规则一共有四种精确匹配/login只匹配这一个路径。路径匹配/admin/*匹配 /admin 开头的所有路径包括 /admin、/admin/user、/admin/user/list。扩展名匹配*.do匹配所有以 .do 结尾的请求。通配符匹配/*匹配所有请求最常用也最容易被误用。很多新手会把/和/*搞混。/在 Servlet 规范里是默认 Servlet 的映射永远不会被过滤器匹配/*是真正匹配所有路径的通配符。写过滤器时绝大多数统一处理场景编码、日志都应该用/*。2.3 FilterChain 执行顺序链式调用的秘密多个过滤器同时存在时执行顺序是最容易踩坑的地方。底层实现可以理解为数据结构里的责任链模式每个过滤器持有对下一个过滤器或 Servlet的引用调用chain.doFilter()就是沿着链条往下传。用两个过滤器举例标注为 FilterA 和 FilterB实际执行顺序是FilterA 前段代码 FilterB 前段代码 Servlet 代码 FilterB 后段代码 FilterA 后段代码这个结果看起来像“栈”先进去的后出来。所以在写多个过滤器时你要想清楚每个过滤器放在哪个位置需要最先执行、最后返回时最后处理逻辑的过滤器应该排在链条最前面需要最靠近 Servlet 的过滤器排在最后面。顺序怎么控制web.xml 方式看filter-mapping的书写顺序从上到下依次执行注解方式比较坑不是按代码书写顺序而是按过滤器类的名字进行字典序排序。比如AuthFilter会排在EncodingFilter前面因为 A 在 E 前面。项目里如果你依赖注解排序建议给类名加上明确前缀比如Filter01Auth、Filter02Encoding这样逻辑一眼就能看出来。我把这块知识总结成一句话过滤器链是“请求自顶向下响应自底向上”配置顺序直接决定执行顺序。3. 实操过程与核心环节实现登录校验 编码处理 日志记录综合案例3.1 案例功能规划与项目结构这一节我带你做一个贴近真实开发场景的小案例场景设定为一个简化版的旅游后台管理系统这也是很多 JavaWeb 课程和毕设里非常常见的业务方向。系统里有用户登录、线路管理、订单管理模块我们只保留最基本的功能重点是把三个过滤器串起来。项目最终效果是这样的所有请求统一 UTF-8 编码不再需要在每个 Servlet 里手动设置。除了登录接口和静态资源其他所有页面都要求登录后才能访问。每次请求都会记录访问日志包括访问时间、请求路径、客户端 IP 和处理耗时。项目结构我建议这样安排src/main/java/com/example/filter/ EncodingFilter.java AuthFilter.java LogFilter.java src/main/java/com/example/servlet/ LoginServlet.java LogoutServlet.java TravelServlet.java src/main/webapp/ login.jsp index.jsp travel/list.jsp用 IDEA 2023 创建项目时选择 Jakarta EE 模板里的 Web Application记得勾选 Servlet 依赖开发时配置一个本地的 Tomcat 9 或 10。这一步如果你还不熟可以选File → New → Project左侧选 Jakarta EE右侧选 Web然后Application Server下拉选择之前配置好的 Tomcat。项目创建完成后在pom.xml或者 Web 结构里确保有 servlet-api 的依赖IDEA 模板通常会自动添加。3.2 编码过滤器最简单也最容易漏的过滤器先写最简单的编码过滤器。这一步其实在 Servlet 的 API 里已经有现成的实现类CharacterEncodingFilter在 Web 框架里可以直接使用但为了搞清楚原理我建议你自己手写一遍。package com.example.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; WebFilter(urlPatterns /*) public class EncodingFilter implements Filter { private String encoding UTF-8; Override public void init(FilterConfig filterConfig) throws ServletException { String param filterConfig.getInitParameter(encoding); if (param ! null !param.trim().isEmpty()) { encoding param; } } Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest (HttpServletRequest) request; HttpServletResponse httpResponse (HttpServletResponse) response; httpRequest.setCharacterEncoding(encoding); httpResponse.setCharacterEncoding(encoding); httpResponse.setContentType(text/html;charset encoding); chain.doFilter(request, response); } Override public void destroy() { // 无需清理资源 } }这里有个细节必须说清楚setCharacterEncoding必须放在chain.doFilter()之前。因为这个方法的作用是告诉容器“请求体使用什么字符集来解码”如果 Servlet 已经读取了参数再设置就晚了参数已经按照默认编码通常是 ISO-8859-1解析过了中文就会变成乱码。还有一个容易被低估的点设置编码不只是request的事response也必须设置。很多项目乱码查了半天最后发现是响应输出给浏览器的编码没有指定导致浏览器用错误的方式解码。上面代码里我设置了setContentType这一步同时指定了页面返回的文档类型是 HTML 以及字符集在实际页面开发里很关键。3.3 登录校验过滤器带白名单的权限控制登录过滤器是整个案例里业务价值最高的一个。它的核心逻辑有三步第一步判断请求路径是否属于白名单属于就直接放行第二步尝试从 Session 获取当前登录用户存在就放行第三步未登录用户统一重定向到登录页。package com.example.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; WebFilter(urlPatterns /*) public class AuthFilter implements Filter { // 白名单登录页、登录接口、注册接口以及静态资源 private static final SetString WHITE_LIST new HashSet(Arrays.asList( /login.jsp, /login, /register.jsp, /register, /css, /js, /images )); Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest (HttpServletRequest) request; HttpServletResponse httpResponse (HttpServletResponse) response; String uri httpRequest.getRequestURI(); String contextPath httpRequest.getContextPath(); // 去掉项目上下文路径只保留应用内路径 String path uri.substring(contextPath.length()); if (isWhite(path)) { chain.doFilter(request, response); return; } HttpSession session httpRequest.getSession(false); Object user session null ? null : session.getAttribute(username); if (user ! null) { chain.doFilter(request, response); return; } httpResponse.sendRedirect(contextPath /login.jsp); } private boolean isWhite(String path) { for (String prefix : WHITE_LIST) { if (path.equals(prefix) || path.startsWith(prefix /)) { return true; } } return false; } }写完这段代码我每次带新手都会专门强调两个细节第一getSession(false)和getSession()的区别。默认的getSession()如果发现没有 Session会自动创建一个新的这样你就永远不可能拦截到“未登录”状态了因为它总能给你一个空 Session。getSession(false)表示没有就返回 null这样才能正确判断未登录。第二白名单匹配不要用字符串的equals简单判断。/login能匹配上但/login/或者页面里引用的/css/style.css就匹配不上。所以我的判断逻辑是要么路径完全相等要么以“白名单前缀 /”开头比如path.startsWith(/css /)。这样/css/style.css、/js/app.js都能被正确放行。3.4 日志过滤器利用请求前后段时间差日志过滤器能同时展示chain.doFilter()前后代码的执行时机我每次讲这块都会让学员打印一下时间亲眼看一看“前段先执行、后段后执行”的效果。package com.example.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; WebFilter(urlPatterns /*) public class LogFilter implements Filter { private static final DateTimeFormatter FORMATTER DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest (HttpServletRequest) request; long start System.currentTimeMillis(); String uri httpRequest.getRequestURI(); String ip httpRequest.getRemoteAddr(); chain.doFilter(request, response); long cost System.currentTimeMillis() - start; System.out.println([ LocalDateTime.now().format(FORMATTER) ] 请求路径: uri | 客户端IP: ip | 耗时: cost ms); } }这段代码展示了过滤器的一个核心能力因为chain.doFilter()会把请求交给下一个组件而这个调用是同步的所以调用结束返回时说明整个 Servlet 处理已经完成。因此chain.doFilter()之前取开始时间、之后取结束时间计算出来的差值就是请求的总处理耗时。应用启动后你在浏览器里访问任意页面IDEA 控制台就会输出一行日志。这种日志在生产环境里一般是不打印到控制台的而是接入日志框架写文件或者日志系统但思路完全一样过滤器就是最佳的日志埋点位置。它能保证所有请求都经过Web 容器里所有访问记录都会在这里留下痕迹。3.5 三个过滤器的组合顺序与效果验证三个过滤器都写完后组合顺序就变得至关重要。如果我用的是注解方式执行顺序按照类名字典序排序因为AuthFilter、EncodingFilter、LogFilter三个类名按字母排序是 A、E、L所以实际执行顺序是 Auth → Encoding → Log。这个顺序在业务上合理吗我的分析是这样的编码过滤器实际上应该最靠前执行因为后续所有组件读取参数都必须基于正确的编码日志过滤器可以放在最外层记录时间也可以放在中间登录过滤器应该优先于具体业务但不能拦截静态资源。所以理想顺序是 Log → Encoding → AuthLog 最外层统计全部耗时然后设置编码最后做登录校验都通过才交给 Servlet。如果想要这个顺序最简单的做法是在 web.xml 里显式配置过滤器映射顺序而不用注解。配置方式如下filter filter-namelogFilter/filter-name filter-classcom.example.filter.LogFilter/filter-class /filter filter filter-nameencodingFilter/filter-name filter-classcom.example.filter.EncodingFilter/filter-class /filter filter filter-nameauthFilter/filter-name filter-classcom.example.filter.AuthFilter/filter-class /filter filter-mapping filter-namelogFilter/filter-name url-pattern/*/url-pattern /filter-mapping filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping filter-mapping filter-nameauthFilter/filter-name url-pattern/*/url-pattern /filter-mapping使用 web.xml 配置时如果类上已经加了WebFilter注解一定要把注解去掉否则会重复注册过滤器的doFilter会被执行两次这是非常隐蔽的 bug。我在实际项目中踩过这个坑查了半天才发现是同一套逻辑同时被注解和 XML 配置了。验证效果时我一般按三个场景测未登录直接访问http://localhost:8080/travel/list.jsp会被重定向到 login.jsp。登录成功后访问同样的地址能正常看到列表页控制台输出两条日志因为登录请求和列表请求都经过了日志过滤器。在表单里输入中文并提交后台 Servlet 获取到的参数不再是乱码。4. 常见问题与排查技巧实录4.1 过滤器不生效先从三个方向查过滤器写了但在页面上完全没效果这是新手问得最多的问题。我一般按三个方向排查第一项目是不是没有重新发布改完过滤器代码后 Tomcat 没有自动热部署需要重启或者重新部署第二urlPatterns是不是写错了比如把/*写成了/导致只匹配默认 Servlet 而不匹配业务请求第三应用上下文路径有没有被忽略很多人在路径匹配时拿全路径去比较忽略了前缀的 contextPath结果永远匹配不上。我自己在排查时有个习惯在doFilter的第一行加上System.out.println(进入了xxx过滤器)然后重启项目随便访问一个页面看控制台有没有输出。如果没输出说明过滤器根本没被加载或者没被匹配到如果输出了再逐步缩小范围。这个土办法比看一堆配置要快得多。4.2 登录过滤器导致死循环一个非常经典的 bug 是这样的用户未登录访问任意页面被过滤器重定向到 login.jsp结果 login.jsp 这个请求又被过滤器拦截又重定向到 login.jsp形成一个无限循环浏览器疯狂刷新最终报错。我见过很多新手在这个问题上卡很久原因就是白名单没有把登录页和登录接口放进去。所以写登录过滤器时第一件事就是先把登录页、登录处理接口、注册页、注册接口、静态资源全部列入白名单。在刚才的实战代码里我用了WHITE_LIST集合来管理这些路径这个方法建议直接抄走。另外一个容易出问题的小细节是重定向路径。sendRedirect里面需要写完整路径包括上下文路径也就是我在代码里写的contextPath /login.jsp。如果不加 contextPath部署到根路径时没问题一旦加了项目名比如部署成/travel重定向就会 404。4.3 过滤器顺序不对注解与 XML 的排序规则差异多个过滤器顺序不对也是高频问题。我之前讲过注解方式按类名排序这里补充一个实际使用建议在项目里如果需要严格的控制顺序建议统一使用 web.xml 方式配置过滤器因为顺序写在文件里谁在上面谁在下面一眼就能看明白。如果用注解类名排序太隐晦很容易在后面加过滤器的时候无意中改变排序结果。还有一个衍生问题如果你看到请求被同一个过滤器处理了两次多半是过滤器被重复注册了。检查一下是否在类上加了WebFilter的同时又在 web.xml 里配了一份过滤器的映射。这种低级错误非常隐蔽因为代码本身没错是重复注册所以执行了两次可能导致编码过滤器设置的字符集被后面的请求读取逻辑覆盖登录过滤器也可能因为重复放行而出现逻辑错乱。4.4 静态资源被拦截页面样式全丢了页面能打开但 CSS 和 JS 文件全部 404这也是登录过滤器的“副作用”。原因很简单你的登录过滤器把/css/style.css、/js/app.js这些请求也拦截了判定未登录后重定向到了 login.jsp。解决方案就是在白名单里加上静态资源的前缀。但这里有个细节要注意如果项目里静态资源路径是/static/css/style.css这种带/static前缀的白名单就写/static如果直接放在 webapp 根目录下比如/css/style.css白名单就写/css。判断逻辑要能匹配资源文件本身的路径不是匹配前缀就万事大吉了建议用我上面写的path.startsWith(prefix /)这种写法既能匹配/css也能匹配/css/style.css还能避免把/css-other这种路径误放。4.5 编码过滤器没解决乱码可能是响应类型没设置如果你的过滤器已经写好了POST 请求参数的中文也没问题但页面显示还是乱码问题往往出在response上。我之前说过光设置setCharacterEncoding还不够还要设置setContentType明确告诉浏览器返回内容的文档类型和字符集。这个乱码的排查路径我再说细一点浏览器收到的响应如果没有charsetutf-8它默认会用系统自带的编码去猜中文 Windows 下经常用 GBK 解析然后页面就出现“锟斤拷”这种经典乱码。所以过滤器里httpResponse.setContentType(text/html;charset encoding);这行千万别省。如果项目里返回的是 JSON 数据就把 content type 换成application/json;charsetutf-8。4.6 问题排查速查表现象可能原因解决方案过滤器完全没执行项目未热部署、url-pattern 写错、类上没有注解打印日志确认检查注解和映射登录过滤出现死循环登录页/登录接口未加入白名单白名单加入 login.jsp 和登录接口静态资源 404过滤器拦截了 css/js 请求白名单加入静态资源前缀过滤器执行了两次注解和 web.xml 同时注册去掉一种注册方式中文参数乱码编码设置放在 doFilter 之后设置编码必须在 chain.doFilter 之前页面显示乱码response 内容类型未设置字符集设置 setContentType 的 charset未登录也能访问页面getSession() 自动创建了空 Session改用 getSession(false)过滤器顺序不对注解按类名排序不符合预期改用 web.xml 显式配置顺序这个速查表基本覆盖了我带项目时见过的高频问题建议保存在你的学习笔记里。排查顺序如果不知道怎么定就按照“先确认过滤器有没有执行 → 再看路径匹配是否正确 → 再查链顺序和重复注册 → 最后查编码和响应设置”这个路径走90% 的问题都能在几分钟内定位到。最后再分享一点个人体会。过滤器这套机制刚开始学觉得就是几个接口方法但真正用多了会发现它教会你的是一种“横切思维”把不同业务里共通的逻辑抽出来找一个统一的位置处理。这种思维在后面的 SpringMVC 拦截器、Spring AOP 里会反复出现底子打好了后面学框架会轻松很多。我在 Day13 学完 Filter 之后回头重构了之前写的几个 Servlet把编码、登录、日志全部拆出来代码瞬间清爽了不少那种“原来代码还能这么写”的感觉可能就是 JavaWeb 学习里最值得记住的瞬间之一。
RELATED

相关推荐

大型包膜机西门子PLC控制程序设计与FB块封装实战解析

大型包膜机西门子PLC控制程序设计与FB块封装实战解析

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

📅 2026/9/10 8:39:43
Flipper Zero中文显示改造指南:4步完成本地化避坑

Flipper Zero中文显示改造指南:4步完成本地化避坑

Flipper Zero中文显示改造指南:4步完成本地化避坑 【免费下载链接】flipperzero-firmware Flipper Zero firmware source code 项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware 在Flipper Zero上刷入自定义固件后,菜单里…

📅 2026/9/10 8:39:43
Flask与Django选型实战:从零构建服装生产管理系统的完整方案

Flask与Django选型实战:从零构建服装生产管理系统的完整方案

1. 项目背景与需求拆解1.1 服装生产管理到底管什么先说这个项目的由头。服装生产的流程和别的行业不太一样,它不是一条简单的流水线,而是典型的“离散批量”混合模式:客户下订单、技术部打样板、采购面料辅料、裁剪车间铺料开裁、缝制车间分组…

📅 2026/9/10 8:39:43
MORE NEWS

更多资讯

📰

CANN/GE算子编译接口

aclopCompile 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前…

📰

激光SLAM超帧技术解析:从单帧配准到连续联合优化的工程实践

前阵子把一台低速巡检机器人拉去地下车库跑测试,用的还是那套“单帧配准+局部地图”的经典 LiDAR SLAM 方案。结果很有意思:过弯道的地方漂了十几厘米,到了两边全是立柱的区域,位姿估计曲线直接出现锯齿。查了半天&…

📰

CVAT 计算机视觉标注工具部署指南:3步启动图像与视频数据标注平台

CVAT 计算机视觉标注工具部署指南:3步启动图像与视频数据标注平台 【免费下载链接】cvat Computer Vision Annotation Tool (CVAT) is a leading platform for building high-quality visual datasets for vision AI. It offers open-source, cloud, and enterprise…

📰

Diffusers 模块化流水线(Modular Pipelines)之 Pipeline Blocks 完全指南

Diffusers 模块化流水线(Modular Pipelines)之 Pipeline Blocks 完全指南 【免费下载链接】diffusers 🤗 Diffusers: State-of-the-art diffusion models for image, video, and audio generation in PyTorch. 项目地址: https://gitcode.c…

📰

GitHub MCP Server 在 Copilot IDE 中的安装指南:Visual Studio、JetBrains、Xcode 与 Eclipse 完整配置

GitHub MCP Server 在 Copilot IDE 中的安装指南:Visual Studio、JetBrains、Xcode 与 Eclipse 完整配置 【免费下载链接】github-mcp-server GitHubs official MCP Server 项目地址: https://gitcode.com/GitHub_Trending/gi/github-mcp-server GitHub MCP …

📰

Codex前端协作五层分工法:结构、逻辑、契约、质量、交付

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

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬