当前位置: 首页 > news >正文

08.SpringBoot请求相应

文章目录

  • 1 请求
    • 1.1 Postman
    • 1.2 简单参数
      • 1.2.1 原始方式
      • 1.2.2 SpringBoot方式
      • 1.2.3 参数名不一致
    • 1.3 实体参数
      • 1.3.1 简单实体对象
      • 1.3.2 复杂实体对象
    • 1.4 数组集合参数
      • 1.4.1 数组
      • 1.4.2 集合
    • 1.5 日期参数
    • 1.6 JSON参数
    • 1.7 路径参数
  • 2 响应
    • 2.1 @ResponseBody注解
    • 2.2 统一响应结果
  • 3 分层解耦
    • 3.1 三层架构
      • 3.1.1 介绍
    • 3.2 分层解耦
      • 3.2.1 耦合问题
      • 3.2.2 解耦思路
    • 3.3 IOC&DI
      • 3.3.1 bean对象声明
      • 3.3.2 IOC详解
      • 3.3.3 DI详解

1 请求

1.1 Postman

  • Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件。

    Postman原是Chrome浏览器的插件,可以模拟浏览器向后端服务器发起任何形式(如:get、post)的HTTP请求

    使用Postman还可以在发起请求时,携带一些请求参数、请求头等信息

  • 作用:常用于进行接口测试

  • 特征

    • 简单
    • 实用
    • 美观
    • 大方

1.2 简单参数

简单参数:在向服务器发起请求时,向服务器传递的是一些普通的请求数据。

在这里插入图片描述
而在后端程序中,接收普通参数数据的方式有两种:

  1. 原始方式
  2. SpringBoot方式

1.2.1 原始方式

在原始的Web程序当中,需要通过Servlet中提供的API:HttpServletRequest(请求对象),获取请求的相关信息。比如获取请求参数:

Tomcat接收到http请求时:把请求的相关信息封装到HttpServletRequest对象中

在Controller中,我们要想获取Request对象,可以直接在方法的形参中声明 HttpServletRequest 对象。然后就可以通过该对象来获取请求信息:

//根据指定的参数名获取请求参数的数据值
String  request.getParameter("参数名")
@RestController
public class RequestController {//原始方式@RequestMapping("/simpleParam")public String simpleParam(HttpServletRequest request){// http://localhost:8080/simpleParam?name=Tom&age=10// 请求参数: name=Tom&age=10   (有2个请求参数)// 第1个请求参数: name=Tom   参数名:name,参数值:Tom// 第2个请求参数: age=10     参数名:age , 参数值:10String name = request.getParameter("name");//name就是请求参数名String ageStr = request.getParameter("age");//age就是请求参数名int age = Integer.parseInt(ageStr);//需要手动进行类型转换System.out.println(name+"  :  "+age);return "OK";}
}

1.2.2 SpringBoot方式

在Springboot的环境中,对原始的API进行了封装,接收参数的形式更加简单。 如果是简单参数,参数名与形参变量名相同,定义同名的形参即可接收参数。

@RestController
public class RequestController {// http://localhost:8080/simpleParam?name=Tom&age=10// 第1个请求参数: name=Tom   参数名:name,参数值:Tom// 第2个请求参数: age=10     参数名:age , 参数值:10//springboot方式@RequestMapping("/simpleParam")public String simpleParam(String name , Integer age ){//形参名和请求参数名保持一致System.out.println(name+"  :  "+age);return "OK";}
}

不论是GET请求还是POST请求,对于简单参数来讲,只要保证请求参数名和Controller方法中的形参名保持一致,就可以获取到请求参数中的数据值。

1.2.3 参数名不一致

对于简单参数来讲,请求参数名controller方法中的形参名不一致时,无法接收到请求数据,当我们在开发中,遇到了这种请求参数名controller方法中的形参名不相同,可以使用Spring提供的@RequestParam注解完成映射
在方法形参前面加上 @RequestParam 然后通过value属性执行请求参数名,从而完成映射。代码如下:

@RestController
public class RequestController {// http://localhost:8080/simpleParam?name=Tom&age=20// 请求参数名:name//springboot方式@RequestMapping("/simpleParam")public String simpleParam(@RequestParam("name") String username , Integer age ){System.out.println(username+"  :  "+age);return "OK";}
}

注意:
@RequestParam中的required属性默认为true(默认值也是true),代表该请求参数必须传递,如果不传递将报错
如果该参数是可选的,可以将required属性设置为false

@RequestMapping("/simpleParam")
public String simpleParam(@RequestParam(name = "name", required = false) String username, Integer age){
System.out.println(username+ ":" + age);
return "OK";
}

1.3 实体参数

在使用简单参数做为数据传递方式时,前端传递了多少个请求参数,后端controller方法中的形参就要书写多少个。如果请求参数比较多,通过上述的方式一个参数一个参数的接收,会比较繁琐。

此时,我们可以考虑将请求参数封装到一个实体类对象中。 要想完成数据封装,需要遵守如下规则:请求参数名与实体类的属性名相同

1.3.1 简单实体对象

定义POJO类:

package com.yongzhi.springbootwebreqresp.pojo;public class User {private String name;private int age;private Address address;public User() {}public User(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}/*** 获取* @return address*/public Address getAddress() {return address;}/*** 设置* @param address*/public void setAddress(Address address) {this.address = address;}public String toString() {return "User{name = " + name + ", age = " + age + ", address = " + address + "}";}
}

Controller方法:

@RestController
public class RequestController {//实体参数:简单实体对象@RequestMapping("/simplePojo")public String simplePojo(User user){System.out.println(user);return "OK";}
}

这里需要指出,当请求参数名中有和实体类属性名不一致的时候,不会报错,而是会自动将没有对应上的实体对象的参数赋值为默认值

1.3.2 复杂实体对象

复杂实体对象指的是,在实体类中有一个或多个属性,也是实体对象类型的。

复杂实体对象的封装,需要遵守如下规则:

  • 请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套实体类属性参数。

定义POJO实体类:

  • Address实体类
package com.yongzhi.springbootwebreqresp.pojo;public class Address {private String province;private String city;public Address() {}public Address(String province, String city) {this.province = province;this.city = city;}/*** 获取* @return province*/public String getProvince() {return province;}/*** 设置* @param province*/public void setProvince(String province) {this.province = province;}/*** 获取* @return city*/public String getCity() {return city;}/*** 设置* @param city*/public void setCity(String city) {this.city = city;}public String toString() {return "Address{province = " + province + ", city = " + city + "}";}
}
  • User实体类
package com.yongzhi.springbootwebreqresp.pojo;public class User {private String name;private int age;private Address address;public User() {}public User(String name, int age, Address address) {this.name = name;this.age = age;this.address = address;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}/*** 获取* @return address*/public Address getAddress() {return address;}/*** 设置* @param address*/public void setAddress(Address address) {this.address = address;}public String toString() {return "User{name = " + name + ", age = " + age + ", address = " + address + "}";}
}

Postman测试:
在这里插入图片描述

1.4 数组集合参数

数组集合参数的使用场景:在HTML的表单中,有一个表单项是支持多选的(复选框),可以提交选择的多个值。
这多个值也是一个个提交的,而后端接收这种数据有两种方式:

  1. 数组
  2. 集合
    在这里插入图片描述

1.4.1 数组

数组参数:请求参数名与形参数组名称相同且请求参数为多个,定义数组类型形参即可接收参数
Controller方法:

@RestController
public class RequestController {//数组集合参数@RequestMapping("/arrayParam")public String arrayParam(String[] hobby){System.out.println(Arrays.toString(hobby));return "OK";}
}

Postman测试:

在前端请求时,有两种传递形式:

方式一: xxxxxxxxxx?hobby=game&hobby=java
方式二:xxxxxxxxxxxxx?hobby=game,java

1.4.2 集合

集合参数:请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam 绑定参数关系

默认情况下,请求中参数名相同的多个值,是封装到数组。如果要封装到集合,要使用@RequestParam绑定参数关系
Controller方法:

@RestController
public class RequestController {//数组集合参数@RequestMapping("/listParam")public String listParam(@RequestParam List<String> hobby){System.out.println(hobby);return "OK";}
}

1.5 日期参数

上述演示的都是一些普通的参数,在一些特殊的需求中,可能会涉及到日期类型数据的封装。

因为日期的格式多种多样(如:2022-12-12 10:05:45 、2022/12/12 10:05:45),那么对于日期类型的参数在进行封装的时候,需要通过@DateTimeFormat注解,以及其pattern属性来设置日期的格式。

  • @DateTimeFormat注解的pattern属性中指定了哪种日期格式,前端的日期参数就必须按照指定的格式传递。
  • 后端controller方法中,需要使用Date类型或LocalDateTime类型,来封装传递的参数。

Controller方法:

@RestController
public class RequestController {//日期时间参数@RequestMapping("/dateParam")public String dateParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime updateTime){System.out.println(updateTime);return "OK";}
}

Postman测试:
在这里插入图片描述

1.6 JSON参数

在前后端进行交互时,如果是比较复杂的参数,前后端通过会使用JSON格式的数据进行传输。 (JSON是开发中最常用的前后端数据交互方式)

学习JSON格式参数,主要从以下两个方面着手:

  1. Postman在发送请求时,如何传递json格式的请求参数
    在这里插入图片描述
    服务端Controller方法接收JSON格式数据:

    • 传递json格式的参数,在Controller中会使用实体类进行封装。
    • 封装规则:JSON数据键名与形参对象属性名相同,定义POJO类型形参即可接收参数。需要使用 @RequestBody标识。

@RequestBody注解:将JSON数据映射到形参的实体类对象中(JSON中的key和实体类中的属性名保持一致)

实体类:Address

public class Address {private String province;private String city;//省略GET , SET 方法
}

实体类:User

public class User {private String name;private Integer age;private Address address;//省略GET , SET 方法
}    

Controller方法:

@RestController
public class RequestController {//JSON参数@RequestMapping("/jsonParam")public String jsonParam(@RequestBody User user){System.out.println(user);return "OK";}
}

1.7 路径参数

在现在的开发中,经常还会直接在请求的URL中传递参数。例如:

http://localhost:8080/user/1		
http://localhost:880/user/1/0

上述的这种传递请求参数的形式呢,我们称之为:路径参数

路径参数:

  • 前端:通过请求URL直接传递参数
  • 后端:使用{…}来标识该路径参数,需要使用@PathVariable获取路径参数

Controller方法:

@RestController
public class RequestController {//路径参数@RequestMapping("/path/{id}")public String pathParam(@PathVariable Integer id){System.out.println(id);return "OK";}
}

Postman测试:
在这里插入图片描述

传递多个路径参数:

Postman:

在这里插入图片描述

Controller方法:

@RestController
public class RequestController {//路径参数@RequestMapping("/path/{id}/{name}")public String pathParam2(@PathVariable Integer id, @PathVariable String name){System.out.println(id+ " : " +name);return "OK";}
}

2 响应

2.1 @ResponseBody注解

  • 类型:方法注解、类注解
  • 位置:书写在Controller方法上或类上
  • 作用:将方法返回值直接响应给浏览器
    • 如果返回值类型是实体对象/集合,将会转换为JSON格式后在响应给浏览器

需要指出的是,在上面的代码中,我们并没有添加@ResponseBody注解,但依然能够将结果响应给浏览器,这是因为我们在类上添加的@RestController注解,是一个组合注解:

  • @RestController = @ResponseBody + @Controller

@RestController源码:

@Target({ElementType.TYPE})   //元注解(修饰注解的注解)
@Retention(RetentionPolicy.RUNTIME)  //元注解
@Documented    //元注解
@Controller   
@ResponseBody 
public @interface RestController {@AliasFor(annotation = Controller.class)String value() default "";
}

故我们在类上添加了@RestController注解就相当于添加了@ResposeBody注解

  • 小结:
    • 类上有@RestController注解或@ResponseBody注解时:表示当前类下所有的方法返回值做为响应数据:
      • 方法的返回值,如果是一个POJO对象或集合时,会先转换为JSON格式,在响应给浏览器

2.2 统一响应结果

对于前端开发人员来讲,如果拿到响应数据,但是没有统一的规范,那么就需要针对不同的响应数据就要使用不同的响应方式,这就会造成开发成本高,项目不方便管理,维护起来也会很困难,所以我们就需要统一响应结果,这样对于前端人员来说,只需要按照统一格式的返回结果进行解析(仅一种解析方案),就可以拿到数据。

  • 统一的返回结果使用类来描述,在这个结果中包含:

    • 响应状态码:当前请求是成功,还是失败

    • 状态码信息:给页面的提示信息

    • 返回的数据:给前端响应的数据(字符串、对象、集合)

3 分层解耦

3.1 三层架构

3.1.1 介绍

在我们进行程序设计以及程序开发时,尽可能让每一个接口、类、方法的职责更单一些(单一职责原则)。

单一职责原则:一个类或一个方法,就只做一件事情,只管一块功能。

这样就可以让类、接口、方法的复杂度更低,可读性更强,扩展性更好,也更利用后期的维护。

一般情况下,我们会将业务分成三个部分:

  • 数据访问:负责业务数据的维护操作,包括增、删、改、查等操作。
  • 逻辑处理:负责业务逻辑处理的代码。
  • 请求处理、响应数据:负责,接收页面的请求,给页面响应数据。

按照上述的三个组成部分,在我们项目开发中可以将代码分为三层:

  • Controller:控制层。接收前端发送的请求,对请求进行处理,并响应数据。
  • Service:业务逻辑层。处理具体的业务逻辑。
  • Dao:数据访问层(Data Access Object),也称为持久层。负责数据访问操作,包括数据的增、删、改、查。

基于三层架构的程序执行流程:
在这里插入图片描述

  • 前端发起的请求,由Controller层接收(Controller响应数据给前端)
  • Controller层调用Service层来进行逻辑处理(Service层处理完后,把处理结果返回给Controller层)
  • Serivce层调用Dao层(逻辑处理过程中需要用到的一些数据要从Dao层获取)
  • Dao层操作文件中的数据(Dao拿到的数据会返回给Service层)

这样,按照三层架构的思想,我们倘若要对业务逻辑(Service层)进行变更,也不会影响到Controller层和Dao层,这使得程序的扩展性和业务性变得更好了

总之,三层架构的好处可以归纳为:

  1. 复用性强
  2. 便于维护
  3. 利用扩展

3.2 分层解耦

上面我们说的是分层的思想,接下来说一下解耦的思想,所谓解耦,就是接触耦合的意思

3.2.1 耦合问题

首先需要了解软件开发涉及到的两个概念:内聚和耦合。

  • 内聚:软件中各个功能模块内部的功能联系。

  • 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。

软件设计原则:高内聚低耦合。

高内聚指的是:一个模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联系程度越高,则内聚性越高,即 “高内聚”。

低耦合指的是:软件中各个层、模块之间的依赖关联程序越低越好。

高内聚、低耦合的目的是使程序模块的可重用性、移植性大大增强。
在这里插入图片描述

3.2.2 解耦思路

  • 我们在使用一个类里面的方法时,我们首先需要创建对应的对象然后调用对应的方法,而我们要解耦,首先就不能在其他类里面使用new对象
  • 但此时又会面临一个问题,我们如果不new出对应的对象,便不能在其他类里面使用对应的方法了,那该怎么办呢?
    • 我们的解决思路是:

      • 提供一个容器,容器中存储一些对象
      • controller程序从容器中获取对应类型的对象

要实现上述解耦操作,就涉及到Spring中的两个核心概念:

  • 控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。

    对象的创建权由程序员主动创建转移到容器(由容器创建、管理对象)。这个容器称为:IOC容器或Spring容器

  • 依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。

    程序运行时需要某个资源,此时容器就为其提供这个资源。

    例:EmpController程序运行时需要EmpService对象,Spring容器就为其提供并注入EmpService对象

IOC容器中创建、管理的对象,称之为:bean对象

3.3 IOC&DI

3.3.1 bean对象声明

前面我们提到IOC控制反转,就是将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对象。IOC容器创建的对象称为bean对象。

在IOC容器中,每一个Bean都有一个属于自己的名字,可以通过注解的value属性指定bean的名字。如果没有指定,默认为类名首字母小写。

注意事项:

  • 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写。
  • 使用以上四个注解都可以声明bean,但是在springboot集成web开发中,声明控制器bean只能用@Controller。

3.3.2 IOC详解

当我们要把某个对象交给IOC容器管理,需要在类上添加一个注解:@Component

而Spring框架为了更好的标识web应用程序开发当中,bean对象到底归属于哪一层,又提供了@Component的衍生注解:

  • @Controller (标注在控制层类上)
  • @Service (标注在业务层类上)
  • @Repository (标注在数据访问层类上)

要把某个对象交给IOC容器管理,需要在对应的类上加上如下注解之一:

注解说明位置
@Controller@Component的衍生注解标注在控制器类上
@Service@Component的衍生注解标注在业务类上
@Repository@Component的衍生注解标注在数据访问类上(由于与mybatis整合,用的少)
@Component声明bean的基础注解不属于以上三类时,用此注解
  • 组件扫描

当我们使用注解声明了一个bean后,这个bean对象不一定会生效,这是因为使用四大注解声明的bean,要想生效,还需要被组件扫描注解@ComponentScan扫描
需要指出:
@ComponentScan注解虽然没有显式配置,但是实际上已经包含在了引导类声明注解 @SpringBootApplication 中,默认扫描的范围是SpringBoot启动类所在包及其子包

@SpringBootApplication源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.boot.autoconfigure;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AliasFor;@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}
), @Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {@AliasFor(annotation = EnableAutoConfiguration.class)Class<?>[] exclude() default {};@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};@AliasFor(annotation = ComponentScan.class,attribute = "basePackages")String[] scanBasePackages() default {};@AliasFor(annotation = ComponentScan.class,attribute = "basePackageClasses")Class<?>[] scanBasePackageClasses() default {};@AliasFor(annotation = ComponentScan.class,attribute = "nameGenerator")Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;@AliasFor(annotation = Configuration.class)boolean proxyBeanMethods() default true;
}

所以为了避免不必要的麻烦,一般推荐的做法是:

  • 将我们定义的controller,service,dao这些包呢,都放在引导类所在包com.itheima的子包下,这样我们定义的bean就会被自动的扫描到

3.3.3 DI详解

依赖注入,是指IOC容器要为应用程序去提供运行时所依赖的资源,而资源指的就是对象。

我们可以使用@Autowired这个注解,完成依赖注入的操作,而这个Autowired翻译过来叫:自动装配。

@Autowired注解,默认是按照类型进行自动装配的(去IOC容器中找某个类型的对象,然后完成注入操作),那么问题来了,当IOC容器中,存在多个相同类型的bean对象时,进行组件扫描的时候就会区分不了该用那个bean对象,从而报错。

为了解决上述问题,Spring提供了三种解决方案:

  • @Primary
    使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。
    在这里插入图片描述

  • @Qualifier
    使用@Qualifier注解:指定当前要注入的bean对象。 在@Qualifier的value属性中,指定注入的bean的名称。

    • @Qualifier注解不能单独使用,必须配合@Autowired使用

在这里插入图片描述

  • @Resource

使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。
在这里插入图片描述

面试题 : @Autowird 与 @Resource的区别

  • @Autowired 是spring框架提供的注解,而@Resource是JDK提供的注解
  • @Autowired 默认是按照类型注入,而@Resource是按照名称注入

相关文章:

08.SpringBoot请求相应

文章目录 1 请求1.1 Postman1.2 简单参数1.2.1 原始方式1.2.2 SpringBoot方式1.2.3 参数名不一致 1.3 实体参数1.3.1 简单实体对象1.3.2 复杂实体对象 1.4 数组集合参数1.4.1 数组1.4.2 集合 1.5 日期参数1.6 JSON参数1.7 路径参数 2 响应2.1 ResponseBody注解2.2 统一响应结果…...

C#详解-Contains、StartsWith、EndsWith、Indexof、lastdexof

目录 简介: 过程: 举例1.1 举例1.2 ​ 总结: 简介: 在C#中Contains、StarsWith和EndWith、IndexOf都是字符串函数。 1.Contains函数用于判断一个字符串是否包含指定的子字符串&#xff0c;返回一个布尔值&#xff08;True或False&#xff09;。 2.StartsWith函数用于判断一…...

FATE框架中pipline基础教程

目录 1. 用pipline上传数据2. 用 Pipeline 进行 Hetero SecureBoost 的训练和预测3. 用 Pipeline 构建神经网络模型3.1 Homo-NN Quick Start: A Binary Classification Task3.2 Hetero-NN Quick Start: A Binary Classification Task 4. 自定义数据集示例&#xff1a;实现一个简…...

Atlas 元数据管理

Atlas 元数据管理 1.Atlas入门 1.1概述 元数据原理和治理功能&#xff0c;用以构建数据资产的目录。对这个资产进行分类和管理&#xff0c;形成数据字典。 提供围绕数据资产的协作功能。 表和表之间的血缘依赖 字段和字段之间的血缘依赖 1.2架构图 导入和导出&#xff1…...

编程题练习@8-23

分享8月23日两道编程题&#xff1a; 1 开幕式排列 题目描述 导演在组织进行大运会开幕式的排练&#xff0c;其中一个环节是需要参演人员围成一个环形。 演出人员站成了一圈&#xff0c;出于美观度的考虑&#xff0c;导演不希望某一个演员身边的其他人比他低太多或者高太多。 现…...

static相关知识点详解

文章目录 一. 修饰成员变量二. 修饰成员方法三. 修饰代码块四. 修饰类 一. 修饰成员变量 static 修饰的成员变量&#xff0c;称为静态成员变量&#xff0c;该变量不属于某个具体的对象&#xff0c;是所有对象所共享的。 public class Student {private String name;private sta…...

Redisson 分布式锁

Redis是基础客户端库&#xff0c;可用于执行基本操作。 Redisson是基于Redis的Java客户端&#xff0c;提供高级功能如分布式锁、分布式集合和分布式对象。 Redisson提供更友好的API&#xff0c;支持异步和响应式编程&#xff0c;提供内置线程安全和失败重试机制。 实现步骤…...

继承(C++)

继承 一、初识继承概念“登场”语法格式 继承方式九种继承方式组合小结&#xff08;对九种组合解释&#xff09; 二、继承的特性赋值转换 一一 切片 / 切割作用域 一一 隐藏 / 重定义 三、派生类的默认成员函数派生类的默认成员函数1. 构造函数2. 拷贝构造3. 赋值运算符重载4. …...

文心一言 VS 讯飞星火 VS chatgpt (80)-- 算法导论7.4 5题

五、如果用go语言&#xff0c;当输入数据已经“几乎有序”时&#xff0c;插入排序速度很快。在实际应用中&#xff0c;我们可以利用这一特点来提高快速排序的速度。当对一个长度小于 k 的子数组调用快速排序时&#xff0c;让它不做任何排序就返回。当上层的快速排序调用返回后&…...

SpringCloud 概述

文章目录 SpringCloud 概述一、微服务中的相关概念1、服务注册与发现2、负载均衡3、熔断4、链路追踪5、API网关 二、SpringCloud的介绍三、SpringCloud的架构1、SpringCloud中的核心组件&#xff08;1&#xff09;Spring Cloud Netflix组件&#xff08;2&#xff09;Spring Clo…...

Apache ShenYu 学习笔记一

1、简介 这是一个异步的&#xff0c;高性能的&#xff0c;跨语言的&#xff0c;响应式的 API 网关。 官网文档&#xff1a;Apache ShenYu 介绍 | Apache ShenYu仓库地址&#xff1a;GitHub - apache/shenyu: Apache ShenYu is a Java native API Gateway for service proxy, pr…...

uniapp 禁止遮罩层下的页面滚动

使用 touchmove.stop.prevent"toMoveHandle" 事件修饰符 若需要禁止蒙版下的页面滚动&#xff0c;可使用 touchmove.stop.prevent"moveHandle"&#xff0c;moveHandle 可以用来处理 touchmove 的事件&#xff0c;也可以是一个空函数。将这个方法直接丢到弹…...

postgresql 分组

postgresql 数据汇总 分组汇总聚合函数注意 总结 分组统计总结 高级分组总结 分组汇总 聚合函数 聚合函数&#xff08;aggregate function&#xff09;针对一组数据行进行运算&#xff0c;并且返回单个结果。PostgreSQL 支持以下常见的聚合函数&#xff1a; • AVG - 计算一…...

RT1052的EPWM

文章目录 1 EPWM介绍1.1 引脚1.2 时钟1.3 比较寄存器 2 函数 1 EPWM介绍 RT1052 具有 4 个 eFlexPWM(eFlexWM1~eFlex_PWM4)。 每个 eFlexPWM 可以产生四路互补 PWM即产生 8 个 PWM&#xff0c;也可以产生相互独立的 PWM 波。四路分别是模块0-3每个 eFlexPWM 具有各自的故障检…...

k8s 安装istio (一)

前置条件 已经完成 K8S安装过程十&#xff1a;Kubernetes CNI插件与CoreDNS服务部署 部署 istio 服务网格与 Ingress 服务用到了 helm 与 kubectl 这两个命令行工具&#xff0c;这个命令行工具依赖 ~/.kube/config 这个配置文件&#xff0c;目前只在 kubernetes master 节点中…...

vue 项目在编译时,总是出现系统崩的状态,报错信息中有v7 或者 v8 的样式-项目太大内存溢出

vue 项目在编译时&#xff0c;总是出现系统崩的状态&#xff0c;node 命令框也会报错&#xff0c;如下图&#xff1a;有v7 或者 v8 的样式。 原因分析&#xff1a; 分析&#xff1a;遇到与上面图片相似的问题&#xff0c;我们要首先要想到是否是 有关内存的问题&#xff0c;当然…...

低功耗蓝牙射频指纹识别

射频指纹 射频指纹是什么 射频指纹是一种利用无线电信号的特征来识别设备或用户的技术。射频指纹可以用来做设备身份认证、位置跟踪、安全防护等应用。射频指纹的优点是难以伪造、不依赖于额外的硬件或软件、适用于多种无线通信协议。 射频指纹识别流程 射频指纹识别的一般…...

怎么检测UI卡顿?(线上及线下)

什么是UI卡顿&#xff1f; 在Android系统中&#xff0c;我们知道UI线程负责我们所有视图的布局&#xff0c;渲染工作&#xff0c;UI在更新期间&#xff0c;如果UI线程的执行时间超过16ms&#xff0c;则会产生丢帧的现象&#xff0c;而大量的丢帧就会造成卡顿&#xff0c;影响用…...

Git 常用操作

一、Git 常用操作 1、切换分支 git checkout命令可以用于三种不同的实体&#xff1a;文件&#xff0c;commit&#xff0c;以及分支。checkout的意思就是对于一种实体的不同版本之间进行切换的操作。checkout一个分支&#xff0c;会更新当前的工作空间中的文件&#xff0c;使其…...

前端修改新增操作导致数据删除——js精度丢失

问题描述 笔者在写前端渲染表格的时候&#xff0c;发现无论是修改还是新增&#xff0c;数据都会被删除。检查了前端逻辑并与后端联调均无问题。 然后就开始和后端一起对数据库&#xff0c;结果发现&#xff0c;十几位的id&#xff0c;接收过来的时候&#xff0c;尾数均变为了…...

winform使用usercontrol 构建了一个复杂的列表,列表速度慢该如何优化?

当使用 WinForms 构建复杂的列表时&#xff0c;可能会面临性能问题&#xff0c;特别是在数据量大或 UI 复杂的情况下。以下是一些优化策略&#xff0c;可以帮助您改善列表的性能&#xff1a; 1. **虚拟模式 (Virtual Mode)**&#xff1a;对于大型数据集&#xff0c;考虑使用虚…...

Lnton羚通算法算力云平台如何在OpenCV-Python中使用cvui库创建复选框

CVUI 之 复选框 Python import numpy as np import cv2 import cvuidef checkbox_test():WINDOW_NAME Checkbox-Testchecked [False]# 创建画布frame np.zeros((300, 400, 3), np.uint8)# 初始化窗口cvui.init(WINDOW_NAME)while True:# 画布填色frame[:] (100, 200, 100…...

中项系统集成项目管理知识点汇总

中项系统集成项目管理知识点汇总 一、成本-进度二、十大管理及47个过程三、质量四、人力资源五、风险六、干系人沟通七、案例分析万能答案八、选择题知识点九、十大管理输入输出工具技术总结十大管理工具技术总结 一、成本-进度 针对进度滞后的绩效情况 /缩短工期&#xff0c;可…...

Docker容器:docker基础及网络

Docker容器&#xff1a;docker基础及安装 一.docker容器概述 1.什么是容器 &#xff08;1&#xff09;Docker是在Linux容器里运行应用的开源工具&#xff0c;是一种轻量级的“虚拟机”。 &#xff08;2&#xff09;是一个开源的应用容器引擎&#xff0c;基于go语言开发并遵…...

Django实现音乐网站 ⑿

使用Python Django框架制作一个音乐网站&#xff0c; 本篇主要是加载静态资源和推荐页-轮播图、推荐歌单功能开发。 目录 加载静态资源 引入jquery.js 引入bootstrap资源文件 创建基类模板样式文件 推荐页开发 轮播图开发 下载 加载swiper 自定义引入继承块设置 使用…...

ORB-SLAM2学习笔记10之图像关键帧KeyFrame

文章目录 0 引言1 KeyFrame类1.1 构造函数1.2 成员函数1.3 关键帧之间共视图1.3.1 AddConnection1.3.2 UpdateBestCovisibles1.3.3 UpdateConnections1.3.4 EraseConnection1.3.5 SetBadFlag 1.4 地图点1.5 生成树 2 KeyFrame用途 0 引言 ORB-SLAM2学习笔记7详细了解了System主…...

【ownCloud】添加信任域

在我进行使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘后 我的虚拟机更改了ip地址导致出现下列状况 报错&#xff1a;您正在访问来自不信任域名的服务器。 please contact your administrator. if you are an administrator of this instance, configure the &q…...

C++--类型转换

1.什么是类型转换 在传统C语言中&#xff0c;由强制类型转换和隐式类型转换&#xff0c;隐式类型转换&#xff0c;编译器在在编译阶段自动处理&#xff0c;能转换则转换&#xff0c;强制类型转换由用户自己转换。 缺陷&#xff1a; 转换的可视性比较差&#xff0c;所有的转换形…...

在服务器上部署 Nginx 并设置图片服务器

问题&#xff1a;我要指定/home/images专门存放图片&#xff01;该怎么做&#xff0c;而且我的系统是centos8系统&#xff0c;只有一个root用户&#xff0c;用root用户已经安装了nginx 答案&#xff1a; 既然你使用了 CentOS 8&#xff0c;并且你想使用 /home/images 目录存放…...

使用NXP GUI GUIDER生成的GUI移植到雅特力MCU平台过程详解(ST/GD/国民/极海通用)

好记性不如烂笔头&#xff0c;既然不够聪明&#xff0c;就乖乖的做笔记&#xff0c;温故而知新。 本文档用于本人对知识点的梳理和记录 一、前言 上一篇我们有介绍NXP GUI Guider工具如何制作和调试GUI&#xff0c;GUI神器 NXP GUI GUIDER开发工具入门教程https://blog.csdn.n…...

王野天 演员/北京seo优化排名推广

1.应用场景 主要用于了解App架构的演进过程&#xff0c;以及对比端上架构与后端架构的区别&#xff0c;联系。 2.学习/操作 1.文档阅读 49 | 谈谈App架构的演进-极客时间 [转]Web 研发模式演变——玉伯 - 知乎 2.整理输出 49 | 谈谈App架构的演进-极客时间 专栏截止到上一期&a…...

怎么用网网站模板做网站/seo排名优化哪家好

Linux 系统中配置 lo:0 一个 IP 后 (该 IP 和 eth0 在同一个网段), 其他电脑就无法 ping 通该主另外个电脑 ping 这个台电脑, 从此就 ping 不通这个电脑了. 没有设置之前是可以正常相互 ping 通的. 另外还发现虽然外面无法 ping 这台电脑, 但是这台电脑可以正常 ping 外面的电脑…...

机关单位特色的网站建设/月嫂免费政府培训中心

Visual Studio 2010其他版本此主题尚未评级 评价此主题静态构造函数用于初始化任何 静态 数据&#xff0c;或用于执行仅需执行一次的特定操作。 在创建第一个实例或引用任何静态成员之前&#xff0c;将自动调用静态构造函数。 C#class SimpleClass {// Static variable that mu…...

办公设备网站推广怎么做/seo站内优化包括

第一章 绪论 问题的提出 基本概念&#xff1a; NLU、 CL、 NLP CL 计算语言学 侧重于&#xff1a; 基础理论和方法 NLU 自然语言理解 &#xff1a;模仿人类 自然语言处理方法 和 实现技术 NLP 自然语言处理 &#xff1a; 对语言文本进行处理和加工 包括对词法 句法 语义和语…...

成都网站建设网站/seo网站推广是什么意思

关于F5负载均衡你认识多少&#xff1f; 2018年06月09日 18:01:09 tvk872 阅读数&#xff1a;14008网络负载均衡&#xff08;load balance&#xff09;&#xff0c;就是将负载&#xff08;工作任务&#xff09;进行平衡、分摊到多个操作单元上进行执行&#xff0c;例如web服务器…...

wordpress 美术馆/大型网站建设平台

模板介绍 精美PPT模板设计&#xff0c;简约创意个人简历求职竞聘PPT模板。一套岗位晋升幻灯片模板&#xff0c;内含橙色多种配色&#xff0c;精美风格设计&#xff0c;动态播放效果&#xff0c;精美实用。 一份设计精美的PPT模板&#xff0c;可以让你在汇报演讲时脱颖而出。 …...