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

高性能 Message ToJavaBean 工具 【easy.server.mapper】

easy.server.mapper 介绍

后端开发中,消息转换常见问题

  • Map 中的数据 转换成实体Bean
  • 数组 中的数据 转换成实体Bean
  • Servet 中的 param 转换成实体Bean

以上的三个问题是最常见的消息转换困扰。

以Map 举例

常见做法是

  1. 手动转换
Map<String,Object> dataMap;
Person person;person.setXX(dataMap.get("XXX"))..................

弊端是 操作繁琐

  1. 采用反射技术实现
   Map<String,Object> dataMap;final Class<Person> personClass = Person.class;Object person = personClass.newInstance();final Field[] fields = personClass.getDeclaredFields();for (Field field : fields) {// 特殊类型if (Modifier.isFinal(field.getModifiers())) {continue;}field.setAccessible(Boolean.TRUE);field.set(person, dataMap.get(field.getName()));}

操作简单,弊端是存在性能消耗

easy.server.mapper
解决实现

final Class<Person> personClass = Person.class;Person person = BeanCopier2Utils.getFullData2Object(Person.class).toMapConverter(dataMap);

操作简单,性能几乎同 手动转换

性能与反射对比

public class ReflectTest {public static boolean warmup = false;private Map<String, Object> data = new HashMap<>();private Map<String, Object> dataMap = new TreeMap<String, Object>() {{put("grep", 1234);put("name", "liaojl");put("age", 26);put("birthday", new Date());put("arr", Arrays.asList("2312", "12423"));put("arr2", data);put("array", new int[]{1, 2, 3});}};private Object[] dataArray = new Object[]{13, "liaojl", 26, new Date(), Arrays.asList("2312", "12423"), data, new int[]{1, 2, 3}};private final ICoreData2Object2<Person> data2Object2 = BeanCopier2Utils.getFullData2Object(Person.class);@org.junit.Ignore@Testpublic void test() throws Exception {testMapCustomize2();testArrayCustomize2();testReflect();warmup = true;testReflect();testMapCustomize2();testArrayCustomize2();}public static final int SIZE = 1000000;private void testMapCustomize2() {final long start = System.currentTimeMillis();Person person;for (int i = 0; i < SIZE; i++) {final Class<Person> personClass = Person.class;person = data2Object2.toMapConverter(dataMap);}final long end = System.currentTimeMillis();if (warmup)System.out.println("testMapCustomize2:" + (end - start));}private void testArrayCustomize2() {final long start = System.currentTimeMillis();Person person = null;for (int i = 0; i < SIZE; i++) {person = data2Object2.toArrayConverter(dataArray);}final long end = System.currentTimeMillis();if (warmup)System.out.println("testArrayCustomize2:" + (end - start));}private void testReflect() throws Exception {final long start = System.currentTimeMillis();for (int i = 0; i < SIZE; i++) {final Class<Person> personClass = Person.class;Object person = personClass.newInstance();final Field[] fields = personClass.getDeclaredFields();for (Field field : fields) {if (Modifier.isFinal(field.getModifiers())) {continue;}Ignore annotation = field.getAnnotation(Ignore.class);if (annotation != null) {continue;}field.setAccessible(Boolean.TRUE);field.set(person, dataMap.get(field.getName()));}}final long end = System.currentTimeMillis();if (warmup)System.out.println("testReflect:" + (end - start));}
}

在这里插入图片描述

easy.mapper性能消耗远远小于反射

easy.mapper 的使用

easy.mapper 介绍

注意项

  • 需要转换的Bean 必须包含一个无参构造方法
  • 需要转换的属性必须包含其Getter 方法
  1. 普通转换
@Data
public class Mapper {private byte b;private Byte b1;private boolean bool;private Boolean bool1;private char c;private Character c1;private short s;private Short s1;private int i;private Integer i1;private long l;private Long l1;private float f;private Float f1;private double d;private Double d1;private Date date;
}
// 转换MAP 到Person 并会对Person父类的属性进行扫描赋值
Person person1 = BeanCopier2Utils.getFullData2Object(Person.class).toMapConverter(dataMap);// 转换MAP 到Person 不会对Person父类的属性进行扫描赋值
Person person2 = BeanCopier2Utils.getData2Object(Person.class).toMapConverter(dataMap);// 转换Servlet 到Person 不会对Person父类的属性进行扫描赋值
Person person3 = BeanCopier2Utils.getFullData2WebObject(Person.class).toHttpServletRequestConverte(servelt);// 转换Servlet 到Person 并会对Person父类的属性进行扫描赋值
Person person4 = BeanCopier2Utils.getData2WebObject(Person.class).toHttpServletRequestConverte(servelt);
  1. 字段忽略
io.github.jinlongliao.easy.server.mapper.core.mapstruct2.annotation.Ignore2

提供 @Ignore2 使用标记的字段在转换时并不会进行赋值操作

demo

public class Person extends Grep implements IAnimal {private static final Logger log = LoggerFactory.getLogger(Person.class);@Ignore@Ignore2private int ignore;
}
  1. 特殊字段转换
  • 字段名称与bean 中属性名不对应
  • 数据类型,双方不匹配
  • 其他特殊类型

easy.mapper 默认对支持所有基础类型及其包装类,String 。详情查看 io.github.jinlongliao.easy.server.mapper.core.mapstruct2.converter.IDataConverter 实现。针对特殊类型转。提供两种转换方案

  • 重写 IDataConverter 实现

io.github.jinlongliao.easy.server.mapper.core.mapstruct2.converter.InnerConverter 接口 ,重写<T> T getT(Class<T> tClass, Object extra, Object data);
针对不支持类型时,会调用此方法,自己仅需要 依据 参数tClass 的类型进行判断 进行返回相应值,参数中的data 为消息中的值

  • 使用 io.github.jinlongliao.easy.server.mapper.core.mapstruct2.annotation.Mapping2
public @interface Mapping2 {/*** @return 映射源名称*/String sourceName() default "";/*** set Method Name* @return*/String putMethod() default "";/*** 针对非基本类型(String,byte,short,int,float,double,long,char)<br/>* 除外需要指定自定义 静态转换函数* eg:* <pre>*     public static Person person(Object obj){*         return (Person)obj;*     }* </pre>** @return 数据强转函数名称*/String converterMethod() default "";/*** @return Class Name* @see {@link Mapping2#converterMethod()}*/Class converterClass() default InnerConverter.class;
}
converterClass 手动指定转换自己的转换类,
converterMethod 设置转换函数的名称  ___ 此函数必须为 public+static ___ 。
putMethod  假设 bean 中的 属性a setter函数 不为 setA 通过 putMethod 可以指定新的setter函数
sourceName 假设 mesaage 中的名字不是属性a 的名字  sourceName 可以指定获取源的名字

提前编译 支持

  1. 手动指定

通过 io.github.jinlongliao.easy.server.mapper.utils.MapperStructConfig可以指定 自动生成消息转换实现的 class 及其源文件

      MapperStructConfig.setDev(true, "./target/", "./target/");
  1. 通过 maven 插件实现 maven-generator-plugin
    <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.10.1</version><configuration><annotationProcessorPaths><annotationProcessorPath><groupId>io.github.jinlongliao</groupId><artifactId>easy.server.mapper</artifactId><version>${project.version}</version></annotationProcessorPath><annotationProcessorPath><groupId>io.github.jinlongliao</groupId><artifactId>easy.server.extend</artifactId><version>${project.version}</version></annotationProcessorPath></annotationProcessorPaths></configuration></plugin><plugin><groupId>io.github.jinlongliao</groupId><artifactId>maven-generator-plugin</artifactId><version>${project.version}</version><executions><execution><phase>compile</phase><goals><goal>java</goal></goals></execution></executions><configuration><arguments><argument>${project.basedir}/target/classes/</argument><argument>${project.basedir}/target/generated-sources/annotations/</argument></arguments></configuration></plugin></plugins></build>

在这里插入图片描述

spring 支持

io.github.jinlongliao.easy.server.mapper.spring.BeanMapperFactoryBean设置spring 托管。既可在 spring 中 使用 IBeanMapper类型 进行操作,IBeanMapper封装了常见的类型操作推荐使用

public interface IBeanMapper {/*** 基于Map 的转换** @param tClass* @param data* @param <T>* @return T*/<T> T mapBeanMapper(Class<T> tClass, Map<String, Object> data);/*** 基于数组 的转换** @param tClass* @param data* @param <T>* @return T*/<T> T arrayBeanMapper(Class<T> tClass, Object[] data);/*** 基于javax.servlet 的转换** @param tClass* @param req* @param <T>* @return T*/<T> T servletBeanMapper(Class<T> tClass, javax.servlet.http.HttpServletRequest req);}

相关文章:

高性能 Message ToJavaBean 工具 【easy.server.mapper】

easy.server.mapper 介绍 后端开发中&#xff0c;消息转换常见问题 Map 中的数据 转换成实体Bean数组 中的数据 转换成实体BeanServet 中的 param 转换成实体Bean 以上的三个问题是最常见的消息转换困扰。 以Map 举例 常见做法是 手动转换 Map<String,Object> da…...

Web前端学习:三 - 练习

三六&#xff1a;风筝效果 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style type"text/css">*{margin: 0;padding: 0;}.d1{width: 200px;height: 200px;background: yellow;position…...

面试题:Android 中 Intent 采用了什么设计模式?

答案是采用了原型模式。原型模式的好处在于方便地拷贝某个实例的属性进行使用、又不会对原实例造成影响&#xff0c;其逻辑在于对 Cloneable 接口的实现。 话不多说看下 Intent 的关键源码&#xff1a; // frameworks/base/core/java/android/content/Intent.java public cla…...

Java数据类型与变量

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【JavaSE_primary】 文章目录字面常量数据类型变量整型变量字节型变量浮点数变量双精度浮点数单精度浮点数字符型变量布尔型变量空常量nu…...

Python为CANoe工程添加/删除DBC文件

前面文章我们对于通过COM来实现打开CANoe、导入CANoe配置工程、导入执行文件、启动CANoe软件和执行脚本;但是这只能完成最基本的功能调用,在实际得到使用过程中,特别是各家在推的CI/CD以及平台化,仅仅是实现这些功能是完全不够用的;比如dbc的添加和删除,这是我们非常必要…...

不同的产品经理特征和需要的能力

产品经理是一个管家&#xff0c;需要和各方沟通推动产品各个决策进展。 每天早上看看线上用户数据、看下今天要安排任务&#xff0c;接着就是和各方开会讨论推动产品实现。每天穿插于与 UI、用户以及完成自己的 todolist 中循环。如果公司体制完善&#xff0c;还要和运营、数据…...

webpack之处理样式资源

处理样式资源 本章节我们学习使用 Webpack 如何处理 Css、Less、Sass、Scss、Styl 样式资源 #介绍 Webpack 本身是不能识别样式资源的&#xff0c;所以我们需要借助 Loader 来帮助 Webpack 解析样式资源 我们找 Loader 都应该去官方文档中找到对应的 Loader&#xff0c;然后…...

Golang 接口笔记

基本介绍接口是一个数据类型&#xff0c;可以定义一组方法&#xff0c;但都不需要实现。并且interface中不能包含任何变量。到某个自定义类型要使用的时候&#xff0c;再根据具体情况把这些方法实现出来语法type 接口名 interface {method1(参数列表) 返回值列表method2(参数列…...

[计算机网络(第八版)]第二章 物理层(章节测试/章节作业)

章节作业 带答案版 选择题 (单选题)双绞线是用两根绝缘导线绞合而成的&#xff0c;绞合的目的是&#xff08; &#xff09;。 A. 减少干扰 B. 提高传输速度 C. 增大传输距离 D. 增大抗拉强度(单选题)在电缆中采用屏蔽技术可以带来的好处主要是&#xff08; &#xff09;。 A…...

[iOS 理解] Swift Runtime (1) 类

Warm up 先看一段代码&#xff1a; import ObjectiveCclass Obj {var x: Double 0 }let v: NSObjectProtocol Obj() as! NSObjectProtocol let result v.isKind(of: Obj.self) let size class_getInstanceSize(Obj.self)我们有一个没有继承 NSObject、没有遵循 NSObjectP…...

ASEMI低压MOS管20N06参数,20N06体积,20N06大小

编辑-Z ASEMI低压MOS管20N06参数&#xff1a; 型号&#xff1a;20N06 漏极-源极电压&#xff08;VDS&#xff09;&#xff1a;60V 栅源电压&#xff08;VGS&#xff09;&#xff1a;20V 漏极电流&#xff08;ID&#xff09;&#xff1a;20A 功耗&#xff08;PD&#xff0…...

常见前端基础面试题(HTML,CSS,JS)(四)

作用域和作用域链的理解 作用域 &#xff08;1&#xff09;全局作用域 最外层函数和最外层函数外面定义的变量拥有全局作用域所有未定义直接赋值的变量自动声明为全局作用域所有window对象的属性拥有全局作用域全局作用域有很大的弊端&#xff0c;过多的全局作用域变量会污染…...

RabbitMQ发布确认模式

目录 一、发布确认原理 二、发布确认的策略 &#xff08;一&#xff09;开启发布确认的方法 &#xff08;二&#xff09;单个确认模式 &#xff08;三&#xff09;批量确认模式 &#xff08;四&#xff09;异步确认模式 &#xff08;五&#xff09;如何处理异步未确认消…...

零基础的人如何入门 Python ?看完这篇文章你就懂了

第一部分&#xff1a;编程环境准备 零基础入门Python的话我不建议用IDE&#xff0c;IDE叫集成开发环境&#xff0c;这东西一般是专业程序员用来实战开发用的&#xff0c;好处很多&#xff0c;比如&#xff1a;调试、语法高亮、项目管理、代码跳转、智能提示、自动完成、单元测…...

Atcoder abc257 E

E - Addition and Multiplication 2 题意: 给你一个数字n表示你现在拥有的金额 然后给你1~9每个经营额所需要的成本, 设总经营额为x, 当前使用的经营额为y, 则每一次使用经营额时都有x10*xy 问, 如何在使用不大于成本数量的金额下, 使得经营额最高 例如: 5 5 4 3 8 1 6 7 …...

模拟退火算法改进

import numpy as np import matplotlib.pyplot as plt import math import random from scipy.stats import norm from mpl_toolkits.mplot3d import Axes3D # 目标函数 def Function(x, y): return -20 * np.exp(-0.2*np.sqrt(0.5*(x*xy*y)))\ -np.exp(0.5*(n…...

SpringBoot+HttpClient+JsonPath提取A接口返回值作为参数调用B接口

前言 在做java接口自动化中&#xff0c;我们常常需要依赖多个接口&#xff0c;A接口依赖B&#xff0c;C&#xff0c;D接口的响应作为请求参数&#xff1b;或者URL中的参数是从其他接口中提取返回值作获取参数这是必不可少的。那么怎么实现呢&#xff1f;下面就来介绍多业务依赖…...

JUC 之 CompletableFuture

——CompletableFuture Future Future 接口&#xff08;FutureTask 实现类&#xff09; 定义了操作异步任务执行的一些方法&#xff0c;如获取异步的执行结果、取消任务的执行、判断任务是否被取消、判断任务执行是否完毕例如&#xff1a; 主线程让一个子线程去执行任务&…...

7-vue-1

谈谈你对MVVM的理解 为什么要有这些模式&#xff0c;目的&#xff1a;职责划分、分层&#xff08;将Model层、View层进行分类&#xff09;借鉴后端思想&#xff0c;对于前端而已&#xff0c;就是如何将数据同步到页面上 MVC模式 代表&#xff1a;Backbone underscore jquer…...

OpenAPI SDK组件介绍

背景 公司成立以来&#xff0c;积累了数以万计的可复用接口。上层的SaaS业务&#xff0c;原则上要复用这些接口开发自己的业务&#xff0c;为了屏蔽调用接口的复杂性&#xff0c;基础服务开发了apisdk组件&#xff0c;定义了一套声明OpenAPI的注解、注解解析器&#xff0c;实例…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...

0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化

是不是受够了安装了oracle database之后sqlplus的简陋&#xff0c;无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话&#xff0c;配置.bahs_profile后也能解决上下翻页这些&#xff0c;但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可&#xff0c…...

嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)

目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 ​编辑​编辑 UDP的特征 socke函数 bind函数 recvfrom函数&#xff08;接收函数&#xff09; sendto函数&#xff08;发送函数&#xff09; 五、网络编程之 UDP 用…...