news 2026/9/30 12:17:02

SpringMVC 6升级实战:javax迁移、拦截器与路径匹配避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringMVC 6升级实战:javax迁移、拦截器与路径匹配避坑指南

先交代一下背景。我手头一个老项目,Spring Boot 2.7.9 + Spring Framework 5.3.x,跑了三年多,一直稳如老狗。因为团队整体要切 JDK 17 和新的基础设施,我被迫把 SpringMVC 一路升到 6.1(对应 Spring Boot 3.2)。当时想得很天真:不就是换个版本号吗?实际动手之后,javax 改 jakarta、路由匹配规则变化、springmvc拦截器不生效、静态资源 404——这些坑排着队等我。

这篇不聊虚的,只讲我实际踩过并且已经解决的问题。我把每个问题的现象、原因、解决办法都整理了,配置和代码直接给全。适合两类人看:一类是从 Spring Boot 2.x / SpringMVC 5 往 SpringMVC 6 升级的开发者;一类是想把 springmvc工作流程、springmvc拦截器这块彻底搞明白的同学,后者可以把第 5 节当作一份精简的复习资料。

先说结论:SpringMVC 6 整体不难,难的是旧习惯。很多报错都是因为“你以为它还是老样子”,下面逐条拆。

1. 升级先捋清版本基线:SpringMVC 6 到底多了什么

升级前先别急着改代码,把版本基线理清楚,后面所有坑都能对上号。我当时的版本对照是这样的:

项目升级前升级后
Spring Boot2.7.93.2.x
Spring Framework5.3.x6.1.x
JDK817
Servlet 命名空间javax.servletjakarta.servlet
默认路径匹配方式AntPathMatcherPathPatternParser
拦截器基类HandlerInterceptorAdapter已移除,直接实现 HandlerInterceptor

Spring Framework 6 的底座是 Jakarta EE 9/10,JDK 要求最低 17。这不是可选项,而是硬门槛——JDK 不到 17 连框架都加载不起来。所以升级之前,先把 JDK 版本统一掉,别想着“先让代码编过再处理环境”,那样只会把问题搅在一起。建议直接在项目根目录的 README 里写清楚目标版本矩阵,团队所有人照着统一环境操作,能省掉一半“在我机器上是好的”这种破事。

1.1 从 javax 到 jakarta,先解决编译都过不去的问题

升级后第一波报错毫无悬念:package javax.servlet does not exist。SpringMVC 6 把整个 Servlet 规范迁移到了jakarta.servlet命名空间,所有直接或者间接引用javax.servlet的代码都要跟着改。

// 升级前 import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // 升级后 import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse;

除 Servlet 之外,Bean Validation 的包名同样从javax.validation变成了jakarta.validation。这地方非常容易漏:很多人只盯着javax.servlet替换,结果@NotNull、@Valid还引用着旧的javax.validation.constraints.NotNull。如果项目里恰好还有旧的 validation-api 依赖,编译能过,但校验完全不生效——这是最隐蔽的坑,我排查了一整个下午才定位到。

替换的方式不用一个个手敲。如果你的代码量不大,直接用 IDE 的全局替换即可;代码量大的话,推荐 OpenRewrite 的 Spring Boot 3 迁移配方,它能把常见的包名替换、API 变更一次性处理掉。不过无论用哪种方式,替换完都要全局搜一遍javax.servlet、javax.validation、javax.annotation,确认没有漏网的。javax.annotation这个也要注意,Spring 6 里@Resource、@PostConstruct这些注解同样迁移到了jakarta.annotation,漏了的话启动时可能会有诡异的 Bean 初始化失败。

还有个容易被忽略的点:HandlerInterceptorAdapter在 Spring 6 中被移除了。以前写拦截器习惯extends HandlerInterceptorAdapter,升级后直接编译报错。正确做法是implements HandlerInterceptor,后面第 3 节我会贴完整代码。遇到这种“类找不到”的报错,别慌,先查这个类是新版本删掉的还是依赖没拉进来,多数是前者。

1.2 第三方依赖里残留的 javax 才是大坑

如果说包名替换是明坑,那第三方依赖里的旧 Servlet API 就是暗坑。我遇到的情况是:项目里有一个内部公共组件,还是两年前编译的,内部引用了javax.servlet.http.HttpServletResponse。项目本身升级后,编译、启动都正常,但只要走到那个组件的方法,立刻抛NoClassDefFoundError: javax/servlet/ServletException。

这就是典型的“依赖残留”。Spring Boot 3 自带的容器(Tomcat 10.1 之后)只认 jakarta,不再提供 javax.servlet 类,谁还引着旧 API,谁就会在运行时炸。而且这种错误往往出现在运行一段时间之后,不是启动时立刻爆出来,排查难度比编译报错高得多。

mvn dependency:tree -Dincludes=javax.servlet

用上面这条命令可以把依赖树里所有 javax.servlet 相关依赖揪出来。找到之后分两种情况处理:能升级的,把第三方组件升到适配 Jakarta 的版本;不能升级的,在 Maven 里排除掉冲突的旧依赖。

<dependency> <groupId>com.example</groupId> <artifactId>legacy-common</artifactId> <exclusions> <exclusion> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </exclusion> </exclusions> </dependency>

注意:排除依赖只是“眼不见为净”,前提是你确认代码里没有再直接调用 javax 的类。最稳妥的办法还是让第三方组件方提供基于 Jakarta 的新版本,排掉旧依赖只是临时方案。

2. 路由匹配规则变了:404 是最忠诚的报警器

版本升级完、编译也过了,进入联调阶段才是真正的好戏开场。我最先遇到的,是一批莫名其妙的 404。接口定义明明没动,前端也没改,发出去的请求就是找不到 handler。

2.1 PathPatternParser 取代 AntPathMatcher,斜杠这种细节最要命

SpringMVC 6 默认使用PathPatternParser做路径匹配,取代了老版本的AntPathMatcher。框架这么做的原因是性能更好,匹配规则更清晰,不再有正则回溯之类的不确定性。但随之而来的规则变化,会让老代码原地崩溃。

其中最典型的:尾部斜杠不再自动匹配。老版本中/user这个映射默认也能接住/user/的请求,很多前端代码因此习惯性地在 URL 后面加一个斜杠。新规则下,/user只匹配/user,/user/是另一个路径,找不到 handler,直接 404。

对比项老版本(AntPathMatcher)SpringMVC 6(PathPatternParser)
URL/user能否匹配请求/user/默认可以不能
/user/*能否匹配/user/a/b不能(* 只匹配单段)不能
/files/{*path}多段路径参数写法复杂原生支持
匹配性能尚可,有回溯风险更快、更稳定

新写法里比较有用的特性是{*path}捕获剩余路径。比如:

@GetMapping("/files/{*path}") public String file(@PathVariable String path) { // path = "report/2025/01/data.xlsx" return handle(path); }

这在老版本里得写正则或者用/**加手动截取,现在一个路径变量就搞定。

2.2 我的 404 排查实录与两种解法

我当时遇到的报错是这样的:系统首页正常,但所有以斜杠结尾的业务接口全部 404,日志里刷着一行No mapping for GET /api/order/detail/。接口定义我确认过是对的,当时第一反应是“springmvc拦截器把请求吞了”,于是把拦截器全部注释掉,404 依旧。然后才想到路径匹配策略。

排查过程其实就三步:

  1. 先看日志里有没有No mapping for ...,有就是根本没找到 handler,跟业务代码无关。
  2. 用 curl 直接把尾部斜杠去掉再请求一次,如果通了,十有八九是尾斜杠匹配问题。
  3. 去 Spring Framework 6 的迁移说明里确认匹配策略的变更。

解法有两种,按团队情况选。

解法 A:统一前端 URL,去掉尾部斜杠。这是官方推荐的方向。HTTP 语义里/api/order/detail和/api/order/detail/本来就是两个不同的 path,后端没必要把两者强行等价。

解法 B:切回 AntPathMatcher 做兼容。项目实在改不动 URL 时,可以临时恢复老规则:

spring: mvc: pathmatch: matching-strategy: ant_path_matcher

如果是纯 Spring MVC 项目(不走 Boot),在WebMvcConfigurer里把匹配器设置回去:

@Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setPathMatcher(new AntPathMatcher()); }

坦白讲,解法 B 只能救急。Spring 官方在新版本里已经明确不鼓励尾斜杠匹配,后续版本会不会彻底移除都是未知数。我最后是让前端做了全局替换,把 URL 全部规范化,一劳永逸。

另外推荐一个配套设置:在配置文件里打开spring.mvc.throw-exception-if-no-handler-found=true,同时配合全局异常处理,把“找不到 handler”的 404 转成统一的 JSON 结构。不然很多 404 会直接打到默认错误页,前端再做一份 404 文案,体验很割裂。这个配置我在升级前完全没在意,踩过一次坑之后才知道它多有用。

3. springmvc拦截器的坑:不生效、拦不到、拦错路径

路径匹配搞定之后,又轮到 springmvc拦截器。这节内容在网上一搜一大把,但我还是要说一句:新版本里拦截器的问题,十有八九不是 API 变了,而是“你以为配了,其实没配到位”。

3.1 拦截器不触发的三个常见原因

原因一:配置类根本不在扫描路径里。WebMvcConfigurer的实现类必须被 Spring 容器扫描到,拦截器才会注册。我见过有人把配置类放在com.example.legacy这种老包,主类在com.example.app,扫描不到,代码看着没什么问题,拦截器就是死活不跑。解决办法很简单,把配置类放到主类所在包的子包下,或者用@ComponentScan显式指定。

原因二:Spring Boot 项目里顺手加了@EnableWebMvc。这可以说是升级头号杀手。@EnableWebMvc会让 Boot 的WebMvcAutoConfiguration直接失效,MVC 的全部默认配置回到框架最基础的状态。表现不只是拦截器不生效,静态资源映射、JSON 消息转换、默认异常处理全部会丢。如果你是在 Spring Boot 里写 Web 配置,不要加@EnableWebMvc,只需要写一个@Configuration类去实现WebMvcConfigurer就够了。

原因三:拦截路径写错。addPathPatterns("/api/*")和addPathPatterns("/api/**")差别巨大。*只能匹配一个路径段,/api/*能拦到/api/login,拦不到/api/user/info。很多人的拦截器“只拦了一半”,不是代码 bug,是对通配符理解偏差。这类问题在新版本里尤其常见,因为 PathPatternParser 对通配符的解释更严格,老版本里一些“半模糊”写法还能匹配上,新版本就直接不认了。

3.2 新版本下拦截器注册的正确姿势(含代码)

先看拦截器本体。Spring 6 之后没有HandlerInterceptorAdapter了,直接实现HandlerInterceptor接口:

public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { return true; } String token = request.getHeader("X-Token"); if (token == null || token.isBlank()) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write("{\"code\":401,\"msg\":\"未登录或token缺失\"}"); return false; } // 这里写 token 解析和用户信息填充 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // handler 执行完后、视图渲染前 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 请求结束,无论是否异常都会调用 } }

注册方式:

@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AuthInterceptor()) .addPathPatterns("/api/**", "/user/**") .excludePathPatterns("/api/login", "/api/register", "/static/**", "/error"); } }

几个细节值得记一下:

  • excludePathPatterns一定要包含登录、注册、静态资源、健康检查这些公开接口,不然系统一上线,还没登录就把自己锁死了。
  • 多个拦截器时,preHandle按addInterceptor的调用顺序执行,postHandle和afterCompletion按相反顺序执行。如果多个拦截器之间有依赖关系,这个先后顺序要想清楚。
  • 如果拦截器里需要访问 Spring 容器中的 Bean,不要用new创建,把拦截器也定义成@Component,再通过构造注入拿进来。直接在addInterceptors里new出来的对象是不受容器管理的,里面注入的任何依赖都是 null,这个坑我见过太多次。

3.3 OPTIONS 预检请求被拦截:跨域失败的常见元凶

跨域问题在新版本里也容易和拦截器撞在一起。浏览器在发起跨域 AJAX 前会先发一个 OPTIONS 预检请求,如果你的拦截器对所有请求都要 token,OPTIONS 直接 401,浏览器的正式请求根本没机会发出去,前端看到的就是“跨域失败”。

我在上面拦截器代码里已经放了放行逻辑:

if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { return true; }

更规范一点可以用 Spring 自带的判断:

import org.springframework.web.cors.CorsUtils; if (CorsUtils.isPreFlightRequest(request)) { return true; }

同时保证 CORS 配置是对的。全局 CORS 可以在WebMvcConfigurer里加:

@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("https://front.example.com") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); }

注意:allowCredentials(true)时,allowedOrigins不能写*,必须写明确域名,否则浏览器直接拒绝。这是我当时在 Safari 下怎么调都不通、换 Chrome 才看到控制台完整报错的原因。跨域问题的排查建议直接用 Chrome 的 Network 面板,看 OPTIONS 请求的响应头,比猜快得多。

4. 静态资源、视图解析与请求响应的连带坑

拦截器消停之后,静态资源又开始闹。CSS、JS 全部 404,接口倒是全好了。

4.1 静态资源 404 的排查思路

先别急着加资源映射,先想一个问题:你的项目里是不是也加了@EnableWebMvc?如果是,恭喜,你找到了问题根源。原因在第 3 节说过:@EnableWebMvc把 Boot 的默认静态资源映射干掉了,classpath:/static/下的文件全部失去访问路径。

去掉@EnableWebMvc,Spring Boot 3 默认会自动把以下位置映射为静态资源:classpath:/META-INF/resources/、classpath:/resources/、classpath:/static/、classpath:/public/。如果你的文件一直放在src/main/resources/static/css/app.css,访问路径应该是/css/app.css,不需要自己配。

特殊情况才需要手工加资源映射:

@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/files/**") .addResourceLocations("file:/data/upload/") .setCachePeriod(3600); }

这种一般用于把服务器磁盘上的目录暴露出来。要注意的是,自定义/files/**这类路径时,别和 Controller 的@GetMapping("/files/{*path}")撞车,否则 Spring 会因为路径冲突报 ambiguous mapping,两个都失效。我升级时就因为本地测试环境保留了一个旧的/files/**映射,结果跟新版 Controller 撞了,报错信息还特别不明显,排查了很久。

4.2 视图解析与转发/重定向的细节

如果项目还在用 JSP,新版本里要格外留个心眼。Spring Boot 3 以 jar 方式打包时,内置容器对 JSP 的支持非常有限,InternalResourceViewResolver经常出现“能找到视图但渲染 500”的尴尬。强烈建议趁升级机会把视图层迁到 Thymeleaf,或者坚持 JSP 就改打成 war 包部署到外部容器。

Thymeleaf 在 Spring Boot 3 下基本是零配置,加依赖后把页面放到src/main/resources/templates/,Controller 返回字符串即可:

@GetMapping("/page") public String page() { return "index"; }

再提醒一个容易忽略的细节:forward:和redirect:的行为差异。forward:是服务端内部转发,浏览器 URL 不变,请求会再走一遍 DispatcherServlet 的流程,但不会重新触发已经执行过的拦截器的preHandle;redirect:是让浏览器重新发起请求,URL 会变,会完整走一遍新的请求链路。写权限控制逻辑时,想清楚用的是哪种,不然会出现“明明要跳转,结果被拦截器拦下来”的乌龙。

另外顺带提一句消息转换器。如果你在WebMvcConfigurer里重写了configureMessageConverters,它会清空默认的消息转换器列表,Jackson 就不会自动生效,表现为接口返回的数据变成纯字符串或者直接 406。如果没有特别明确的需求,优先用extendMessageConverters做追加而不是覆盖。这是升级后一个比较典型的隐藏坑,尤其是老项目里如果有人为了“定制 JSON”重写过这个方法。

5. 顺带把 springmvc工作流程彻底捋一遍

聊到这里,其实已经把 SpringMVC 工作流程里最容易出问题的几个环节全部踩了一遍。借着这次升级,我把整套流程重新梳理一遍,这部分对你理解新版本和面试都有用。

5.1 一次请求从头到尾经历了什么

环节核心组件一句话职责
1. 入口DispatcherServlet前端控制器,统一接收 HTTP 请求
2. 找 handlerHandlerMapping根据 URL 找到对应的 Controller 方法
3. 适配调用HandlerAdapter执行定位到的方法,处理参数绑定、校验
4. 前置/后置HandlerInterceptor请求前、handler 后、完成后三段拦截
5. 结果封装ModelAndView / HttpMessageConverter返回视图或直接输出 JSON
6. 视图渲染ViewResolver + View把逻辑视图名解析成真实视图并渲染

一次请求进来后,完整链路是这样的:

  1. 请求先落在DispatcherServlet。它是 SpringMVC 的“中央调度器”,所有 handler 的查找、适配、结果处理都从这里开始,但它自己不做业务。
  2. HandlerMapping根据请求 URL 和 Controller 上的@RequestMapping生成匹配结果。默认实现是RequestMappingHandlerMapping,新版本里它用的路径匹配器就是 PathPatternParser。匹配结果里除了 handler 方法本身,还有一组需要执行的拦截器。
  3. HandlerAdapter开始调用 handler。这一步会做参数解析:@PathVariable、@RequestParam、@RequestBody全部在这里绑定。参数绑定出错时,比如 JSON 格式不对,会抛HttpMessageNotReadableException,这就要靠@ControllerAdvice接住。
  4. 拦截器链路在这个阶段起作用。顺序是:preHandle(进入 handler 前)→ 业务方法 →postHandle(handler 返回后、视图渲染前)→afterCompletion(请求结束)。
  5. Controller 方法执行完,结果的归途分两种:方法上有@ResponseBody或者类上有@RestController时,RequestMappingHandlerAdapter会用HttpMessageConverter(默认是 Jackson 的MappingJackson2HttpMessageConverter)把对象序列化成 JSON 写回;否则返回的字符串会当作逻辑视图名交给 ViewResolver。
  6. ViewResolver拿到逻辑视图名后解析成真实视图。Thymeleaf 有ThymeleafViewResolver,JSP 有InternalResourceViewResolver,解析成功后由View.render输出 HTML。

5.2 新版本里工作流程里哪些环节悄悄变了

对照上面流程,升级后的变化集中在几个地方:

  • 第 2 步的匹配器换了。AntPathMatcher变成PathPatternParser,规则和性能都变了。权限系统里如果用了/**之类的表达式,要按新规则重新验证一遍。
  • 第 4 步的拦截器简化了。HandlerInterceptorAdapter删除,接口方法本身就是默认空实现,直接implements HandlerInterceptor就行。
  • 第 5 步的错误处理更规范了。Spring 6 中ResponseEntityExceptionHandler默认生成ProblemDetail(RFC 9457 格式)响应体,异常结构变成{ "type": "...", "title": "Bad Request", "status": 400, "detail": "..." },做全站统一报错时比之前的自定义 Map 更规范。
  • 第 5 步的异步支持更完善。DeferredResult、CompletableFuture这类异步返回在 Spring 6 里是原生支持的,适合对接慢接口、消息队列回调,不会因为线程阻塞占满容器线程池。
  • 内容协商策略收敛了。老版本可以通过 URL 后缀(.json、.xml)来协商响应格式,新版本默认不再支持后缀匹配,必须通过Accept请求头来定。如果你有/user.json这种老接口,升级后大概率 404,要改用Accept: application/json。这个问题很多 migrate 项目都会遇到,前端和后端要同步改造。

6. 高频问题速查表与升级实操清单

最后把这次升级过程中遇到的所有问题汇总成一张速查表,再给你一份升级前自查清单。

6.1 常见报错与解决方案对照表

现象原因解决方案
编译报错package javax.servlet does not existServlet 命名空间迁移全部替换为jakarta.servlet
运行时报NoClassDefFoundError: javax/servlet/...第三方依赖残留旧 Servlet APImvn dependency:tree排查后升级或排除
接口 404,URL 最后带斜杠PathPatternParser 不做尾斜杠匹配前端去掉斜杠,或临时切 ant_path_matcher
静态资源 404误用@EnableWebMvc导致默认映射丢失去掉该注解,或手动补 resource handler
拦截器完全不执行配置类没被扫描 / 路径写错检查包扫描、addPathPatterns写成/**
拦截器只拦住部分接口*与**通配符理解错误用/**匹配多段路径
跨域请求失败、控制台报 OPTIONS 401拦截器拦截了预检请求preHandle放行 OPTIONS /CorsUtils.isPreFlightRequest
HandlerInterceptorAdapter找不到Spring 6 已移除该类改为implements HandlerInterceptor
JSP 渲染 500Boot 3 jar 打包对 JSP 支持弱迁移 Thymeleaf 或改 war 部署
JSON 输出异常或 406configureMessageConverters覆盖默认转换器改用extendMessageConverters
/user.json老接口 404新版本不支持后缀内容协商改成Accept请求头协商

6.2 升级前建议你按这个清单自查

  1. 先统一 JDK 17,再动框架版本,避免环境变量和编译目标互相干扰。
  2. 全局搜一遍javax.servlet、javax.validation、javax.annotation,替换成 jakarta 同名包。
  3. 检查所有extends HandlerInterceptorAdapter的地方,改成implements HandlerInterceptor。
  4. 用mvn dependency:tree排查旧 Servlet API,对每个第三方依赖确认它是否支持 Jakarta。
  5. 对着接口清单测试一遍 URL,重点看尾斜杠、大小写、URL 编码,前端如有拼斜杠的习惯必须改。
  6. 检查拦截器、过滤器、Spring Security 的路径规则,如果 Security 还在用antMatchers,Spring Security 6 已经把它标记为弃用并建议移除,统一换requestMatchers。
  7. 静态资源和 JSP/模板:确认@EnableWebMvc没被误加、资源路径没冲突、模板方案在新版本可用。

最后再分享一个我自己的习惯:升级这种事,别指望一次到位,也别怕当场报错。报错日志其实是最诚实的老师,它告诉你哪里变了、哪里漏了。我每次升级完都会先跑一遍全链路接口测试,再用浏览器把页面全部点一遍,把 404、406、500 这些问题在前置环境里全部炸出来,而不是等上线后让用户帮你测。

我在这个项目里踩过的最大教训是:改动之前,先把“旧行为”和“新行为”的差异表列出来,逐项核对,而不是看到一个报错改一个。如果你正在做 SpringMVC 升级,强烈建议把我这份清单拿着,一边升级一边打勾,能少走一半弯路。

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

TensorFlow生产级部署核心:SavedModel、tf.function与可观测性

1. 这不是“又一个深度学习框架”&#xff1a;TensorFlow 的真实定位与误用重灾区 很多人第一次听说 TensorFlow&#xff0c;是在某篇“2024年最值得学的AI框架”榜单里&#xff0c;和 PyTorch 并列排在前两位&#xff1b;也有人是在安装时卡在 pip install tensorflow 命令…

作者头像 李华
网站建设 2026/9/30 12:16:38

HER事后经验回放:破解强化学习稀疏奖励难题的工程实践

1. 先搞懂为什么要引入“事后聪明”1.1 强化学习中的一个老大难&#xff1a;稀疏奖励做强化学习的同学&#xff0c;十有八九都会被同一个问题折磨过&#xff1a;稀疏奖励。举个例子&#xff0c;你让一个机械臂去抓取桌面上的方块&#xff0c;只有把方块送到指定位置才给1奖励&a…

作者头像 李华
网站建设 2026/9/30 12:16:19

使用Kubeeasy工具快速部署kubernetes

使用Kubeeasy工具快速部署kubernetes 镜像链接&#xff1a;https://pan.baidu.com/s/1zA0cWvXZXxZPSUceNaJHDA 提取码&#xff1a;8888 Kubeeasy 部署 Kubernetes 与传统部署方式的对比 Kubeeasy 是一个面向企业级用户设计的 Kubernetes 自动化部署与管理工具&#xff0c;旨在简…

作者头像 李华
网站建设 2026/9/30 12:15:45

uni-app应用内更新:整包更新与wgt热更新双通道实战

应用内更新这件事&#xff0c;做过的都知道&#xff0c;第一次接入的时候觉得不就是下载个包然后装上吗&#xff0c;真跑起来才发现坑全在细节里。我手头这个 uni-app 项目从最早让用户自己去应用市场搜关键词更新&#xff0c;一路迭代到现在整包更新加资源包热更新双通道并行&…

作者头像 李华
网站建设 2026/9/30 12:15:21

AgentScope多智能体框架实战:从消息传递到协作编排的完整指南

1. 为什么我会盯上 AgentScope 这个多智能体框架 第一次听到 AgentScope 这个名字&#xff0c;是在一个做智能体应用开发的小圈子里。当时有人丢了一句“多智能体编排终于有个像样的开源方案了”&#xff0c;我顺手去翻了下它的仓库和文档&#xff0c;结果一晚上没干别的&#…

作者头像 李华
网站建设 2026/9/30 12:15:07

佳易王棋牌桌球计时计费管理系统:从选型到实操全解析

棋牌室和桌球厅这类按时间收费的营业场所&#xff0c;最怕的不是生意不好&#xff0c;而是生意好了账却乱了。开台时间靠人记、加钟靠口头喊、会员折扣靠翻手机备忘录&#xff0c;月底一对账单&#xff0c;老板和前台各执一词&#xff0c;这种场景我见过太多。佳易王棋牌桌球计…

作者头像 李华