对controller层进行深入学习

目录

  • 1. controller层是干什么的?
    • 1.1 controller原理图
    • 1.2 controller层为什么要存在?
      • 1.2.1 分离关注点
      • 1.2.2 响应HTTP请求
      • 1.2.3 数据处理与转换
      • 1.2.4 错误处理与状态管理
      • 1.2.5 流程控制
      • 1.2.6 依赖注入与测试
    • 1.3 controller层的优点
      • 1.3.1 多端支持
      • 1.3.2 安全性保障
      • 1.3.3 性能优化
    • 1.4 All in All
  • 2. 研究Restful风格
    • 2.1 什么是Restful风格?
      • 2.1.1 功能
      • 2.1.2 Restful风格与传统风格的区别
        • 2.1.2.1 请求方法
        • 2.1.2.2 数据格式
        • 2.1.2.3 状态码使用
        • 2.1.2.4 异常处理
        • 2.1.2.5 无状态性
        • 2.1.2.6 总结
  • 3. controller层代码
    • 3.1 定义controller风格的注解
      • 3.1.1 @RestController
      • 3.1.2 @RequestMapping
      • 3.1.3 @Slf4j
    • 3.2 依赖注入注解
      • 3.2.1 @Resource和@Autowired的相同点
      • 3.2.2 @Resource和@Autowired的不同点
      • 3.2.3 总结
    • 3.3 依赖注入三种方式
      • 3.3.1 字段注入(最简单,有风险)
      • 3.3.2 构造器注入(最安全,推荐)
      • 3.3.3 Setter方法注入
  • 4. controller层接口代码详解
    • 4.0 HTTP常见请求方法合集
    • 4.1 模糊查询---接口
    • 4.2 findAll---接口
    • 4.3 根据id查询---接口
    • 4.4 增加---接口
    • 4.5 删除---接口
    • 4.5 更新---接口
  • 5 总结

1. controller层是干什么的?

1.1 controller原理图

在这里插入图片描述
在Web应用程序中,控制器层(Controller)是模型-视图-控制器(MVC)架构模式的一个关键组成部分。控制器负责接收用户的输入调用业务逻辑层来处理这些输入并返回适当的响应给视图层
举个例子吧:

平时登陆账号的时候,你想要输入账号和密码吧,然后点击登陆的时候,用户请求是最先传到controller层的,然后controller层再传到service层,为什么不直接传给service层?例如,密码长度不符合要求,或者账号不是有效的电子邮件格式,那么没有必要将请求转发到服务层或数据库层进行更深入的验证。通过在控制器层进行初步验证,可以减少不必要的服务层或数据库层操作,从而提高系统性能和响应速度。另外,在控制器层进行格式验证可以作为安全措施的一部分,防止恶意或格式错误的数据到达后端服务,减少潜在的安全风险。以前的黑客不就玩的sql注入吗,当时的开发者都没有意识到在数据库查询中直接使用用户输入的危险。

1.2 controller层为什么要存在?

在现代Web应用程序中,用户请求通常不会直接传递给服务层(Service),而是通过控制器层(Controller)来处理,这种设计主要是基于以下几个原因:

1.2.1 分离关注点

控制器层和业务逻辑层分离,使得每一层都只关注自己的职责。控制器层关注如何接收请求、验证输入和调用相应的业务逻辑。服务层则关注业务规则和业务流程的具体实现。

1.2.2 响应HTTP请求

在Spring框架中,Controller通过@Controller或@RestController注解标识,配合@RequestMapping等注解,能够响应不同路径的HTTP请求。如果没有Controller,系统将无法正确解析和响应用户请求,导致功能无法实现。

1.2.3 数据处理与转换

Controller负责将接收到的数据(如用户输入的用户名和密码)传递给Service层进行验证,并将验证结果转换为适合客户端展示的格式。例如,使用@ResponseBody注解可以将Java对象自动转换为JSON格式,方便前端处理。

1.2.4 错误处理与状态管理

Controller还负责处理请求过程中可能出现的错误情况,并管理HTTP状态码。如果去掉Controller,这些错误处理和状态管理将无处安放,可能导致用户体验不佳和安全风险

1.2.5 流程控制

Controller通过方法调用和返回值决定后续执行流程。例如,如果用户登录失败,Controller可以决定重新显示登录页面和错误信息;如果登录成功,则跳转到用户的主页。这种流程控制能力是细粒度处理请求不可或缺的。

1.2.6 依赖注入与测试

Spring框架中的Controller可以利用依赖注入(DI)集成其他组件(如Service、DAO等),并通过@Autowired注解自动装配所需的依赖。这使得单元测试变得更加容易,同时也降低了组件间的耦合度。

1.3 controller层的优点

1.3.1 多端支持

在一个多端应用(如网页、移动端)中,不同的前端可能发送类似的请求(如获取用户信息)。Controller可以统一处理这些请求,减少重复代码。

1.3.2 安全性保障

Controller可以结合Spring Security等安全框架,提供认证、授权和跨站请求伪造(CSRF)防护等功能,增强应用的安全性。

1.3.3 性能优化

通过合理的Controller设计(如缓存、异步处理),可以提升系统的响应速度和并发处理能力。

1.4 All in All

Controller在Web应用中扮演着核心角色,负责处理请求、响应、数据转换、错误处理和流程控制等关键任务。去掉Controller将导致系统无法正常响应用户请求,破坏架构的模块化和可维护性。因此,在实际开发中应充分重视Controller的设计和实现。

以下是控制器层的详细阐述:

2. 研究Restful风格

2.1 什么是Restful风格?

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

2.1.1 功能

  1. 资源:互联网所有的事物都可以被抽象为资源
  2. 资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。
  3. 分别对应 添加、 删除、修改、查询。

2.1.2 Restful风格与传统风格的区别

2.1.2.1 请求方法

Restful风格:Restful风格的Controller全面使用HTTP的方法,包括GET、POST、PUT、DELETE等。每种方法都有具体的含义,例如GET用于获取资源,POST用于创建新资源,PUT用于更新资源,DELETE用于删除资源。
传统风格:传统风格的Controller通常只使用GET和POST请求方法。这意味着不管需要进行什么样的操作,基本都依赖于这两种方法,可能导致一个操作对应多个URL。

2.1.2.2 数据格式

Restful风格:Restful风格的接口通常使用JSON或XML作为数据交换格式,它们易于解析和生成,同时具有良好的可读性。
传统风格:通常使用xml。

2.1.2.3 状态码使用

Restful风格:Restful风格的Controller充分利用了HTTP状态码来表示不同的结果状态,如200(成功)、201(已创建)、404(未找到)、500(服务器错误)等,这些状态码能明确告诉客户端请求的处理结果。
传统风格:传统风格的Controller中,状态码的使用较为单一,通常只有200(成功)被频繁使用,其他状态码较少出现。

2.1.2.4 异常处理

Restful风格:Restful风格的Controller采用统一的异常处理器,可以集中管理错误处理逻辑,并返回统一的错误信息和状态码。
传统风格:传统风格的异常处理可能分散在不同的Controller中,导致代码重复和管理不便。

2.1.2.5 无状态性

Restful风格:Restful风格的设计是无状态的,每次请求都包含了所有必需的信息,这使得系统更加简单且易于扩展。
传统风格:传统风格的Controller可能会依赖存储在服务器端的会话(Session)状态,这导致系统在水平扩展时面临挑战。

2.1.2.6 总结

Restful风格的Controller在URL设计、HTTP方法使用、状态码管理等方面具有明显优势,使得后端服务更加标准化和易于维护。在实际开发中,应当尽量采用Restful风格的设计原则来构建Web应用的后端服务。

3. controller层代码

package com.goblin.BIbackend.controller;import com.goblin.BIbackend.common.BaseResponse;
import com.goblin.BIbackend.common.ListWithTotal;
import com.goblin.BIbackend.common.ResultUtils;
import com.goblin.BIbackend.model.entity.Complaints;
import com.goblin.BIbackend.service.ComplaintsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.List;@RestController
@RequestMapping("/complaints")
@Slf4j
public class ComplaintsController {@Resourceprivate ComplaintsService complaintsService;//模糊查询@PostMapping("/search")public BaseResponse<ListWithTotal<Complaints>> search(@RequestBody Complaints keyword) {log.info("查询投诉信箱:{}", keyword);List<Complaints> complaints = complaintsService.search1(keyword);int total = complaints.size();log.info("查询投诉信箱总数:{}", total);ListWithTotal<Complaints> list = new ListWithTotal<>(complaints, total);return ResultUtils.success(list);}@GetMapping("/list")public BaseResponse<ListWithTotal<Complaints>> list() {List<Complaints> complaints = complaintsService.getList();int total = complaintsService.count1();log.info("查询投诉信箱总数:{}", total);ListWithTotal<Complaints> list = new ListWithTotal<>(complaints, total);return ResultUtils.success(list);}@GetMapping("/select2")public BaseResponse<Complaints> select2(Long id) {log.info("查询投诉信息:{}", id);Complaints complaints = complaintsService.select2(id);log.info("查询投诉信息:{}", complaints);return ResultUtils.success(complaints);}@PostMapping("/insert2")public BaseResponse<Complaints> insert2(@RequestBody Complaints complaints) {Complaints result = complaintsService.insert2(complaints);return ResultUtils.success(result);}@DeleteMapping("/delete2")public BaseResponse<Long> delete2(Long id) {complaintsService.delete2(id);return ResultUtils.success(id);}@PutMapping("/update2")public BaseResponse<Complaints> update2(@RequestBody Complaints complaints) {complaintsService.update2(complaints);return ResultUtils.success(complaints);}}

这段代码是一个Spring Boot应用程序中的ComplaintsController类,它使用Spring MVC框架来处理(Complaints)相关的HTTP请求。以下是对代码的逐行解析:

3.1 定义controller风格的注解

@RestController
@RequestMapping("/complaints")
@Slf4j

这段代码的主要作用是定义一个处理与"/complaints"相关的HTTP请求的控制器,并自动生成日志对象。

3.1.1 @RestController

这是Spring 4之后新加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。这个注解标识这个类是一个RestController,即控制器(Controller),主要用来处理由DispatcherServlet分发的请求,还可以对数据进行校验等操作。

DispatcherServlet是Spring MVC框架中的一个核心组件,它作为前端控制器(Front Controller),负责将接收到的HTTP请求转发到相应的处理器(Controller)。DispatcherServlet是Spring MVC中的中央调度器,它扩展了Servlet API,提供了一种机制来映射请求URL到对应的处理器方法。

3.1.2 @RequestMapping

这个注解用于映射Web请求,即访问"/complaints"路径时,会执行该类下的某个方法。它可以应用于类或方法上,当应用于类上时,表示类中的所有响应请求的方法都是以该地址作为父路径。

3.1.3 @Slf4j

这是Lombok库中的一个注解,用于自动生成日志对象。在使用时,只需在类上添加此注解,就可以自动生成名为log的SLF4J、Log4j、java.util.logging、Commons Logging、Logback以及java.lang.Appendable的实例。

3.2 依赖注入注解

    @Resourceprivate ComplaintsService complaintsService;

先说说@Resource和@Autowired。@Resource和@Autowired都是Spring框架提供的依赖注入(DI)注解,用于实现自动装配bean。

3.2.1 @Resource和@Autowired的相同点

1.依赖注入:两者都用于将Spring容器中的bean自动注入到字段、构造函数或setter方法中。
2.减少代码:通过使用这两个注解,可以减少样板代码,即不需要手动编写代码来从容器中获取bean。
3.支持类型注入:它们都支持通过类型来自动装配,意味着Spring会查找容器中相应类型的bean来注入。

3.2.2 @Resource和@Autowired的不同点

1.来源:@Autowired是Spring自己的注解,属于org.springframework.beans.factory.annotation包。
@Resource是Java EE的注解,适用于更广泛的Java应用,不仅限于Spring框架。
2.注入方式:@Autowired:默认按类型(byType)注入,需要时可以结合@Qualifier指定具体的bean名称。
@Resource:默认按名称(byName)注入,也可通过配置type属性改为按类型注入。
3.参数配置:@Autowired:只有一个required参数,表示是否需要这个依赖。
@Resource:包含多个参数,最重要的是name和type,灵活性更高。
4.使用场景:@Autowired更常用于Spring应用程序中,特别是在使用Spring框架的注解配置时。
@Resource可以用于那些需要兼容Java EE注解的场合,或者在某些特定情况下,开发者可能更倾向于使用Java EE的注解风格。
5.应用建议:@Autowired:更适合Spring环境,特别是当需要更灵活的依赖注入时(例如构造器注入)。
@Resource:更适合与Spring解耦的情境,或者在EE环境中使用。
在Spring配置中,如果同时使用了@Autowired和@Resource,Spring会首先尊重@Autowired的配置。
7.异常处理:@Autowired在找不到bean时会抛出NoSuchBeanDefinitionException。
@Resource在找不到bean时可能会抛出ResourceException。

3.2.3 总结

@Autowired和@Resource都可以用来实现依赖注入,但它们在自动装配的默认行为、来源、使用场景和异常处理等方面存在差异。在Spring应用程序中,推荐使用@Autowired,因为它提供了更好的Spring集成和更灵活的配置选项。

3.3 依赖注入三种方式

依赖注入是一种设计模式,用来实现对象之间的依赖关系。传统的面向对象编程中,类与类之间的依赖关系是通过硬编码来实现的,而依赖注入则将这种依赖关系交给外部容器来处理,从而实现了解耦。
在Spring中依赖注入有三大类:字段注入、构造器注入、Setter方法注入。

3.3.1 字段注入(最简单,有风险)

字段注入是通过在类的字段上使用注解来直接注入依赖对象的一种方式,虽然简单直接,但并不推荐使用,因为它破坏了类的封装性。
字段注入会引起以下的问题

  1. 对象的外部可见性
  2. 可能导致循环依赖
  3. 无法设置注入的对象为final,也无法注入静态变量

什么是字段注入?举例如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MyClass {// 使用@Autowired注解进行字段注入@Autowiredprivate MyService myService;public void doSomething() {myService.performAction();}
}

字段注入非常的简便,通过以上代码我们可以轻松的使用MyService类。

MyService myService= new MyService();
myService.performAction();

这样执行结果为空指针异常,这就是字段注入的第一个问题:对象的外部可见性

public class TestA(){@Autowiredprivate TestB testB;}
public class TestB(){@Autowiredprivate TestA testA;}

上面两段代码卡bug,这段代码在idea中不会报任何错误,但是启动项目时会发现报错,大致意思是:创建Bean失败,原因是当前Bean已经作为循环引用的一部分注入到了其他Bean中。
这就是字段注入的第二个问题:可能导致循环依赖
字段注入还有第三个问题:无法设置注入的对象为final,也无法注入静态变量,原因是变量必须在类实例化进行初始化。

3.3.2 构造器注入(最安全,推荐)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class MyClass {private final MyService myService;// 使用@Autowired注解进行构造器注入@Autowiredpublic MyClass(MyService myService) {this.myService = myService;}public void doSomething() {myService.performAction();}
}

在这个例子中,MyClass的构造函数接收一个MyService类型的参数,并通过@Autowired注解告诉Spring框架自动注入一个合适的MyService实例。这样,当创建MyClass的实例时,Spring会自动调用带有@Autowired注解的构造函数,并将相应的依赖项传递给它。

构造器注入通过在类的构造函数上使用注解来自动装配依赖对象。与字段注入相比,构造器注入有以下优点:
1.强制依赖关系:构造器注入要求必须提供所有必需的依赖项,否则将无法创建类的实例。这有助于确保类在使用之前已经正确地初始化了其依赖项。
2.不可变性:由于构造器注入是在构造函数中完成的,一旦对象被创建,其依赖项就无法更改。这有助于保持对象的不变性,并减少潜在的错误和副作用。
3.可测试性:构造器注入使得单元测试更加容易,因为可以在测试时轻松地提供模拟或存根依赖项。

3.3.3 Setter方法注入

Setter方法注入是依赖注入的一种方式,它**通过在目标类中定义一个或多个setter方法来接收依赖项的实例。**这种方式允许将依赖项的创建和管理从使用对象的类中分离出来,从而实现解耦和易于维护的代码。

public class MyClass {private MyDependency myDependency;// Setter method for dependency injectionpublic void setMyDependency(MyDependency myDependency) {this.myDependency = myDependency;}public void doSomething() {// Use the injected dependencymyDependency.performAction();}
}

在这个例子中,MyClass 有一个 myDependency 属性,它需要被注入一个 MyDependency类型的实例。通过定义一个名为 setMyDependency的setter方法,我们可以在外部容器(如Spring)中配置并注入所需的依赖项。
当Spring容器启动时,它会扫描所有的bean定义,并根据配置文件或其他配置信息自动调用相应的setter方法,将依赖项注入到目标对象中。这样,我们就可以在不修改目标类的代码的情况下,灵活地更改依赖项的实现或配置。
需要注意的是,尽管setter方法注入是一种常见的依赖注入方式,但它并不是唯一的选择。其他依赖注入方式,如构造器注入、字段注入和接口注入等,也可以用来满足不同的需求和场景。

4. controller层接口代码详解

4.0 HTTP常见请求方法合集

在RESTful API设计中,通常使用GET、POST、PUT、PATCH和DELETE方法来操作资源。这些方法的选择反映了操作的语义,有助于保持API的直观性和一致性。例如,使用GET来请求数据,使用POST来创建新资源,使用PUT来更新现有资源,使用DELETE来删除资源。

  1. GET:请求获取指定的资源。
  2. POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
  3. PUT:从客户端向服务器传送的数据取代指定的文档的内容。
  4. DELETE:请求服务器删除指定的内容。
  5. PATCH:对资源进行部分修改。

4.1 模糊查询—接口

@PostMapping("/search")public BaseResponse<ListWithTotal<Complaints>> search(@RequestBody Complaints keyword) {log.info("查询投诉信箱:{}", keyword);List<Complaints> complaints = complaintsService.search1(keyword);int total = complaints.size();log.info("查询投诉信箱总数:{}", total);ListWithTotal<Complaints> list = new ListWithTotal<>(complaints, total);return ResultUtils.success(list);}

模糊查询:客户端返回一个Complaints 类对象到controller层,用POST接口。

在Spring框架中,@PostMapping(“/search”)是一个注解,用于将HTTP的POST请求映射到特定的处理方法。这里的"/search"是URL路径的一部分,表示当客户端向服务器发送一个POST请求到"/search"路径时,该请求将被路由到带有@PostMapping(“/search”)注解的方法进行处理。
具体来说,@PostMapping(“/search”)中的"search"是一个字符串字面量,它定义了处理POST请求的URL路径。在这个例子中,当客户端发送一个POST请求到"/search"路径时,服务器会调用带有@PostMapping(“/search”)注解的方法来处理这个请求。这个方法可以接收和处理来自客户端的数据,并返回相应的响应。

BaseResponse是一个通用的响应类,用于封装API接口的返回结果。它包含一些常见的属性,如code、message和data。BaseResponse表示返回的数据类型是一个包含投诉的列表和总数的对象。

@RequestBody Complaints keyword是一个Spring框架中的注解,用于将HTTP请求体中的数据绑定到方法参数上。在上面的代码中,Complaints是一个Java类,表示投诉信息的数据结构。keyword 是这个类的一个实例,用于接收客户端发送的投诉信息。
当客户端发送一个POST请求到服务器的"/search"路径时,请求体中的数据会被解析并转换为Complaints类的实例。然后,这个实例会被传递给search方法作为参数keyword。

ResultUtils.success(list) 是一个方法调用,它是一个工具类中的一个静态方法。这个方法的作用是创建一个成功的响应对象,并将传入的参数 list 作为数据返回给客户端。
在上面的代码中,list 是一个包含投诉信息的列表,而 ResultUtils.success(list) 方法会创建一个BaseResponse 类型的对象,并设置状态码为成功(例如200),同时将 list作为响应的数据部分。这样,当客户端接收到这个响应时,它将能够获取到包含投诉信息的数据。
ResultUtils.success()`方法封装一些常见的响应结构,如状态码、消息和数据等,以便在应用程序中统一处理响应结果。

在这里插入图片描述

4.2 findAll—接口

@GetMapping("/list")public BaseResponse<ListWithTotal<Complaints>> list() {List<Complaints> complaints = complaintsService.getList();int total = complaintsService.count1();log.info("查询投诉信箱总数:{}", total);ListWithTotal<Complaints> list = new ListWithTotal<>(complaints, total);return ResultUtils.success(list);}

findAll:请求获取所有的Complaints对象,用GET接口。

4.3 根据id查询—接口

@GetMapping("/select2")public BaseResponse<Complaints> select2(Long id) {log.info("查询投诉信息:{}", id);Complaints complaints = complaintsService.select2(id);log.info("查询投诉信息:{}", complaints);return ResultUtils.success(complaints);}

4.4 增加—接口

@PostMapping("/insert2")public BaseResponse<Complaints> insert2(@RequestBody Complaints complaints) {Complaints result = complaintsService.insert2(complaints);return ResultUtils.success(result);}

增加:将一个Complaints 对象传到controller层,用POST接口。

4.5 删除—接口

@DeleteMapping("/delete2")public BaseResponse<Long> delete2(Long id) {complaintsService.delete2(id);return ResultUtils.success(id);}

删除:传id给controller层,请求删除指定的Complaints对象,用DELETE接口。

4.5 更新—接口

@PutMapping("/update2")public BaseResponse<Complaints> update2(@RequestBody Complaints complaints) {complaintsService.update2(complaints);return ResultUtils.success(complaints);}

更新:将一个Complaints 对象传到controller层取代原有Complaints ,从客户端向服务器传送的数据取代指定的文档的内容,用PUT接口。

5 总结

文章首先讲了controller层的重要性和优点,然后讲了restful风格和传统风格,接着对代码进行分析:分析了依赖注入的三种方法,最后是对接口的解析,不可谓不深刻。看完这篇文章应该能知道什么是controller层。代码谁都会写,真正的区别在于对代码底层的理解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/43499.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++ | Leetcode C++题解之第225题用队列实现栈

题目&#xff1a; 题解&#xff1a; class MyStack { public:queue<int> q;/** Initialize your data structure here. */MyStack() {}/** Push element x onto stack. */void push(int x) {int n q.size();q.push(x);for (int i 0; i < n; i) {q.push(q.front());…

C++ 【 Open3D 】 点云按高程进行赋色

一、 Open3D中根据点云的高程度信息为点云中的每个点附上颜色&#xff0c;并保存颜色渲染结果&#xff01; #include<iostream> #include<open3d/Open3D.h>using namespace std;int main() {//-------------------------------读取点云--------------------------…

nasa数据集——1 度网格单元的全球月度土壤湿度统计数据

AMSR-E/Aqua level 3 global monthly Surface Soil Moisture Averages V005 (AMSRE_AVRMO) at GES DISC GES DISC 的 AMSR-E/Aqua 第 3 级全球地表土壤水分月平均值 V005 (AMSRE_AVRMO) AMSR-E/Aqua level 3 global monthly Surface Soil Moisture Standard Deviation V005 (…

vue中el-table单元格复制功能

一、单页面中使用 1.在el-table上绑定单击事件 cell-click“copyText” 或双击事件 cell-dblclick“copyText” 注&#xff1a;cell-dblclick函数有四个参数&#xff0c;分别是row, column, cell, event&#xff1b; row&#xff1a;可看到被其操作单元格所在行的所有的数据&…

【IT领域新生必看】解锁 `final` 关键字的秘密:Java 编程中的终极武器

文章目录 引言什么是 final 关键字&#xff1f;一、 final 变量final 局部变量final 实例变量final 静态变量 二、 final 方法三、 final 类四、 final 关键字的实际应用1. 定义常量2. 防止方法被重写3. 创建不可变类4. 优化性能 五、 final 的一些常见误区1. final 变量不能在…

【JavaSE】程序逻辑控制

目录 1. 顺序结构 2. 分支结构 2.1 if语句 2.1.1 语法格式1 2.1.2 语法格式2 2.1.3 语法格式3 2.1.4 练习 2.1.5 注意事项 2.2 switch 语句 3. 循环结构 3.1 while循环 3.1.1 语法格式 3.1.2 代码示例 3.1.3 注意事项 3.2 break 3.3 continue 3.4 for循环 …

scratch3编程05-画笔绘制圆及与圆相关的图形

目录 一&#xff0c;圆 1&#xff0c;空心圆 2&#xff0c;实心圆 3&#xff0c;嵌套在一起的圆 4&#xff0c;圆环 二&#xff0c;五角星 1&#xff0c;空心五角星 1&#xff09;思路 2&#xff09;完整的程序 2&#xff0c;实心五角星 1&#xff09;思路 2&…

RK3568笔记三十三: helloworld 驱动测试

若该文为原创文章&#xff0c;转载请注明原文出处。 报着学习态度&#xff0c;接下来学习驱动是如何使用的&#xff0c;从简单的helloworld驱动学习起。 开始编写第一个驱动程序—helloworld 驱动。 一、环境 1、开发板&#xff1a;正点原子的ATK-DLRK3568 2、系统&#xf…

d3dcompiler_43.dll文件是什么?如何快速有效的解决d3dcompiler_43.dll文件丢失问题

dcompiler_43.dll 是一个Windows系统中的系统文件&#xff0c;属于DirectX软件的一部分。这个dcompiler_43.dll&#xff08;动态链接库&#xff09;文件主要用于处理与3D图形编程有关的任务&#xff0c;是运行许多游戏和高级图形程序必需的组件之一。那么如果电脑丢失d3dcompil…

香蕉派BPI-Wifi6迷你路由器公开发售

Banana Pi BPI-Wifi6 Mini 公开发售。 Banana Pi BPI-Wifi6 Mini 开源路由器采用Triductor TR6560 TR5220 wifi SOC设计&#xff0c;是一款迷你尺寸的wifi6路由器解决方案。内置高性能双核ARM Cortec A9处理器用于WIFI报文转发或智能业务处理&#xff0c;内置高性能LSW和硬件N…

ubuntu 上vscode +cmake的debug调试配置方法

在ubuntu配置pcl点云库以及opencv库的时候&#xff0c;需要在CMakeLists.txt中加入相应的代码。配置完成后&#xff0c;无法调试&#xff0c;与在windows上体验vs studio差别有点大。 找了好多调试debug配置方法&#xff0c;最终能用的有几种&#xff0c;但是有一种特别好用&a…

ubuntu部署minio集群

minio集群介绍 官方文档&#xff1a;https://min.io/docs/minio/linux/operations/install-deploy-manage/deploy-minio-multi-node-multi-drive.html 本方案采用在多节点多驱动器 (MNMD) 或“分布式”配置部署 MinIO。 MNMD 部署提供企业级性能、可用​​性和可扩展性&#…

jmeter-beanshell学习4-beanshell截取字符串

再写个简单点的东西&#xff0c;截取字符串&#xff0c;参数化文件统一用csv&#xff0c;然后还要用excel打开&#xff0c;如果是数字很容易格式就乱了。有同事是用双引号把数字引起来&#xff0c;报文里就不用加引号了&#xff0c;但是这样beanshell处理起来&#xff0c;好像容…

Facebook社交平台的未来发展趋势分析

随着科技和社交需求的不断演变&#xff0c;Facebook作为全球最大的社交平台之一&#xff0c;其未来发展的趋势备受关注。从技术创新到社会影响&#xff0c;Facebook正在经历着前所未有的变化和挑战。本文将探讨Facebook未来发展的几个关键趋势&#xff0c;并分析其可能的影响和…

MySQL MVCC

总结自小林coding&#xff0c;bojiangzhou 脏读、不可重复读、幻读 说的都是并发读取的问题&#xff0c;最简单的方式就是给记录加一把锁&#xff0c;不管是更新、读取记录都需要竞争到这把锁之后才能操作。但这种方式的并发性能可想而知会有多么低。 于是 InnoDB 就设计了MVC…

LeetCode HOT100(二)双指针

移动0 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 解法1&#xff1a;双指针交换 指针L&…

“论基于构件的软件开发方法及其应用”写作框架,软考高级论文,系统架构设计师论文

论文真题 基于构作的软件开发 (Component-Based Software Development&#xff0c;CBSD) 是一种基于分布对象技术、强调通过可复用构件设计与构造软件系统的软件复用途径。基于构件的软件系统中的构件可以是COTS &#xff08;Commercial-Off-the-Shelf&#xff09;构件&#x…

Spring Boot轻松整合Minio实现文件上传下载功能

一、Linux 安装Minio 安装 在/root/xxkfz/soft目录下面创建文件minio文件夹&#xff0c;进入minio文件夹&#xff0c;并创建data目录&#xff1b; [rootxxkfz soft]# mkdir minio [rootxxkfz soft]# cd minio [rootxxkfz minio]# mkdir data 执行如下命令进行下载 [rootxx…

Java内存划分详解:从基础到进阶

Java内存划分详解&#xff1a;从基础到进阶 1. 程序计数器&#xff08;Program Counter Register&#xff09;2. Java虚拟机栈&#xff08;Java Virtual Machine Stack&#xff09;3. 堆&#xff08;Heap&#xff09;4. 方法区&#xff08;Method Area&#xff09;5. 运行时常量…

[计网初识1] TCP/UDP

学习内容 1.TCP建立链接的3次握手&#xff0c;断开连接的4次挥手 2.TCP报文段组成 内容 1.TCP 建立连接的3次握手? 假设主动方是客户端&#xff0c;被动方是服务端。 第一次 客户端给服务端发送 “hello,我是客户端” (TCP段中 SYN1) 第二次 服务端给客户端发送"我接…