首页 文章 精选 留言 我的

精选列表

搜索[前端设计],共10000篇文章
优秀的个人博客,低调大师

实践 | Sentinel 扩展性设计

Sentinel 提供多样的 SPI 接口用于提供扩展的能力。用户可以在用同一个 sentinel-core 的基础上自行扩展接口实现,从而可以方便地给 Sentinel 添加自定义的逻辑。 初始化逻辑扩展机制 为了统一初始化的流程,我们抽象出了 InitFunc 接口代表 Sentinel 的一些初始化逻辑,如: 注册动态规则源(示例) 注册 StatisticSlot 回调函数(示例) 启动 Command Center 初始化心跳发送 我们可以通过注解设置 InitFunc 执行的优先级。当应用首次访问资源时,注册的初始化函数会依次执行。若希望手动提前触发初始化,可以在相应的位置(如 Spring Bean)调用 InitExecutor.doInit() 函数,重复调用只会执行一次。 Slot Chain 扩展机制 Sentinel 内部是

优秀的个人博客,低调大师

转换器(Converter)设计模式

在日常开发的时候,需要在对象之间进行值的 copy,如 POJO,DTO,VO,对象之间有相同的属性,想把一个对象的值 copy 到另一个对象中去,如 从数据库中查询出我们的 POJO 对象的数据,又有个对象是对 POJO 进行包装DTO,现在想把查询出来的 POJO 的值 copy 到 DTO 中相应的属性中去,之后再扩展其属性,对此,一般可以有三种方式进行解决:setter,转换器模式和反射,接下来就看下它们的一个区别: 在区分这三种方式之前,先要定义一下需要进行数据copy的两个类: Person类: @Getter @Setter @NoArgsConstructor @AllArgsConstructor @ToString public class Person { private String name; private int age; private String gender; private String job; } PersonDto类: @Getter @Setter @NoArgsConstructor @AllArgsConstructor @ToString public class PersonDto { private String name; private int age; private String gender; private String address; } 下面的演示都是用这两个类进行。 setter 通过 setter 方式 copy 数据比较方便,但是如果在很多地方需要进行数据的 copy,就显得有点重复了,当然可以写个工具,专门对该数据进行扩展,如下所示: public Person copy(PersonDto personDto) { Person person = new Person(); person.setName(personDto.getName()); person.setAge(personDto.getAge()); person.setGender(personDto.getGender()); return person; } 使用该方式比较简单。 转换器(Converter)模式 接下来就到该文章的主题了,可以使用转换器模式来解决该问题,先看下该模式的一个类图: 首先 Converter 类是一个顶层的接口,定义了公共的转换方法,不同类实现该接口来定义自己的转换规则 PersonConverter 类是继承于 Converter 的,定义了从 Person 到 PersonDto 和从 PersonDto 到 Person 的一个转换规则,并向外提供接口以供使用。接下来看下 顶层接口 Converter 类的定义: /** * 定义转换器 * @ Date:Created in 下午 4:44 2018/9/27 0027 */ public class Converter<T, U> { // 从 T 转换为 U private Function<T, U> fromDto; // 从 U 转换为 T private Function<U, T> fromEntity; public Converter(final Function<T, U> fromDto, final Function<U, T> fromEntity) { this.fromDto = fromDto; this.fromEntity = fromEntity; } public final U converterFromDto(final T dto){ return fromDto.apply(dto); } public final T converterFromEntity(final U entity){ return fromEntity.apply(entity); } public final List<U> batchConverterFromDto(final List<T> dtos){ return dtos.stream().map(this::converterFromDto).collect(Collectors.toList()); } public final List<T> batchConverterFromEntity(final List<U> entities){ return entities.stream().map(this::converterFromEntity).collect(Collectors.toList()); } } 然后在看看 Person 类的自定义转换规则,PersonConverter类: /** * Person 转换器 * @ Date:Created in 下午 5:00 2018/9/27 0027 */ public class PersonConverter extends Converter<PersonDto, Person> { public PersonConverter() { super(new PersonDtoFunction(), new PersonFunction()); } // 自定义转换规则 static class PersonDtoFunction implements Function<PersonDto, Person> { @Override public Person apply(PersonDto personDto) { // 可定制需要复制的属性 Person person = new Person(); person.setName(personDto.getName()); person.setAge(personDto.getAge()); person.setGender(personDto.getGender()); return person; } } // 自定义转换规则 static class PersonFunction implements Function<Person, PersonDto> { @Override public PersonDto apply(Person person) { // 可定制需要复制的属性 PersonDto dto = new PersonDto(); dto.setName(person.getName()); dto.setAge(person.getAge()); dto.setGender(person.getGender()); return dto; } } } 接下来进行测试一番: PersonDto 转换为 Person: Converter<PersonDto, Person> converter = new PersonConverter(); PersonDto personDto = new PersonDto("zhangsan", 23, "male", "chengdou"); Person person = converter.converterFromDto(personDto); System.out.println(person); // Person(name=zhangsan, age=23, gender=male, job=null) 批量PersonDto 转换为 Person: PersonDto pd1 = new PersonDto("AAA", 20, "male", "beijing"); PersonDto pd2 = new PersonDto("BBB", 21, "female", "shanghai"); PersonDto pd3 = new PersonDto("CCC", 22, "male", "chengdou"); List<PersonDto> dtos = Lists.newArrayList(pd1, pd2, pd3); List<Person> persons = converter.batchConverterFromDto(dtos); persons.forEach((x) -> System.out.println(x)); 结果: Person(name=AAA, age=20, gender=male, job=null) Person(name=BBB, age=21, gender=female, job=null) Person(name=CCC, age=22, gender=male, job=null) 从 Perosn 转换为 PersonDto: Person person1 = new Person("lisi", 25, "female", "java"); PersonDto personDto1 = converter.converterFromEntity(person1); System.out.println(personDto1); // PersonDto(name=lisi, age=25, gender=female, address=null) 批量从 Perosn 转换为 PersonDto: Person p1 = new Person("DDD", 25, "male", "java"); Person p2 = new Person("EEE", 26, "male", "python"); Person p3 = new Person("FFF", 27, "female", "C++"); List<Person> persons1 = Lists.newArrayList(p1, p2, p3); List<PersonDto> dtos1 = converter.batchConverterFromEntity(persons1); dtos1.forEach((x) -> System.out.println(x)); 结果: PersonDto(name=DDD, age=25, gender=male, address=null) PersonDto(name=EEE, age=26, gender=male, address=null) PersonDto(name=FFF, age=27, gender=female, address=null) 以上就是转换器模式的内容了,还是很好扩展的,不过,每个类需要自己定义一个转换规则,这个和写一个该类的转换工具方法有什么区别哦?? 反射 第三种 copy 数据的方法就是反射了,使用反射后,可以复制所有的类的数据,不用每个类专门写工具方法和转换器了,如下所示: import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * * @ Date:Created in 上午 9:27 2018/9/28 0028 */ public final class BeanDataConverter { public static void converterData(Object fromBean, Object toBean, String[] excludeProperties) throws InvocationTargetException, IllegalAccessException { Objects.requireNonNull(fromBean); Objects.requireNonNull(toBean); Objects.requireNonNull(excludeProperties); List<String> excludes = Arrays.stream(excludeProperties).map(String::toLowerCase).collect(Collectors.toList()); Method[] methods = fromBean.getClass().getMethods(); for (Method method : methods) { String methodName = method.getName(); if (!methodName.startsWith("get") || "getClass".equals(methodName) || excludes.contains(methodName.replaceFirst("get", "").toLowerCase())){ continue; } Class<?> returnType = method.getReturnType(); Object value = method.invoke(fromBean, new Object[]{ }); String setMethodName = String.format("set%s", methodName.replaceFirst("get", "")); try { Method setMethod = toBean.getClass().getMethod(setMethodName, returnType); setMethod.invoke(toBean, value); } catch (NoSuchMethodException e) { } } } } 测试一波: PersonDto personDto = new PersonDto("zhangsan", 23, "male", "chengdou"); Person p4 = new Person(); // 不排除属性,复制全部属性 String[] excludes = {}; BeanDataConverter.converterData(personDto, p4, excludes); System.out.println(p4); // Person(name=zhangsan, age=23, gender=male, job=null) Person p5 = new Person(); // 排除 name 属性,即不复制 name 属性的值: String[] excludes2 = {"name"}; BeanDataConverter.converterData(personDto, p5, excludes2); System.out.println(p5); // Person(name=null, age=23, gender=male, job=null) 以上就是使用 反射来进行copy数据了,可以看到反射是很强大的,适用于所有的数据copy,个人感觉比 转换模式要好些呢。

优秀的个人博客,低调大师

Spark SQL程序设计(2)

读取JSON数据 {"age":"45","gender":"M","occupation":"7","userID":"4","zipcode":"02460"} {"age":"1","gender":"F","occupation":"10","userID":"1","zipcode":"48067"} scala> val jsondf=spark.read.textfile("//user.json") 生成另外一个json文件 scala> josndf.write.mode("overwrite").json("//user2.json") 查看DF scala>userDF.show(4) scala> userDF.printSchema root |-- age: string (nullable = true) |-- gender: string (nullable = true) |-- occupation: string (nullable = true) |-- userID: string (nullable = true) |-- zipcode: string (nullable = true) 修改DF/DS元信息

优秀的个人博客,低调大师

JavaScript海报定时弹框设计

tml代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>网页的顶端海报弹框操作</title> </head> <body> <div id="ad" style="width:100%;display: none;"> <img src="img/banner1.jpg" width="100%" /> </div> </body> </html> JavaScript代码如下: <script type="text/javascript"> //记录次数 var i=0; //定时器id var timer; onload=function(){ //设置定时器 间隔4秒后展示图片 timer=setInterval(showAd,4000); } //展示广告方法 展示2秒之后隐藏 function showAd(){ //展示的次数加1 i++; //若i=3 清空由setinterval设置的定时器 if(i==3){ clearInterval(timer); } //1.获取广告 var divObj=document.getElementById("ad"); //2.修改广告的样式 将其显示 divObj.style.display="block"; //3.2秒之后隐藏 只执行一次 setTimeout(hideAd,2000); } //隐藏广告 function hideAd(){ //1.获取广告 var divObj=document.getElementById("ad"); //2.修改样式 将其隐藏 divObj.style.display="none"; } </script> 图片素材: banner1 作者: 杨校 出处:http://www.cnblogs.com/xiaoxiao5016 分享是快乐的,也见证了个人成长历程,文章大多都是工作经验总结以及平时学习积累,基于自身认知不足之处在所难免,也请大家指正,共同进步。 本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 如有问题, 可邮件(397583050@qq.com)咨询。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册