2022年都快结束了,Java的这些新技术、热门技术,你不会还不知道吧?

Java是Sun Microsystems于1995年发布的一种跨平台的面向对象的编程语言,因为其快速、可靠、通用、安全且易于学习,所以成为目前最流行和广泛使用的编程语言之一。

从1995年到2022年,JDK从1.0已经更新到19,27年来,Java的每次更新可谓是惊艳无比,给开发者带来极大的方便,同时与时俱进。那么2022年了,Java有哪些最新最热门的技术?

一、JDK19最新更新

谈到Java最新技术,那么一定会谈到JAVA 19,这一小节,我们先来看下JAVA 19有哪些更新。

JAVA 19特性,来源于openJDK

从openJDK看出,JAVA 19主要有以上截图中的特性,我们来一一了解一下。

1.1 记录模式 (预览)

如果不经常关注JDK更新的朋友肯定对记录模式很陌生,甚至都没听过,其实记录模式非常好用。官方的解释是这样的:“记录模式由一个类型、一个可能为空的记录组件模式列表(用于匹配相应的记录组件)和一个可选标识符组成,带有标识符的记录模式称为命名记录模式,变量称为记录模式变量。”

对于新手来说,不加以白话文的解释是看不懂的。我们直接上代码,用代码给大家作解释:

record Test(int a, int b) {}

形如以上代码的就是记录模式。

record是一种新类型,本质上是一个final类,在修改所有属性的同时加final,会自动编译public get hashcodeequalstoString方法,这样减少了代码量。record在Java 14中被提出,在Java 15中进入预览阶段,并在Java 16中发布。

我们编写一个Drone类,定义sn、brand、name:

package com.wljslmz;

public record Drone(String sn, String brand, String name) {
}

record的使用:

package com.wljslmz;

public class RecordTest {

    public static void main(String[] args) {
        Drone drone1 = new Drone("0a9f55785ebc4c52", "DJI", "M30无人机");
        Drone drone2 = new Drone("7400f6c1c5644c6e", "DJI", "精灵4无人机");
        System.out.println(drone1);
        System.out.println(drone2);
    }
}

输出结果:

Drone[sn=0a9f55785ebc4c52, brand=DJI, name=M30无人机]
Drone[sn=field 7400f6c1c5644c6e, brand=DJI, name=精灵4无人机]

在Java 19中,模式匹配被引入record中,这样的话就可以使用instanceof

package com.wljslmz;

public class RecordTest {

    public static void main(String[] args) {
        Drone drone1 = new Drone("0a9f55785ebc4c52", "DJI", "M30无人机");
        if(drone1 instanceof Drone droneType){
            System.out.println(drone1.sn());
         }
         
         Drone drone2 = new Drone("7400f6c1c5644c6e", "DJI", "精灵4无人机");
        if(drone2 instanceof Drone(String sn, String brand, String name)){
            System.out.println("无人机2的序列号为:"+sn+",厂商为:"+brand+",名称为:"+name);
         }
    }
}

输出结果:

0a9f55785ebc4c52

无人机2的序列号为:7400f6c1c5644c6e,厂商为:DJI,名称为:精灵4无人机

1.2 虚拟线程(预览)

在讲虚拟线程前,给大家稍微普及一下线程的知识。

研究过Java虚拟机的朋友都知道,线程一直是Java并发编程中非常重要的一部分。Thread是Java中的并发单元,每个Thread线程都提供了一个栈来存储局部变量和方法调用,以及关于线程上下文的信息。Java线程和系统内核线程是一一对应的,Java线程是由系统内核线程调度的,所以到并发场景中,我们第一个想到的是增加线程数目去提高系统的性能。

多线程模型

多线程模型能不能解决并发中绝大多数问题?

答案肯定是:能!但是可取吗?

小型的并发场景可取,但是并发数很大的场景就不可取了。线程的数目当然是越多,越能提高系统的性能,但是这个带来的直接后果就是成本增加,上面我们说过了,Java的线程是由系统内核直接调用的,那么也就意味着,多线程需要在物理上增加机器,试想一下,这种成本代价得多高?

那有人肯定说了,不是还有线程池吗?

不错,线程池确实能提高并发场景下系统的性能,但是,请注意,线程池只是帮助你如何更好的管理线程、利用线程,本身不会凭空给你创造出线程来,最终工作的还是底层的内核线程。而且线程池往往会受限于CPU、网络、内存等,所以从硬件的角度来看,并没有解决实际问题。

因此,Java19引入了虚拟线程。

我们来看下虚拟线程的模型是什么样的:

虚拟线程模型

多线程模型中的线程在虚拟线程模型中被称为平台线程,一个平台线程对应多个虚拟线程,最终其实也是由内核线程去驱动。

在体验上虚拟线程与Threads没有区别,并且兼容之前的API,但相比而言它们占用的资源非常少,并且优化了硬件使用效率。

package com.wljslmz.demo;

import Java.util.concurrent.ExecutorService;
import Java.util.stream.IntStream;

import static Java.util.concurrent.Executors.*;

/**
 * @author: wangrui
 * @date: 2022/10/18 15:12
 * @description: 虚拟线程测试
 */
public class VirtualThreadTest {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        try (ExecutorService executor = newVirtualThreadPerTaskExecutor()) {
            IntStream.range(0, 1000000).forEach(index -> {
                executor.submit(() -> {
                    Thread.sleep(1000);
                    return index;
                });
            });
            System.out.println("执行消耗时间:" + (System.currentTimeMillis() - start) + "毫秒");
        }
    }
}

执行结果:

执行消耗时间:8550毫秒

代码中我们创建了100万个线程,每个线程睡眠1秒钟,完成这个操作最终只花了8秒多,假如我们使用的是普通线程去处理或者线程池去处理,那么这个速度能差异到多少呢?

我们稍微改动一下代码:

long start = System.currentTimeMillis();

        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 1000000; i++) {
            executor.submit(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        System.out.println("执行消耗时间:" + (System.currentTimeMillis() - start) + "毫秒");

最后执行的时间:

执行消耗时间:13459毫秒

差距是不是也不是很大,确实是的,因为虚拟线程只会增加程序的吞吐量,不会增加程序的处理速度

1.3 Vector API

Vector API最初在Java 16中被引入,Java 19带来了它的第四次迭代。简单来说Vector API可以加速矢量计算,在数学计算领域非常有用。

在传统计算中,数据的处理都是一个一个处理的,这种操作被称为“SISD”,即“单指令,单数据”:

但是在Vector API中,数据的计算可以做到“单指令,多数据”,即“SIMD”:

这个代表什么意思呢?

比如我们对两组数据进行处理,普通处理的方式就是,遍历这些数组,然后逐个处理:

int[] array1 = {1, 2, 3, 4, 5};
int[] array2 = {6, 7, 8, 9, 10};
int[] array3 = new int[5];
for (int i = 0; i < 5; i++) {
    array3[i] = array1[i] + array2[i];
}

System.out.println(Arrays.toString(array3));

如上代码,我们定义了两个数组,现在我们想对相同下标的数进行相加,所以我们遍历了数组,一对一对进行处理,最终的结果就是:

[7, 9, 11, 13, 15]

如果使用Vector API应该怎么写?

int[] array1 = {1, 2, 3, 4, 5};
int[] array2 = {6, 7, 8, 9, 10};
int[] array3 = new int[5];

VectorSpecies<Integer> intvector = IntVector.SPECIES_PREFERRED;
int[] intvectorBound = intvector.loopBound(5);

int i = 0;
for (; i < intvectorBound; i += intvector.length()) {
    var array1Intvector = IntVector.fromArray(intvector, array1, i);
    var array2Intvector = IntVector.fromArray(intvector, array2, i);
    var array3Intvector = array1Intvector.add(array2Intvector);
    array3Intvector.intoArray(array3, i);
}

for (; i < 5; i++) {
    array3[i] = array1[i] + array2[i];
}

System.out.println(Arrays.toString(array3));

这个代码看起来是比非Vector API复杂了,但是处理的思想完全不一样,普通处理方法是单个数据单个数据进行处理,而Vector API是多组数据处理,两者如果在大数据量计算的时候,其性能就可想而知了。

1.4 switch 模式匹配

模式匹配在Java 19中得到了相当大的更新,改进后的Switch模式匹配代码更简洁,逻辑更清晰。

在Java 19中,使用when 子句增强保护,在Java 17和Java 18中,Switch是这样使用的:

switch (t) {
  case student s && s.age() > 18 -> System.out.println("学生成年");
  case student s ->  System.out.println("学生未成年");
  default -> System.out.println("数据有误");
}

那么在Java19中就是这样的:

switch (t) {
  case student s when  s.age() > 18 -> System.out.println("学生成年");
  case student s ->  System.out.println("学生未成年");
  default -> System.out.println("数据有误");
}

这种保护模式可比if else条件判断好用多了。

1.5 外部函数和内存API(预览)

访问堆外内存有几种方式:

  • 使用ByteBuffer;
  • 使用Unsafe;
  • 使用JNI。

每种方式都有其优缺点,使用带ByteBuffer的直接缓冲区时,限制为2GB,这是int可以处理的范围,内存释放取决于GC。Unsafe 性能不错,但并不安全,访问释放的内存会导致JVM崩溃。使用JNI需要编写C代码,性能不好。

Java 19为Java程序引入一系列的 API,以便与Java运行时之外的代码和数据进行交互。API高效地执行外部函数(即JVM之外的代码)并安全地访问外部内存(不受JVM管理的内存),允许Java程序调用本地库和管理本地数据,从而使得程序拥有易用性高性能通用性安全性等特点。

1.6 结构化并发

JDK 19引入了结构化并发,目前处于孵化阶段。

当我们在Java中创建一个新线程时,操作系统会进行系统调用,告诉它创建一个新的系统线程。我们都知道,创建系统线程的成本很高,因为调用会占用大量时间,并且每个线程都会占用一些内存,线程也共享相同的CPU,我们是不希望出现阻塞的情况。

这个时候可能就会想到使用异步编程来防止阻塞情况的发生,启动一个线程并告诉它在数据到达时要做什么。在数据可用之前,其他线程可以将CPU资源用于其任务。异步编程确实实现了其想要的效果,但是往往处理起来比较麻烦,那么结构化并发就可以简化并发编程中的种种麻烦事,使得编写和调试多线程代码变得更加容易。

结构化并发的原理就是使线程的生命周期与结构化编程中的代码块相同。如果在方法1中调用方法2 ,则必须先完成方法2,然后才能退出方法1,方法2的生命周期不能超过方法1的生命周期。

我们来画个图进行解释一下,看完你就懂了。

如图,线程1启动了一个线程,我们暂且叫它线程2,两者彼此分开工作,但在线程 1完成之前,它必须等待线程2完成其工作。

1.7 Linux/RISC-V移植

这个我们简单了解一下,其思想就是将JDK移植到开源Linux RISC-V架构。RISC-V标准是12年前由加州大学伯克利分校教授David Patterson和Krste Asanović发明的,开发人员可以自由更改RISC-V芯片的指令集架构与英特尔x86、Arm处理器的指令集架构。

估计这个解释,各位看官不认可或者直接不知所云,说的简单点,就是通过Linux/RISC-V移植,Java可以支持对硬件发送指令,这个就很厉害了,以前提到硬件,那么必然想到的语言就是C或者C++,但是目前Linux/RISC-V移植还不完善,我们期待有一天在硬件开发的领域中,Java能够有自己的一席之地!

二、热门技术

在第一章节,我们介绍了目前Java最新版本Java19中最新的功能,本章节,我们介绍一下2022年比较热门的Java技术。

2.1 微服务

微服务的火热其实已经持续很长时间了,传统服务一般是单体服务,但是随着业务的增加、架构的复杂,单体服务会使得本身服务变得非常臃肿,性能也会非常低。

那么把服务拆分,不仅可以做到解耦合,还能在很大程度上提高系统的性能。

微服务的特点:

  • 自治:微服务是自包含的,可以独立开发和部署,而不会影响其他服务。
  • 专业化:每个微服务都针对一种特定功能而设计。
  • 无状态:微服务不共享服务的状态,在某些情况下,如果需要维护状态,可以在数据库中进行维护。

在微服务中,Java相关的技术主要是Spring Boot + Spring Cloud,这也是 Java开发微服务的最佳选择,因为两者的体系非常成熟,而且社区活跃度也非常高。Spring Cloud 提供了许多开箱即用的特性,比如服务发现和负载均衡。

2.2 并发

并发编程一直是非常火热的技术,不仅仅在企业开发中出场率高,在面试中也是占据主要席位的,还有人说并发是区分普通开发人员和优秀程序员的标准,可见并发编程的重要性和难度。

在并发中,常见的技术主要有Thread、Runnable对象锁、同步、死锁、活锁、CyclicBarrier、CountDownLatch、Phaser和CompleteableFuture等。

2.3 NoSQL

数据库是Java开发中最基本的技术,就跟人的手脚一样,但是NoSQL不一样,它就像我们出行方式中的高铁、飞机一样,虽然说去某个地方也能走路过去,但是坐高铁、坐飞机,速度提升的不是一般的快。所以说NoSQL的应用是非常重要的,也是比较热门的技术。

出场率比较高的两个NoSQL有:

  • Redis:即REmote Dictionary Server,由Salvatore Sanfilippo创立。它最初于2009年4月10日发布,是一种内存数据库,可用作数据库、缓存和消息代理。
  • MongoDB:MongoDB由DoubleClick、ShopWiki和Gilt Groupe于2007年创立,是一个面向文档的数据库,使用动态模式来存储类似JSON的文档。

三、总结

2022年即将结束,不知道你这一年写了多少行代码,写代码的同时是否想过今年比较热门的技术有哪些?比较新的技术又有哪些?本文,笔者给大家着重介绍了Java最新版本Java19的新特性以及比较热门的微服务、并发、NoSQL。在今年11月中旬,还会有SpringBoot3和Spring6的发布,到时候大家别忘了去看看有哪些新特性哦,希望本文可以让您快速的了解2022年最新最热门的Java技术,有任何问题欢迎在下方评论区与我讨论。

提供典型应用案例,剖析JSP/Servret技术与Struts 2技术在Web开发中的不同 提供完整的应用案例,使读者可以深入体会SSH开发模式的精髓 所有开发工具和框架均使用目前的最新版本,紧跟技术发展的趋势 提供230个实例和4个综合案例,可以作为案头必备的查询手册 一线开发人员全力打造,分享技术盛宴! 重点内容及特色 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》介绍了Web开发中客户端技术的基础知识,包括JavaScript、CSS、AJAX等,这些技术都是Web应用中常用的客户端技术。 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax+》讲解了JSP/S rvlet技术的基础知识,并提供了一个综合案例展示其具体应用,它们是Java Web服务端技术的基石,也是学习Java Web开发所要必须掌握的技术。 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》重点讲解了Struts 2、Speing和HIbernate框架的基础知识和高级技术,如Sruts 2中的*、类型转换、国际化和标签等,HIbe rna{e的会话、0/R映射和事务管理等,Spring中的数据库技术与AOP等。 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》特别介绍了Struts 2对AjAX的支持,还重点剖析了SSH框架的整合开发,并给出了两个综合案例来展示整合SSH框架开发Web应用。 和已经出版的同类图书相比,《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》讲解由浅入深,涵盖更多内容,列举了大量典型实例具有超强的实用性,另外,《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》各篇独立,适合读者全面学习或对部分内容重点学习。 读者对象 有Java基础,想进一步学习SSH框架整合开发的人员 了解SSH整合开发,想进一步提高开发技术的人员 正在使用SSH整合技术开发项目,想查阅资料的人员 大中专院校的学生和老师,以及Java培训班的学员和讲师 需要一本案头必备查询手册的程序员 光盘内容 6小时多媒体体视频讲解 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》所涉及的源代码 布衣暖,菜根香,好书滋味长!清华大学出版社长期以来一直秉承为读者多出好书的宗旨,多来为读者奉献了大量脍炙人口的精品图书。尤其在计算机图书出版领域更是形成了鲜明特色,所出版的各类计算机图书受到了广大读者的好评。本次出版的“原创经典,程序员典藏”系列图书是清华大学出版社的重点精品计算机图书,旨在帮助读者全面学习各类程序设计语言开发工具,提高开发水平。同时也为广大程序员提供良好的技术参考,以便作为案头必备的查询手册。 内容提要 -------------------------------------------------------------------------------- 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》通过对SSH中的各种技术循序渐进地讲解,使读者尽掌握开发基于SSH的Web程序的方法。《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》内容包括Web客户端技术、JSP/Servlet技术、Struts 2(*、类型转换、输入校验、上传和下载文件、Struts 2的各种标签、对 AJAX的支持等)、Spring(Ioc容器、装配Java Bean、Jdbc和Hibernate模板、事务管理、Spring AOP等)以及 Hibernate(会话、映射、标准查询API、HQL、事务管理、锁等)。除此之外,《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》还提供了两个完整的实例来讲解开发SSH的详细步骤和方法。通过对这两个实例的学习,读者可以对SSH开发模式有更透彻地理解和认识。SSH是目前最流行的Java Web开发技术。 《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》适合广大从事Java Web开发工作的技术人员、对SSH开发感兴趣的人员以及大专院校学生阅读,尤其是具有一定的Web开发经验的技术人员。 目录 -------------------------------------------------------------------------------- 第1篇 web开发基础篇 第1章 搭建开发环境 1.1 本书使用的软件和框架的版本 1.2 JDK6的下载与安装 1.3 Eclipse3.4 的下载与安装 1.4 MyEclipse6.5 的下载与安装 1.5 Eclipse:IDEforJavaEEDevelopers的下载与安装 1.6 Tomcat6的下载与安装 1.7 在MyEclipse中配置。Tomcat 1.8 在EclipseIDEforJavaEEDevelopers中配置Tomcat 1.9 小结 第2章 JavaWeb应用开发基础 2.1 Web技术的发展 2.2 JavaWeb技术 2.2.1 Java.Welb程序的基本组成 2.2.2 Java,Web程序的目录结构 2.2.3 JavaWeb程序的配置文件 2.3 MVC模式与MvC框架 2.3.1 JSP模型1和JSP模型2 2.3.2 Web应用程序需要的基础服务 2.3.3 MVC模式概述 2.3.4 常用的MvC框架 2.4 小结 第3章 Web开发中的客户端技术 3.1 常用的JavaScriptIDE简介 3.1.1 在MyEclipse中使用JavaScript 3.1.2 在EclipseIDEforJavaEE中使用JavaScript 3.1.3 在NetBeans中使用JavaScript 3.1.4 其他的JavaScriptIDE 3.2.1 avaScdpt语法基础 3.2.1 实例:编写第一个JavaScript程序:Greet 3.2.2 变量 3.2.3 原始类型 3.2.4 类型转换 3.2.5 函数与函数调用 3.2.6 类和对象 3.3 JavaScript高级技术 3.3.1 DOM技术概述 3.3.2 获得HTML元素的3种方法 3.3.3 实例:图像自动切换 3.3.4 正则表达式 3.3.5 实例:表格排序 3.4 CSS基础 3.4.1 CSS的基本语法 3.4.2 在Style属性中定义样式 3.4.3 在HTML中定义样式 3.4.4 在外部文件中定义样式 3.4.5 样式的继承 3.5 AJAX.基础 3.5.1 AJAX概述 3.5.2 实例:使用XMLHttpRequest获得Web资源 3.5.3 实例:使用XMLHttpRequest跨域访问Web资源 3.5.4 实例:AJAX的3种交换数据方法 3.6 小结 第4章 Servlet技术 4.1 Servlet的Helloworld程序 4.1.1 实例:在My Eclipse中编写Helloworld程序 4.1.2 实例:手工编写:Helloworld程序 4.2 Servlet基础 4.2.1 配置数据库连接池 4.2.2 数据库连接池的应用 4.2 -3实例:用doGet方法处理客户端请求 4.2.4 实例:用doPost方法处理客户端请求 4.2.5 实例:用service方法处理客户端请求 4.2.6 实例:初始化(init)和销毁(destroy)Servlet 4.2.7 实例:使用PrintWriter输出响应消息 4.2.8 实例:用ServletOutputStream显示图像 4.2.9 实例:使用RequestDispatcher包含Web资源 4.2.10 实例:使用RequestDispatcher转发Web资源 4.3 HttpServletResponse类的其他功能 4.3.1 产生状态响应码 4.3.2 设置响应消息头 4.3.3 实例:验证响应头设置情况 4.4 使用:HttpServletRequest获得请求消息 4.4.1 获取请求行消息 4.4.2 获取网络连接消息 4.4.3 获取请求头消息 4.5 处理Cookie 4.5.1 什么是Cookie 4.5.2 Cookie类中的方法 4.5.3 实例:用Cookie读写客户端信息 4.5.4 实例:用Cookie读写复杂数据 4.6 处理Session 4.6.1 什么是Session 4.6.2 HttpSession接口中的方法 4.6.3 HttpServletRequest接口中的Session方法 4.6.4 实例:通过Cookie跟踪Session 4.6.5 实例:通过重写uRL跟踪Session 4.7 Web开发的中文问题 4.7.1 Java的编码原理 4.7.2 实例:解决输出中文乱码问题 4.7.3 实例:解决服务端程序读取中文请求消息的乱码问题 4.7.4 实例:用AJAX技术发送和接收中文信息 4.7.5 实例:在请求消息头和响应消息头中转输中文 4.8 小结 第5章 JSP技术 5.1 用MyEclipse编写第一个JSP程序 5.1.1 实例:编写显示服务器当前时间的JSP程序 5.1.2 调试JSP程序 5.1.3 改变JSP的访问路径和扩展名 5.1.4 手动发布JSP程序 5.2 JSP的运行原理 5.2.1 Tomcat如何处理JSP页 5.2.2 分析由JSP生成的Servlet代码 5.3 JSP基本语法 5.3.1 JSP表达式 5.3.2 在JSP中嵌入Java代码 5.3.3.JSP声明 5.3.4.JSP表达式语言(EL) 5.3.5 实例:用EL函数替换HTML中的特殊字符 5.3.6 JSP页面中的注释 5.4 JSP指令 5.4.1 JSP指令简介 5.4.2 page页面指令 5.4.3 include加入指令 5.5.JSP的9个内置对象 5.5.1 out输出对象 5.5.2 pageContext封装对象 5.5.3 其他的JSP内置对象 5.6 JSP标签 5.6.1 插入标签 5.6.2 转发标签 5.6.3 传参标签 5.6.4 创建:Bean标签 5.6.5 设置属性值标签 5.6.6 获取属性值标签 5.7 JSP的标准标签库(JSTL) 5.7.1 如何使用JSTL 5.7.2 条件标签 5.7.3 循环标签 5.8 小结 第6章 用Servlet和JSP实现注册登录系统 第2篇 Struts 2篇 第7章 编写Struts 2的第一个程序 第8章 Struts 2进阶 第9章 Struts 2的* 第10章 Struts 2的类型转换 第11章 Struts 2的输入校验 第12章 文件的上传和下载 第13章 国际化 第14章 Struts 2的标签库 第15章 Struts 2对AJAX的支持 第16章 用Struts 2实现注册登录系统 第3篇 Hibernate篇 第17章 Hibernate的Helloworld程序 第18章 配置Hibernate 第19章 Hibernate的会话与O/R映射 第20章 Hibernate的查询与更新技术 第21章 Hibernate的高级技术 第4篇 Spring篇 第22章 Spring的Helloworld程序 第23章 反向控制(Ioc)与装配JavaBean 第24章 Spring中的数据库技术 第25章 Spring的其他高级技术 第5篇 综合实例篇 第26章 Struts 2与Hibernate、Spring的整合 第27章 网络硬盘 第28章 论坛系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wljslmz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值