死磕 Java 精心打造的 Java 进阶类系列教程,希望可以帮助到您。 更多死磕系列

  • 上一个死磕Java专栏【死磕NIO】(当然写的不是很好,争取今年将它重写一遍)是**【死磕Netty】**的铺垫,对于我们Java程序员而言,我们在实际开发过程一般都不会直接使用JavaNIO作为我们的网络编程框架,因为写出一套高质量的JavaNIO程序并不是一件容易的事,除了JavaNIO固有的复杂性和bug之外,作为NIO服务端,我们要处理的事情太多了,如网络闪断、客户端认证、消息编解码、半包读写,客户端一样也有很多复杂的事情要处理,所以如果我们对JavaNIO没有足够了解,没有足够的网络编程经验的话,利用JavaNIO来编写一个高性能的稳定网络编程框架并不是一件容易的事。所以我们一般都不

    2023-10-06
    阅读(505)
  • Java9提供了新的HTTP客户端(HttpClient)来处理HTTP调用,但是那时还处于孵化器阶段,经历了Java9、Java10,终于在Java11版本正式“转正”。为什么要提供全新的HTTP客户端Java11引入新的HTTP客户端的原因是为了解决旧的HttpURLConnection类存在的多个问题和局限性。HttpURLConnection存在如下几个局限性:不直观的API设计:HttpURLConnection的API设计过于复杂,对于新手比较难上手,例如我们必须手动处理输入和输出流,以及错误处理。不支持HTTP/2:HttpURLConnection仅支持HTTP/1.1,不支持

    2023-11-28
    阅读(10)
  • 局部变量类型推断是Java10引入的,通过使用var关键字允许编译器推断变量的类型,这大大简化了Java代码的编写。但是在Java10中我们是不能在Lambda参数使用var,这在Java11中得到了改进。关于局部变量类型推断参考文章:Java10新特性—局部变量类型推断在Java11之前,我们是不能在Lambda表达式的参数中使用var,例如:Function<String,String>func=(varstr)->str.toUpperCase();这种写法在Java11之前是非法的,但是在Java11中是合法的,在这个例子中,str的类型被推断为String。由于可以

    2023-11-28
    阅读(12)
  • Optional是在Java8中引入用于处理可能为null的对象。它提供了一种更优雅的方法来减少NullPointerException的可能性。为了我们能够方便地使用Optional,Java11对它进行了增强,主要是新增了一个API:方法描述isEmpty()判断容器是否为空,如果包含的值不存在,则返回true。isEmpty()如果Optional对象为空,isEmpty()返回true,它是isPresent()的对立面。Optional<String>optional=Optional.empty();if(optional.isEmpty()){System.out.p

    2023-11-28
    阅读(9)
  • Java11对java.nio.file.Files新增了三个API:readString():读取文件内容writeString():写入文件内容isSameFile():比较两个路径是否指向文件系统中的同一个文件这三个API简化了我们对文件的操作,使得操作文件变得更加简便了。readString()该方法可以一次性读取文件的全部内容,避免了以前我们使用BufferedReader类的繁琐过程。@TestpublicvoidreadStringTest()throwsIOException{Pathpath=Paths.get("skjava.txt");Stringco

    2023-11-27
    阅读(20)
  • String绝对是Java中最常用的一个类了,String类的方法使用率也都非常的高,Java11为了更好地处理字符串,引入了几个新的API:方法名描述isBlank()检查字符串是否为空或仅包含空白字符lines()分割获取字符串流(Stream)strip()去除字符串首尾的空白字符repeat(n)复制字符串isBlank()用于判断字符串是否为空或者只包含空白字符。"".isBlank();//true"".isBlank();//true"\n\t".isBlank()//true"skjava.com"

    2023-11-27
    阅读(16)
  • Java10是Java历史上的一个较小的版本,发布于2018年3月。JEP286:局部变量类型推断Java10中引入了var关键字,允许开发者在声明局部变量时不必显式声明变量的类型,编译器会自动根据变量的初始值推断变量的类型。这使得代码更加简洁,尤其是在处理泛型时。例如:varlist=newArrayList<String>();//编译器推断list是ArrayList<String>类型varstream=list.stream();//编译器推断stream是Stream<String>类型**需要注意的是,****var**只能用在局部变量上,不能

    2023-11-26
    阅读(23)
  • Java9开始引入不可变集合,我们通过of()即可创建一个不可变集合(详情见:Java9新特性—新增只读集合和工厂方法)。但是有时候我们需要利用现有集合来创建一个不可变副本,然而Java9并没有提供该方法,所以Java10对其进行了增强。Java10新增copyOf()用于创建现有集合的不可变副本。分为以下两种情况:如果原集合已经是不可变的,那么则返回原集合,如果元集合不是不可变的,那么则创建一个新的对象。如下:@TestpublicvoidcopyOfTest(){varlist1=List.of("死磕Java新特性","死磕Java并发",&quo

    2023-11-26
    阅读(16)
  • 局部变量类型推断是Java10中引入的一项重要特性,通过使用var关键字,允许我们在声明局部变量时省略显式类型。类型推断意味着编译器会查看变量的初始化器并推断出变量的类型。产生背景刚刚学Java语法时,我们就被告知:在Java中,所有的变量在使用前必须声明,所以我们就有了如下代码:inti=10;Stringstr="死磕Java新特性";List<String>list=newArrayList<>();甚至很多小伙伴已经养成了习惯,在声明变量时永远都是从左写到右,即先写变量类型,然后变量名,最后初始化,这样写有问题吗?没有问题,但是比较繁琐,简单

    2023-11-26
    阅读(22)
  • Java9发布于2017年9月22日。JEP261:模块系统在传统的Java应用中,类路径的机制限制了封装性。即使类被标记为package-private,也可以被同一个类路径中的其他任意代码访问。而且随着应用程序规模的增长,类路径依赖变得越来越复杂。Java为了能够改进大型应用程序和库的封装性、可维护性和性能,在Java9版本引入模块系统。模块系统是Java平台架构的一次重大变革,它旨在解决长期以来Java应用所面临的一些结构性问题,特别是在大型系统和微服务架构中。其主要内容是:模块化JDK:JDK被划分为一系列的模块,使得可以只需要引入必需的JDK模块,减少了应用程序的体积。模块路径:取代

    2023-11-26
    阅读(21)
  • CompletableFuture是Java8中引入用于处理异步编程的核心类,它引入了一种基于Future的编程模型,允许我们以更加直观的方式执行异步操作,并处理它们的结果或异常。关于CompletableFuture的核心原理请阅读:Java8新特性—深入理解CompletableFuture。但是在实际使用过程中,发现CompletableFuture还有一些改进空间,所以Java9对它做了一些增强,主要内容包括:新的工厂方法支持超时和延迟执行支持子类化新的工厂方法在Java9中CompletableFuture新增了三个工厂方法。completedFuture()此方法用于创建一个已经完

    2023-11-26
    阅读(22)
  • Java8是Java历史上一个重大的版本更新,发布于2014年3月18日。JEP126:Lambda表达式Lambda表达式是Java8新特性中最重要且最显著的一个,为Java增加了函数式编程的能力,使得代码变得更加简洁和易读。Lambda表达式主要用于简化匿名内部类的实现。Lambda表达式的基本语法:(parameters)->expression或(parameters)->{statements;}parameters:是Lambda表达式的参数列表,可以为空或包含一个或多个参数。->:是Lambda操作符,用于将参数和Lambda主体分开。expression:是L

    2023-11-25
    阅读(42)
  • 引言Base64编码是一种用64个字符表示二进制数据的方法,它使用一组64个可打印字符来表示二进制数据,每6个比特位为一个单元,对应某个可打印字符。注意它并不是一种加密算法,所以Base64常用于在不支持二进制数据的系统间传输二进制数据。但是,Java8之前并不支持Base64,我们需要依赖第三方库如ApacheCommonsCodec或者在JDK内部类sun.misc.BASE64Encoder和sun.misc.BASE64Decoder等不推荐使用的方式来实现Base64编码解码。为了能够提供一个更加标准的、更加安全的方法来进行Base64的编码和解码操作,使得开发者们不再需要依赖外部库

    2023-11-25
    阅读(34)
  • 理解泛型在讨论类型推断之间,我们有必要先理解下泛型。泛型是Java1.5引入的特性,主要目的是增强Java程序的类型安全性,同时提高代码的重用性和可读性。比如,在泛型引入之前,所有的集合都是保存Object类型的,很容易意外地将错误类型的对象放入集合中,这可能导致运行时异常。Listlist=newArrayList();list.add("skjava.com");list.add(1234);同时,从集合中取出的对象也是Object类型的,需要我们显式强制转换为适当的类型:Stringstr=(String)list.get(0);通过引入泛型可以解决这两个问题:泛型通

    2023-11-25
    阅读(29)
  • 注解,我相信小伙伴应该都使用过,Java从Java5开始引入该特性,发展到现在已经是遍地开花了,且在很多框架都得到了广泛的使用,用来简化程序中的配置。但是,在Java8之前,注解仅能用于声明(如方法、类、字段)。这意味着注解无法直接应用于类型本身(例如,方法的返回类型、变量的类型等等)。这种限制减少了注解在代码分析、检查及处理中的潜在用途(虽然不会产生什么问题)。为了提升注解的功能,使其能够更全面地支持各种编程场景(如增强静态代码分析、提供更丰富的编译时检查等等),Java8引入了类型注解。类型注解可以用在哪些地方?类型注解扩展了注解的应用范围,使其不仅能应用于声明,还能应用于任何使用类型的地

    2023-11-25
    阅读(29)
  • Java接口我相信所有学过Java的人一定都知道,而且我也相信99%的人一定都背过这个面试题:Java接口和抽象类的区别是什么?答案都是什么接口方法不能有实现,都是抽象的,接口的方法都默认为public修饰等等之类的,这些在Java8之前是正确的,但是随着Java的发展,它不再是正确的了。这篇文章就跟着大明哥一起来探索Java接口的进化之路。出生:Java1.0引入接口Java1.0,作为Java语言的最初版本,于1996年发布。在这个版本中,Java引入了接口(Interface)这一概念,标志着面向对象编程(OOP)在Java中的深入应用。在Java1.0中,接口被定义为完全抽象的,它具备

    2023-11-19
    阅读(53)
  • 对于大多数小伙伴而言,其实是很少使用只读集合的,甚至有蛮大一部分小伙伴可能都没有听过这个,大部分使用集合无非就是如下两种方式:List<String>list=newArrayList();orList<String>list=getXxxList();其实只读集合在编程中还是蛮有用处的,首先只读就意味着不可变,即线程安全,在使用它的过程中我们无需使用同步机制来保护其内部状态。同时只读集合通常比可变集合更加高效。因为它们是不可变的,不需要支持修改操作,因此在内部数据结构上可以进行优化,这可以提高数据访问的速度和降低内存开销。这篇文章我们来看看Java引入的一项重要特性—

    2023-11-19
    阅读(39)
  • 我们知道Java8强势推出StreamAPI,让我们能够以一种更加简洁、易读、高效的方式来处理集合数据,大大地提高了我们的生产力,在文章StreamAPI对元素流进行函数式操作,大明哥对StreamAPI做了非常详细的说明,各位小伙伴可以去阅读阅读。为了提高StreamAPI的灵活性和性能,Java9对StreamAPI做了一些增强,主要体现在以下几个方法:新增ofNullable()重载iterate()新增dropWhile()和takeWhile()新增ofNullable()ofNullable()用于创建一个Stream,其中包含一个非空元素或者为空。该方法的主要目的是简化处理可能包

    2023-11-19
    阅读(47)
  • 只要学过Java的小伙伴都需要知道,资源用了是要关闭的,否则会发生大麻烦,轻则被骂,重则滚蛋,不要以为是玩笑话,很严重的!!Java7之前,资源需要手动关闭我相信有5年以上工作经验的小伙伴一定写过这样的代码:FileInputStreamfileInputStream=null;try{fileInputStream=newFileInputStream("file.txt");//读取文件内容}catch(IOExceptione){//处理异常}finally{if(fileInputStream!=null){try{fileInputStream.close();}

    2023-11-19
    阅读(43)
  • 在文章Optional解决NullPointerException大明哥详细的介绍如何利用Optional来解决NullPointerException。然后Java9对它又进行了一些增强,以提高其实用性和易用性。主要是增加三个方法:or()ifPresentOrElse()stream()下面就一一介绍这三个方法。or()or()方法定义如下:publicOptional<T>or(Supplier<?extendsOptional<?extendsT>>supplier);方法接受一个Supplier,当Optional为空时,将执行该Supplier,

    2023-11-19
    阅读(43)
  • 大明哥相信绝大数小伙伴一定看过Java8的String源码,对于它的底层存储结构一定不陌生,在Java9之前,String的底层存储结构都是char[]:publicfinalclassStringimplementsjava.io.Serializable,Comparable<String>,CharSequence{//Thevalueisusedforcharacterstorage.privatefinalcharvalue[];}每个char都以2个字节存储在内存中。然而Oracle的JDK开发人员调研了成千上万个应用程序的heapdump信息,他们注意到大多数字符串都

    2023-11-19
    阅读(35)
  • 从我们一接触接口开始我们就知道JavaInterface接口中是不能定义private私有方法的,但是这个在Java9中被打破了。为了减少代码重复,提高代码的可维护性,Java9接口支持私有方法,这样做有几个好处:接口更好地演化:在不破坏现有实现的前提下,我们可以向接口中添加默认方法,这是接口演化的一种方式。然后,如果默认方法之间有重复代码,就会导致代码容易重复。在接口中定义私有方法,可以将这些重复的代码抽离出来,使接口更容易维护和扩展。代码复用:将重复的,通用的功能封装在私有方法中,私有方法可以被接口中的其他方法调用,这有助于减少代码重复和提高代码的可维护性。防止子类滥用:由于私有方法只能在

    2023-11-19
    阅读(49)
  • 熟悉Python和Scala之类的语言的小伙伴应该知道,他们在很早就已经有了交互式编程环境REPL(Read-Eval-PrintLoop),REPL以交互式的方式对语句和表达式进行求值。REPL提供了一个交互式的方式,允许开发人员输入代码,立即执行它,无需编译,然后查看执行结果。Java在Java9引入Java版的REPL工具:JavaShell。什么是JShellJavaShell是Java在Java9中引入的一个交互式编程工具,它可以让开发人员能够在一个命令行界面即时编写、编辑和执行Java代码片段,而无需创建和编译传统的Java源代码文件。JShell的目的是提供一个更快速、更便捷的方

    2023-11-19
    阅读(39)
  • Java9中最大的特性毫无疑问就是模块化,其实模块化的概念在Java7的时候就已经提出来了,由于它的复杂性,不断跳票,从Java7到Java8,最后Java9终于姗姗来迟,它的出现犹如壮士断腕。那模块化到底是什么呢?在实际开发中又有什么用呢?这篇文章大明哥带你彻底了解Java9的模块化。什么是模块化模块是Java9中新增的一个组件,官方是这么定义它的:**一个被命名的,代码和数据的自描述集合。(themodule,whichisanamed,self-describingcollectionofcodeanddata)。**怎么理解呢?我们可以简单地将它理解为package的上一级单位,是多个

    2023-11-19
    阅读(53)
  • Java8中两个最为重要的的更新:第一个是Lambda表达式,另外一个就是StreamAPI,这篇文章就来跟随大明哥彻底了解强大的StreamAPI。什么是StreamAPIStreamAPI是Java8引入的一个用于对集合数据进行函数式编程操作的强大的库。它允许我们以一种更简洁、易读、高效的方式来处理集合数据,可以极大提高Java程序员的生产力,是目前为止对Java类库最好的补充。StreamAPI的核心思想是将数据处理操作以函数式的方式链式连接,以便于执行各种操作,如过滤、映射、排序、归约等,而无需显式编写传统的循环代码。下面是StreamAPI的一些重要概念和操作:Stream****(

    2023-11-16
    阅读(74)
  • 接口默认方法在Java8之前,接口中可以申明方法和变量的,只不过变量必须是public、static、final的,方法必须是public、abstract的。我们知道接口的设计是一项巨大的工作,因为如果我们需要在接口中新增一个方法,需要对它的所有实现类都进行修改,如果它的实现类比较少还可以接受,如果实现类比较多则工作量就比较大了。为了解决这个问题,Java8引入了默认方法,默认方法允许在接口中添加具有默认实现的方法,它使得接口可以包含方法的实现,而不仅仅是抽象方法的定义。默认方法允许接口在不破坏实现类的情况下进行演进。这对于标准化库的维护和扩展非常重要,因为可以添加新的方法来满足新的需求,而

    2023-11-16
    阅读(61)
  • Java8之前如何使用重复注解在Java8之前我们是无法在一个类型重复使用多次同一个注解,比如我们常用的@PropertySource,如果我们在Java8版本以下这样使用:@PropertySource("classpath:config.properties")@PropertySource("classpath:application.properties")publicclassPropertyTest{}编译会报错,错误信息是:Duplicateannotation。那怎么解决这个问题呢?在Java8之前想到一个方案来解决Duplicatean

    2023-11-16
    阅读(54)
  • 通过前一篇文章(日期时间API)我们知道如何在Java8中得到我们需要的日期和时间,但是有时候我们需要将日期和时间对象转换为字符串又或者将字符串解析为日期时间对象,这个时候我们需要用到Java8提供的日期时间格式化工具:DateTimeFormatter。DateTimeFormatterDateTimeFormatter用于格式化和解析日期和时间,它能够轻松地将日期时间对象转换为字符串以及将字符串解析为日期时间对象。而且它是不可变的,线程安全的。创建DateTimeFormatterDateTimeFormatter提供了ofPattern()静态方法用于构建DateTimeFormatte

    2023-11-16
    阅读(65)
  • 为什么Java8要重新设计日期时间API作为Java开发者你一定直接或者间接使用过java.util.Date、java.util.Calendar、java.text.SimpleDateFormat这三个类吧,这三个类是Java用于处理日期、日历、日期时间格式化的。由于他们存在一些问题,诸如:线程不安全:java.util.Date和java.util.Calendar线程不安全,这就导致我们在多线程环境使用需要额外注意。java.text.SimpleDateFormat也是线程不安全的,这可能导致性能问题和日期格式化错误。而且它的模式字符串容易出错,且不够直观。可变性:java.uti

    2023-11-16
    阅读(47)
  • NullPointerException是我们最常见也是最烦的异常处理,它非常常见,处理起来有很简单,但是你又不得不去处理,超级烦。引言我们先看一个简单的例子:@DatapublicclassUser{privateStringname;privateAddressaddress;}@DatapublicclassAddress{privateStringprovince;privateStringcity;privateStringarea;}如果我们需要获取用户所在城市,我们会这么写:publicstaticStringgetUserCity(Useruser){returnuser.ge

    2023-11-16
    阅读(78)
  • 在前面我们了解了Lambda表达式,它能够简化我们的程序,但是它还不是最简单的,Java8引入了方法引用可以对Lambda表达式再进一步简化。什么是方法引用我们先看一个例子。首先定义一个Student类:publicclassStudent{privateStringname;privateIntegerage;publicstaticintcompareByAge(Studenta,Studentb){returna.getAge().compareTo(b.getAge());}}Student中含有一个静态方法compareByAge(),它是用来比较年龄的。现在需要实现一个需求,有一批

    2023-11-16
    阅读(52)
  • 在文章Lambda表达式提过,Lambda能够简化的一个依据就是函数式接口,这篇文章我们就来深入了解函数式接口。什么是函数式接口函数式接口是一个只有一个抽象方法的接口,最开始的时候也叫做SAM类型的接口(SingleAbstractMethod)。它具有两个特点:只包含一个抽象方法:函数式接口只能有一个抽象方法,但可以包含多个默认方法或静态方法。用**@FunctionalInterface**注解标记:该注解不强制,但通常会使用它来标记该接口为函数式接口。这样做可以让编译器检查接口是否符合函数式接口的定义,以避免不必要的错误。Java引入函数式接口的主要目的是支持函数式编程范式,也就是Lam

    2023-11-16
    阅读(70)
  • 什么是Lambda表达式Lambda表达式是在Java8中引入,并且被吹捧为Java8最大的特性。它是函数式编程的的一个重要特性,标志着Java向函数式编程迈出了重要的第一步。它的语法如下:(parameters)->expression或者(parameters)->{statements;}其中parameters:是Lambda表达式的参数列表,可以为空或包含一个或多个参数。->:是Lambda操作符,用于将参数和Lambda主体分开。expression:是Lambda表达式的返回值,或者在主体中执行的单一表达式。{statements;}:是Lambda主体,包含了

    2023-11-16
    阅读(80)
  • 上篇文章(【死磕NIO】—详解Selector)详细介绍了Selector的核心原理和使用方法,这篇文章我们来深入了解Selector的源码,主要讲三个最常用的方法open(),register()和selector()。open()调用Selector.open()方法会创建一个Selector实例。publicstaticSelectoropen()throwsIOException{returnSelectorProvider.provider().openSelector();}SelectorProvider是一个抽象类,它提供了创建Selector、ServerSocketChan

    2023-11-14
    阅读(50)
  • 前面4篇文章深入分析了NIO三大组件中的两个:Buffer和Channel:【死磕NIO】—深入分析Buffer【死磕NIO】—深入分析Channel和FileChannel【死磕NIO】—跨进程文件锁:FileLock【死磕NIO】—探索SocketChannel的核心原理这篇文章则介绍第三个组件:Selector。相比Buffer和Channel而言,Selector对于NIO来说显得更加重要,因为它是NIO实现多路复用的核心,它的使命就是完成IO的多路复用。Selector简介在前一篇文章:【死磕NIO】—ServerSocketChannel的应用实例,大明哥分析了ServerSock

    2023-11-14
    阅读(61)
  • 在上篇文章(Netty入门—ChannelHandler,Netty的数据加工厂)提到ChannelHandler虽然是一个好的打工人,但是在我们实际业务线中,他不可能一个人干所有的活啊,毕竟都21世纪了,我们是要讲究分工的。所以Netty就需要一个好的组织者将这些ChannelHandler组织起来,形成一个条完整,高效的业务线,这个组织者就是ChannelPipeline。ChannelPipeline概述pipeline翻译为管道、流水线,在Netty这个大工厂中,ChannelPipeline就像一条流水线,数据流过ChannelPipeline,被一步一步地加工,最后得到一个成熟的工

    2023-11-08
    阅读(170)
  • 经过前面几篇文章的介绍,我们掌握了Netty的5个核心组件,但是有了这5个核心组件Netty这个工厂还是无法很好的运转,因为缺少了一个最核心的组件:EventLoop,它是Netty中最最核心的组件,也是Netty最精华的部分,它负责Netty中I/O事件的分发,也就是说,这个事件谁来做,它说了算。再谈Reactor线程模型要想弄明白Netty的EventLoop,我们就必须先理解Reactor线程模型,Netty高性能的奥秘就在于Reactor线程模型。线程模型的优劣直接决定了系统的性能,一个好的线程模型比不好的线程模型性能会高出好多倍。而目前主流的网络框架选择的线程模型几乎都是I/O多路复

    2023-11-08
    阅读(97)
  • CompletableFuture是Java8中引入用于处理异步编程的核心类,它引入了一种基于Future的编程模型,允许我们以更加直观的方式执行异步操作,并处理它们的结果或异常。Future的局限性学过Java并发或者接触过异步开发的小伙伴应该都知道Future,通过Future我们能够知道异步执行的操作结果,它提供了isDone()来检测异步是否已经完成,也可以通过get()方法来获取计算结果。在异步计算中,Future确实是一个非常优秀的接口,但是它依然存在一些局限性:缺乏回调机制:Future没有内置的回调机制,这就意味着我们必须轮询Future对象来检查任务是否完成,而不是等待通知。

    2023-11-04
    阅读(138)
  • 我相信小伙伴一定看过多篇怎么去掉if...else的文章,也知道大家都很有心得,知道多种方法来去掉if...else,比如Option,策略模式等等,但我相信大明哥这篇文章绝对是最全,最完备怎么去掉if...else的文章,里面有些方法我相信有小伙伴肯定不知道,我也不卖关子,直接进入主题,如何干掉if...else。方法一:提前return假如有如下代码:if(condition){doSomething;}else{return;}这种代码我们一般采用提前return的方式,去掉不必要的else。if(!condition){return}doSomething;这种方法一般只适合分支结构很

    2023-11-02
    阅读(128)
  • 在《阿里巴巴Java开发规范》手册最后一节的应用分层中推荐了应用系统的分层结构。我比较赞同这种分层结构,这种分层结构带来了诸多好处,但是有一个麻烦之处就是分层领域模型,也就是我们所说的各种O,比如DTO、POJO、DO、VO等等,这样就导致我们项目中存在各种属性相同的xxO,对于有些工作经验的小伙伴们来说知道使用BeanUtils来实现属性复制,但是对于工作经验不是很多的小伙伴可能就是各种set和get了。这是非常尴尬的一件事。Spring的BeanUtils虽然可以满足我们大部分的需要,但是只能赋值属性名相同且类型一致的两个属性,比如VO里面的beginTime是String类型的,而BO里

    2023-10-23
    阅读(136)
  • 通过上篇文章(Netty入门—Channel,把握Netty通信的命门),我们知道Channel是传输数据的通道,但是有了数据,也有数据通道,没有数据加工也是没有意义的,所以今天学习Netty的第四个组件:ChannelHandler,它是Netty的数据加工厂。ChannelHandler在上篇文章(Netty入门—Channel,把握Netty通信的命门)中,大明哥提到:EventLoop接收到Channel的I/O事件后会将该事件转交给Handler来处理,这个Handler就是ChannelHandler。ChannelHandler它是对Netty输入输出数据进行加工处理的载体,它包

    2023-10-18
    阅读(244)
  • 上篇文章(Netty入门—ByteBuf,Netty数据传输的载体),我们了解了Netty的数据是以ByteBuf为单位进行传输的,但是有了数据,你没有通道,数据是无法传输的,所以今天我们来熟悉Netty的第三个核心组件:Channel。ByteBuf是数据,那Channel则是负责传输数据的通道,它是把握Netty通信的命门,没有它Netty是无法通信的。Channel简介在JavaNIO中我们知道,Channel,即通道,是用来传输数据的一条“管道”,它与Buffer相辅相成,在JavaNIO中,我们只能从Channel读取数据到Buffer中,或者从Buffer读取数据到Channel中

    2023-10-18
    阅读(219)
  • 上篇文章(Netty入门—Bootstrap,一切从这里开始),我们了解了Netty的第一个核心组件:Bootstrap,它是Netty程序的开端。今天我们来熟悉Netty的第二个组件:ByteBuf,Netty数据传输的载体。在Netty中,数据的读写都是以ByteBuf为单位进行交互的。为什么要造轮子?在学习JavaNIO的时候,JavaNIO有一个原生的ByteBuffer,为什么Netty不直接使用原生的,要重复造一个呢?因为不好用啊。为什么不好用呢?因为JavaNIO的ByteBuffer有一些设计上的缺陷和痛点。我们先看ByteBuffer内部结构。JavaNIO的ByteBuff

    2023-10-11
    阅读(243)
  • 上篇文章(Netty入门—要想掌握Netty,你必须知道它的这些核心组件)大明哥阐述了Netty的整体结构,从这篇文章开始大明哥就将这个整体进行拆分讲解,今天是第一个核心组件:Bootstrap。一句话来概括Bootstrap,无论是Netty的客户端还是服务端程序,都是从这里开始的。在Netty入门—亘古不变的HelloWorld一文的demo中,我们首先创建一个ServerBootstrap对象(服务端)或者Bootstrap对象(客户端),然后调用他们的各个方法进行组装整个Netty服务端和客户端,从代码中我们可以看出这两个类是一个辅助类,用来辅助服务端或者客户端初始化和启动的。Boot

    2023-10-09
    阅读(317)
  • 在上篇文章(Netty入门—亘古不变的HelloWorld)中,我们简单认识了开发一个Netty服务端和客户端代码的主要步骤了,在这几大步骤中我们基本上可以看出Netty的几个核心组件。在真正进入Netty的学习之前,我们非常有必要先对这些组件进行一个整体的认识,对于Netty入门阶段的讲解,大明哥采用整体—>分解—>总结的模式来阐述。对于一头牛,我们需要先知道这是一头牛,了解这头牛有哪些组织,然后再把这些组织一个一个地拆开来认识,清楚里面每一个组织的功能,最后再将这些组织组合成一头牛,是不是就会清晰很多。Bootstrap:引导器Bootstrap的意思是引导,一个Netty应用

    2023-10-08
    阅读(328)
  • 这篇文章我们正式开始学习Netty,在入门之前我们还是需要了解什么是Netty。什么是Netty为什么很多人都推崇Javaboy去研究Netty?Netty这么高大上,它到底是何方神圣?用官方的话说:Netty是一款异步的、基于事件驱动的网络应用程序框架,用以快速开发高性能、高可靠性的网络IO程序。为什么要使用Netty呢?因为使用原生的JavaNIO非常不爽,它存在一系列的问题,比如:使用JavaNIO需要了解很多概念,而且API非常繁琐。使用JavaNIO编程复杂,一不小心就会Bug横飞。开发工作量和难度也很大,例如我们要处理断开重连、网络闪断、半包读写、网络拥塞、异常处理,等等异常情况,

    2023-10-06
    阅读(388)