mapstruct个人学习记录

news2024/11/26 12:31:01

mapstruct核心技术学习

  • 简介
  • 入门案例
    • maven依赖
  • IDEA插件
    • 单一对象转换
      • 测试结果
  • mapping属性
  • Spring注入的方式
    • 测试
  • 集合的映射
    • set类型的映射
    • 测试
    • map类型的映射
      • 测试
    • @MapMapping
      • keyDateFormat
      • valueDateFormat
  • 枚举映射
    • 基础入门

简介

在工作中,我们经常要进行各种对象之间的转换。
PO: persistent object持久对象,对应数据库中的一条
VO: view object表现层对象,最终返回给前端的对象
DTO:data transfer object数据传输对象,如dubbo服务之间的传输的对象
po、vo、dto的详细介绍
如果这些对象的属性名相同还好,可以使用如下工具类赋值
Spring BeanUtils
Cglib BeanCopier
避免使用Apache BeanUtils,性能较差

如果属性名不同呢?如果是将多个PO对象合并成一个VO对象呢?好在有MapStruct,可以帮助我们快速转换
mapstruct官网
mapstruct技术文档

入门案例

maven依赖

 <properties>
        <java.version>1.8</java.version>
        <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
</properties>
<dependencies>
		<dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
</dependencies>        

IDEA插件

IDEA中搜索"MapStruct Support"插件,进行安装,安装成功后重启IDEA。
在这里插入图片描述

单一对象转换

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class CarDTO {

    private String make;

    private int seatCount;

    private String type;
}
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class Car {

    private String make;

    private int numberOfSeats;
}
import com.example.demo.dto.CarDTO;
import com.example.demo.po.Car;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;


@Mapper
public interface CarMapper {

    CarMapper instance = Mappers.getMapper(CarMapper.class);

    /**
     * 表达式需要自动提示的话,需要安装IDEA插件mapstruct support
     * @param car
     * @return
     */

    @Mapping(source = "numberOfSeats",target = "seatCount")
    @Mapping(target = "type",expression = "java(car.getMake())")
    CarDTO carToCarDto(Car car);
}
import com.example.demo.dto.CarDTO;
import com.example.demo.mapper.CarMapper;
import com.example.demo.po.Car;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {DemoApplication.class})
public class ApplicationTest {

    @Test
    public void test() {
        CarMapper instance = CarMapper.instance;
        Car car = new Car();
        car.setMake("中国")
                .setNumberOfSeats(1000);
        CarDTO carDTO = instance.carToCarDto(car);
        System.out.println(carDTO);
    }
}

测试结果

在这里插入图片描述
项目结构图
在这里插入图片描述
在target文件夹下生成了CarMapperImpl.java

package com.example.demo.mapper;

import com.example.demo.dto.CarDTO;
import com.example.demo.po.Car;
import javax.annotation.Generated;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-11-08T23:35:28+0800",
    comments = "version: 1.5.5.Final, compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)"
)
public class CarMapperImpl implements CarMapper {

    @Override
    public CarDTO carToCarDto(Car car) {
        if ( car == null ) {
            return null;
        }

        CarDTO carDTO = new CarDTO();

        carDTO.setSeatCount( car.getNumberOfSeats() );
        carDTO.setMake( car.getMake() );

        carDTO.setType( car.getMake() );

        return carDTO;
    }
}

mapping属性

    /**
     * @Mappings 一组映射关系,值为一个数组,元素为@Mapping
     * @Mapping 一一对应关系
     * source:源属性
     * target:目标属性,赋值的过程是把源属性赋值给目标属性
     * dateFormat:用于源属性是Date,转换为String
     * numberFormat:用户数值类型与String类型之间的转
     * constant: 常量
     * expression:使用表达式进行属性之间的转换
     * ignore:忽略某个属性的赋值
     * qualifiedByName: 自定义的方法赋值
     * defaultValue:默认值
     * @defaultExpression 如果源数据没有设置的时候,可以指定相关表达式进行处理
     * 基本数据类型与包装类可以自动映射
     * @MappingTaget 用在方法参数的前面,使用此注解,源对象同时也会作为目标对象,用于更新
     * @InheritConfiguration 指定映射方法
     * @InheritInverseConfiguration 表示方法继承相应的反向方法的反向配置
     * @param car 入参
     * @return 返回结果
     */
package com.example.demo.entity;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class CarBrand {

    private String carBrand;
}

package com.example.demo.entity;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class Brand {

    private String brandName;

}

package com.example.demo.entity;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class CarDto {

    private String make;

    private int seatCount;

    private String type;

    private CarBrand carBrand;

    private String date;

    private String price;

    private String extral;
}

package com.example.demo.entity;

import lombok.Data;
import lombok.experimental.Accessors;

import java.math.BigDecimal;
import java.util.Date;

@Data
@Accessors(chain = true)
public class Car {

    private String make;

    private int numberOfSeats;

    private Brand brand;

    private Date date;

    private BigDecimal price;

}
package com.example.demo.entity;

import org.mapstruct.*;

import static org.mapstruct.MappingConstants.ComponentModel.SPRING;

/**
 * @Mapper 表示该接口作为映射接口,编译时MapStruct处理器的入口
 * componentModel 主要是指定实现类的类型,一般用到两个
 * default:默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象
 * spring:在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入
 * uses 外部引入的转换类
 */
@Mapper(componentModel = SPRING)
public interface CarMapper {


    /**
     * @Mappings 一组映射关系,值为一个数组,元素为@Mapping
     * @Mapping 一一对应关系
     * source:源属性
     * target:目标属性,赋值的过程是把源属性赋值给目标属性,当目标属性和源属性一致时候,source和target可以省略不写
     * dateFormat:用于源属性是Date,转换为String
     * numberFormat:用户数值类型与String类型之间的转
     * constant: 常量
     * expression:使用表达式进行属性之间的转换
     * ignore:忽略某个属性的赋值
     * qualifiedByName: 自定义的方法赋值
     * defaultValue:默认值
     * @defaultExpression 如果源数据没有设置的时候,可以指定相关表达式进行处理
     * 基本数据类型与包装类可以自动映射
     * @MappingTaget 用在方法参数的前面,使用此注解,源对象同时也会作为目标对象,用于更新
     * @InheritConfiguration 指定映射方法
     * @InheritInverseConfiguration 表示方法继承相应的反向方法的反向配置
     * @param car 入参
     * @return 返回结果
     */
    @Mappings({
            @Mapping(source = "date",target = "date",dateFormat = "yyyy-MM-dd HH:mm:ss"),
            @Mapping(source = "price",target = "price",numberFormat = "0.00"),
            @Mapping(source = "numberOfSeats",target = "seatCount"),
            @Mapping(target = "type",constant = "hello type"),
            @Mapping(source = "brand",target = "carBrand",qualifiedByName = {"brand2CarBrandV2"})
    })

    CarDto carToCarDtoV2(Car car);

    /**
     * @Named 定义类/方法的名称
     * @param brand
     * @return
     */
    @Named("brand2CarBrandV2")
    @Mappings({
        @Mapping(source = "brandName",target = "carBrand")
    })
    CarBrand brand2CarBrandV2(Brand brand);
}

package com.example.demo;

import com.example.demo.entity.Brand;
import com.example.demo.entity.Car;
import com.example.demo.entity.CarDto;
import com.example.demo.entity.CarMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.math.BigDecimal;
import java.util.Date;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {DemoApplication.class})
public class CarMapperTest {

    @Autowired
    private CarMapper carMapper;

    @Test
    public void test() {
        Car car = new Car();
        car.setMake("from source")
                .setNumberOfSeats(100)
                .setBrand(new Brand()
                        .setBrandName("保密"))
                .setPrice(BigDecimal.valueOf(100.12345))
                .setDate(new Date());
        CarDto dto = carMapper.carToCarDtoV2(car);
        System.out.println(dto);
    }
}

测试结果,输出如下

CarDto(make=from source, seatCount=100, type=hello type, carBrand=CarBrand(carBrand=保密), date=2023-11-11 20:22:49, price=100.12, extral=null)

Spring注入的方式

中声明INSTANCE的方式来进行调用之外,MapStruct也同时支持Spring的依赖注入机制

package com.example.MapStructDemo.dto;

import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class CarDto {

    private String manufacturer;

    private int seatCount;
}

package com.example.MapStructDemo.po;

import lombok.Data;
import lombok.experimental.Accessors;


@Data
@Accessors(chain = true)
public class Car {

    private String make;

    private int numberOfSeats;
}

package com.example.MapStructDemo.mapper;

import com.example.MapStructDemo.dto.CarDto;
import com.example.MapStructDemo.po.Car;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import static org.mapstruct.MappingConstants.ComponentModel.SPRING;

/**
 * @Mapper 只有在接口加上这个注解, MapStruct 才会去实现该接口
 * @Mapper 里有个 componentModel 属性,主要是指定实现类的类型,一般用到两个
 * default:默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象
 * SPRING:在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入
 */
@Mapper(componentModel = SPRING)
public interface CarMapper {

    @Mapping(target = "manufacturer",source = "make")
    @Mapping(target = "seatCount",source = "numberOfSeats")
    CarDto carToCarDto(Car car);

}

测试

package com.example.MapStructDemo;

import com.example.MapStructDemo.dto.CarDto;
import com.example.MapStructDemo.mapper.CarMapper;
import com.example.MapStructDemo.po.Car;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class ApplicationTests {
    @Autowired
    private CarMapper carMapper;

    @Test
    public void contextLoads() {
        Car car = new Car();
        car.setMake("中国").setNumberOfSeats(1000);
        CarDto carDto = carMapper.carToCarDto(car);
        System.out.println("测试结果");
        System.out.println(carDto);
    }

}

在这里插入图片描述

集合的映射

set类型的映射

package com.example.MapStructDemo.mapper;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Set;
import static org.mapstruct.MappingConstants.ComponentModel.SPRING;

@Mapper(componentModel = SPRING)
public interface CarMapper {

    /**
     * 集合的映射
     * @param set 入参
     * @return Set<String>
     */
    Set<String> integerSetToStringSet(Set<Integer> set);
}

CarMapper的实现类CarMapperImpl,会生成如下代码,集合set为null的时候,默认返回null
在这里插入图片描述

测试

package com.example.MapStructDemo;

import com.example.MapStructDemo.mapper.CarMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.HashSet;
import java.util.Set;

@SpringBootTest
public class ApplicationTests {
    @Autowired
    private CarMapper carMapper;

    @Test
    public void test(){
        Set<Integer> set = new HashSet<>();
        for (int i=0;i<10;i++){
            set.add(i);
        }
        Set<String> strings = carMapper.integerSetToStringSet(set);
        System.out.println("集合类型的测试");
        strings.forEach(System.out::println);
    }
}

测试结果如下:
在这里插入图片描述

map类型的映射

package com.example.MapStructDemo.mapper;

import org.mapstruct.MapMapping;
import org.mapstruct.Mapper;

import java.util.Date;
import java.util.Map;

import static org.mapstruct.MappingConstants.ComponentModel.SPRING;

@Mapper(componentModel = SPRING)
public interface SourceTargetMapper {

    /**
     * map类型的映射
     * @param source 入参
     * @return Map<String, String>
     * map中value的值是Date类型的转换为String类型
     */
    @MapMapping(valueDateFormat = "dd.MM.yyyy")
    Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source);
}

map映射的实现类SourceTargetMapperImpl

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.MapStructDemo.mapper;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.stereotype.Component;

@Component
public class SourceTargetMapperImpl implements SourceTargetMapper {
    public SourceTargetMapperImpl() {
    }

    public Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source) {
        if (source == null) {
            return null;
        } else {
            Map<String, String> map = new LinkedHashMap(Math.max((int)((float)source.size() / 0.75F) + 1, 16));
            Iterator var3 = source.entrySet().iterator();

            while(var3.hasNext()) {
                Map.Entry<Long, Date> entry = (Map.Entry)var3.next();
                String key = (new DecimalFormat("")).format(entry.getKey());
                String value = (new SimpleDateFormat("dd.MM.yyyy")).format((Date)entry.getValue());
                map.put(key, value);
            }

            return map;
        }
    }
}

测试

package com.example.MapStructDemo;

import com.example.MapStructDemo.mapper.SourceTargetMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@SpringBootTest
public class SourceTargetMapperTests {

    @Autowired
    private SourceTargetMapper sourceTargetMapper;

    @Test
    public void test() {
        Map<Long, Date> map = new HashMap<>();
        map.put(1L, new Date());
        System.out.println(map);
        System.out.println("map类型的映射");
        Map<String, String> result = sourceTargetMapper.longDateMapToStringStringMap(map);
        System.out.println(result);
    }
}

测试结果
在这里插入图片描述

@MapMapping

配置的是Map<String,String>Map<Long,Date>之间的转换

keyDateFormat

mapkey的类型是从DateString类型的转换

valueDateFormat

map中value的类型从DateString类型的转换

枚举映射

基础入门

package com.example.MapStructDemo.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum OrderType {

    EXTRA,

    STANDARD,

    NORMAL
}

package com.example.MapStructDemo.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public enum ExternalOrderType {

    SPECIAL,

    DEFAULT
}

package com.example.MapStructDemo.mapper;

import com.example.MapStructDemo.enums.ExternalOrderType;
import com.example.MapStructDemo.enums.OrderType;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;

import static org.mapstruct.MappingConstants.ComponentModel.SPRING;

@Mapper(componentModel = SPRING)
public interface OrderMapper {

    /**
     * 枚举类型映射
     * @param orderType 入参
     * @return ExternalOrderType
     */
    @ValueMappings({
            @ValueMapping(target = "SPECIAL",source = "EXTRA"),
            @ValueMapping(target = "DEFAULT",source = "STANDARD"),
            @ValueMapping(target = "DEFAULT",source = "NORMAL")
    })
    ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}

OrderMapper的实现类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.example.MapStructDemo.mapper;

import com.example.MapStructDemo.enums.ExternalOrderType;
import com.example.MapStructDemo.enums.OrderType;
import org.springframework.stereotype.Component;

@Component
public class OrderMapperImpl implements OrderMapper {
    public OrderMapperImpl() {
    }

    public ExternalOrderType orderTypeToExternalOrderType(OrderType orderType) {
        if (orderType == null) {
            return null;
        } else {
            ExternalOrderType externalOrderType;
            switch (orderType) {
                case EXTRA:
                    externalOrderType = ExternalOrderType.SPECIAL;
                    break;
                case STANDARD:
                    externalOrderType = ExternalOrderType.DEFAULT;
                    break;
                case NORMAL:
                    externalOrderType = ExternalOrderType.DEFAULT;
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected enum constant: " + orderType);
            }

            return externalOrderType;
        }
    }
}

package com.example.MapStructDemo;

import com.example.MapStructDemo.enums.ExternalOrderType;
import com.example.MapStructDemo.enums.OrderType;
import com.example.MapStructDemo.mapper.OrderMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class OrderMapperTest {

    @Autowired
    private OrderMapper orderMapper;

    @Test
    public void test1() {
        System.out.println("测试结果");
        OrderType orderType = OrderType.EXTRA;
        ExternalOrderType externalOrderType = orderMapper.orderTypeToExternalOrderType(orderType);
        System.out.println(externalOrderType);
    }
}

测试结果
在这里插入图片描述

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

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

相关文章

综述 2022-Genome Biology:“AI+癌症multi-omics”融合方法benchmark

Leng, Dongjin, et al. "A benchmark study of deep learning-based multi-omics data fusion methods for cancer." Genome biology 23.1 (2022): 1-32. 被引次数&#xff1a;34作者单位 红色高亮表示写论文中可以借鉴的地方 一、方法和数据集 1. 3个数据集&…

【数学建模】《实战数学建模:例题与讲解》第八讲-回归分析(含Matlab代码)

【数学建模】《实战数学建模&#xff1a;例题与讲解》第八讲-回归分析&#xff08;含Matlab代码&#xff09; 回归分析基本概念经典多元线性回归&#xff08;MLR&#xff09;主成分回归&#xff08;PCR&#xff09;偏最小二乘回归&#xff08;PLS&#xff09;建模过程应用和优势…

Vue3中的defineModel

目录 一、vue3的defineModel介绍 二、defineModel使用 &#xff08;1&#xff09;在vite.config.js中开启 &#xff08;2&#xff09;子组件 &#xff08;3&#xff09;父组件 一、vue3的defineModel介绍 为什么要使用到defineModel呢&#xff1f;这里有这样一种场景&…

面向对象类的设计和实现

实验目标 本实验任务是实现 Java 类的设计和实现&#xff0c;实验任务是根据每年新生的报到流程&#xff0c; 设计一 个学生管理系统&#xff0c;实现学生的注册和报到功能。设置类的基本属性&#xff0c;实现 getter 和 setter 方 法&#xff0c;通过 set 方法设置…

【第三届】:“玄铁杯”RISC-V应用创新大赛(基于yolov5和OpenCv算法 — 智能警戒哨兵)

文章目录 前言 一、智能警戒哨兵是什么&#xff1f; 二、方案流程图 三、硬件方案 四、软件方案 五、演示视频链接 总结 前言 最近参加了第三届“玄铁杯”RISC-V应用创新大赛&#xff0c;我的创意题目是基于 yolov5和OpenCv算法 — 智能警戒哨兵 先介绍一下比赛&#xf…

FFmpeg抽取视频h264数据重定向

根据视频重定向技术解析中的 截获解码视频流的思路&#xff0c;首先需要解决如何输出视频码流的问题。 目前只针对h264码流进行获取&#xff0c;步骤如下&#xff1a; 打开mp4文件并创建一个空文件用于存储H264数据 提取一路视频流资源 循环读取流中所有的包(AVPacket),为…

pytorch中的归一化:BatchNorm、LayerNorm 和 GroupNorm

1 归一化概述 训练深度神经网络是一项具有挑战性的任务。 多年来&#xff0c;研究人员提出了不同的方法来加速和稳定学习过程。 归一化是一种被证明在这方面非常有效的技术。 1.1 为什么要归一化 数据的归一化操作是数据处理的一项基础性工作&#xff0c;在一些实际问题中&am…

【c++随笔16】reserve之后,使用std::copy会崩溃?

【c随笔16】reserve之后&#xff0c;使用std::copy会崩溃? 一、reserve之后&#xff0c;使用std::copy会崩溃?二、函数std::reserve、std::resize、std::copy1、std::resize&#xff1a;2、std::reserve&#xff1a;3、std::copy&#xff1a; 三、崩溃原因分析方案1、你可以使…

【概率方法】重要性采样

从一个极简分布出发 假设我们有一个关于随机变量 X X X 的函数 f ( X ) f(X) f(X)&#xff0c;满足如下分布 p ( X ) p(X) p(X)0.90.1 f ( X ) f(X) f(X)0.10.9 如果我们要对 f ( X ) f(X) f(X) 的期望 E p [ f ( X ) ] \mathbb{E}_p[f(X)] Ep​[f(X)] 进行估计&#xff0…

极速学习SSM之SpringMVC笔记

文章目录 一、SpringMVC简介1、什么是MVC2、什么是SpringMVC3、SpringMVC的特点 二、HelloWorld1、开发环境2、创建maven工程a>添加web模块b>打包方式&#xff1a;warc>引入依赖 3、配置web.xmla>默认配置方式b>扩展配置方式 4、创建请求控制器5、创建springMVC…

ansible中的角色

1.理解roles在企业中的定位及写法 查看创建目录结构 ansible - galaxy list 指定新的位置 vim ansible.cfg roles_path ~/.ansible/roles 建立项目 cd roles/ ansible-galaxy init vsftpd tree vsftpd/ 编辑任务执行&#xff08;顺序&#xff09;文件 vim vsftpd/tas…

selenium库的使用

来都来了给我点个赞收藏一下再走呗&#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339; 目录 一、下载需要用到的python库selenium 二、selenium的基本使用 1.在python代码引入库 2.打开浏览器 3.元素定位 1&#xff09;通过id定位 2&#xff09;通过标…

Go开发运维:Go服务发布到K8S集群

目录 一、实验 1.Go服务发布到k8s集群 二、问题 1.如何从Harbor拉取镜像 一、实验 1.Go服务发布到k8s集群 &#xff08;1&#xff09;linux机器安装go(基于CentOS 7系统) yum install go -y &#xff08;2&#xff09;查看版本 go version &#xff08;3&#xff09;创…

UE引擎 LandscapeGrass 实现机制分析(UE5.2)

前言 随着电脑和手机硬件性能越来越高&#xff0c;游戏越来越追求大世界&#xff0c;而大世界非常核心的一环是植被&#xff0c;目前UE5引擎提供给植被生成的主流两种方式为 手刷植被和LandscapeGrass(WeightMap程序化植被)。当然UE5.3推出新一代PCGFramework 节点程序化生成框…

办公word-从不是第一页添加页码

总结 实际需要注意的是&#xff0c;分隔符、分节符和分页符并不是一个含义 分隔符包含其他两个&#xff1b;分页符&#xff1a;是增加一页&#xff1b;分节符&#xff1a;指将文档分为几部分。 从不是第一页插入页码1步骤 1&#xff0c;插入默认页码 自己可以测试时通过**…

一文掌握Ascend C孪生调试

1 What&#xff0c;什么是孪生调试 Ascend C提供孪生调试方法&#xff0c;即CPU域模拟NPU域的行为&#xff0c;相同的算子代码可以在CPU域调试精度&#xff0c;NPU域调试性能。孪生调试的整体方案如下&#xff1a;开发者通过调用Ascend C类库编写Ascend C算子kernel侧源码&am…

784. 字母大小写全排列

字母大小写全排列 描述 : 给定一个字符串 s &#xff0c;通过将字符串 s 中的每个字母转变大小写&#xff0c;我们可以获得一个新的字符串。 返回 所有可能得到的字符串集合 。以 任意顺序 返回输出。 题目 : LeetCode 784.字母大小写全排列 : 784. 字母大小写全排列 分析…

JavaScript常用技巧专题二

文章目录 一、前言二、生成随机字符串三、转义HTML特殊字符四、单词首字母大写五、将字符串转换为小驼峰六、删除数组中的重复值七、移除数组中的假值八、获取两个数字之间的随机数九、将数字截断到固定的小数点十、日期10.1、计算两个日期之间天数10.2、从日期中获取是一年中的…

fd信息查看

一、/proc/pid/fdinfo和/proc/pid/fd的含义 二、实例 ref&#xff1a; linux下的/proc/pid/fdinfo和/proc/pid/fd_proc/417/fdinfo/0-CSDN博客 linux select read阻塞_图解Linux的IO模型和相关技术-CSDN博客

实现加盐加密方法以及java nio中基于MappedByteBuffer操作大文件

自己实现 传统MD5可通过彩虹表暴力破解&#xff0c; 加盐加密算法是一种常用的密码保护方法&#xff0c;它将一个随机字符串&#xff08;盐&#xff09;添加到原始密码中&#xff0c;然后再进行加密处理。 1. 每次调用方法产生一个唯一盐值&#xff08;UUID &#xff09;密码…