从 JDK 8 到 JDK 17:Swagger 升级迁移指南

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

从 jdk 8 到 jdk 17:swagger 升级迁移指南

随着 %ignore_a_1% 生态向 jdk 17jakarta ee 的演进,许多项目面临从 jdk 8 升级的挑战,其中 swagger(api 文档工具)的兼容性调整尤为关键。本文将从 技术栈差异、升级迁移步骤、常见问题 等多个维度,解析 jdk 8(springfox)向 jdk 17(springdoc/knife4j)的升级路径。

1、背景

1.1 技术演进

JDK 版本演进:JDK 17 是继 JDK 8 后的首个 LTS 版本,支持模块化、Records 等新特性,但移除了部分旧 API(如 javax.servlet)。直接影响:基于 JDK 8 构建的 SpringFoxSwagger 2.x)因依赖旧规范无法兼容新版本。Jakarta EE 的崛起:Java EE 移交 Eclipse 基金会后更名为 Jakarta EE,包名从 javax.* 改为 jakarta.*。核心冲突:Spring Boot 3.xSpringDocSwagger 3.x)强制依赖 Jakarta EE 9+,导致旧项目升级时需全局替换包名。

1.2 升级的必要性

安全风险:SpringFox 已停止维护,存在未修复漏洞(如 CVE-2021-28170)。功能需求:SpringDoc 支持 OpenAPI 3.0 规范,提供更灵活的文档定义和响应示例。生态兼容:微服务、云原生场景下,JDK 17 的容器化支持更优。

2、技术栈对比与选型

2.1 JDK 8 与 JDK 17 的 Swagger 技术栈对比

特性

JDK 8 + SpringFox (Swagger 2.x)

JDK 17 + SpringDoc/Knife4j (Swagger 3.x)

核心框架

SpringFox 2.x(已停止维护)

SpringDoc OpenAPI 3.x(官方推荐)

JDK 兼容性

仅支持 JDK 8~11

支持 JDK 17+ 的模块化特性

Spring Boot 支持

Spring Boot 2.x

Spring Boot 3.x(兼容 2.7.x)

Servlet 规范

基于 javax.servlet

迁移至 jakarta.servlet(Jakarta EE 9+)

注解库

io.swagger.annotations

io.swagger.v3.oas.annotations

注解风格

@Api, @ApiOperation

@Tag, @Operation(更符合 OpenAPI 3.0)

依赖管理

需手动管理版本,易冲突

通过 Spring Boot Starter 简化依赖

文档生成

需配置 Docket

自动扫描,通过 OpenAPI Bean 全局配置

文档规范

OpenAPI 2.0

OpenAPI 3.0

UI 工具

Swagger UI(基础功能)

Knife4j(增强功能,支持离线文档、权限控制、接口分组等)

维护状态

停止维护(最后版本 3.0.0)

活跃维护(SpringDoc 2.x + Knife4j 4.x)

2.2 版本兼容性矩阵

技术栈

JDK 8

JDK 11

JDK 17

Spring Boot 2.7.x

Spring Boot 3.x

SpringFox 2.x

⚠️ 部分兼容

SpringDoc 1.x

SpringDoc 2.x

3、快速升级步骤

3.1 依赖管理升级

移除旧依赖 io.springfoxspringfox-swagger23.0.0io.springfoxspringfox-swagger-ui3.0.0添加新依赖 org.springdocspringdoc-openapi-starter-webmvc-ui2.5.0com.github.xiaoyminknife4j-openapi3-jakarta-spring-boot-starter4.5.0排除冲突依赖 org.apache.tomcat.embedtomcat-embed-corejavax.servletjavax.servlet-api

3.2 代码层迁移(注解更新)

控制器注解迁移:

SpringFox (Swagger 2.x)

SpringDoc (OpenAPI 3.x)

用途

示例

@Api

@Tag

标记控制器类的作用

@Tag(name = “用户管理”, description = “用户接口”)

@ApiOperation

@Operation

描述接口方法的功能

@Operation(summary = “创建用户”, description = “根据DTO创建用户”)

@ApiParam

@Parameter

描述接口参数(路径、查询、表单参数等)

@Parameter(name = “id”, description = “用户ID”, required = true)

@ApiResponse

@ApiResponse

定义接口的响应状态码和描述

闪念贝壳 闪念贝壳

闪念贝壳是一款AI 驱动的智能语音笔记,随时随地用语音记录你的每一个想法。

闪念贝壳 218 查看详情 闪念贝壳

@ApiResponse(responseCode = “404”, description = “用户不存在”)

@ApiIgnore

@Hidden 或 @Parameter(hidden = true)

隐藏接口或参数

@Hidden // 隐藏整个接口方法

@ApiImplicitParams

@Parameters + @Parameter

描述非直接声明的参数(如 Header 参数)

@Parameters({ @Parameter(name = “token”, in = HEADER, description = “认证令牌”) })

@ApiImplicitParam

@Parameter

单个隐式参数定义

同上

// JDK 8(SpringFox)@Api(tags = "用户管理", description = "用户接口")@RestControllerpublic class UserController {    @ApiOperation("创建用户")    @PostMapping("/users")    public User createUser(@ApiParam("用户DTO") @RequestBody UserDTO dto) {        // ...    }   @ApiImplicitParams({      @ApiImplicitParam(name = "token", value = "认证令牌", paramType = "header")   })   @GetMapping("/profile")   public UserProfile getProfile() {      //...   }}
// JDK 17(SpringDoc)@Tag(name = "用户管理", description = "用户接口")@RestControllerpublic class UserController {    @Operation(summary = "创建用户", description = "根据DTO创建用户")    @PostMapping("/users")    public User createUser(@Parameter(description = "用户DTO", required = true)        @RequestBody UserDTO dto) {        // ...    }   @Parameters({      @Parameter(name = "token", description = "认证令牌", in = ParameterIn.HEADER)   })   @GetMapping("/profile")   public UserProfile getProfile() {      // ...   }}

模型类注解迁移:

SpringFox (Swagger 2.x)

SpringDoc (OpenAPI 3.x)

用途

示例

@ApiModel

@Schema

描述数据模型类

@Schema(name = “UserDTO”, description = “用户传输对象”)

@ApiModelProperty

@Schema

描述模型字段的详细信息

@Schema(description = “用户名”, example = “张三”, requiredMode = REQUIRED)

// JDK 8(SpringFox)@ApiModel(value = "User", description = "用户实体")public class User {    @ApiModelProperty(value = "用户名", required = true, example = "张三")    private String name;}
// JDK 17(SpringDoc)@Schema(name = "User", description = "用户实体")public class User {    @Schema(description = "用户名", example = "张三", requiredMode = Schema.RequiredMode.REQUIRED)    private String name;}

3.3 全局配置调整

是否还需要传统 SwaggerConfig?

不需要:Knife4j OpenAPI3 基于 SpringDoc,无需配置 DocketSwagger2Markup。必要配置:仅需定义 OpenAPI Bean(如上文的 OpenApiConfig)即可。

3.3.1 SpringDoc 配置类
@Configurationpublic class OpenApiConfig {    @Bean    public OpenAPI customOpenAPI() {        return new OpenAPI()                .info(new Info()                        .title("API 文档")                        .version("1.0")                        .description("JDK 17 迁移示例")                        .contact(new Contact().name("xcbeyond技术支持").email("support@example.com"))                        .license(new License().name("Apache 2.0").url("https://springdoc.org")))                .externalDocs(new ExternalDocumentation()                        .description("详细文档")                        .url("https://xcbeyond.com"))                .components(new Components()                        .addSecuritySchemes("BearerAuth", new SecurityScheme()                                .type(SecurityScheme.Type.HTTP)                                .scheme("bearer")                                .bearerFormat("JWT")));    }}
3.3.2 分组配置(多模块场景)

在微服务架构中,API 文档分组配置的核心管理需求是:

模块化展示:将不同业务域(用户/订单/支付)分离展示。权限隔离:区分公共 API 和管理 API。版本管理:同时维护 v1 和 v2 接口。依赖解耦:避免单个文档过大导致加载性能问题。

分组配置参数详解:

配置方法

参数说明

默认值

示例

.group(String group)

分组唯一标识(显示在 UI 中)

必填

.group(“用户管理”)

.pathsToMatch(String… paths)

路径匹配规则(支持 Ant 风格)

可选

.pathsToMatch(“/api/user/**”)

.packagesToScan(String… pkgs)

扫描的包路径

可选

.packagesToScan(“com.example”)

.pathsToExclude(String… paths)

排除的路径

空数组

.pathsToExclude(“/internal/**”)

.addOpenApiMethodFilter(Predicate)

自定义方法过滤逻辑

见下面示例

.displayName(String name)

显示名称(覆盖 group 的显示)

同 group 值

.displayName(“用户模块”)

.addOperationCustomizer(…)

自定义操作处理器

见下面示例

通过合理的分组配置,可在 JDK 17 环境下构建清晰、安全、易维护的 API 文档体系,充分发挥 SpringDocKnife4j 的现代化文档能力。

基础分组配置:

import org.springdoc.core.models.GroupedOpenApi;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class OpenApiGroupConfig {    // 用户管理分组    @Bean    public GroupedOpenApi userApi() {        return GroupedOpenApi.builder()                .group("用户管理")                   // 分组显示名称                .pathsToMatch("/api/user/**")        // 路径匹配规则                .packagesToScan("com.example.user") // 包扫描路径                .build();    }    // 订单管理分组    @Bean    public GroupedOpenApi orderApi() {        return GroupedOpenApi.builder()                .group("订单管理")                .pathsToMatch("/api/order/**")                .packagesToScan("com.example.order")                .build();    }    // 分组自定义排序    @Bean    public GroupedOpenApi firstGroup() {      return GroupedOpenApi.builder()               .group("01-核心接口")               .order(1)  // 分组排序(数值越小越靠前)               .pathsToMatch("/core/**")               .build();    }    @Bean    public GroupedOpenApi secondGroup() {      return GroupedOpenApi.builder()               .group("02-辅助接口")               .order(2)               .pathsToMatch("/support/**")               .build();    }}

按安全权限分组:

@Beanpublic GroupedOpenApi adminApi() {    return GroupedOpenApi.builder()            .group("管理员接口")            .pathsToMatch("/api/admin/**")            // 只包含带有 @PreAuthorize("hasRole('ADMIN')") 的接口            .addOpenApiMethodFilter(method ->                 method.isAnnotationPresent(PreAuthorize.class) &&                 method.getAnnotation(PreAuthorize.class).value().contains("ADMIN")            )            .build();}

多版本 API 分组:

@Beanpublic GroupedOpenApi v1Api() {    return GroupedOpenApi.builder()            .group("API-v1")            .pathsToMatch("/api/v1/**")            .displayName("版本 1.0 (已弃用)")            .build();}@Beanpublic GroupedOpenApi v2Api() {    return GroupedOpenApi.builder()            .group("API-v2")            .pathsToMatch("/api/v2/**")            .displayName("版本 2.0 (最新)")            .build();}

第三方接口分组:

@Beanpublic GroupedOpenApi paymentApi() {    return GroupedOpenApi.builder()            .group("支付网关")            .pathsToMatch("/payment/**")            // 排除内部实现类            .packagesToExclude("com.example.internal.payment")             .build();}

3.4 包名迁移与模块化适配

3.4.1 全局替换包名

IDE 操作:使用 IntelliJ/Eclipse 的全局替换功能(Ctrl+Shift+R),将以下包名替换:javax.servletjakarta.servletjavax.validationjakarta.validationjavax.persistencejakarta.persistenceMaven 插件辅助:使用 maven-replacer-plugin 自动化替换:com.google.code.maven-replacer-pluginreplacer1.5.3process-sourcesreplace**/*.javajavax.servletjakarta.servlet

3.4.2 模块化配置(JDK 17+)
// src/main/java/module-info.javaopen module com.example.api {    requires spring.boot;    requires spring.boot.autoconfigure;    requires spring.web;    requires springdoc.openapi.common;    requires com.fasterxml.jackson.databind;    exports com.example.api.controller;    exports com.example.api.model;}

4、迁移后的验证与优化

4.1 验证访问

启动应用后,访问以下地址:

Knife4j UI 文档:http://localhost:8080/doc.html

OpenAPI JSON:http://localhost:8080/v3/api-docs

4.2 文档增强

响应示例:

@Operation(summary = "创建用户")@ApiResponses({    @ApiResponse(        responseCode = "201",        content = @Content(            mediaType = "application/json",            schema = @Schema(implementation = User.class),            examples = @ExampleObject(                name = "successExample",                value = """                    {                      "id": 1,                      "name": "张三"                    }                    """            )        )    ),    @ApiResponse(        responseCode = "400",        content = @Content(            examples = @ExampleObject(                name = "errorExample",                value = """                    {                      "code": "INVALID_REQUEST",                      "message": "用户名不能为空"                    }                    """            )        )    )})public ResponseEntity createUser(@RequestBody User user) { ... }

离线文档导出:

Knife4j 导出:访问 http://localhost:8080/doc.html#/home,点击“下载 Markdown”或“下载 OpenAPI JSON”。

4.3 性能与安全优化

生产环境禁用 UI: springdoc: swagger-ui: enabled: false # 禁用 UI api-docs: enabled: true # 保留 JSON 生成(供内部系统使用)启用 OAuth2 支持: @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers(“/v3/api-docs/**”).hasRole(“DEVOPS”) .anyRequest().authenticated() ) .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); return http.build(); }

5、常见问题与解决方案

5.1. 错误:Type javax.servlet.http.HttpServletRequest not present

错误日志:java.lang.TypeNotPresentException: Type javax.servlet.http.HttpServletRequest not present

原因:未迁移到 Jakarta EE 包名。

解决步骤:

检查是否遗漏包名替换(使用 IDE 全局搜索 javax.servlet),更新依赖至 Jakarta 版本。全局替换代码中的 javax.servletjakarta.servlet。运行 mvn dependency:tree | grep javax.servlet 确认无冲突依赖。更新第三方库至 Jakarta 兼容版本(如 Hibernate 6.x、Tomcat 10.x)。

5.2. Knife4j 访问 /doc.html 报 404

原因:静态资源被拦截或未正确映射。

解决步骤:

确认使用的是 Knife4j OpenAPI3 的 Spring Boot Starter(knife4j-openapi3-jakarta-spring-boot-starter),而非旧版 Knife4jSpringFox。检查静态资源路径(若自定义了 WebMvcConfigurer):Knife4j 的静态资源默认位于 classpath:/META-INF/resources/webjars/knife4j-openapi3-ui/,需确保资源未被拦截或覆盖。

import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class WebConfig implements WebMvcConfigurer {   @Override   public void addResourceHandlers(ResourceHandlerRegistry registry) {      // 添加 Knife4j 的静态资源映射      registry.addResourceHandler("/doc.html")               .addResourceLocations("classpath:/META-INF/resources/");      registry.addResourceHandler("/webjars/**")               .addResourceLocations("classpath:/META-INF/resources/webjars/");   }}

检查 Spring Security 配置是否放行 /doc.html 和 /webjars/**:如果项目集成了 Spring Security,需放行 Knife4j 的静态资源和 API 文档接口。

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.web.SecurityFilterChain;@Configurationpublic class SecurityConfig {   @Bean   public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {      http            .authorizeHttpRequests(auth -> auth               // 放行 Knife4j 相关路径               .requestMatchers(                  "/doc.html",                  "/webjars/**",                  "/v3/api-docs/**",                  "/favicon.ico"               ).permitAll()               .anyRequest().authenticated()            )            .csrf(csrf -> csrf.disable()); // 如果不需要 CSRF 防护      return http.build();   }}

5.3 注解不生效或文档无内容

检查项:

确保控制器添加 @Tag,方法添加 @Operation。模型类字段未标注 @Schema。包扫描路径未覆盖(通过 @ComponentScanspringdoc.packagesToScan 配置)。排除旧版 Swagger 依赖冲突:mvn dependency:tree -Dincludes=io.springfox

6、总结

从 JDK 8 迁移到 JDK 17 不仅是版本的升级,更是技术栈向现代 Java 生态的过渡。通过 依赖替换、注解迁移、包名调整、模块化适配 四步核心操作,可高效完成 Swagger 升级。Knife4j 和 SpringDoc 的组合,不仅解决了兼容性问题,还提供了更强大的 API 文档管理能力。升级后,建议通过自动化测试和持续监控,确保系统的稳定性和可维护性。

以上就是从 JDK 8 到 JDK 17:Swagger 升级迁移指南的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/984325.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
CSS框架Foundation与响应式图片布局应用_多屏适配实践
上一篇 2025年12月1日 21:10:52
主板坏了开机会怎么样?
下一篇 2025年12月1日 21:10:59

相关推荐

  • 修复Django电商项目中AJAX过滤产品列表图片不显示问题

    在Django电商项目中,当使用AJAX动态加载过滤后的产品列表时,常遇到图片无法正常显示的问题。这通常是由于前端模板中图片加载方式(如data-setbg属性结合JavaScript库)与AJAX动态内容更新机制不兼容所致。解决方案是直接在AJAX返回的HTML中使用标准的标签来渲染图片,确保浏览…

    2026年5月10日
    000
  • 开源免费PHP工具 PHP开发效率提升利器

    推荐开源免费PHP开发工具以提升效率:VS Code、Sublime Text轻量高效,PhpStorm专业强大;调试用Xdebug、Kint、Ray;依赖管理选Composer;代码质量工具包括PHPStan、Psalm、PHP_CodeSniffer;数据库管理可用%ignore_a_1%MyA…

    2026年5月10日
    000
  • Matplotlib 地图中多类型图例的创建与优化

    Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化

    本教程旨在解决matplotlib地图可视化中,如何在一个图例中同时展示颜色块(如区域分类)和自定义标记(如特定兴趣点)的问题。文章详细介绍了当传统`patch`对象无法正确显示标记时,如何利用`matplotlib.lines.line2d`创建标记图例句柄,并将其与颜色块图例句柄合并,从而生成一…

    2026年5月10日 用户投稿
    100
  • Golang JSON序列化:控制敏感字段暴露的最佳实践

    本教程探讨golang中如何高效控制结构体字段在json序列化时的可见性。当需要将包含敏感信息的结构体数组转换为json响应时,通过利用`encoding/json`包提供的结构体标签,特别是`json:”-“`,可以轻松实现对特定字段的忽略,从而避免敏感数据泄露,确保api…

    2026年5月10日
    000
  • 怎么在PHP代码中实现图片上传功能_PHP图片上传功能实现与安全处理教程

    首先创建含enctype的HTML表单,再用PHP接收文件,检查目录、移动临时文件,验证类型与大小,生成唯一文件名,并调整php.ini限制以确保上传成功。 如果您尝试在PHP项目中添加图片上传功能,但服务器无法正确接收或保存文件,则可能是由于表单配置、文件处理逻辑或安全限制的问题。以下是实现该功能…

    2026年5月10日
    100
  • HTML如何隐藏滚动条或去除滚动条

    滚动条可以存在也可以不存在,本文主要介绍了html 隐藏滚动条和去除滚动条的方法的相关资料,大家一起来学习一下html隐藏滚动条或去除滚动条的方法吧。 1. html 标签加属性 XML/HTML Code复制内容到剪贴板 2.body中加入以下代码 立即学习“前端免费学习笔记(深入)”; html…

    用户投稿 2026年5月10日
    000
  • 如何让动态追加元素的类事件生效?

    如何在追加元素后使其绑定类事件生效 在页面中引入三方 JavaScript 类并通过添加相应 class 来调用事件方法是一种常见的做法。然而,如果通过 JavaScript 追加标签元素,即使添加了对应的 class,事件也可能无法生效。 为了解决这个问题,可以尝试以下步骤: 检查追加的标签是否为…

    2026年5月10日
    000
  • Golang gRPC流式请求异常处理

    在Golang的gRPC流式通信中,必须通过context.Context处理异常。应监听上下文取消或超时,及时释放资源,设置合理超时,避免连接长时间挂起,并在goroutine中通过context控制生命周期。 在使用 Golang 和 gRPC 实现流式通信时,异常处理是确保服务健壮性的关键部分…

    2026年5月10日
    000
  • Go语言mgo查询构建:深入理解bson.M与日期范围查询的正确实践

    本文旨在解决go语言mgo库中构建复杂查询时,特别是涉及嵌套`bson.m`和日期范围筛选的常见错误。我们将深入剖析`bson.m`的类型特性,解释为何直接索引`interface{}`会导致“invalid operation”错误,并提供一种推荐的、结构清晰的代码重构方案,以确保查询条件能够正确…

    2026年5月10日
    100
  • vscode上怎么运行html_vscode上运行html步骤【指南】

    首先保存文件为.html格式,再通过浏览器或Live Server插件打开预览;推荐安装Live Server实现本地服务器运行与实时刷新,提升开发体验。 在 VS Code 上运行 HTML 文件并不需要复杂的配置,只需几个简单步骤即可预览页面效果。VS Code 本身是一个代码编辑器,不直接运行…

    2026年5月10日
    100
  • RichHandler与Rich Progress集成:解决显示冲突的教程

    在使用rich库的`richhandler`进行日志输出并同时使用`progress`组件时,可能会遇到显示错乱或溢出问题。这通常是由于为`richhandler`和`progress`分别创建了独立的`console`实例导致的。解决方案是确保日志处理器和进度条组件共享同一个`console`实例…

    2026年5月10日
    000
  • 修复点击时按钮抖动:CSS垂直对齐实践

    本文探讨了在Web开发中,交互式按钮(如播放/暂停按钮)在点击时发生意外垂直位移的问题。通过分析CSS样式变化对元素布局的影响,我们发现这是由于按钮不同状态下的边框样式和内边距改变,以及默认的垂直对齐行为共同作用所致。核心解决方案是利用CSS的vertical-align属性,将其设置为middle…

    2026年5月10日
    000
  • Golang goroutine与channel调试技巧

    使用go run -race检测数据竞争,结合runtime.NumGoroutine监控协程数量,通过pprof分析阻塞调用栈,利用select超时避免永久阻塞,有效排查goroutine泄漏、死锁和数据竞争问题。 Go语言的goroutine和channel是并发编程的核心,但它们也带来了调试上…

    2026年5月10日
    000
  • 页面中文本域的值怎么设置

    标签定义多行的文本输入控件。 文本区中可容纳无限数量的文本,其中的文本的默认字体是等宽字体(通常是 Courier)。 可以通过 cols 和 rows 属性来规定 textarea 的尺寸,不过更好的办法是使用 CSS 的 height 和 width 属性。 注释:在文本输入区内的文本行间,用 …

    2026年5月10日
    000
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 《魔兽世界》将于6月11日开启国服回归技术测试

    《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试

    《%ign%ignore_a_1%re_a_1%》官方宣布,将于6月11日开启国服回归技术测试,时间为7天,并称可以在6月内正式开服,玩家们可以访问官网下载战网客户端并预下载“巫妖王之怒”客户端,技术测试详情见下图。 WordAi WordAI是一个AI驱动的内容重写平台 53 查看详情 以上就是《…

    2026年5月10日 用户投稿
    200
  • 如何在HTML中插入表单元素_HTML表单控件与输入类型使用指南

    HTML表单通过标签构建,包含action和method属性定义数据提交目标与方式,常用input类型如text、password、email等适配不同输入需求,配合label、required、placeholder提升可用性,结合textarea、select、button等控件实现完整交互,是…

    2026年5月10日
    000
  • 前端缓存策略与JavaScript存储管理

    根据数据特性选择合适的存储方式并制定清晰的读写与清理逻辑,能显著提升前端性能;合理运用Cookie、localStorage、sessionStorage、IndexedDB及Cache API,结合缓存策略与定期清理机制,可在保证用户体验的同时避免安全与性能隐患。 前端缓存和JavaScript存…

    2026年5月10日
    100
  • HTML5网页如何实现手势操作 HTML5网页移动端交互的处理技巧

    首先利用原生touch事件实现滑动判断,再通过preventDefault解决滚动冲突,接着引入Hammer.js处理复杂手势,最后通过优化点击区域、避免事件冲突和增加视觉反馈提升体验。 在移动端浏览器中,HTML5网页可以通过触摸事件实现手势操作,提升用户体验。虽然原生JavaScript提供了基…

    2026年5月10日
    000
  • 创建指定大小并填充特定数据的Golang文件教程

    本文将介绍如何使用Golang创建一个指定大小的文件,并用特定数据填充它。我们将使用 `os` 包提供的函数来创建和截断文件,从而实现快速生成大文件的目的。示例代码展示了如何创建一个10MB的文件,并将其填充为全零数据。掌握这些方法,可以方便地在例如日志系统或磁盘队列等场景中,预先创建测试文件或初始…

    2026年5月10日
    000

发表回复

登录后才能评论
关注微信