首页 文章 精选 留言 我的

精选列表

搜索[零点击],共10000篇文章
优秀的个人博客,低调大师

从零开始学习Java8 Stream,看这篇就够了

为何需要引入流 在我们平常的开发中几乎每天都会有到List、Map等集合API,若是问Java什么API使用最多,我想也应该是集合了。举例:假如我有个集合List,里面元素有1,7,3,8,2,4,9,需要找出里面大于5的元素,具体实现代码: public List<integer> getGt5Data() { List<integer> data = Arrays.asList(1, 7, 3, 8, 2, 4, 9); List<integer> result = new ArrayList&lt;&gt;(); for (Integer num : data) { if (num &gt; 5) { result.add(num); } } return result; } 这个实现让我们感觉到了集合的操作不是太完美,如果是数据库的话,我们只需要简单的在where后面加一个条件大于5就可以得到我们想要的结果,为什么Java的集合就没有这种API呢? 其次,如果我们遇到有大集合需要处理,为了提高性能,我们可能需要使用到多线程来处理,但是写并行程序的复杂度有提高了不少。 基于以上的问题,所有Java8推出了Stream Stream简介 Stream有哪些特点: 元素的序列:与集合一样可以访问里面的元素,集合讲的是数据,而流讲的是操作,比如:filter、map 源: 流也需要又一个提供数据的源,顺序和生成时的顺序一致 数据的操作:流支持类似于数据库的操作,支持顺序或者并行处理数据;上面的例子用流来实现会更加的简洁 public List<integer> getGt5Data() { return Stream.of(1, 7, 3, 8, 2, 4, 9) .filter(num -&gt; num &gt; 5) .collect(toList()); } 流水线操作:很多流的方法本身也会返回一个流,这样可以把多个操作连接起来,形成流水线操作 内部迭代:与以往的迭代不同,流使用的内部迭代,用户只需要专注于数据处理 只能遍历一次: 遍历完成之后我们的流就已经消费完了,再次遍历的话会抛出异常 使用Stream Java8中的Stream定义了很多方法,基本可以把他们分为两类:中间操作、终端操作;要使用一个流一般都需要三个操作: 定义一个数据源 定义中间操作形成流水线 定义终端操作,执行流水线,生成计算结果 构建流 使用Stream.of方法构建一个流 Stream.of("silently","9527","silently9527.cn") .forEach(System.out::println); 使用数组构建一个流 int[] nums = {3, 5, 2, 7, 8, 9}; Arrays.stream(nums).sorted().forEach(System.out::println); 通过文件构建一个流 使用java.nio.file.Files.lines方法可以轻松构建一个流对象 Files.lines(Paths.get("/Users/huaan9527/Desktop/data.txt")) .forEach(System.out::println); 中间操作 中间操作会返回另外一个流,这样可以让多个操作连接起来形成一个流水线的操作,只要不触发终端操作,那么这个中间操作都不会实际执行。 filter 该操作接受一个返回boolean的函数,当返回false的元素将会被排除掉 举例:假如我们100个客户,需要筛选出年龄大于20岁的客户 List<customer> matchCustomers = allCustomers.stream() .filter(customer -&gt; customer.getAge()&gt;20) .collect(toList()); distinct 该操作将会排除掉重复的元素 List<integer> data = Stream.of(1, 7, 3, 8, 2, 4, 9, 7, 9) .filter(num -&gt; num &gt; 5) .distinct() .collect(toList()); limit 该方法限制流只返回指定个数的元素 List<integer> data = Stream.of(1, 7, 3, 8, 2, 4, 9, 7, 9) .filter(num -&gt; num &gt; 5) .limit(2) .collect(toList()); skip 扔掉前指定个数的元素;配合limit使用可以达到翻页的效果 List<integer> data = Stream.of(1, 7, 3, 8, 2, 4, 9, 7, 9) .filter(num -&gt; num &gt; 5) .skip(1) .limit(2) .collect(toList()); map 该方法提供一个函数,流中的每个元素都会应用到这个函数上,返回的结果将形成新类型的流继续后续操作。 举例:假如我们100个客户,需要筛选出年龄大于20岁的客户,打印出他们的名字 allCustomers.stream() .filter(customer -&gt; customer.getAge() &gt; 20) .map(Customer::getName) .forEach(System.out::println); 在调用map之前流的类型是Stream<customer>,执行完map之后的类型是Stream<string> flatMap 假如我们需要把客户的名字中的每个字符打印出来,代码如下: List<customer> allCustomers = Arrays.asList(new Customer("silently9527", 30)); allCustomers.stream() .filter(customer -&gt; customer.getAge() &gt; 20) .map(customer -&gt; customer.getName().split("")) .forEach(System.out::println); 执行本次结果,你会发现没有达到期望的结果,打印的结果 [Ljava.lang.String;@38cccef 这是因为调用map之后返回的流类型是Stream<string[]>,所有forEach的输入就是String[];这时候我们需要使用flatMap把String[]中的每个元素都转换成一个流,然后在把所有的流连接成一个流,修改后的代码如下 List<customer> allCustomers = Arrays.asList(new Customer("silently9527", 30)); allCustomers.stream() .filter(customer -&gt; customer.getAge() &gt; 20) .map(customer -&gt; customer.getName().split("")) .flatMap(Arrays::stream) .forEach(System.out::println); 执行结果: sorted 对所有的元素进行排序 List<integer> numbers = Arrays.asList(1, 7, 3, 8, 2, 4, 9); numbers.stream().sorted(Integer::compareTo).forEach(System.out::println); 终端操作 终端操作会执行所有的中间操作生成执行的结果,执行的结果不在是一个流。 anyMatch 如果流中有一个元素满足条件将返回true if (allCustomers.stream().anyMatch(customer -&gt; "silently9527".equals(customer.getName()))) { System.out.println("存在用户silently9527"); } allMatch 确保流中所有的元素都能满足 if (allCustomers.stream().allMatch(customer -&gt; customer.getAge() &gt; 20)) { System.out.println("所有用户年龄都大于20"); } noneMatch 与allMatch操作相反,确保流中所有的元素都不满足 if (allCustomers.stream().noneMatch(customer -&gt; customer.getAge() &lt; 20)) { System.out.println("所有用户年龄都大于20"); } findAny 返回流中的任意一个元素,比如返回大于20岁的任意一个客户 Optional<customer> optional = allCustomers.stream() .filter(customer -&gt; customer.getAge() &gt; 20) .findAny(); findFirst 返回流中的第一个元素 Optional<customer> optional = allCustomers.stream() .filter(customer -&gt; customer.getAge() &gt; 20) .findFirst(); reduce 接受两个参数:一个初始值,一个BinaryOperator<t> accumulator将两个元素合并成一个新的值 比如我们对一个数字list累加 List<integer> numbers = Arrays.asList(1, 7, 3, 8, 2, 4, 9); Integer sum = numbers.stream().reduce(0, (a, b) -&gt; a + b); 上面的代码,我们可以简写 Integer reduce = numbers.stream().reduce(0, Integer::sum); 找出流中的最大值、最小值 min、max numbers.stream().reduce(Integer::max) numbers.stream().reduce(Integer::min) count 统计流中元素的个数 numbers.stream().count() 数据收集器collect 在Java8中已经预定义了很多收集器,我们可以直接使用,所有的收集器都定义在了Collectors中,基本上可以把这些方法分为三类: 将元素归约和汇总成一个值 分组 分区 归约和汇总 先看下我们之前求最大值和最小值采用收集器如何实现 找出年龄最大和最小的客户 Optional<customer> minAgeCustomer = allCustomers.stream().collect(minBy(Comparator.comparing(Customer::getAge))); Optional<customer> maxAgeCustomer = allCustomers.stream().collect(maxBy(Comparator.comparing(Customer::getAge))); 求取年龄的平均值 Double avgAge = allCustomers.stream().collect(averagingInt(Customer::getAge)); 进行字符串的连接 把客户所有人的名字连接成一个字符串用逗号分隔 allCustomers.stream().map(Customer::getName).collect(joining(",")); 分组 在数据库的操作中,我们可以轻松的实现通过一个属性或者多个属性进行数据分组,接下来我们看看Java8如何来实现这个功能。 根据客户的年龄进行分组 Map<integer, list<customer>&gt; groupByAge = allCustomers.stream().collect(groupingBy(Customer::getAge)); Map的key就是分组的值年龄,List<customer>就是相同年龄的用户 我们需要先按照用户的地区分组,在按年龄分组 Map<string, map<integer, list<customer>&gt;&gt; groups = allCustomers.stream() .collect(groupingBy(Customer::getArea, groupingBy(Customer::getAge))); 在相对于普通的分组,这里多传了第二个参数又是一个groupingBy;理论上我们可以通过这个方式扩展到n层分组 分组后再统计数量 Map<string, long> groupByCounting = allCustomers.stream() .collect(groupingBy(Customer::getArea, counting())); 以用户所在地区分组后找出年龄最大的用户 Map<string, optional<customer>&gt; optionalMap = allCustomers.stream() .collect(groupingBy(Customer::getArea, maxBy(Comparator.comparing(Customer::getAge)))); 这时候返回的Map中的value被Optional包裹,如果我们需要去掉Optional,可以使用collectingAndThen Map<string, customer> customerMap = allCustomers.stream() .collect(groupingBy(Customer::getArea, collectingAndThen(maxBy(Comparator.comparing(Customer::getAge)), Optional::get) )); 写在最后(看完不点赞,你们想白嫖我吗) 首先感谢大家可以耐心地读到这里。点关注,不迷路 当然,文中或许会存在或多或少的不足、错误之处,有建议或者意见也非常欢迎大家在评论交流。 最后,白嫖不好,创作不易,希望朋友们可以点赞评论关注三连,因为这些就是我分享的全部动力来源🙏 > 原创不易 转载请注明出处:https://silently9527.cn/archives/66 参数资料《Java8实战》

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

从零开始搭建Kafka+SpringBoot分布式消息系统

前言 由于kafka强依赖于zookeeper,所以需先搭建好zookeeper集群。由于zookeeper是由java编写的,需运行在jvm上,所以首先应具备java环境。 (ps:默认您的centos系统可联网,本教程就不教配置ip什么的了) (ps2:没有wget的先装一下:yum install wget) (ps3:人啊,就是要条理。东边放一点,西边放一点,过段时间就不知道自己装在哪里了。本教程所有下载均放在/usr/local目录下) (ps4:kafka可能有内置zookeeper,感觉可以越过zookeeper教程,但是这里也配置出来了。我没试过) 文章首发公众号:Java架构师联盟,每日更新技术好文 一、配置jdk 因为oracle 公司不允许直接通过wget 下载官网上的jdk包。所以你直接wget以下地址下载下来的是一个只有5k的网页文件而已,并不是需要的jdk包。(垄断地位就是任性)。 (请通过java -version判断是否自带jdk,我的没带) 1、官网下载 下面是jdk8的官方下载地址: https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8u211-later-5573849.html 2、上传解压 这里通过xftp上传到服务器指定位置:/usr/local 对压缩文件进行解压: tar -zxvf jdk-8u221-linux-x64.tar.gz 对解压后的文件夹进行改名: mv jdk1.8.0_221 jdk1.8 3、配置环境变量 vim /etc/profile #java environment export JAVA_HOME=/usr/local/jdk1.8 export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar export PATH=$PATH:${JAVA_HOME}/bin 操作之后的界面如下: 运行命令使环境生效 source /etc/profile 二、搭建zookeeper集群 1、下载zookeeper 创建zookeeper目录,在该目录下进行下载: mkdir /usr/local/zookeeper 这一步如果出现连接被拒绝时可多试几次,我就是第二次请求才成功的。 wget http://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz 等待下载完成之后解压: tar -zxvf zookeeper-3.4.6.tar.gz 重命名为zookeeper1 mv zookeeper-3.4.6 zookeeper1 cp -r zookeeper1 zookeeper2 cp -r zookeeper1 zookeeper3 2、创建data、logs文件夹 在zookeeper1目录下创建 在data目录下新建myid文件。内容为1 3、修改zoo.cfg文件 cd /usr/local/zookeeper/zookeeper1/conf/ cp zoo_sample.cfg zoo.cfg 进行过上面两步之后,有zoo.cfg文件了,现在修改内容为: dataDir=/usr/local/zookeeper/zookeeper1/data dataLogDir=/usr/local/zookeeper/zookeeper1/logs server.1=192.168.233.11:2888:3888 server.2=192.168.233.11:2889:3889 server.3=192.168.233.11:2890:3890 4、搭建zookeeper2 首先,复制改名。 cd /usr/local/zookeeper/ cp -r zookeeper1 zookeeper2 然后修改具体的某些配置: vim zookeeper2/conf/zoo.cfg 将下图三个地方1改成2 vim zookeeper2/data/myid 同时将myid中的值改成2 5、搭建zookeeper3 同上,复制改名 cp -r zookeeper1 zookeeper3 vim zookeeper3/conf/zoo.cfg 修改为3 vim zookeeper3/data/myid 修改为3 6、测试zookeeper集群 cd /usr/local/zookeeper/zookeeper1/bin/ 由于启动所需代码比较多,这里简单写了一个启动脚本: vim start start的内容如下 cd /usr/local/zookeeper/zookeeper1/bin/ ./zkServer.sh start ../conf/zoo.cfg cd /usr/local/zookeeper/zookeeper2/bin/ ./zkServer.sh start ../conf/zoo.cfg cd /usr/local/zookeeper/zookeeper3/bin/ ./zkServer.sh start ../conf/zoo.cfg 下面是连接脚本: vim login login内容如下: ./zkCli.sh -server 192.168.233.11:2181,192.168.233.11:2182,192.168.233.11:2183 脚本编写完成,接下来启动: sh start sh login 启动集群成功,如下图: 这里zookeeper就告一段落了,由于zookeeper占用着输入窗口,这里可以在xshell右键标签,新建ssh渠道。然后就可以在新窗口继续操作kafka了! 三、搭建kafka集群 1、下载kafka 首先创建kafka目录: mkdir /usr/local/kafka 然后在该目录下载 cd /usr/local/kafka/ wget https://archive.apache.org/dist/kafka/1.1.0/kafka_2.11-1.1.0.tgz 下载成功之后解压: tar -zxvf kafka_2.11-1.1.0.tgz 2、修改集群配置 首先进入conf目录下: cd /usr/local/kafka/kafka_2.11-1.1.0/config 修改server.properties 修改内容: broker.id=0 log.dirs=/tmp/kafka-logs listeners=PLAINTEXT://192.168.233.11:9092 复制两份server.properties cp server.properties server2.properties cp server.properties server3.properties 修改server2.properties vim server2.properties 修改主要内容为: broker.id=1 log.dirs=/tmp/kafka-logs1 listeners=PLAINTEXT://192.168.233.11:9093 如上,修改server3.properties 修改内容为: broker.id=2 log.dirs=/tmp/kafka-logs2 listeners=PLAINTEXT://192.168.233.11:9094 3、启动kafka 这里还是在bin目录编写一个脚本: cd ../bin/ vim start 脚本内容为: ./kafka-server-start.sh ../config/server.properties & ./kafka-server-start.sh ../config/server2.properties & ./kafka-server-start.sh ../config/server3.properties & 通过jps命令可以查看到,共启动了3个kafka。 4、创建Topic cd /usr/local/kafka/kafka_2.11-1.1.0 bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 1 --topic my-replicated-topic kafka打印了几条日志 在启动的zookeeper中可以通过命令查询到这条topic! ls /brokers/topics 查看kafka状态 bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic my-replicated-topic 可以看到此时有三个节点 1 , 2 , 0 Leader 是1 , 因为分区只有一个 所以在0上面, Replicas:主从备份是 1,2,0, ISR(in-sync):现在存活的信息也是 1,2,0 5、启动生产者 bin/kafka-console-producer.sh --broker-list localhost:9092 --topic my-replicated-topic 由于不能按删除,不能按左右键去调整,所以语句有些乱啊。em… 6、启动消费者 bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --from-beginning --topic my-replicated-topic 可以看出,启动消费者之后就会自动消费。 在生产者又造了一条。 消费者自动捕获成功! 四、集成springboot 先贴一张kafka兼容性目录: 不满足的话启动springboot的时候会抛异常的!!!ps:该走的岔路我都走了o(╥﹏╥)o (我的kafka-clients是1.1.0,spring-kafka是2.2.2,中间那列暂时不用管) 回归正题,搞了两个小时,终于搞好了,想哭… 遇到的问题基本就是jar版本不匹配。 上面的步骤我也都会相应的去修改,争取大家按照本教程一遍过!!! 1、pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.gzky</groupId> <artifactId>study</artifactId> <version>0.0.1-SNAPSHOT</version> <name>study</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> <version>1.3.8.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka --> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.2.0.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients --> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> pom文件中,重点是下面这两个版本。 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.2.0.RELEASE</version> </dependency> 2、application.yml spring: redis: cluster: #设置key的生存时间,当key过期时,它会被自动删除; expire-seconds: 120 #设置命令的执行时间,如果超过这个时间,则报错; command-timeout: 5000 #设置redis集群的节点信息,其中namenode为域名解析,通过解析域名来获取相应的地址; nodes: 192.168.233.11:9001,192.168.233.11:9002,192.168.233.11:9003,192.168.233.11:9004,192.168.233.11:9005,192.168.233.11:9006 kafka: # 指定kafka 代理地址,可以多个 bootstrap-servers: 192.168.233.11:9092,192.168.233.11:9093,192.168.233.11:9094 producer: retries: 0 # 每次批量发送消息的数量 batch-size: 16384 buffer-memory: 33554432 # 指定消息key和消息体的编解码方式 key-serializer: org.apache.kafka.common.serialization.StringSerializer value-serializer: org.apache.kafka.common.serialization.StringSerializer consumer: # 指定默认消费者group id group-id: test-group auto-offset-reset: earliest enable-auto-commit: true auto-commit-interval: 100 # 指定消息key和消息体的编解码方式 key-serializer: org.apache.kafka.common.serialization.StringSerializer value-serializer: org.apache.kafka.common.serialization.StringSerializer server: port: 8085 servlet: #context-path: /redis context-path: /kafka 没有配置Redis的可以把Redis部分删掉,也就是下图: 想学习配置Redis集群的可以参考:《Redis集群redis-cluster的搭建及集成springboot》 3、生产者 package com.gzky.study.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Component; /** * kafka生产者工具类 * * @author biws * @date 2019/12/17 **/ @Component public class KfkaProducer { private static Logger logger = LoggerFactory.getLogger(KfkaProducer.class); @Autowired private KafkaTemplate<String, String> kafkaTemplate; /** * 生产数据 * @param str 具体数据 */ public void send(String str) { logger.info("生产数据:" + str); kafkaTemplate.send("testTopic", str); } } 4、消费者 package com.gzky.study.utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; /** * kafka消费者监听消息 * * @author biws * @date 2019/12/17 **/ @Component public class KafkaConsumerListener { private static Logger logger = LoggerFactory.getLogger(KafkaConsumerListener.class); @KafkaListener(topics = "testTopic") public void onMessage(String str){ //insert(str);//这里为插入数据库代码 logger.info("监听到:" + str); System.out.println("监听到:" + str); } } 5、对外接口 package com.gzky.study.controller; import com.gzky.study.utils.KfkaProducer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** * kafka对外接口 * * @author biws * @date 2019/12/17 **/ @RestController public class KafkaController { @Autowired KfkaProducer kfkaProducer; /** * 生产消息 * @param str * @return */ @RequestMapping(value = "/sendKafkaWithTestTopic",method = RequestMethod.GET) @ResponseBody public boolean sendTopic(@RequestParam String str){ kfkaProducer.send(str); return true; } } 6、postman测试 这里首先应该在服务器启动监听器(kafka根目录),下面命令必须是具体的服务器ip,不能是localhost,是我踩过的坑: 推荐此处重启一下集群 关闭kafka命令: cd /usr/local/kafka/kafka_2.11-1.1.0/bin ./kafka-server-stop.sh ../config/server.properties & ./kafka-server-stop.sh ../config/server2.properties & ./kafka-server-stop.sh ../config/server3.properties & 此处应该jps看一下,等待所有的kafka都关闭(关不掉的kill掉),再重新启动kafka: ./kafka-server-start.sh ../config/server.properties & ./kafka-server-start.sh ../config/server2.properties & ./kafka-server-start.sh ../config/server3.properties & 等待kafka启动成功后,启动消费者监听端口: cd /usr/local/kafka/kafka_2.11-1.1.0 bin/kafka-console-consumer.sh --bootstrap-server 192.168.233.11:9092 --from-beginning --topic testTopic 曾经我乱输的测试信息全部被监听过来了! 启动springboot服务 然后用postman生产消息: 然后享受成果,服务器端监听成功。 项目中也监听成功!

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

从零入门 Serverless | 一文详解 Serverless 架构模式

作者 |Hongqi 阿里云高级技术专家 本文整理自《Serverless 技术公开课》,关注“Serverless”公众号,回复入门,即可获取 Serverless 系列文章 PPT。 什么是 Serverless 架构?按照 CNCF 对 Serverless 计算的定义,Serverless 架构应该是采用 FaaS(函数即服务)和 BaaS(后端服务)服务来解决问题的一种设计。这个定义让我们对 Serverless 的理解稍显清晰,同时可能也造成了一些困扰和争论。 随着需求和技术的发展,业界出现了一些 FaaS 以外的其它形态的 Serverless 计算服务,比如 Google Cloud Run,阿里云推出的面向应用的 Serverless 应用引擎服务以及 Serverless K8s,这些服务也提供了弹性伸缩能力

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

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等操作系统。

用户登录
用户注册