Java 阶段三 Day13 RESTful、Lombok基础组件及Knife4j

  • 一、RESTful -Representational State Transfer
    • 原则和概念
    • RESTful的特征
    • 设计符合RESTful 特征的API
  • 二、整合 Lombok 基础组件
    • 2.1 Lombok 介绍
    • 2.2 安装和配置 Lombok
    • 2.3 Lombok 注解及其用法
      • 2.3.1 @Getter 和 @Setter
      • 2.3.2 @ToString
      • 2.3.3 @AllArgsConstructor 和 @NoArgsConstructor
      • 2.3.4 @Data
  • 三、Knife4j
    • 3.1 Knife4j快速上手
      • 3.1.1 添加依赖
      • 3.1.2 配置Swagger的相关信息
      • 3.1.3 查看生成的接口文档
    • 3.2 常用注解应用分析
    • 3.4 限制请求方式
    • 3.5 导出离线API文档

一、RESTful -Representational State Transfer

RESTful(Representational State Transfer)是一种用于设计网络应用程序的架构风格。它基于一组原则和约束,以便创建具有高性能、可扩展性、简单性和可维护性的分布式系统。RESTful风格通常与HTTP协议一起使用,因此在Web开发中非常常见。

原则和概念

  1. 资源(Resource):在RESTful中,资源是系统中的任何对象或数据,可以通过URL唯一标识(直接通过URI访问)。资源可以是实际对象(如用户、产品)或虚拟概念(如订单、会话)。

  2. 表现层(Representation):资源的表现层是资源的具体表示方式,通常以XML、JSON或HTML等格式呈现。客户端与服务器之间通过这些表现层进行通信。

  3. 状态无关性(Statelessness):RESTful架构是状态无关的,每个请求都包含了足够的信息,使服务器能够理解并处理请求,而不需要维护客户端的状态。这有助于系统的可伸缩性和可靠性。

  4. 统一接口(Uniform Interface):RESTful架构使用统一的接口来访问资源,这包括一组明确定义的HTTP方法(如GET、POST、PUT、DELETE)和标准的URL结构。这使得客户端和服务器之间的通信更加一致和可预测。

  5. 无层次约束(Layered System):RESTful允许在架构中引入层次结构,例如代理服务器、负载均衡器等,以提高性能和安全性。

  6. 可缓存性(Caching):RESTful支持缓存,客户端可以缓存资源的表现层,以减少服务器负载和提高性能。

  7. 按需状态(On-Demand State):RESTful要求客户端包含所有必需的信息,而不依赖于服务器的状态。这使得客户端更加独立,并减少了服务器端的复杂性。

  8. 自描述性(Self-Descriptive Messages):RESTful的表现层应该包含足够的信息,以便客户端能够理解如何处理资源。这降低了客户端与服务器之间的耦合度。

  9. 无需会话管理(No Session Management):RESTful不依赖于会话管理机制,客户端可以在每个请求中包含所有必要的信息。

  10. HTTP方法:RESTful使用标准的HTTP方法来执行操作。最常用的HTTP方法包括GET(获取资源)、POST(创建资源)、PUT(更新资源)和DELETE(删除资源)。这些方法对应于常见的CRUD操作(创建、读取、更新、删除)。

RESTful架构常用于构建Web服务、API和分布式系统,它提供了一种简单、直观和高效的方式来进行网络通信。许多现代Web应用程序和移动应用程序都使用RESTful API来与服务器进行通信。RESTful的设计原则使得开发人员能够构建易于理解和扩展的系统。

RESTful的特征

  • 每一个URI代表一种资源

  • 客户端和服务器端之前传递着资源的某种表现

  • 客户端通过HTTP的几个动作 对 资源进行操作 - 状态转化

状态转化:访问一个URI即发生了一次 客户端和服务端的交互;此次交互将会涉及到数据和状态得变化。

设计符合RESTful 特征的API

详细要求:

  1. 资源的命名

    • 使用名词来表示资源,而不是动词。例如,使用/users表示用户资源,而不是/getUsers
    • 使用复数名词形式来表示集合资源,使用单数名词形式来表示单一资源。例如,/users表示用户集合,/user/123表示单个用户。
  2. 使用HTTP方法

    • 使用HTTP方法来执行操作。最常用的HTTP方法包括GET(获取资源)、POST(创建资源)、PUT(更新资源)和DELETE(删除资源)。
    • 遵循HTTP方法的语义。例如,使用GET来获取资源,而不是用于创建或更新资源。
  3. 统一接口

    • 使用一组明确定义的URI模板来表示资源。这有助于客户端理解如何构建和解析URL。
    • 使用HTTP状态码来表示操作结果。常见状态码包括200 OK、201 Created、204 No Content、400 Bad Request、404 Not Found、500 Internal Server Error等。
  4. 资源的表现层

    • 支持多种数据格式,例如JSON、XML等,以满足不同客户端的需求。客户端可以通过设置Accept头来请求特定的数据格式。
    • 使用恰当的媒体类型来标识表现层,例如application/jsonapplication/xml
  5. 无状态性

    • 避免在服务器端保存客户端的状态信息。每个请求应该包含所有必要的信息,以便服务器能够理解和处理请求。
  6. 关联资源

    • 使用超链接来关联资源,使得客户端可以轻松地导航到相关资源。超链接可以嵌入到资源的表现层中,或者通过Link头部来提供。
  7. 版本控制

    • 使用版本控制来处理API的演进。在URI中包含版本号(例如/v1/resource)或者使用自定义头部来指定版本。
  8. 安全性

    • 使用HTTPS来保护数据的传输,特别是在涉及敏感信息的情况下。
    • 使用身份验证和授权机制来保护API,确保只有合法用户可以访问资源。
  9. 错误处理

    • 提供有意义的错误消息,以帮助客户端识别和处理错误。错误消息应该包括HTTP状态码、错误代码和错误描述。
    • 使用标准的HTTP状态码来表示错误类型,避免自定义错误码。
  10. 文档和元数据

    • 提供详细的文档,描述API的使用方法、资源、端点、参数等信息。常见的方式包括Swagger、OpenAPI规范等。
    • 使用HATEOAS(Hypertext As The Engine Of Application State)来提供API的自描述性,使得客户端能够动态探索API。
  11. 测试和监控

    • 进行全面的单元测试和集成测试,以确保API的稳定性和正确性。
    • 实施监控机制来跟踪API的性能和可用性,及时发现并解决问题。

设计RESTful API需要权衡许多因素,包括资源的命名、URI结构、HTTP方法的选择、错误处理等。遵循上述最佳实践有助于确保API的一致性、可读性和可维护性,同时提供良好的开发者体验。此外,与团队成员和其他开发者进行讨论和审查也是设计API的重要步骤,以确保满足实际需求。

具体介绍

  • 协议 - http/https

  • 域名
    域名中体现出api字样,如
    https://api.example.com
    或者
    https://example.org/api/

  • 版本:
    https://api.example.com/v1/

  • 路径:
    路径中避免使用动词,资源用名词表示,案例如下

    https://api.example.com/v1/users
    https://api.example.com/v1/animals
    
  • HTTP动词语义

    请求动词 说明
    GET(SELECT) 从服务器取出资源(一项或多项)
    POST(CREATE) 在服务器新建一个资源
    PUT(UPDATE) 在服务器更新资源
    DELETE(DELETE) 从服务器删除资源

    案例:

    请求动作 请求资源 说明
    GET /zoos 列出所有动物园
    POST /zoos 新建一个动物园
    GET /zoos/ID 获取某个指定动物园的信息
    PUT /zoos/ID 更新某个指定动物园的信息
    DELETE /zoos/ID 删除某个动物园
    GET /zoos/ID/animals 列出某个指定动物园的所有动物
    DELETE /zoos/ID/animals/ID 删除某个指定动物园的指定动物
  • 巧用查询字符串

    ?type_id=1:指定筛选条件
    ?limit=10:指定返回记录的数量
    ?offset=10:指定返回记录的开始位置。
    ?page=2&per_page=100:指定第几页,以及每页的记录数。
    
  • 状态码

    用HTTP响应码表达 此次请求结果,例如

    响应码 说明
    200 OK - [GET] 服务器成功返回用户请求的数据
    404 NOT FOUND 用户发出的请求针对的是不存在的记录,服务器没有进行操作
    500 INTERNAL SERVER ERROR 服务器发生错误

二、整合 Lombok 基础组件

2.1 Lombok 介绍

Lombok(发音为"LOM-bok",意为"Less Code, More Fun")是一个用于Java编程语言的开源项目,它旨在减少Java代码中的样板代码(boilerplate code)编写,以提高代码的可读性和可维护性。Lombok通过使用注解来自动生成常见的Java代码,例如getter和setter方法、构造函数、equals和hashCode方法等,从而简化了Java类的编写过程。

以下是Lombok的一些主要功能和用途:

  1. 自动生成Getter和Setter:通过在类字段上添加@Getter@Setter注解,Lombok会自动生成相应的getter和setter方法,减少了冗长的getter和setter代码的编写。

  2. 自动生成构造函数:Lombok支持自动生成各种类型的构造函数,包括无参构造函数、全参构造函数、带有指定字段的构造函数等。

  3. 自动生成toString方法:通过在类上添加@ToString注解,Lombok可以自动生成toString方法,用于方便地打印对象的字符串表示。

  4. 自动生成equalshashCode方法:通过在类上添加@EqualsAndHashCode注解,Lombok可以自动生成equalshashCode方法,用于对象的比较和哈希计算。

  5. 自动生成@NoArgsConstructor@AllArgsConstructor:这些注解用于生成无参构造函数和全参构造函数,可减少构造函数的编写。

  6. 自动生成@Data注解@Data注解包含了@Getter@Setter@ToString@EqualsAndHashCode等功能,可一次性自动生成所有这些方法。

  7. 自动生成@Builder注解@Builder注解用于生成建造者模式的构建器方法,用于创建对象的复杂实例。

  8. 自动生成@Slf4j和其他日志注解:Lombok支持生成与不同日志框架(如SLF4J、Log4j、Logback)兼容的日志注解,以便快速添加日志记录功能。

  9. 自动生成@Value注解@Value注解用于创建不可变(immutable)的JavaBean,它生成final字段和无参构造函数。

Lombok的主要目标是减少样板代码的编写,使Java代码更加简洁和易读。开发人员可以通过添加Lombok注解来自动生成常见的代码,而无需手动编写。这有助于提高开发效率并降低错误的可能性。但需要注意的是,使用Lombok的代码可能会对阅读代码的开发者造成一些困惑,因为生成的代码在源代码中是看不到的,因此文档和注释的编写变得尤为重要。

要使用Lombok,需要将Lombok库添加到项目的依赖中,并在IDE中安装Lombok插件,以便在开发过程中正确显示生成的代码,每个IDE和构建工具都有自己的配置方式。

2.2 安装和配置 Lombok

  1. 添加Lombok依赖:首先,在项目的构建工具中(例如Maven、Gradle)添加Lombok依赖。具体添加方式取决于你的构建工具。

    • 如果使用Maven,可以在项目的pom.xml文件中添加以下依赖:

      <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version> <!-- 根据当前最新版本更新 --><scope>provided</scope>
      </dependency>
      
    • 如果使用Gradle,可以在项目的build.gradle文件中添加以下依赖:

      compileOnly 'org.projectlombok:lombok:1.18.22' // 根据当前最新版本更新
      annotationProcessor 'org.projectlombok:lombok:1.18.22'
      

    注意:Lombok的compileOnly依赖用于编译时,annotationProcessor依赖用于处理Lombok注解。

  2. 安装Lombok插件:为了在IDE中正确显示和处理Lombok注解,你需要安装适用于你的IDE的Lombok插件。Lombok支持的IDE包括Eclipse、IntelliJ IDEA、NetBeans等。

    • 对于IntelliJ IDEA,你可以在IDE内使用插件市场(Plugin Marketplace)搜索"Lombok"并安装它。

    • 对于Eclipse,你可以在Eclipse Marketplace搜索"Lombok"并安装它。

    • 对于其他IDE,也可以查找适用于Lombok的插件或集成工具。

  3. 配置IDE:安装Lombok插件后,你可能需要进行一些IDE的配置以确保Lombok正常工作。

    • 对于IntelliJ IDEA,打开IDE设置(File -> Settings or IntelliJ IDEA -> Preferences),然后在"Build, Execution, Deployment"下找到"Lombok"。启用"Lombok"支持并重启IDE。

    • 对于Eclipse,通常无需额外配置。

  4. 使用Lombok注解:在项目中使用Lombok注解,例如@Getter@Setter@Data等,以减少样板代码的编写。在你的Java类中添加这些注解,它们会自动生成相应的代码。

  5. 构建项目:重新构建项目以应用Lombok的功能。在IDE中,通常无需手动构建,因为Lombok插件会自动处理。

2.3 Lombok 注解及其用法

2.3.1 @Getter 和 @Setter

用来生成 getter 和 setter 方法

@Getter
@Setter
public class Student {private String name;private int age;
}

这将自动生成 getName(), setName(), getAge(), setAge() 方法

2.3.2 @ToString

@ToString
public class Student {private String name;private int age;
}

这将自动生成 toString() 方法。

2.3.3 @AllArgsConstructor 和 @NoArgsConstructor

@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private int age;
}

这将自动生成一个有参构造函数和一个无参构造函数。

2.3.4 @Data

是一个组合的注解,它等价于同时使用了 @Getter、@Setter、@NoArgsConstructor、@AllArgsConstructor 和 @ToString 注解。

@Data
public class Student {private String name;private int age;
}

这将自动生成 getName(), setName(), getAge(), setAge(),有参构造函数、无参构造函数,以及 toString() 方法。

三、Knife4j

Knife4j 是一款开源的基于 Swagger 的 API 文档生成工具,旨在为 Java 开发者提供方便的 API 文档管理和在线测试功能。它是 Swagger-UI 的增强版,提供了更多的功能和自定义选项,以改善 API 文档的呈现和交互性。

以下是 Knife4j 的一些主要特点和功能:

  1. 自动生成 API 文档:Knife4j 可以自动解析项目中的 Swagger 注解(例如 @ApiOperation@ApiParam)并生成 API 文档。这使得创建和维护 API 文档变得更加轻松。

  2. 在线测试:Knife4j 具有强大的在线 API 测试功能,允许开发人员在浏览器中执行 API 请求并查看响应。这有助于快速验证 API 的功能和正确性。

  3. 美观的界面:Knife4j 的界面与 Swagger-UI 相比更加美观和用户友好。它提供了更多的交互功能,如折叠和展开操作、参数验证和示例值的显示等。

  4. 权限控制:Knife4j 支持对 API 文档的访问权限控制,你可以配置谁可以查看和使用 API 文档。

  5. 多种主题:Knife4j 支持多种主题,你可以根据项目的需求选择合适的主题样式。

  6. 导出功能:你可以将 Knife4j 生成的 API 文档导出为静态 HTML 文件,以便在没有 Knife4j 运行时也能访问文档。

  7. Spring Boot 集成:Knife4j 针对 Spring Boot 提供了集成支持,使得在 Spring Boot 项目中使用 Knife4j 更加简便。

  8. 参数校验:Knife4j 提供了参数校验功能,可以在在线测试时验证输入参数的合法性。

  9. 全局配置:你可以根据项目需求进行全局配置,包括文档标题、描述、联系信息等。

3.1 Knife4j快速上手

3.1.1 添加依赖

要快速上手使用 Knife4j 生成 API 文档,你需要按照以下步骤进行配置和使用:
如果你使用 Maven,可以在项目的 pom.xml 文件中添加以下依赖:

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.2</version> <!-- 根据最新版本更新 -->
</dependency>

如果你使用 Gradle,可以在项目的 build.gradle 文件中添加以下依赖:

implementation 'com.github.xiaoymin:knife4j-spring-boot-starter:3.0.2' // 根据最新版本更新

3.1.2 配置Swagger的相关信息

工程目录下创建config.Knife4jConfig

@Configuration
@EnableSwagger2
public class Knife4jConfig {//配置Swagger2的Docket的Bean实例@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2)// apiInfo():配置 API 的一些基本信息,比如:文档标题title,文档描述description,文档版本号version.apiInfo(apiInfo())// select():生成 API 文档的选择器,用于指定要生成哪些 API 文档.select()// apis():指定要生成哪个包下的 API 文档.apis(RequestHandlerSelectors.basePackage("com.example.egmvc2.controller"))// paths():指定要生成哪个 URL 匹配模式下的 API 文档。这里使用 PathSelectors.any(),表示生成所有的 API 文档。.paths(PathSelectors.any()).build();}//文档信息配置private ApiInfo apiInfo() {return new ApiInfoBuilder()// 文档标题.title("地址存储")// 文档描述信息.description("地址存储在线API文档")// 文档版本号.version("1.0").build();}
}

pom.xml添加配置

<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.1</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.1</version></dependency><dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>1.5.19</version></dependency>

application.properties添加

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

3.1.3 查看生成的接口文档

在 SpringBoot 项目启动后,访问 http://localhost:8080/doc.html 地址即可查看生成的Knife4j接口文档。

左侧的address-controller及放在controller中的AddressController文件

3.2 常用注解应用分析

  • @Api注解
    添加在控制器类上的注解,通过此注解的tags属性可以修改原本显示控制器类名称的位置的文本,通常,建议在配置的tags属性值上添加序号,例如:“01. 用户模块”、“02. 微博模块”,则框架会根据值进行排序。

    • 参数说明

      • tags:配置模块名称
    • 代码示例

      // 1. AddressController
      @Api(tags = "地址管理模块")
      public class AddressController {...}
      
    • 文档效果(重启工程并刷新页面:http://localhost:8080/doc.html#/home)

  • @ApiOperation注解
    添加在控制器类中处理请求的方法上的注解,用于配置此方法处理的请求在API文档中显示的文本。

    • 参数说明
      value:配置业务名称

    • 代码示例
      此处以添加地址功能为例,其他所有方法请添加说明

      @RequestMapping("insert")@ApiOperation("添加地址数据")public String insert(Address address) {return addressMapper.insert(address) == 1 ? "添加成功" : "添加失败";}
      

  • @ApiModelProperty注解
    是添加在POJO类的属性上的注解,用于对请求参数或响应结果中的某个属性进行说明,主要通过其value属性配置描述文本,并可通过example属性配置示例值。

    • 参数说明

      • value属性:配置参数名称
      • required属性:配置是否必须提交此请求参数
      • example属性:配置示例值

      注意:如果配置了 required=true,只是一种显示效果,Knife4j框架并不具备检查功能

    • 代码示例
      以添加AddressDTO为例

      @Data
      public class AddressDTO {@ApiModelProperty(value = "收件人", required = true, example = "左大凯")private String receiver;@ApiModelProperty(value = "收件地址", required = true)private String address;@ApiModelProperty(value = "邮箱", required = true)private String email;@ApiModelProperty(value = "手机号码", required = true)private String mobile;@ApiModelProperty(value = "已收件", required = true)private String tag;
      }
      

  • @ApiImplicitParam注解

    添加在控制器类中处理请求的方法上的注解,主要用于配置非封装的参数

    • 参数说明

      • name:指定参数名称(参数变量名)
      • value:配置参数名称
      • dataType:配置数据类型
      • required:配置是否必须提交此请求参数
      • example:配置参数的示例值

    注意:一旦使用此注解,各个参数的数据类型默认都会显示String,可以通过dataType指定数据类型

    • 代码示例
      此处以根据ID搜索地址功能为例

      @RequestMapping("selectById")
      @ApiOperation("根据ID进行搜索")
      @ApiImplicitParam(name = "id", value = "邮箱", required = true, dataType = "int", example = "0")
      public AddressDTO selectById(int id) {return addressMapper.selectById(id);
      }
      
    • 文档效果(重启工程并刷新页面:http://localhost:8080/doc.html#/home)
  • @ApiImplicitParams注解
    添加在控制器类中处理请求的方法上的注解,当方法有多个非封装的参数时,在方法上添加此注解,并在注解内部通过@ApiImplicitParam数组配置多个参数。

    • 代码示例
      此处以根据收件人和收货地址搜索功能为例(并无实际价值)

      @GetMapping("selectByNameAndAddress")@ApiOperation("根据用户名和地址进行搜索")@ApiImplicitParams(value = {@ApiImplicitParam(name = "receiver", value = "收件人", required = true),@ApiImplicitParam(name = "address", value = "地址", required = true)})public List<AddressDTO> selectByNameAndAddress(String receiver, String address) {return addressMapper.selectByNameAndAddress(receiver, address);}
      
    • 文档效果(重启工程并刷新页面:http://localhost:8080/doc.html#/home)

  • @ApiIgnore注解
    添加在处理请求的方法的参数上,用于表示API文档框架应该忽略此参数
    此处还以根据收件人和收货地址搜索功能为例(并无实际价值)
    将address的required删除,在address前添加@ApiIgnore

    • 代码示例

      @GetMapping("selectByNameAndAddress")
      @ApiOperation("根据用户名和地址进行搜索")
      @ApiImplicitParams(value = {@ApiImplicitParam(name = "receiver", value = "收件人", required = true),@ApiImplicitParam(name = "address", value = "地址")
      })
      public List<AddressDTO> selectByNameAndAddress(String receiver,@ApiIgnore String address) {return addressMapper.selectByNameAndAddress(receiver, address);
      }
      
    • 文档效果(重启工程并刷新页面:http://localhost:8080/doc.html#/home)

      对比上图,可以发现请求类型和是否必读均发生变化。

3.4 限制请求方式

API文档中默认每个功能会展示7种请求方式,遵循RESTful规则将 @RequestMapping 注解修改为对应请求方法的注解,比如:@GetMapping @PostMapping @PutMapping @DeleteMapping 注解,重启工程后刷新测试。

3.5 导出离线API文档

  1. 文档管理 - 离线文档 中存在多种格式的导出格式

  1. 选择合适的文档格式,导出即可到本地磁盘

Java 阶段三 Day13 RESTful、Lombok基础组件及Knife4j相关推荐

  1. Java第三次作业——面向对象基础(封装)

    Java第三次作业--面向对象基础(封装) (一)学习总结 1.什么是面向对象的封装性,Java中是如何实现封装性的?试举例说明. 封装性就是指对外部不可见,用对象直接访问类中的属性,在面向对象法则中 ...

  2. java反射三种方法_Java基础入门要学哪些 怎么掌握反射和枚举

    Java基础入门要学哪些?怎么掌握反射和枚举?Java是老牌编程语言,是一种可以撰写跨平台应用软件的面向对象的程序设计语言.Java所包含的基础知识点很多,只有掌握了这些知识才能更好地运用,下面就来给 ...

  3. java变量三要素_Java零基础快速入门|变量

    本文章主要内容:字面量 变量概述 使用变量 变量分类 变量作用域 难点疑惑 学习目标:理解变量本质是什么,在开发中有什么用? 变量三要素是什么? 怎么声明变量? 怎么给变量赋值? 变量是如何分类的? ...

  4. [Java面试三]JavaWeb基础知识总结.

    [Java面试三]JavaWeb基础知识总结. 1.web服务器与HTTP协议 Web服务器 l WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. l Int ...

  5. java第三阶段源代码_有效Java第三版的源代码已更新为使用较新的功能

    java第三阶段源代码 那些已经阅读了有效Java 第三版的人可能知道与该书相关的源代码可以在GitHub上获得 . jbloch / effective-java-3e-source-code项目拥 ...

  6. java在高峰期才用缓存,我司基础组件更新本地缓存策略问题导致young gc时间升高...

    背景 有次想研究一下服务QPS和young gc的时间的关系.假如服务对外提供的接口的平均响应时间是1s,那么最坏情况下该请求用到的对象就应该存活1s(为什么是最坏,因为很多中间变量不需要这么存活这么 ...

  7. java三个环境变量_java基础(一):我对java的三个环境变量的简单理解和配置

    首先说说java的三个环境变量:java_home,classpath,path java_home:jdk的安装路径[你一层一层点开安装路径,直到当前目录有一个bin目录,然后在地址栏里面右键单击复 ...

  8. 【Java笔记+踩坑】SpringBoot——基础

      导航: [黑马Java笔记+踩坑汇总]JavaSE+JavaWeb+SSM+SpringBoot+瑞吉外卖+SpringCloud/SpringCloudAlibaba+黑马旅游+谷粒商城 目录 ...

  9. java中override快捷键_【基础回溯1】面试又被 Java 基础难住了?推荐你看看这篇文章。...

    本文已经收录自 https://github.com/Snailclimb/JavaGuide  (59k+ Star):[Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识. ...

  10. 基础组件完善的今天,如何通过业务组件提效?

    简介: 无论是在前端刀耕火种的 jQuery/YUI 时代,还是到现在基于数据驱动 UI 的 React/Vue 时代,物料/组件一直是前端永恒的话题.基于大量重复逻辑的封装可以很显而易见地提升前端 ...

最新文章

  1. Java必会的工具库,让你的代码量减少90%
  2. 独家 | 使用Python的OpenAI Gym对Deep Q-Learning的实操介绍(附学习资源)
  3. python3练习题:11-20
  4. Honeycomb Gym - 102028F(bfs)
  5. web前端(12)—— 页面布局2
  6. PostgreSQL学习总结(6)—— PostgreSQL 模式(SCHEMA)详解
  7. MOSS关于Workflow
  8. 跋山涉水 —— 深入 Redis 字典遍历
  9. 第4次作业类测试代码 021
  10. 简单的解决办法,复杂的分析工作
  11. centos系统加入windows域
  12. 第五课多元函数偏导与全微分
  13. 用scribefire写blog
  14. 每日一课 | python烤地瓜案例
  15. IMG按图搜索商品详情
  16. 洛谷P1021 邮票面值设计
  17. 重磅!中国电信物联网用户超4亿
  18. GlusterFS源码学习——函数指针数组的妙用
  19. 多码头多式联运集装箱港口的全局规划
  20. 计算机摄像头打不开,电脑摄像头打不开、用不了怎么办(操作简单),这几步你要了解...

热门文章

  1. RecyclerView布局靠左问题
  2. 人生如逆水行舟,只为红尘梦一风方
  3. 书单推荐 — 《浪潮之巅》
  4. Linux驱动基础(HC-SR04超声波模块)
  5. Windows10 安装cx_Oracle
  6. 【设计模式】设计模式入门知识
  7. 2022年我国医疗器械行业市场规模以及细分领域竞争格局分析
  8. 基于YOLO-fastest-xl的OCR
  9. android知识(三)
  10. 多宁生物冲刺港股:年营收8亿 红杉中国与药明生物是股东