基于grpc从零开始搭建一个准生产分布式应用(6) - 02 - MapStruct数据转换

一、基础转换

1.1、基础类型

基本类型、包装类、BigDecimal转String默认使用DecimalFormat格式化,@Mapping#numberFormat可以指定格式,Date转String默认使用SimpleDateFormat格式化,如默认格式不符要求,可以用,@Mapping可以指定格式。

  1. enum和String:可直接转枚举定义的值,不支持MappingConstants.ANY_REMAINING
  2. BigDecimal(等)、基本数据类(包括包装类)和String:
  3. java.time.LocalDateTime(等)和String:
  4. java.util.Date转String:Date->String,
  5. java.sql.Timestamp和java.util.Date:

注意在@Mapping#target、source设置的属性的含义。mapstruct并不是按照设置的属性找到字段,在找此字段的getter/setter方法的,而是直接通过get/set前缀 + 属性值找到相应的方法。所以如果属性名与getter和setter方法名不对象,则会报错。

@Data
public class TransformBO {
    private String level;
    private int price;
    private String date;
    private Date timestamp;
    private String localDateTime
}
@Data
public class TransformPO {
    private LevelEnum level;
    private BigDecimal price;
    private Date date;
    private Timestamp timestamp;
    private LocalDateTime localDateTime;
}

@Mapper
public interface TestMapper {
    TransformBO toTransformBO(TransformPO transformPO);
    TransformPO toTransformPO(TransformBO transformPO);
}

//@Mapping(target = "date", dateFormat = "yyyy-MM-dd HH:mm")
//@Mapping(target = "price", numberFormat = "$#.00")

TransformBO transformBO = new TransformBO();
transformBO.setLevel("PERFECT");
transformBO.setPrice(12);
transformBO.setDate("2022-01-31 01:30:19");
transformBO.setTimestamp(new Date(System.currentTimeMillis()));
transformBO.setLocalDateTime("2022-01-31T01:34:47.986");
System.out.println(mapper.toTransformPO(transformBO));

-->互转后Date的出入值是比较大的,需要特殊处理
TransformBO(level=PERFECT, price=12, date=2022-01-31 01:35:21, timestamp=2022-01-31 01:35:21.024, localDateTime=2022-01-31T01:35:21.107)
TransformPO(level=PERFECT, price=12, date=Mon Jan 31 01:30:19 CST 2022, timestamp=2022-01-31 01:35:21.138, localDateTime=2022-01-31T01:34:47.986)

1.2、Booble

private Boolean delete;
private String delete;


transformPO.setDelete(false);
//正常输出

二、集合转换

2.1、List

这个比较简单,需要定义一个集合类和一个单体转换类,类的名字随意,但建议起成对的名字,便于记录。

@Mapper
public interface TestMapper {
    TestBO testToBO(TestPO testPO);
    List<TestBO> testToBOS(List<TestPO> testPOS);
}

2.2、Map

@Mapper
public interface TestMapper {
    TestBO testToBO(TestPO testPO);
    Map<TestBO, TestBO> testToBOS(Map<TestPO, TestPO> testPOS); 
}

2.3、Enum

枚举通常是直接映射到同名的枚举对象中,不同名需@ValueMapping指定,并且源和目标上可以设置

  • MappingConstants.ANY_REMAINING:只能用在source上,标识source中除了同名自动映射和指定映射外,其余所有对象都映射到指定的target对象上;
  • MappingConstants.ANY_UNMAPPED:只能用在source上,不能和MappingConstants.ANY_REMAINING同时使用,会将source除指定对象(不包括同名自动映射)的剩余对象映射到target对象,只是为了省事;
  • MappingConstants.NULL:设置在source上表示source是null时,会被映射到指定的target;设置在target上表示source对象映射到null。
enum LevelEnum {
    PERFECT(1, "完美"),
    PASS(2, "合格"),
    normal_status(3, "普通"),
    failed(4, "不及格"),
    normal(5, "正常");
}

enum DisableStatus {
    able_status(1, "完美"),
    disable_status(2, "合格"),
    normal_status(3, "普通"),
    failed_status(4, "不及格"),
    ok_status(5, "还行"),
    fine_status(6, "可以");
}

@Mapper
interface TestMapper {
    @ValueMappings({
            @ValueMapping(source = "able_status", target = "PERFECT"),//一对一映射
            @ValueMapping(source = MappingConstants.NULL, target = "PASS"),//
            @ValueMapping(source = "failed_status", target = MappingConstants.NULL),//==在新代码中failed_status=null
            @ValueMapping(source = MappingConstants.ANY_REMAINING, target = "normal"),//==default=normal
    })
    LevelEnum toEnum(DisableStatus disableStatus);
}
public class TestMapperImpl implements TestMapper {
    @Override
    public LevelEnum toEnum(DisableStatus disableStatus) {
        if ( disableStatus == null ) {
            return LevelEnum.PASS;//--------
        }
        LevelEnum levelEnum;

        switch ( disableStatus ) {
            case able_status: levelEnum = LevelEnum.PERFECT;
                break;
            case failed_status: levelEnum = null;
                break;
            case normal_status: levelEnum = LevelEnum.normal_status;
                break;
            default: levelEnum = LevelEnum.normal;
        }
        return levelEnum;
    }
}
//生成的代码
@Mapper
public interface TestMapper {
    @ValueMappings({
            @ValueMapping(source = MappingConstants.ANY_UNMAPPED, target = "normal_status"),
    })
    LevelEnum toEnum(DisableStatus disableStatus);
}
 
@Component
public class TestMapperImpl implements TestMapper {
    @Override
    public LevelEnum toEnum(DisableStatus disableStatus) {
        if ( disableStatus == null ) {
            return null;
        } 
        LevelEnum levelEnum;
        switch ( disableStatus ) {
            default: levelEnum = LevelEnum.normal_status;
        }
        return levelEnum;
    }
}

2.3.1、自定义名称转换

可以通过删除或添加源枚举字符串的前后缀来映射目标枚举对象,这也是一种快捷方式。@EnumMapping#nameTransformationStrategy支持的参数有:suffix(添加源后缀)、stripSuffix(删除源后缀)、prefix(添加源前缀)、stripPrefix(删除源前缀)。

@Mapper
public interface TestMapper {
    @EnumMapping(nameTransformationStrategy = "stripSuffix", configuration = "_status")
    LevelEnum toEnum(DisableStatus disableStatus);
}
//比如原Enum值为
public enum LevelEnum { 
    able_status(1, "完美")
}
//生成的源码为
@Override
    public LevelEnum toEnum(DisableStatus disableStatus) {
        if ( disableStatus == null ) {
            return null;
        }
        LevelEnum levelEnum; 
        switch ( disableStatus ) {
            case able_status: levelEnum = LevelEnum.able;
            break;
            case disable_status: levelEnum = LevelEnum.disable;
            break;
            case normal_status: levelEnum = LevelEnum.normal;
            break;
            case failed_status: levelEnum = LevelEnum.failed;
            break;
            case ok_status: levelEnum = LevelEnum.ok;
            break;
            case fine_status: levelEnum = LevelEnum.fine;
            break;
            default: throw new IllegalArgumentException( "Unexpected enum constant: " + disableStatus );
        }
        return levelEnum;
    }

三、数据映射策略

3.1、@mappingControl属性映射优先级策略(不建议修改)

在mapStruct框架中可以从【全局-类-属性】等地方可以配置映射策略,@MappingConfig,@Mapper,@BeanMapping,@Mapping越往后的优先级越高,这4个注解都有mappingControl属性,默认值是MappingControl.class,可选值还有NoComplexMapping.class、DeepClone.class,用于控制每个字段属性映射的方式;

3.1.1、MappingControl.class的优先级逻辑如下:

  1. MappingControl.Use.DIRECT——直接复制具有相同属性类型的字段,但如果有自定义的映射配置@Mapping和导入了其他Mapper的自定义的映射,会将直接赋值覆盖;自定义的映射配置@Mapping优先级高于导入了其他Mapper的自定义的映射;
  2. MappingControl.Use.MAPPING_METHOD——属性类型不同的字段,会去查找将源属性的类型作为参数,将目标属性的类型作为返回的映射方法(包括自定义方法、抽象类实现方法和接口默认方法);
  3. MappingControl.Use.BUILT_IN_CONVERSION——如果不存在上述方法,查找内置转换方法,就像BigDecimal转String;
  4. MappingControl.Use.COMPLEX_MAPPING——如果内置转换方法不存在,将进行一些复杂转换,也就是结合现有的映射方法和内置转换,互相嵌套生成一个能够映射的方法;
  5. 如果都没有,则会自动生成子映射方法,就像上面的例子若是不指定TestPO到TestBO的接口方法,则也会主动生成;
  6. 若这也没法生成则编译就会报错了。

3.1.2、NoComplexMapping.class的优先级逻辑如下:

  1. MappingControl.Use.DIRECT——直接复制具有相同属性类型的字段,但如果有自定义的映射配置@Mapping和导入了其他Mapper的自定义的映射,会将直接赋值覆盖;自定义的映射配置@Mapping优先级高于导入了其他Mapper的自定义的映射;
  2. MappingControl.Use.MAPPING_METHOD——属性类型不同的字段,会去查找将源属性的类型作为参数,将目标属性的类型作为返回的映射方法(包括自定义方法、抽象类实现方法和接口默认方法);
  3. MappingControl.Use.BUILT_IN_CONVERSION——如果不存在上述方法,查找内置转换方法,就像BigDecimal转String;
  4. 如果都没有,则会自动生成子映射方法,就像上面的例子若是不指定TestPO到TestBO的接口方法,则也会主动生成;
  5. 若这也没法生成则编译就会报错了。

3.1.3、DeepClone.class的优先级逻辑如下:

  • MappingControl.Use.MAPPING_METHOD——属性类型不同的字段,会去查找将源属性的类型作为参数,将目标属性的类型作为返回的映射方法(包括自定义方法、抽象类实现方法和接口默认方法)。
//比如使用DeepClone的mappingControl,这样我们就只能进行MappingControl.Use.MAPPING_METHOD映射了
@Mapper(mappingControl = DeepClone.class)
public interface TestMapper {
 
    @Mapping(target = "localDateTime", dateFormat = "yyyy-MM-dd HH")
    TransformBO toTransformBO(TransformPO transformPO);
}

3.2、@TargetType泛型的应用-将映射目标类型传递给自定义映射器

就是在使用@Mapper#uses()时,使用的自定义映射器中的方法可以接受Class<T>对象,要使用 @TargetType标注。可用于一些通用设置。

@Data
public class BasePO {
    private Long id;
}
 @Data
public class TestFivePO {
    private TestFourPO test;
}
@EqualsAndHashCode(callSuper = true)
@Data
public class TestFourPO extends BasePO {
}

//-----
@Data
public class BaseBO {
    private Long id;
    private String name;
}
@Data
public class TestSevenBO {
    private TestSixBO test;
}
@EqualsAndHashCode(callSuper = true)
@Data
public class TestSixBO extends BaseBO {

}
------------源码实现--------------------------------

@Mapper(uses = {BaseMapper.class})
public interface TestMapper { 
    TestSevenBO testToBO(TestFivePO testPO);
}

@Mapper
public class BaseMapper {
    public <T extends BaseBO> T testToBO(BasePO basePO, @TargetType Class<T> baseBOClass)  {
        try {
            T t = baseBOClass.newInstance();
            t.setId(basePO.getId());
            return t;
        } catch (Exception e) {
            return null;
        }
    }
}
------------生成的源码实现--------------------------------
@Component
public class TestMapperImpl implements TestMapper {
    @Autowired
    private BaseMapper baseMapper;

    public TestMapperImpl() {
    }

    public TestSevenBO testToBO(TestFivePO testPO) {
        if (testPO == null) {
            return null;
        } else {
            TestSevenBO testSevenBO = new TestSevenBO();
            testSevenBO.setTest((TestSixBO)this.baseMapper.testToBO(testPO.getTest(), TestSixBO.class));
            return testSevenBO;
        }
    }
}

3.3、@Context将上下文ThreadLocal或状态对象传递给自定义方法

就是线程间共享值的一种方式,用了ThreadLocal特性。

@Data
public class ThreadLocalContext {
    private ThreadLocal<Object> threadLocal;
    public ThreadLocalContext() {
        threadLocal = new ThreadLocal<>();
    }
}
 
@Mapper
public class BaseMapper {
    public TestSixBO toTestSixBOWithContext(TestFourPO testFourPO, @Context ThreadLocalContext threadLocalContext) {
        TestSixBO testBO = new TestSixBO();
        testBO.setId(testFourPO.getId());
        testBO.setName((String) threadLocalContext.getThreadLocal().get());
        return testBO;
    }
}
 
@Mapper(uses = {BaseMapper.class})
public interface TestMapper {
    TestSevenBO testToBO(TestFivePO testPO, @Context ThreadLocalContext threadLocalContext);
}
 
@Component
public class TestMapperImpl implements TestMapper {
    @Autowired
    private BaseMapper baseMapper;
    @Override
    public TestSevenBO testToBO(TestFivePO testPO, ThreadLocalContext threadLocalContext) {
        if ( testPO == null ) {
            return null;
        }
        TestSevenBO testSevenBO = new TestSevenBO();
        testSevenBO.setTest( baseMapper.toTestSixBOWithContext( testPO.getTest(), threadLocalContext ) );
        return testSevenBO;
    }
}
 
ThreadLocalContext threadLocalContext = new ThreadLocalContext();
threadLocalContext.getThreadLocal().set("xx");
 
TestFivePO testFivePO = new TestFivePO();
TestFourPO testFourPO = new TestFourPO();
testFourPO.setId(1L);
testFivePO.setTest(testFourPO);
System.out.println(testMapper.testToBO(testFivePO, threadLocalContext));

---
TestSevenBO(test=TestSixBO(super=BaseBO(id=1, name=xx)))

3.4、@Qualifier区别相同参数类型和返回类型的映射方法

@Mapper
public class BaseMapper {
    public String toString1(String name) {
        return name + "1";
    }
    public String toString2(String name) {
        return name + "2";
    }
}
toString1、toString2方法的参数类型和返回类型相同,编译直接报错 
@Mapper(uses = {BaseMapper.class})
public interface TestMapper {
    TestSixBO testToBO(TestFourPO testPO); 
}

3.4.1、解决方案1-自定义注解ElementType.METHOD

@Qualifier
@Target(ElementType.METHOD) //ElementType.TYPE
@Retention(RetentionPolicy.CLASS)
public @interface StringToString1 {
}
@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface StringToString2 {
}
------------------------------
@Mapper(uses = {BaseMapper.class})
public interface TestMapper {
    @Mapping(target = "name", qualifiedBy = {StringToString1.class})//qualifiedBy属性
    TestSixBO testToBO(TestFourPO testPO);
}
 
@Mapper
public class BaseMapper {
    @StringToString1
    public String toString1(String name) {
        return name + "1";
    }
    @StringToString2
    public String toString2(String name) {
        return name + "2";
    }
}
------------------------生成的代码如下------------------------
@Component
public class TestMapperImpl implements TestMapper {
 
    @Autowired
    private BaseMapper baseMapper;
 
    @Override
    public TestSixBO testToBO(TestFourPO testPO) {
        if ( testPO == null ) {
            return null;
        }
 
        TestSixBO testSixBO = new TestSixBO();
        // 使用qualifiedBy中设置的注解的方法
        testSixBO.setName( baseMapper.toString1( testPO.getName() ) );
        testSixBO.setId( testPO.getId() );
 
        return testSixBO;
    }
}

3.4.2、解决方案2-自定义注解ElementType.TYPE

@Qualifier
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface StringToString1 {
}
 
@Qualifier
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface StringToString2 {
}
 
 
@Mapper
@StringToString1//----------------------
public class BaseMapper {
    public String toString1(String name) {
        return name + "1";
    }
}
 
@Mapper
@StringToString2
public class BaseMapper2 { 
    public String toString2(String name) {
        return name + "2";
    }
}
 
@Mapper(uses = {BaseMapper.class, BaseMapper2.class})
public interface TestMapper {
    @Mapping(target = "name", qualifiedBy = {StringToString2.class})
    TestSixBO testToBO(TestFourPO testPO);
}

3.4.3、解决方案3-@Named取代定义一个@Qualifier的接口

//若类上注解了@Named,mapper中引入了此类,要想使用引入类中自定义的映射方法,映射字段时就必须指定qualifiedByName
@Mapper
@Named("StringToString1")
public class BaseMapper {
    public String toString1(String name) {
        return name + "1";
    }
}
 
@Mapper
@Named("StringToString2")
public class BaseMapper2 {
    public String toString2(String name) {
        return name + "2";
    }
}
 
@Mapper(uses = {BaseMapper.class, BaseMapper2.class})
public interface TestMapper {
    @Mapping(target = "name", qualifiedByName = {"StringToString2"})//qualifiedByName属性
    TestSixBO testToBO(TestFourPO testPO);
 
}

四、集合策略

通过@Mapping#collectionMappingStrategy设置集合的映射策略:CollectionMappingStrategy.ACCESSOR_ONLY(默认)、CollectionMappingStrategy.SETTER_PREFERRED、CollectionMappingStrategy.ADDER_PREFERRED、CollectionMappingStrategy.TARGET_IMMUTABLE。

public class TestPOS {
 
    private List<TestPO> list; 
    public List<TestPO> getList() {
        return list;
    }
    public void addList(TestPO testPO) {
        this.list.add(testPO);
    }
}
 
public class TestBOS {
    private List<TestBO> list;
    public List<TestBO> getList() {
        return list;
    } 
    public void addList(TestBO testBO) {
        this.list.add(testBO);
    }
}
 
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface TestMapper {
    TestBO toBO(TestPO testPO);
    TestBOS toBOS(TestPOS testPOS);
}

4.1、使用默认集合策略CollectionMappingStrategy.ACCESSOR_ONLY

@Data
public class TestPOS {
    private List<TestPO> list;
} 
@Data
public class TestBOS {
    private List<TestBO> list;
}
 
@Mapper
public interface TestMapper {
    TestBO toBO(TestPO testPO);
    void toBOS(TestPOS testPOS, @MappingTarget TestBOS testBOS);
}
testBOS.getList().clear();
testBOS.getList().addAll( list )//先清空再添加

4.2、使用CollectionMappingStrategy.ADDER_PREFERRED策略

手动创建add方法,使用CollectionMappingStrategy.ADDER_PREFERRED

这里在介绍下List属性字段名的映射规则,

public class TestBOS {
    private List<TestBO> oneTest_;
    public List<TestBO> getOneTestList() {
        return oneTest_;
    }
    public void addOneTest(TestBO testBO) {//手动创建了此方法
        oneTest_.add(testBO);
    }
}

@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface TestMapper {
    @Mapping(target = "oneTest_", source = "tests") //这处的oneTest_要改成oneTestList才能正确调用addOneTest方法
    TestBOS toBean(TestPOS testPO);
}

自定义add方法,使用CollectionMappingStrategy.ADDER_PREFERRED

public class TestBOS {
    private List<Integer> oneTest_;
    public List<TestBO> getOneTestList() {
        return new ArrayList<>();
    }
    public void addOneTest(Integer integer) {//入参不一样
        oneTest_.add(integer);
    }
}
//testBOS.getOneTestList().addAll( list )
public class TestBOS {
    private List<Integer> oneTest_;
    public List<TestBO> getOneTestList() {
        return new ArrayList<>();
    }
    public void addOneTest(TestBO testBO) {//入参不一样
        oneTest_.add(testBO.getId().intValue());
    }
}
//testBOS.addOneTest( testPOToTestBO( test ) )

只有add方法,使用CollectionMappingStrategy.ADDER_PREFERRED策略

TestBOS testBOS = new TestBOS();
 
        if ( testPOS.getList() != null ) {
            for ( TestPO list : testPOS.getList() ) {
                testBOS.addList( toBO( list ) );
            }
        }

去掉add方法,使用CollectionMappingStrategy.ACCESSOR_ONLY策略

TestBOS testBOS = new TestBOS();
 
        if ( testBOS.getList() != null ) {
            List<TestBO> list = testPOListToTestBOList( testPOS.getList() );
            if ( list != null ) {
                testBOS.getList().addAll( list );
            }
        }
//以上结论是一样的,都是保持原集合内容不变,再增加新内容。

4.3、使用CollectionMappingStrategy.TARGET_IMMUTABLE策略

@Data
public class TestPOS {
    private List<TestPO> list;
} 
@Data
public class TestBOS {
    private List<TestBO> list;
}
 
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE)
public interface TestMapper {
    TestBO toBO(TestPO testPO);
    void toBOS(TestPOS testPOS, @MappingTarget TestBOS testBOS);
}
@Override
    public void toBOS(TestPOS testPOS, TestBOS testBOS) {
        if ( testPOS == null ) {
            return;
        }
        testBOS.setList( testPOListToTestBOList( testPOS.getList() ) );
    }
    //这个直接使用setter方式,会覆盖掉原集合的内容

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PMP项目管理主要学习内容是什么?

PMP项目管理是指根据美国项目管理学会(Project Management Institute&#xff0c;简称PMI)制定的项目管理知识体系和方法论进行项目管理的一种认证。PMP主要关注项目的规划、执行和控制等方面的知识和技能。 下面是PMP项目管理《PMBOK指南》第六版的主要学习内容&#xff1a; …

FFmpeg4.3.1+h264在windows下编译与VS2017项目集成

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》&#xff0c;结合我自己的工作学习经历&#xff0c;我准备写一个音视频系列blog。本文是音视频系…

【Grasshopper基础15】“右键菜单似乎不太对劲”

距离上一篇文章已经过去了挺久的&#xff0c;很长时间没有写GH基础部分的内容了&#xff0c;原因其一是本职工作太忙了&#xff0c;进度也有些落后&#xff0c;白天工作累成马&#xff0c;回家只想躺着&#xff1b;其二则是感觉GH基础系列基本上也介绍得差不多了&#xff0c;电…

【微服务部署】08-监控与告警

文章目录 1. PrometheusOperator1.1 优势1.2 配置脚本1.3 部署脚本 2. Granfana实现监控看板2.1 Granfana核心特性2.2 部署文件 3. prometheus-net收集自定义指标3.1 组件包3.2 使用场景 目前Kubernetes中最流行的监控解决方案是使用Prometheus和AlertManager 1. PrometheusOpe…

尚硅谷SpringMVC (5-8)

五、域对象共享数据 1、使用ServletAPI向request域对象共享数据 首页&#xff1a; Controller public class TestController {RequestMapping("/")public String index(){return "index";} } <!DOCTYPE html> <html lang"en" xmln…

INDEMIND:“大+小”多机协同,实现机器人商用场景全覆盖

随着商用清洁机器人进入越来越多的场景中&#xff0c;单一的中型机器人并不能有效覆盖所有区域&#xff0c;更加细分化的产品组合正在成为新的趋势。 产品形态的“新趋势” 在商用场景中&#xff0c;目前的商用清洁机器人几乎均是中大型的产品形态&#xff0c;较大的体型意味…

性能测试(测试系列10)

目录 前言&#xff1a; 1.什么是性能测试 1.1生活中遇到的软件问题 1.2性能测试的定义 1.3性能测试和功能测试有什么区别 1.4性能的好坏的区分 1.5影响一个软件性能的因素 2.为什么要进行性能测试 3.性能测试常见的术语以及衡量指标 3.1并发 3.2用户数 3.3响应时间 …

Vulnhub: Ragnar Lothbrok: 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.226 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.226 作者提示修改hosts文件 目录爆破 gobuster dir -u http://armbjorn -w /usr/share/wordlists/dirbuster/directory-l…

HFSS 3维曲线导入

HFSS 3维曲线导入 简介环境参考代码使用结果 简介 如图一所示&#xff0c;CST中可以通过导入和到出由任意点组成的曲线&#xff0c;但是HFSS中貌似不能导入&#xff08;如图二所示&#xff09;&#xff0c;如果我们要将matlab的产生的曲线的点的数据导入特变麻烦&#xff0c;特…

英码深元“三位一体”AI场景化解决方案,助力多地化工园区快速实现智慧化转型!

我国是世界公认的化工大国&#xff0c;同时也是崛起中的化工强国。近年来多起重大爆炸事故暴露出我国化工园区安全问题突出&#xff0c;特别是在安全风险管控数字化转型、智能化升级方面存在明显短板和不足&#xff0c;尤其突出的痛点&#xff1a;化工园区的日常管理方式较为粗…

【DRONECAN】(三)WSL2 及 ubuntu20.04 CAN 驱动安装

【DRONECAN】&#xff08;三&#xff09;WSL2 及 ubuntu20.04 CAN 驱动安装 前言 这一篇文章主要介绍一下 WSL2 及 ubuntu20.04 CAN 驱动的安装&#xff0c;首先说一下介绍本文的目的。 大家肯定都接触过 ubuntu 系统&#xff0c;但是我们常用的操作系统都是 Windows&#x…

python unitest自动化框架

以下举一个最简单的unitest实例&#xff0c;包含备注&#xff0c;自己拉取代码运行一次就知道原理了 import unittest import osclass TestSample(unittest.TestCase):classmethoddef setUpClass(cls) -> None:print(整个测试类只执行一次)def setUp(self) -> None:prin…

睿趣科技:抖音开网店卖玩具怎么样

近年来&#xff0c;随着社交媒体平台的飞速发展&#xff0c;抖音作为一款短视频分享应用也迅速崭露头角。而在这个充满创业机遇的时代背景下&#xff0c;许多人开始探索在抖音平台上开设网店&#xff0c;尤其是卖玩具类商品&#xff0c;那么抖音开网店卖玩具究竟怎么样呢? 首先…

QT的介绍和优点,以及使用QT初步完成一个登录界面

QT介绍 QT主要用于图形化界面的开发&#xff0c;QT是基于C编写的一套界面相关的类库&#xff0c;进程线程库&#xff0c;网络编程的库&#xff0c;数据库操作的库&#xff0c;文件操作的库…QT是一个跨平台的GUI图形化界面开发工具 QT的优点 跨平台&#xff0c;具有较为完备…

leetcode做题笔记107. 二叉树的层序遍历 II

给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 思路一&#xff1a;递归调换顺序 int** levelOrderBottom(struct TreeNode* root, int* returnSize, i…

技术干货 —— 手把手教你通过缓存提升 API 性能

许多开发者都希望能够彻底搞清楚 API 的工作方式&#xff0c;以及如何利用缓存 API 请求来提升业务&#xff0c;但是当这个需求进入实现阶段时&#xff0c;许多人就会发现手头并没有合适的工具和恰当的方法&#xff0c;所以我们今天就为大家做一个全面的讲解&#xff1a; ① 几…

数据结构(Java实现)-字符串常量池与通配符

字符串常量池 在Java程序中&#xff0c;类似于&#xff1a;1&#xff0c; 2&#xff0c; 3&#xff0c;3.14&#xff0c;“hello”等字面类型的常量经常频繁使用&#xff0c;为了使程序的运行速度更快、更节省内存&#xff0c;Java为8种基本数据类型和String类都提供了常量池。…

【数据结构】栈---C语言版(详解!!!)

文章目录 &#x1f438;一、栈的概念及结构&#x1f344;1、栈的概念定义&#x1f344;2、动图演示&#x1f332;入栈&#x1f332;出栈&#x1f332;整体过程 &#x1f438;二、栈的实现&#x1f438;三、数组结构栈详解&#x1f34e;创建栈的结构⭕接口1&#xff1a;定义结构…

R语言中缺失值的处理

目录 一.寻找缺失值 1.complete.cases() 2.manyNAs 二.缺失值的处理 1.直接删除 2.填补缺失值 一.寻找缺失值 1.complete.cases() #会展现缺失值 algae[!complete.cases(algae),] 2.manyNAs > manyNAs(algae) [1] 62 199 #表示第62条和第199条都有很多缺失值>m…

Systrace分析App性能学习笔记

学习Gracker Systrace系列文章&#xff0c;总结使用Systrace分析App性能的方法。推荐想通过Systrace学习Framework的同学&#xff0c;去看原文。 文章目录 概述Systrace使用流程Systrace 文件生成图形方式(不推荐)命令行方式 Systrace分析快捷键使用帧状态线程状态查看线程唤醒…
最新文章