Spring Cloud的Ribbon-Hystrix-Feign

2024-09-05 22:58

本文主要是介绍Spring Cloud的Ribbon-Hystrix-Feign,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Ribbon 作为负载均衡,在客户端实现,服务段可以启动两个端口不同但servername一样的服务

Hystrix作为熔断流量控制,在客户端实现,在方法上注解,当请求出错时可以调用注解中的方法返回

Feign 可以定义请求到其他服务的接口,用于微服务间的调用,不用自己再写http请求,在客户端实现,调用此接口就像远程调用其他服务一样,当请求出错时可以调用接口的实现类来返回

一、客户端负载均衡:Spring Cloud Ribbon。
Spring Cloud Ribbon是基于HTTP和TCP的客户端负载工具,它是基于Netflix Ribbon实现的。通过Spring Cloud的封装,可以轻松地将面向服务的REST模板请求,自动转换成客户端负载均衡服务调用。

客户端负载均衡示意图

废话不多说,进入代码实例,通过一个小例子学习一下Ribbon。

Demo实例学习
(1)服务模块介绍:
sc-eureka:服务注册中心,微服务的核心和基础模块,实现各服务的自动化注册与发现。

sc-service_a,sc-service_b:具体的微服务,提供特定的服务,为了实现负载均衡,a、b两个服务具有相同的实例名SERVICE-AB(也可以只创建一个服务SERVICE-AB,同时启动不同的实例)。

sc-customer:微服务消费服务,调用负载均衡客户端调用SERVICE-AB服务。

(2)项目结构与代码实例:

sc-eureka:

maven 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.springcloud</groupId>
    <artifactId>sc-eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>sc-eureka</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
</project>

配置文件application.yml:
server:
  port: 1111
eureka:
  client:
    service-url:
      default-zone: http://localhost:1111/eureka/ #服务注册中心的地址,供其他服务组件调用进行注册。
    fetch-registry: false
    register-with-eureka: false
  instance:
    hostname: localhost
  server:
    enable-self-preservation: false #在调试时关闭eureka注册中心的保护机制

启动类:ScEurekaApplication.java
package com.springcloud;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
 
@EnableEurekaServer //启动一个服务注册中心提供给其他应用进行对话
@SpringBootApplication //注解等价于以默认属性使用 @Configuration ,@EnableAutoConfiguration 和 @ComponentScan 。
public class ScEurekaApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(ScEurekaApplication.class, args);
    }
}

项目结构:


sc-service_a,sc-service_b:

service a,b服务属于同一服务的两个不同实例此处代码只给出service a 的代码结构,service b代码与a并无差别。

maven pom.xml文件


<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.springcloud</groupId>
    <artifactId>sc-service_a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>sc-service_a</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <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>
        </dependency>
    </dependencies>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
 
</project>

配置文件application.properties(也可写成yml文件,根据个人爱好):

server.port=1112
#配置服务命名,不区分大小写,在注册中心管理界面默认大写显示。
spring.application.name=service-ab
#指定服务注册中心的地址
eureka.client.service-url.defaultZone=http://127.0.0.1:1111/eureka/
management.security.enabled=false

启动类:ScServiceAApplication.java

package com.springcloud;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 
@SpringBootApplication
@EnableDiscoveryClient //该注解会根据配置文件中的地址,将服务自身注册到服务注册中心
public class ScServiceAApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(ScServiceAApplication.class, args);
    }
}

 服务Controller层,ServiceAController.java

package com.springcloud;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * Created by lizheng on 2017/7/20.
 */
@RestController
public class ServiceAController {
 
    @RequestMapping("/info")
    public String testA() {
        return "hello I am is service A"; //测试代码直接返回一个字符串,不再调用service层等等。
    }
 
}

项目结构:


sc-customer_a:

sc-customer_a调用服务中心注册好的服务service-ab,通过负载均衡Ribbon按照默认的负载策略(轮询交替访问a,b)调用服务,通过Spring Cloud Hystrix进行服务的容错保护。具体的负载均衡配置和容错如下配置。

依赖的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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.springcloud</groupId>
    <artifactId>sc-customer_a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>sc-customer_a</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 加入断路器依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
 
</project>


配置文件application.properties

server.port=1114
#为服务命名
spring.application.name=ribbon-consumer
#指定服务注册中心的地址
eureka.client.service-url.defaultZone=http://localhost:1111/eureka/

启动类:ScCustomerAApplication.java(配置负载均衡的RestTemplate,启动容错服务)

package com.springcloud;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
 
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker //开启断路器功能,进行容错管理
public class ScCustomerAApplication {
 
    @LoadBalanced //开启负载均衡客户端
    @Bean //注册一个具有容错功能的RestTemplate
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
 
    public static void main(String[] args) {
        SpringApplication.run(ScCustomerAApplication.class, args);
    }
}

Controller层,CustomerAController.java

package com.springcloud;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * Created by lizheng on 2017/7/20.
 */
@RestController
public class CustomerAController {
 
    @Autowired
    HelloService service;
 
    @RequestMapping("/ribbon-consumer")
    public String coutomerA() {
        return service.helloService();
    }
 
}

Service层,HelloSrvice.java

package com.springcloud;
 
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
 
/**
 * Created by lizheng on 2017/7/21.
 */
@Service
public class HelloService {
 
    @Autowired
    RestTemplate restTemplate;
 
    //注解指定发生错误时的回调方法
    @HystrixCommand(fallbackMethod = "helloFallBack")
    public String helloService() {
        //Get请求调用服务,restTemplate被@LoadBalanced注解标记,Get方法会自动进行负载均衡
        return restTemplate.getForObject("http://SERVICE-AB/info", String.class);
    }
 
    public String  helloFallBack() {
        return "Error occurred !";
    }
 
}
项目结构

服务启动并注册成功后,调用sc-customer的‘/ribbon-consumer’会交替调用service a,b返回“hello I am is service A”、“hello I am is service B”,调用出错后会由容错机制返回“Error occurred !”

二、Spring Cloud的负载均衡与容错Spring Cloud Feign 
第一部分介绍了spring cloud的负载均衡和容错的入门配置,在实际开发中微服务的负载均衡和容错基本同时出现而且是每个服务不可缺少的一部分。在使用ribbon时,通常会使用resttemplate实现对http请求的封装,形成了模板化的调用方法。spring cloud feign在此基础上做了进一步的封装,Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。比如:
@Autowired
private AdvertGropRemoteService service; // 远程服务
 
public AdvertGroupVO foo(Integer groupId) {
    return service.findByGroupId(groupId); // 通过HTTP调用远程服务
}

接下来通过入门程序进行学习。
在第一部分服务架构的基础上搭建一个新的服务消费者sc-customer_b,其余服务配置不变。

sc-customer_b的maven 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.springboot</groupId>
    <artifactId>sc-customer_b</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
 
    <name>sc-customer_b</name>
    <description>Demo project for Spring Boot</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>
        <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>
        </dependency>
    </dependencies>
 
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
 
</project>

配置文件application.properties
server.port=1114
#为服务命名
spring.application.name=ribbon-consumer
#指定服务注册中心的地址
eureka.client.service-url.defaultZone=http://localhost:1111/eureka/

启动类:ScCustomerBApplication.java
package com.springboot;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
 
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //开启spring cloud feign的支持
public class ScCustomerBApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(ScCustomerBApplication.class, args);
    }
}

Controller层,HelloCotroller.java
package com.springboot;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
/**
 * Created by lizheng on 2017/7/21.
 */
@RestController()
public class HelloCotroller {
 
    @Autowired
    HelloService helloService;
 
    @RequestMapping(value = "/feign-customer")
    public String helloCustomer() {
       
        return helloService.hello();
    }
 
}

为了让Feign知道在调用方法时应该向哪个地址发请求以及请求需要带哪些参数,我们需要定义一个接口,放在service层,HelloService.java

package com.springboot;
 
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
 
/**
 * Created by lizheng on 2017/7/21.
 */
@FeignClient("SERVICE-AB" ) //用于通知Feign组件对该接口进行代理(不需要编写接口实现), SERVICE-AB代理的具体服务
public interface HelloService {
    @RequestMapping("/info") //对应具体服务中的接口地址(具体服务controller 层的暴露接口)可以指定具体的get/post
    String hello();
}


Spring Cloud Feign 的容错,HystrixCommand定义被封装起来,没有办法通过@HystrixCommand注解的fallback,指定服务降级(错误处理)方法。但Spring Cloud Feign提供也更为简洁明了的方法实现服务降级处理。只需要编写一个feign接口的具体实现类即可,比如:

package com.springboot;
 
/**
 * Created by lizheng on 2017/9/4.
 */
public class HelloServiceFallback implements HelloService {
    @Override
    public String hello() {
 
        return "request error";
    }
}

同时在Fegin接口中做一下改变即可:

package com.springboot;
 
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
 
/**
 * Created by lizheng on 2017/7/21.
 */
@FeignClient(value = "SERVICE-AB", fallback = HelloServiceFallback.class) //用于通知Feign组件对该接口进行代理(不需要编写接口实现), SERVICE-AB代理的具体服务
public interface HelloService {
    @RequestMapping("/info") //对应具体服务中的接口地址(具体服务controller 层的暴露接口)
    String hello();
}

项目结构


Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里。通过Feign, 我们能把HTTP远程调用对开发者完全透明,得到与调用本地方法一致的编码体验。这一点与阿里Dubbo中暴露远程服务的方式类似,区别在于Dubbo是基于私有二进制协议,而Feign本质上还是个HTTP客户端。如果是在用Spring Cloud Netflix搭建微服务,那么Feign无疑是最佳选择。(此处文字参考:http://blog.csdn.net/neosmith/article/details/52449921)

这篇关于Spring Cloud的Ribbon-Hystrix-Feign的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1140306

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定