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

MapStruct的用法总结及示例

       MapStruct是一个代码生成器,它基于约定优于配置的原则,使用Java注解来简化从源对象到目标对象的映射过程。它主要用于减少样板代码,提高开发效率,并且通过编译时代码生成来保证性能。

     我的个人实践方面是在2021年前那时候在项目中使用dozer较多,后来发现MapStruct处理对象映射属性复制更灵活方便,就直接转向使用MapStruct。

    学习MapStruct的用法,最简单高效就是去阅读官网的文档:MapStruct – Java bean mappings, the easy way!以及下载官方的示例代码:GitHub - mapstruct/mapstruct-examples: Examples for using MapStruct

各种用法还是比较详细的

目录

1. java对象基本属性映射

2.设置属性的默认值

3.使用条件表达式

4.映射集合类属性

5.使用自定义映射方法

6.继承和多态

7. 使用组件模型

8.忽略默认值

9.MapStruct的注解

10.使用 @Mapper 注解定义映射器

11.映射多个源对象到一个目标对象

12. 映射一个源对象到多个目标对象

13.SpringBoot项目整合使用MapStruct

 以下是MapStruct的一些常见用法和相应的代码示例:

1. java对象基本属性映射
@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);@Mapping(target = "address", source = "personAddress")PersonDto personToPersonDto(Person person);
}class Person {private String name;private Address personAddress;// getters and setters
}class PersonDto {private String name;private AddressDto address;// getters and setters
}class Address {private String street;// getters and setters
}class AddressDto {private String street;// getters and setters
}

如果有多个属性值的名称不一样,则需要使用@Mappings注解来使用多个 @Mapping来制定属性映射关系

比如:

@Mapper
public interface MyMapper {@Mappings({@Mapping(target = "name", source = "fullName"),@Mapping(target = "age", source = "years")})void updateTargetFromSource(Source source,Target target);
}
2.设置属性的默认值
@Mapper
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);@Mapping(target = "email", expression = "java(email != null ? email : 'default@email.com')")UserDto userToUserDto(User user);
}class User {private String name;private String email;// getters and setters
}class UserDto {private String name;private String email;// getters and setters
}
3.使用条件表达式
@Mapper
public interface OrderMapper {OrderMapper INSTANCE = Mappers.getMapper(OrderMapper.class);@Mapping(target = "status", expression = "java(order.isShipped() ? \"SHIPPED\" : \"PENDING\")")OrderDto orderToOrderDto(Order order);
}class Order {private boolean shipped;// getters and setters
}class OrderDto {private String status;// getters and setters
}
4.映射集合类属性
@Mapper
public interface ItemMapper {ItemMapper INSTANCE = Mappers.getMapper(ItemMapper.class);@Mapping(target = "items", expression = "java(mapItemsToItemDtos(order.getItems()))")OrderDto orderToOrderDto(Order order);List<ItemDto> mapItemsToItemDtos(List<Item> items);
}class Order {private List<Item> items;// getters and setters
}class OrderDto {private List<ItemDto> items;// getters and setters
}class Item {// properties and methods
}class ItemDto {// properties and methods
}
5.使用自定义映射方法
@Mapper
public interface CarMapper {CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);@Mapping("licensePlate", ignore = true)CarDto carToCarDto(@MappingTarget CarDto target, Car car);void setLicensePlateIfPresent(@MappingTarget CarDto target, Car car);
}class Car {private String make;private String licensePlate;// getters and setters
}class CarDto {private String make;// getters and setters
}// 在项目编译后MapStruct会自动在映射器实现类中实现该方法
void setLicensePlateIfPresent(CarDto target, Car car) {if (car.getLicensePlate() != null && !car.getLicensePlate().isEmpty()) {target.setLicensePlate(car.getLicensePlate());}
}

@MappingTarget 是 MapStruct 中一个重要的注解,用于标识目标对象。在使用 MapStruct 进行对象映射时,有时我们需要将映射结果更新到一个已经存在的实例中,而不是创建一个新的对象。@MappingTarget 就是为此目的而设计的。

或者你可以直接在映射接口中实现一个默认的方法,来自定义映射关系

public interface MyMapper {// 其他映射方法// 自定义映射逻辑的默认方法void customMapping(@MappingTarget MyTarget target, MySource source) {if (source.getCondition()) {target.setSomeProperty("valueIfConditionTrue");} else {target.setSomeProperty("valueIfConditionFalse");}
}
}

或者直接调用另外的映射方法做属性映射: 

/** Copyright MapStruct Authors.** Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0*/
package org.mapstruct.example.mapper;import java.lang.annotation.Target;
import java.util.Map;import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.example.dto.Department;
import org.mapstruct.example.dto.Employee;
import org.mapstruct.factory.Mappers;/*** @author Filip Hrisafov*/
@Mapper
public interface MapToBeanMapper {MapToBeanMapper INSTANCE = Mappers.getMapper(MapToBeanMapper.class);@Mapping(target = "department", ignore = true)Employee fromMap(Map<String, String> map);@AfterMappingdefault void finishEmployee(@MappingTarget Employee employee, Map<String, String> map) {employee.setDepartment(fromMapToDepartment(map));}@Mapping(target = "id", source = "did")@Mapping(target = "name", source = "dname")Department fromMapToDepartment(Map<String, String> map);
}

 这段代码通过 MapStruct 提供了一个完整的映射解决方案,用于将 Map<String, String> 转换为 Employee 对象,并通过一个 @AfterMapping 方法在映射完成后手动设置 Employee 对象的 department 字段。

6.继承和多态
@Mapper
public interface AnimalMapper {AnimalMapper INSTANCE = Mappers.getMapper(AnimalMapper.class);AnimalDto animalToAnimalDto(Animal animal);
}class Animal {private String name;// getters and setters
}class Cat extends Animal {private String favoriteToy;// getters and setters
}class AnimalDto {private String name;// getters and setters
}class CatDto extends AnimalDto {private String favoriteToy;// getters and setters
}

MapStruct会自动处理继承关系,将子类的属性也映射到相应的DTO中。

7. 使用组件模型

MapStruct允许开发者定义组件,这些组件可以包含自定义的映射逻辑,可以被多个映射器使用。

@Mapper(componentModel = "spring",uses=DepartmentNameMapper.class)
public interface EmployeeMapper {EmployeeMapper INSTANCE = Mappers.getMapper(EmployeeMapper.class);@Mapping(target = "departmentName", source = "department.name")EmployeeDto employeeToEmployeeDto(Employee employee);
}@Component
public class DepartmentNameMapper {public String toDepartmentName(Department department) {return department.getName();}
}

在这个例子中,DepartmentNameMapper是一个Spring组件,它提供了一个方法来获取部门的名称,这个方法可以在映射过程中被使用。

这些只是MapStruct的一些基本用法。MapStruct非常灵活,支持许多高级特性,如映射多个源对象到一个目标对象、使用自定义的映射方法、处理复杂的数据结构等

8.忽略默认值

在映射过程中,你可能希望忽略源对象中的默认值,只复制非默认值的属性。

@Mapper
public interface ProductMapper {ProductMapper INSTANCE = Mappers.getMapper(ProductMapper.class);@Mapping(target = "price", ignore = true)ProductDto productToProductDto(Product product);
}class Product {private double price = 0.0; // 默认值// 其他属性和getter/setter
}class ProductDto {private double price;// getter/setter
}

在这个例子中,ProductDtoprice 字段将不会被 Product 对象的默认值 0.0 填充

9.MapStruct的注解

MapStruct 允许你使用 @Mapping 注解来指定映射关系,包括如何从源属性映射到目标属性。

@Mapper
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);@Mapping(target = "fullName", expression = "java(user.getFirstName() + ' ' + user.getLastName())")UserDto userToUserDto(User user);
}class User {private String firstName;private String lastName;// getters and setters
}class UserDto {private String fullName;// getter/setter
}

在这个例子中,UserDtofullName 属性是通过连接 User 对象的 firstNamelastName 属性来生成的。

使用@MappingTarget可以自定义源对象到目标对象的属性的映射关系;

使用 @AfterMapping@BeforeMapping 注解结合 @MappingTarget 来在映射前后执行自定义逻辑。上边的有结合 @AfterMapping的示例

@AfterMapping相对应,MapStruct还提供了@BeforeMapping注解,用于在映射开始之前执行自定义逻辑。

@Mapper
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);@BeforeMappingdefault void beforeMapping(@MappingTarget UserDto target, User source) {// 执行映射前的自定义逻辑,例如初始化或验证源对象if (source == null) {throw new IllegalArgumentException("Source user cannot be null");}}UserDto userToUserDto(User user);
}
10.使用 @Mapper 注解定义映射器

@Mapper 注解用于定义映射器接口,你可以通过这个注解来配置映射器的行为,从而使用其他的自定义的映射器

@Mapper(uses = {DateMapper.class, EnumMapper.class})
public interface MyCustomMapper {// 映射方法
}@Mapper
public abstract class DateMapper {@Mapping(target = "dateAsString", expression = "java(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE.format(source.getDate()))")abstract void mapDate(@MappingTarget MyTarget target, MySource source);
}@Mapper
public abstract class EnumMapper {// 映射枚举类型的逻辑
}

在这个例子中,MyCustomMapper 使用了 uses 属性来指定其他映射器类,这些类提供了额外的映射逻辑。

示例二

/** Copyright MapStruct Authors.** Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0*/
package org.mapstruct.example.mapper;import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.example.dto.Customer;
import org.mapstruct.example.dto.CustomerDto;
import org.mapstruct.factory.Mappers;/*** @author Filip Hrisafov*/
@Mapper(uses = { OrderItemMapper.class })
public interface CustomerMapper {CustomerMapper MAPPER = Mappers.getMapper( CustomerMapper.class );@Mapping(source = "orders", target = "orderItems")@Mapping(source = "customerName", target = "name")Customer toCustomer(CustomerDto customerDto);@InheritInverseConfigurationCustomerDto fromCustomer(Customer customer);
}
/** Copyright MapStruct Authors.** Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0*/
package org.mapstruct.example.mapper;import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.example.dto.OrderItem;
import org.mapstruct.example.dto.OrderItemDto;
import org.mapstruct.factory.Mappers;/*** @author Filip Hrisafov*/
@Mapper
public interface OrderItemMapper {OrderItemMapper MAPPER = Mappers.getMapper(OrderItemMapper.class);OrderItem toOrder(OrderItemDto orderItemDto);@InheritInverseConfigurationOrderItemDto fromOrder(OrderItem orderItem);
}

@InheritInverseConfiguration 是 MapStruct 中的一个注解,用于继承已有映射方法的逆向配置。这在需要定义双向映射(从一个类到另一个类,然后从另一个类再映射回第一个类)时非常有用,可以减少代码重复,提高代码的可维护性。

11.使用 @Named 注解

在mapstruct的源码中@Named注解类就有对应的示例:

/** Copyright MapStruct Authors.** Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0*/
package org.mapstruct;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Marks mapping methods with the given qualifier name. Can be used to qualify a single method or all methods of a given* type by specifying this annotation on the type level.* * Will be used to select the correct mapping methods when mapping a bean property type, element of an iterable type* or the key/value of a map type.* * Example (both methods of {@code Titles} are capable to convert a string, but the ambiguity is resolved by applying* the qualifiers in {@code @Mapping}:** * @Named("TitleTranslator")* public class Titles {**   @Named("EnglishToGerman")*   public String translateTitleEG(String title) {*       // some mapping logic*   }**   @Named("GermanToEnglish")*   public String translateTitleGE(String title) {*       // some mapping logic*   }* }** @Mapper( uses = Titles.class )* public interface MovieMapper {**    @Mapping( target = "title", qualifiedByName = { "TitleTranslator", "EnglishToGerman" } )*    GermanRelease toGerman( OriginalRelease movies );** }** The following implementation of {@code MovieMapper} will be generated:*** public class MovieMapperImpl implements MovieMapper {*     private final Titles titles = new Titles();**     @Override*     public GermanRelease toGerman(OriginalRelease movies) {*         if ( movies == null ) {*             return null;*         }**         GermanRelease germanRelease = new GermanRelease();**         germanRelease.setTitle( titles.translateTitleEG( movies.getTitle() ) );**         return germanRelease;*     }* }*** @author Sjaak Derksen* @see org.mapstruct.Mapping#qualifiedByName()* @see IterableMapping#qualifiedByName()* @see MapMapping#keyQualifiedByName()* @see MapMapping#valueQualifiedByName()*/
@Target( { ElementType.TYPE, ElementType.METHOD } )
@Retention( RetentionPolicy.CLASS )
@Qualifier
public @interface Named {/*** A name qualifying the annotated element** @return the name.*/String value();
}

在 MapStruct 中,@Named 注解主要用于自定义方法,以便在映射器中引用这些方法。通过给这些方法加上 @Named 注解,并在 @Mapping 注解中引用这些方法,可以实现复杂的映射逻辑。MapStruct 支持 JSR-330 的 @Named 注解,这使得定义和使用自定义的转换逻辑更加灵活和清晰。

使用@Named注解定义自定义方法

假设我们有一个自定义的方法需要在映射过程中使用,我们可以使用 @Named 注解为该方法命名,并在 @Mapping 注解中引用它。

示例

假设我们有以下两个类:

public class Source {private String name;private String date;// getters and setters
}public class Target {private String fullName;private LocalDate birthDate;// getters and setters
}

我们想要将 Sourcename 映射到 TargetfullName,并将 date 字符串转换为 LocalDate 并映射到 birthDate。为此,我们可以定义一个自定义的日期转换方法。

定义映射器接口和自定义方法

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;import java.time.LocalDate;
import java.time.format.DateTimeFormatter;@Mapper
public interface SourceToTargetMapper {SourceToTargetMapper INSTANCE = Mappers.getMapper(SourceToTargetMapper .class);@Mapping(source = "name", target = "fullName")@Mapping(source = "date", target = "birthDate", qualifiedByName = "stringToLocalDate")Target sourceToTarget(Source source);@Named("stringToLocalDate")default LocalDate stringToLocalDate(String date) {return LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));}
}

测试使用映射器

public class TestMapping {public static void main(String[] args) {Source source = new Source();source.setName("John Doe");source.setDate("1980-01-01");Target target = SourceToTargetMapper.INSTANCE.sourceToTarget(source);System.out.println("Full Name: " + target.getFullName()); // 输出: John DoeSystem.out.println("Birth Date: " + target.getBirthDate()); // 输出: 1980-01-01}
}
11.映射多个源对象到一个目标对象

MapStruct允许你映射多个源对象到一个目标对象;这对于需要将来自不同源的数据合并到一个目标对象的情况非常有用。MapStruct 提供了灵活的注解配置,使得这种映射变得直观和易于实现。

示例:假设我们有以下两个源对象 Source1Source2,以及一个目标对象 Target

public class Source1 {private String name;private String email;// getters and setters
}public class Source2 {private String address;private String phoneNumber;// getters and setters
}public class Target {private String name;private String email;private String address;private String phoneNumber;// getters and setters
}

我们希望将 Source1Source2 的属性合并到 Target 对象中

定义映射器接口

我们需要在映射器接口中定义一个方法,该方法接受多个源对象并返回目标对象。

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;@Mapper
public interface MyMapper {MyMapper INSTANCE = Mappers.getMapper(MyMapper.class);@Mapping(source = "source1.name", target = "name")@Mapping(source = "source1.email", target = "email")@Mapping(source = "source2.address", target = "address")@Mapping(source = "source2.phoneNumber", target = "phoneNumber")Target map(Source1 source1, Source2 source2);
}

由于两个源对象和目标对象中的属性名称一致,所以也可以省略掉方法上的四个@Mapping 

测试类

public class TestMapping {public static void main(String[] args) {Source1 source1 = new Source1();source1.setName("John Doe");source1.setEmail("john.doe@example.com");Source2 source2 = new Source2();source2.setAddress("123 Main St");source2.setPhoneNumber("555-1234");Target target = MyMapper.INSTANCE.map(source1, source2);System.out.println("Name: " + target.getName()); // 输出: John DoeSystem.out.println("Email: " + target.getEmail()); // 输出: john.doe@example.comSystem.out.println("Address: " + target.getAddress()); // 输出: 123 Main StSystem.out.println("Phone Number: " + target.getPhoneNumber()); // 输出: 555-1234}
}
12. 映射一个源对象到多个目标对象

使用 @MappingTarget 注解,可以一次映射到多个目标对象。

示例:

假设我们有一个源对象 Source 和两个目标对象 Target1Target2,我们希望将 Source 对象的一部分属性映射到 Target1,另一部分属性映射到 Target2

public class Source {private String name;private String email;private String address;private String phoneNumber;// getters and setters
}public class Target1 {private String name;private String email;// getters and setters
}public class Target2 {private String address;private String phoneNumber;// getters and setters
}

定义映射接口

 我们需要在映射器接口中定义一个方法,该方法接受 Source 对象和两个目标对象,并将 Source 对象的属性映射到相应的目标对象中。

import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;@Mapper
public interface MyMapper {MyMapper INSTANCE = Mappers.getMapper(MyMapper.class);void toMultiTargets(Source source, @MappingTarget Target1 target1, @MappingTarget Target2 target2);
}

 或者也可以自定义辅助方法实现具体的映射逻辑

@Mapper
public interface MyMapper {MyMapper INSTANCE = Mappers.getMapper(MyMapper.class);void toMultiTargets(Source source, @MappingTarget Target1 target1, @MappingTarget Target2 target2);default void toMultiTargets(Source source, @MappingTarget Target1 target1, @MappingTarget Target2 target2) {if (source != null) {target1.setName(source.getName());target1.setEmail(source.getEmail());target2.setAddress(source.getAddress());target2.setPhoneNumber(source.getPhoneNumber());}}
}

测试类:

public class TestMapping {public static void main(String[] args) {Source source = new Source();source.setName("John Doe");source.setEmail("john.doe@example.com");source.setAddress("123 Main St");source.setPhoneNumber("555-1234");Target1 target1 = new Target1();Target2 target2 = new Target2();MyMapper.INSTANCE.toMultiTargets(source, target1, target2);System.out.println("Target1 Name: " + target1.getName()); // 输出: John DoeSystem.out.println("Target1 Email: " + target1.getEmail()); // 输出: john.doe@example.comSystem.out.println("Target2 Address: " + target2.getAddress()); // 输出: 123 Main StSystem.out.println("Target2 Phone Number: " + target2.getPhoneNumber()); // 输出: 555-1234}
}
13.SpringBoot项目整合使用MapStruct

在Spring Boot项目中集成MapStruct主要涉及几个步骤:添加依赖、配置Mapper组件、使用MapStruct注解以及享受自动映射带来的便利。下面是详细的步骤和用法示例:

添加依赖

首先,需要在Spring Boot项目的pom.xml(对于Maven项目)或build.gradle(对于Gradle项目)中添加MapStruct的依赖。

Maven:

<dependencies><!-- MapStruct依赖 --><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>1.5.2.Final</version></dependency><!-- 处理器依赖,用于生成映射代码 --><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>1.5.2.Final</version><scope>provided</scope></dependency>
</dependencies>

Gradle

dependencies {// MapStruct依赖implementation 'org.mapstruct:mapstruct:1.5.2.Final'// 处理器依赖,用于生成映射代码annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.2.Final'
}

2.配置Mapper组件

package com.example.demo.mapper;import org.mapstruct.Mapper;
import org.springframework.stereotype.Component;@Mapper(componentModel = "spring")
public interface MyEntityMapper {MyDto entityToDto(MyEntity entity);@Mapping(target = "createdDate", expression = "java(java.time.LocalDate.now())")MyDto entityToDtoWithDefaultDate(MyEntity entity);
}

在Spring组件中,通过自动装配MapStruct Mapper接口来实现对象之间的自动映射。

package com.example.demo.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.mapper.MyEntityMapper;
import com.example.demo.entity.MyEntity;
import com.example.demo.dto.MyDto;@Service
public class MyService {private final MyEntityMapper myEntityMapper;@Autowiredpublic MyService(MyEntityMapper myEntityMapper) {this.myEntityMapper = myEntityMapper;}public MyDto convert(MyEntity entity) {return myEntityMapper.entityToDto(entity);}
}

确保Spring Boot的启动类或配置类中包含了@EnableAutoConfiguration@SpringBootApplication注解,这样Spring Boot就能自动配置应用程序,包括MapStruct的Mapper组件。

package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

更多用法可以详细参照官方的example示例代码,分类挺详细的:

 

相关文章:

MapStruct的用法总结及示例

MapStruct是一个代码生成器&#xff0c;它基于约定优于配置的原则&#xff0c;使用Java注解来简化从源对象到目标对象的映射过程。它主要用于减少样板代码&#xff0c;提高开发效率&#xff0c;并且通过编译时代码生成来保证性能。 我的个人实践方面是在2021年前那时候在项目中…...

redis 05 复制 ,哨兵

01.redis的复制功能&#xff0c;使用命令slaveof 2. 2.1 2.2 3. 3.1 3.1.1 3.1.2 3.1.3 4 4.1 4.2 例子 5.1 这里是从客户端发出的指令 5.2 套接字就是socket 这里是和redis事件相关的知识 5.3 ping一下...

强大的.NET的word模版引擎NVeloDocx

在Javer的世界里&#xff0c;存在了一些看起来还不错的模版引擎&#xff0c;比如poi-tl看起来就很不错&#xff0c;但是那是人家Javer们专属的&#xff0c;与我们.Neter关系不大。.NET的世界里Word模版引擎完全是一个空白。 很多人不得不采用使用Word XML结合其他的模版引擎来…...

MySQL中所有常见知识点汇总

存储引擎 这一张是关于整个存储引擎的汇总知识了。 MySQL体系结构 这里是MySQL的体系结构图&#xff1a; 一般将MySQL分为server层和存储引擎两个部分。 其实MySQL体系结构主要分为下面这几个部分&#xff1a; 连接器&#xff1a;负责跟客户端建立连 接、获取权限、维持和管理…...

Flink 基于 TDMQ Apache Pulsar 的离线场景使用实践

背景 Apache Flink 是一个开源的流处理和批处理框架&#xff0c;具有高吞吐量、低延迟的流式引擎&#xff0c;支持事件时间处理和状态管理&#xff0c;以及确保在机器故障时的容错性和一次性语义。Flink 的核心是一个分布式流数据处理引擎&#xff0c;支持 Java、Scala、Pytho…...

远程访问及控制

SSH协议 是一种安全通道协议 对通信数据进行了加密处理&#xff0c;用于远程管理 OpenSSH(SSH由OpenSSH提供) 服务名称&#xff1a;sshd 服务端控制程序&#xff1a; /usr/sbin/sshd 服务端配置文件&#xff1a; /etc/ssh/sshd_config ssh存放的客户端的配置文件 ssh是服务端额…...

【代码随想录训练营】【Day 44】【动态规划-4】| 卡码 46, Leetcode 416

【代码随想录训练营】【Day 44】【动态规划-4】| 卡码 46&#xff0c; Leetcode 416 需强化知识点 背包理论知识 题目 卡码 46. 携带研究材料 01 背包理论基础01 背包理论基础&#xff08;滚动数组&#xff09;01 背包 二维版本&#xff1a;dp[i][j] 表示从下标为[0-i]的物…...

html5实现个人网站源码

文章目录 1.设计来源1.1 网站首页页面1.2 个人工具页面1.3 个人日志页面1.4 个人相册页面1.5 给我留言页面 2.效果和源码2.1 动态效果2.2 目录结构 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/139564407 ht…...

【内存管理】内存布局

ARM32位系统的内存布局图 32位操作系统的内存布局很经典&#xff0c;很多书籍都是以32位系统为例子去讲解的。32位的系统可访问的地址空间为4GB&#xff0c;用户空间为1GB ~ 3GB&#xff0c;内核空间为3GB ~ 4GB。 为什么要划分为用户空间和内核空间呢&#xff1f; 一般处理器…...

软件试运行方案(Word)

软件试运行方案&#xff08;直接套用实际项目&#xff0c;原件获取通过本文末个人名片直接获取。&#xff09; 一、试运行目的 二、试运行的准备 三、试运行时间 四、试运行制度 五、试运行具体内容与要求...

Redis原理篇——哨兵机制

Redis原理篇——哨兵机制 1.Redis哨兵2.哨兵工作原理2.1.哨兵作用2.2.状态监控2.3.选举leader2.4.failover 1.Redis哨兵 主从结构中master节点的作用非常重要&#xff0c;一旦故障就会导致集群不可用。那么有什么办法能保证主从集群的高可用性呢&#xff1f; 2.哨兵工作原理 …...

web前端的MySQL:跨领域之旅的探索与困惑

web前端的MySQL&#xff1a;跨领域之旅的探索与困惑 在数字化浪潮的推动下&#xff0c;web前端与MySQL数据库似乎成为了两个不可或缺的领域。然而&#xff0c;当我们将这两者放在一起&#xff0c;尝试探索web前端与MySQL之间的交互与关联时&#xff0c;却发现这是一次充满困惑…...

Postgresql源码(135)生成执行计划——Var的调整set_plan_references

1 总结 set_plan_references主要有两个功能&#xff1a; 拉平&#xff1a;生成拉平后的RTE列表&#xff08;add_rtes_to_flat_rtable&#xff09;。调整&#xff1a;调整前每一层计划中varno的引用都是相对于本层RTE的偏移量。放在一个整体计划后&#xff0c;需要指向一个统一…...

Python魔法之旅专栏(导航)

目录 推荐阅读 1、Python筑基之旅 2、Python函数之旅 3、Python算法之旅 4、博客个人主页 首先&#xff0c;感谢老铁们一直以来对我的支持与厚爱&#xff0c;让我能坚持把Python魔法方法专栏更新完毕&#xff01; 其次&#xff0c;为了方便大家查阅&#xff0c;我将此专栏…...

Python第二语言(五、Python文件相关操作)

目录 1. 文件编码的概念 2. 文件的读取操作 2.1 什么是文件 2.2 open()打开函数 2.3 mode常用的三种基础访问模式 2.4 文件操作及案例 3. 文件的写入操作及刷新文件&#xff1a;write与flush 4. 文件的追加操作 5. 文件操作的综合案例&#xff08;文件备份操作&#x…...

Vue3 组合式 API:依赖注入(四)

provide() provide() 函数是用于依赖注入的一个关键部分。这个函数允许你在组件树中提供一个值或对象&#xff0c;使得任何子组件&#xff08;无论层级多深&#xff09;都能够通过 inject() 函数来访问这些值。 import { provide, ref } from vue; export default { setup(…...

Vue如何引入ElementUI并使用

Element UI详细介绍 Element UI是一个基于Vue 2.0的桌面端组件库&#xff0c;旨在构建简洁、快速的用户界面。由饿了么前端团队开发&#xff0c;提供丰富的组件和工具&#xff0c;帮助开发者快速构建高质量的Vue应用&#xff0c;并且以开放源代码的形式提供。 1. VueElementU…...

VS2019 QT无法打开 源 文件 “QTcpSocket“

VS2019 QT无法打开 源 文件 "QTcpSocket" QT5.15.2_msvc2019_64 严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) E1696 无法打开 源 文件 "QTcpSocket" auto_pack_line_demo D:\vs_qt_project\auto_pack_line_de…...

【Golang】Map 稳定有序遍历的实现与探索:保序遍历之道

【Golang】Map 稳定有序遍历的实现与探索&#xff1a;保序遍历之道 大家好 我是寸铁&#x1f44a; 总结了一篇【Golang】Map 稳定有序遍历的实现与探索&#xff1a;保序遍历之道✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言&#x1f34e; 在计算机科学中&#xff0c;数据结…...

使用Nextjs学习(学习+项目完整版本)

创建项目 运行如下命令 npx create-next-app next-create创建项目中出现的各种提示直接走默认的就行,一直回车就行了 创建完成后进入到项目运行localhost:3000访问页面,如果和我下面页面一样就是创建项目成功了 整理项目 将app/globals.css里面的样式都删除,只留下最上面三…...

KUKA机器人KRC5控制柜面板LED显示

对于KUKA机器人新系列控制柜KRC5控制柜来说&#xff0c;其控制柜面板LED布局如下图&#xff1a; 其中①②③④分别为&#xff1a; 1、机器人控制柜处于不同状态时&#xff0c;LED显示如下&#xff1a; 2、机器人控制柜正在运行时&#xff1a; 3、机器人控制柜运行时出现的故障…...

为什么选择Python作为AI开发语言

为什么Python适合AI 在当前的科技浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;无疑是最热门的话题之一。无论是自动驾驶、智能推荐还是自然语言处理&#xff0c;AI都在不断改变我们的生活。而在这场技术革命中&#xff0c;Python作为主要的编程语言之一&#xff0c;…...

【算法篇】求最长公共前缀JavaScript版本

题目描述 给你一个大小为 n 的字符串数组 strs &#xff0c;其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀&#xff0c;返回这个公共前缀。 数据范围&#xff1a; 数据范围:0<n<5000&#xff0c;0<len(strsi)< 5000 进阶:空间复杂度 O(1)&a…...

搭建RocketMQ主从异步集群

搭建RocketMQ主从异步集群 1、RocketMQ集群模式 为了追求更好的性能&#xff0c;RocketMQ的最佳实践方式都是在集群模式下完成的。RocketMQ官方提供了三种集群搭建方式&#xff1a; 2主2从异步通信方式&#xff1a;使用异步方式进行主从之间的数据复制。吞吐量大&#xff0c;…...

最大子段和问题

最大子段和问题 分数 15 全屏浏览 切换布局 作者 王东 单位 贵州师范学院 最大子段和问题。给定由n个整数组成的序列&#xff0c;求序列中子段的最大和&#xff0c;若所有整数均为负整数时定义最大子段和为0。 输入格式: 第一行输入整数个数n&#xff08;1≤n≤1000&…...

Vue3中的常见组件通信之mitt

Vue3中的常见组件通信之mitt 概述 ​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refs、parent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。 组件关系传递方式父传子1. props2. v-model3. $refs…...

MySQL快速入门(极简)

SQL 介绍及 MySQL 安装 一、实验简介 本课程为实验楼提供的 MySQL 实验教程&#xff0c;所有的步骤都在实验楼在线实验环境中完成&#xff0c;学习中请按照实验步骤依次操作。 本课程为 SQL 基本语法及 MySQL 基本操作的实验&#xff0c;理论内容较少&#xff0c;动手实践多…...

CentOS7安装NVIDIA显卡驱动指引【笔记】

CentOS7安装NVIDIA显卡驱动指引【笔记】 实践设备:华硕FX-PRO(NVIDIA GeForce GTX 960M) 环境准备: 1、将系统安装到设备上正常运行; 2、设备网络调试,可以正常访问外网; 3、配置ssh服务(非必要,根据实际情况)。 说明: 本文档所提供的指引和参考主要基于特定实践…...

【RabbitMQ】RabbitMQ配置与交换机学习

【RabbitMQ】RabbitMQ配置与交换机学习 文章目录 【RabbitMQ】RabbitMQ配置与交换机学习简介安装和部署1. 安装RabbitMQ2.创建virtual-host3. 添加依赖4.修改配置文件 WorkQueues模型1.编写消息发送测试类2.编写消息接收&#xff08;监听&#xff09;类3. 实现能者多劳 交换机F…...

常见排序算法,快排,希尔,归并,堆排

后面的排序中都要用到的函数 //交换 void Swap(int* p1, int* p2) {int* tmp *p1;*p1 *p2;*p2 tmp; } 包含的头文件 "Sort.h" #pragma once #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<time.h> #include<s…...

国内vps做网站要备案吗/自助发外链网站

夜光序言&#xff1a; 人有了物质才能生存&#xff1b;人有了理想才谈得上生活。你要了解生存与生活的不同吗&#xff1f;动物生存&#xff0c;而人则生活。 正文&#xff1a; 1&#xff1a;ctrl/ : 可以用显示灰色&#xff0c;那个东西 ctrl/shift:用于注释一个部分 <!D…...

怎样做浏览的网站不被发现/深圳快速seo排名优化

在docker写 dockerfile的时候。如果你需要传完整文件夹上去而不是把里面所有的内容都递归一个一个拿出来&#xff0c;那么你需要就不能直接用copy命令&#xff0c;需要其他婉转的方法。例如&#xff1a;先进行压缩在copy。 Note: The directory itself is not copied, just it…...

网站的规划与建设/今天重大新闻头条新闻

作者&#xff1a;Andreas译者&#xff1a;前端小智来源&#xff1a;dev尽管我们经常使用 VS Code中的许多快捷方式&#xff0c;但是我们有可能会忘记它们。这里用可视化制作了一些GIF&#xff0c;以便更好地记住它们&#xff0c;希望对你有所帮助。VSCode中的每个命令也可以通过…...

个人网站的设计与开发/营销渠道有哪些

发那科机器人应用项目大揭秘FANUC iR PickTool是对传送带上的工件使用相机或光电传感器等设备进行检测&#xff0c;机器人配合传送带的运动对工件进行动态拾取的定制化软件。该软件提供了多台机器人共享一条传送带上工件数据信息的应用&#xff0c;支持一台机器人同时对应多条传…...

建设b2c商城网站定/百度自助建站官网

第七章 开发向导 7.1 和ITK 的关系 大部分的elastix代码是基于ITK的。使用ITK意味着可以测试基类&#xff08;图片类&#xff0c;存储分配&#xff09;。自然ITK支持的图片格式elastix也支持。C源码可以在多种操作系统上使用多种编译器&#xff08;最新版本VS2010&#xff0…...

电子商务网站建设哪好/网店如何推广

综合布线常用公式 RJ-45头的需求量&#xff1a;mn*4n*4*15% m:表示RJ-45接头的总需求量 n:表示信息点的总量 n*4*15%:表示留有的富余 信息模块的需求量&#xff1a;mnn*3% m&#xff1a;表示信息模块的总需求量 n:表示信息点的总量 n*3%&#xff1a;表示富余量 每层楼用线量…...