个网搭(三):1、搭建微服务project框架,加上网关模块

本文介绍了如何搭建一个SpringCloud项目,包括下载并部署Nacos作为注册中心和配置中心,以及在IDEA中创建项目并设置模块。详细步骤包括删除默认的src目录,初始化为Git项目,配置父项目的pom.xml,创建子module并引入服务发现和网关服务的依赖。此外,还展示了如何配置Nacos,实现动态路由,并提供了源码链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、下载微服务的nacos(注册中心+配置中心)

https://github.com/alibaba/nacos/releases
把Linux版的nacos-server-1.4.0.tar.gz下载下来
在服务器上解压 tar zxvf nacos-server-1.4.0.tar.gz
可以不改配置,默认集群启动,所以启动要加上-m standalone参数,我是直接修改/bin/startup.sh中的export MODE="standalone",然后nacos/bin/startup.sh直接启动,
访问http://192.168.1.178:8848/nacos,输入初始nacos/nacos登录。
看到是没有任何注册的服务,也没有配置的:
nacos页面

打开idea,搭建springcloud项目

  • 1、新建一个blog-parent项目,把src目录删掉,添加.gitignore文件,在根目录下执行git init初始化为git项目。
  • 2、为了便于统一管理所有依赖,直接在blog-parent的pom.xml文件中继承springboot parent,同时指定版本:
<?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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
    </parent>

    <groupId>org.lwr</groupId>
    <artifactId>blog-parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <spring.cloud.version>Hoxton.SR8</spring.cloud.version>
        <spring.cloud.alibaba.version>2.2.3.RELEASE</spring.cloud.alibaba.version>
    </properties>

    <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>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

</project>

解析:
1、<packaging>pom</packaging>表示父项目不打包
2、<dependencyManagement><scope>import</scope>表示引入spring-cloud和Alibaba的版本管理

  • 3、新建第一个子moduleblog-gateway(new -> module选择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>

    <parent>
        <artifactId>blog-parent</artifactId>
        <groupId>org.lwr</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>blog-gateway</artifactId>

    <dependencies>
        <!-- 注册到注册中心 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- 启动服务网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 使用jwt签名验证 -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.11.0</version>
        </dependency>
        <!-- 使用redis -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <!--
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>-->
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

说明:
1、继承blog-parent,使用统一的版本依赖,使用blog-parent的依赖
2、引入依赖:服务发现spring-cloud-starter-alibaba-nacos-discovery
3、引入依赖:网关服务:spring-cloud-starter-gateway
4、gateway一般需要做登录鉴权,使用jwt签名配合redis来做

  • 4、gateway模块的application.yml配置和启动类
server:
  port: 8080
spring:
  application:
    name: blog-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.178:8848
  redis:
    host: 192.168.1.178
    database: 8

#自定义配置中心参数
nacos:
  config:
    address: 192.168.1.178:8848
    data-id: blog.gateway.routes
    group-id: blog
    timeout: 5000

#启用监控
management:
  endpoints:
    web:
      exposure:
        include:
          - "*"  # 开放所有端点包括health,info,metrics
  endpoint:
    health:
      show-details: always

说明: server-addr: 192.168.1.178:8848指定nacos注册中心的地址

启动类:
说明:@EnableDiscoveryClient注解把服务注册到注册中

@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }

}
  • 5、在nacos配置中心添加data-id: blog.gateway.routes配置:
[
  {
    "id": "gateway-router",
    "order": 0,
    "predicates": [
      "Path=/gateway/**"
    ],
    "filters": [
      "RewritePath=/gateway/(?<segment>.*), /$\\{segment}"
    ],
    "uri": "lb://blog-gateway"
  },
  {
    "id": "auth-router",
    "order": 2,
    "predicates": [
      "Path=/auth/**"
    ],
    "filters": [
      "RewritePath=/auth/(?<segment>.*), /$\\{segment}"
    ],
    "uri": "lb://blog-auth"
  }
]
  • 6、动态路由配置类:

@Service
public class DynamicRouteService implements ApplicationEventPublisherAware {

    @Resource
    private RouteDefinitionRepository routeDefinitionRepository;

    private ApplicationEventPublisher publisher;

    /**
     * 手动刷新路由,立即生效
     */
    public void refreshRoutes() {
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
    }

    /**
     * 保存单个路由,id相同直接覆盖
     */
    public void save(RouteDefinition definition) {
        routeDefinitionRepository.save(Mono.just(definition)).subscribe();
    }

    /**
     * 删除单个路由
     */
    public void delete(String id) {
        routeDefinitionRepository.delete(Mono.just(id)).subscribe();
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }

    /**
     * 清空路由
     */
    public void removeAll() {
        routeDefinitionRepository.getRouteDefinitions().toStream().forEach(routeDefinition -> {
            routeDefinitionRepository.delete(Mono.just(routeDefinition.getId())).subscribe();
        });
    }
}
@Component
@Slf4j
public class DynamicNacosRouteConfig implements CommandLineRunner {
    @Resource
    private DynamicRouteService dynamicRouteService;
    @Resource
    private NacosRouteConfigProperties nacosRouteConfigProperties;
    @Resource
    private ObjectMapper mapper;

    @Override
    public void run(String... args) throws Exception {
        dynamicRouteByNacosListener();
        initRoutersByNacosConfig();
    }

    private void dynamicRouteByNacosListener() {
        try {
            ConfigService configService = NacosFactory.createConfigService(nacosRouteConfigProperties.getAddress());
            configService.addListener(nacosRouteConfigProperties.getDataId(), nacosRouteConfigProperties.getGroupId(), new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    refreshRouters(configInfo);
                }

                @Override
                public Executor getExecutor() {
                    return null;
                }
            });
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }

    /**
     * 项目启动时从nacos配置中心初始化网关路由
     */
    private void initRoutersByNacosConfig() {
        try {
            ConfigService configService = NacosFactory.createConfigService(nacosRouteConfigProperties.getAddress());
            String configInfo = configService.getConfig(nacosRouteConfigProperties.getDataId(), nacosRouteConfigProperties.getGroupId(), nacosRouteConfigProperties.getTimeout());
            if (configInfo != null) {
                refreshRouters(configInfo);
            }
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }

    private void refreshRouters(String configInfo) {
        log.info(configInfo);
        try {
            JavaType javaType = mapper.getTypeFactory().constructParametricType(ArrayList.class, RouteDefinition.class);
            List<RouteDefinition> list = mapper.readValue(configInfo, javaType);
            dynamicRouteService.removeAll();
            list.forEach(definition -> {
                dynamicRouteService.save(definition);
            });
            dynamicRouteService.refreshRoutes();
        } catch (JsonProcessingException e) {
            log.error(e.getMessage());
        }
    }

}
@Data
@Configuration
@ConfigurationProperties(prefix = "nacos.config")
public class NacosRouteConfigProperties {

    private String address;

    private String dataId;

    private String groupId;

    private Long timeout;
}

至此,网关模块就能跑起来了,等后面加入其他模块再动态加下路由即可。
源码我放到这里了:https://gitee.com/luckcy/blog-all/tree/gateway-init/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值