赞
踩
写在前面:有朋友私信作者,现在都是springcloud2.0时代了,能不能出nacos版本的教程,而且因为springcloud确实不太争气好多组件不维护了,就比如eureka,而且阿里nacos生态确实要比eureka好一点,还是那句话,网上也有很多优秀的教程或者说是博文,作者写这篇文章只是想记录一下曾经自己在项目过程中从0到1的一个过程,作者会从之前做过的一个简单企业级微服务架构系统来演示如何用springcloud-alibaba版本也是目前国内最流行的微服务开发
nacos官网
这是nacos官网的第一句话:Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
说人话:nacos其实就是把之前的服务注册中心(eureka)和配置中心(config)以及CAP理论中的CP和AP整合在一起的阿里开源的微服务注册和配置中心,阿里还是蛮diao的,言简意赅!
不多bb,开干,在这之前唯一要做的就是去官网下载nacos
这里作者用的是nacos2.1.0版本
修改bin目录下startup.cmd这里为standalone,默认是集群,我们本地改成单机就好,改好后双击启动并访问http://localhost:8848/nacos输入账号nacos密码nacos
作者这里采用的是maven聚合项目(父子项目)
给大家附上springboot-springcloud-springcloud-alibaba毕业版本依赖关系
作者这里用的是:
springboot 2.6.11
springcloud 2021.0.4
springcloud-alibaba 2021.0.4.0
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" 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.cawis</groupId> <artifactId>lightning</artifactId> <version>1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.11</version> <relativePath/> <!-- lookup parent from repository --> </parent> <name>lightning</name> <description>闪电系统</description> <packaging>pom</packaging> <properties> <java.version>8</java.version> <springcloud.version>2021.0.4</springcloud.version> <springcloud-alibaba.version>2021.0.4.0</springcloud-alibaba.version> </properties> <modules> <module>center-service</module> <module>flashquery-service</module> <module>gateway-service</module> </modules> <dependencies> <!--bootstrap.yml支持--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> <!--openfign和gateway的新负载均衡器--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency> <!-- knife4j提供的微服务starter --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-micro-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.18.Final</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.18</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.71</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.clickhouse</groupId> <artifactId>clickhouse-jdbc</artifactId> <version>0.4.6</version> </dependency> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc8</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>cn.easyproject</groupId> <artifactId>orai18n</artifactId> <version>12.1.0.2.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</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> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${springcloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${springcloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
项目结构
<?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>com.cawis</groupId> <artifactId>lightning</artifactId> <version>1.0</version> </parent> <groupId>com.cawis</groupId> <artifactId>flashquery-service</artifactId> <version>1.0</version> <name>flashquery-service</name> <description>雷电查询服务</description> <properties> <java.version>8</java.version> </properties> <dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> </dependencies> <repositories> <repository> <id>osgeo</id> <name>OSGeo Release Repository</name> <url>https://repo.osgeo.org/repository/release/</url> <snapshots> <enabled>false</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> </repository> </repositories> </project>
新在nacos里面创建一个命名空间lighting
在lighting命名空间里面新建一个flashquery-service的配置并保存配置信息
这里一定要选YAML
nacos中flashquery-service的配置
server: port: 10010 spring: mvc: pathmatch: matching-strategy: ANT_PATH_MATCHER #还原swagger扫描方式 datasource: url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=true driver-class-name: com.mysql.cj.jdbc.Driver username: root password: your密码 redis: host: 127.0.0.1 port: 6379 password: your密码 # datasource: # url: jdbc:postgresql://127.0.0.1:5432/pms30app_db?currentSchema=power_met # driver-class-name: org.postgresql.Driver # username: postgres # password: 123456 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mybatis-plus: type-aliases-package: com.cawis configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl call-setters-on-nulls: true #日志配置 logging: level: org: springframework: INFO file: name: /logs/${spring.application.name}.log
本地bootstrap.yml
spring:
application:
name: flashquery-service #服务名-对应nacos中的Data Id
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: adc3ed94-a259-4ef6-924f-074a63f6e65d #命名空间ID
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${spring.cloud.nacos.discovery.namespace}
file-extension: yml
统一返回对象类
package com.cawis.common; import lombok.*; import lombok.experimental.Accessors; import java.io.Serializable; /** * 响应信息主体 * * @param <T> * @author lengleng */ @ToString @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class R<T> implements Serializable { private static final long serialVersionUID = 1L; @Getter @Setter private int code; @Getter @Setter private String msg; @Getter @Setter private T data; public static <T> R<T> ok() { return restResult(null, 0, null); } public static <T> R<T> ok(T data) { return restResult(data, 0, null); } public static <T> R<T> ok(T data, String msg) { return restResult(data, 0, msg); } public static <T> R<T> failed() { return restResult(null, 1, null); } public static <T> R<T> failed(String msg) { return restResult(null, 1, msg); } public static <T> R<T> failed(T data) { return restResult(data, 1, null); } public static <T> R<T> failed(T data, String msg) { return restResult(data, 1, msg); } public static <T> R<T> restResult(T data, int code, String msg) { R<T> apiResult = new R<>(); apiResult.setCode(code); apiResult.setData(data); apiResult.setMsg(msg); return apiResult; } }
各种配置类
package com.cawis.config; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.TimeZone; //springboot高版本日期格式化 @Configuration public class DateFormatConfiguration { @Bean Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(@Value("${spring.jackson.date-format}") String pattern, @Value("${spring.jackson.time-zone}") String timeZone) { return (builder) -> { DateFormat dateFormat = new SimpleDateFormat(pattern); dateFormat.setTimeZone(TimeZone.getTimeZone(timeZone)); // Date builder.dateFormat(dateFormat); // LocalDateTime // 序列化LocalDateTime builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern))); // 反序列化LocalDateTime builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(pattern))); // TimeZone builder.timeZone(TimeZone.getTimeZone(timeZone)); }; } }
package com.cawis.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class Knife4jConfiguration { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).pathMapping("/").select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("雷电查询服务").description("雷电查询服务").version("1.0").contact(new Contact("一剑光寒", "", "")).license("Home").licenseUrl("http://127.0.0.1:19090/doc.html").build(); } }
package com.cawis.config; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MybatisPlusConfiguration { // @Bean // public PaginationInterceptor paginationInterceptor() { // PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false // // paginationInterceptor.setOverflow(false); // // 设置最大单页限制数量,默认 500 条,-1 不受限制 // // paginationInterceptor.setLimit(500); // // 开启 count 的 join 优化,只针对部分 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); // return paginationInterceptor; // } @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } }
package com.cawis.config; import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; @Configuration public class RedisConfig { @Bean public RedisTemplate redisTemplate(RedisConnectionFactory factory) { RedisTemplate template = new RedisTemplate(); template.setConnectionFactory(factory); //redis序列化--key采用String的序列化方式,value采用json的序列化方式 // template.setKeySerializer(RedisSerializer.string()); // template.setHashKeySerializer(RedisSerializer.string()); // template.setValueSerializer(RedisSerializer.json()); // template.setHashValueSerializer(RedisSerializer.json()); //Jackson序列化--key采用String的序列化方式,value采用Jackson的序列化方式 // Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); // //序列化包括类型描述 否则反向序列化实体会报错,一律都为JsonObject // ObjectMapper mapper = new ObjectMapper(); // mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); // jackson2JsonRedisSerializer.setObjectMapper(mapper); // template.setKeySerializer(RedisSerializer.string()); // template.setHashKeySerializer(RedisSerializer.string()); // template.setValueSerializer(jackson2JsonRedisSerializer); // template.setHashValueSerializer(jackson2JsonRedisSerializer); //FastJson序列化--key采用String的序列化方式,value采用FastJson的序列化方式 GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer(); template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); template.setValueSerializer(fastJsonRedisSerializer); template.setHashValueSerializer(fastJsonRedisSerializer); template.afterPropertiesSet(); return template; } }
package com.cawis.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfiguration implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedOriginPatterns("*").allowedHeaders("*").allowedMethods("*").maxAge(3600).allowCredentials(true); } }
对象实体类
package com.cawis.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @Data @TableName("flash") public class Flash { // @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") @TableField("TIMEDATE") Object TIMEDATE; @TableField("XSECOND") Object XSECOND; @TableField("LATITUDE") Object LATITUDE; @TableField("LONGITUDE") Object LONGITUDE; @TableField("PEAKCURRENT") Object PEAKCURRENT; @TableField("MULTIPLICITY") Object MULTIPLICITY; @TableField("HOSTID") Object HOSTID; @TableField("TDFSUM") Object TDFSUM; @TableField("TDFVALUE") Object TDFVALUE; @TableField("TDFVALUESTRING") Object TDFVALUESTRING; @TableField("GOODTIME") Object GOODTIME; @TableField("ACCORDANCE") Object ACCORDANCE; @TableField("MODIFIEDTIMEDATE") Object MODIFIEDTIMEDATE; @TableField("MEANANGLEERROR") Object MEANANGLEERROR; @TableField("ELLIPSESEMIMAJOR") Object ELLIPSESEMIMAJOR; @TableField("ELLIPSESEMIMINOR") Object ELLIPSESEMIMINOR; @TableField("ELLIPSEANGLE") Object ELLIPSEANGLE; @TableField("FLAG") Object FLAG; @TableField("GUID") Object GUID; @TableField("RAWID") Object RAWID; }
Mapper
package com.cawis.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cawis.entity.Flash;
import java.util.List;
import java.util.Map;
public interface FlashMapper extends BaseMapper<Flash> {
List<Map<String, Object>> dataList(String listName, Integer lineId);
}
XML
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cawis.mapper.FlashMapper"> <select id="dataList" resultType="java.util.Map"> SELECT a.LISTID, a.PROVINCE, a.BUREAU, a.COUNTY, a.PRESSURE, a.LIST_NAME, b.LONGITUDE, b.LATITUDE, b.SERIAL_NUMBER FROM list a JOIN DATA b ON a.`LISTID` = b.`LISTID` <where> <if test="listName != null and listName != ''"> AND a.LIST_NAME LIKE CONCAT('%' ,#{listName}, '%' ) </if> <if test="lineId != null and lineId != ''"> AND a.LISTID=#{lineId} </if> </where> order by SERIAL_NUMBER </select> </mapper>
service
package com.cawis.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.cawis.entity.Flash; import java.util.List; import java.util.Map; public interface FlashService extends IService<Flash> { Page selectPage(String startTime, String endTime, Integer current, Integer pageSize); List<Map<String, Object>> dataList(String listName, Integer lineId); }
service实现类
package com.cawis.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.cawis.entity.Flash; import com.cawis.mapper.FlashMapper; import com.cawis.service.FlashService; import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class FlashServiceImpl extends ServiceImpl<FlashMapper, Flash> implements FlashService { @Override public Page selectPage(String startTime, String endTime, Integer current, Integer pageSize) { QueryWrapper qw = new QueryWrapper(); qw.between("timedate", startTime, endTime); Page page = baseMapper.selectPage(new Page(current, pageSize), qw); return page; } @Override public List<Map<String, Object>> dataList(String listName, Integer lineId) { return this.baseMapper.dataList(listName, lineId); } }
controller
package com.cawis.controller; import com.cawis.common.R; import com.cawis.service.FlashService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Api(tags = "雷电查询服务接口") @RestController @RequiredArgsConstructor public class FlashController { private final FlashService flashService; @ApiOperation(value = "雷电信息查询", notes = "雷电信息查询") @GetMapping("flashList") public R flashList(String startTime, String endTime, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer pageSize) { return R.ok(flashService.selectPage(startTime, endTime, current, pageSize)); } @ApiOperation(value = "线路杆塔关联查询", notes = "线路杆塔关联查询") @GetMapping("dataList") public R dataList(String lineName, Integer lineId) { return R.ok(flashService.dataList(lineName, lineId)); } }
启动类
package com.cawis; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan("com.cawis.mapper") @SpringBootApplication public class FlashqueryServiceApplication { public static void main(String[] args) { SpringApplication.run(FlashqueryServiceApplication.class, args); } }
数据库表SQL
CREATE TABLE `flash` ( `TIMEDATE` datetime NOT NULL, `XSECOND` int(11) NOT NULL, `LATITUDE` decimal(10,6) DEFAULT NULL, `LONGITUDE` decimal(10,6) DEFAULT NULL, `PEAKCURRENT` decimal(5,1) DEFAULT NULL, `MULTIPLICITY` smallint(6) DEFAULT NULL, `HOSTID` smallint(6) NOT NULL, `TDFSUM` smallint(6) DEFAULT NULL, `TDFVALUE` float DEFAULT NULL, `TDFVALUESTRING` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, `GOODTIME` smallint(6) DEFAULT NULL, `ACCORDANCE` smallint(6) DEFAULT NULL, `MODIFIEDTIMEDATE` datetime DEFAULT NULL, `MEANANGLEERROR` int(11) DEFAULT NULL, `ELLIPSESEMIMAJOR` int(11) DEFAULT NULL, `ELLIPSESEMIMINOR` int(11) DEFAULT NULL, `ELLIPSEANGLE` smallint(6) DEFAULT NULL, `FLAG` smallint(6) DEFAULT NULL, `GUID` bigint(20) DEFAULT NULL, `RAWID` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, PRIMARY KEY (`TIMEDATE`,`XSECOND`,`HOSTID`) USING BTREE, KEY `timedate_index` (`TIMEDATE`) USING BTREE, KEY `timedate_bbox_index` (`LATITUDE`,`LONGITUDE`) USING BTREE, KEY `timedate_host` (`HOSTID`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
插入测试数据
INSERT INTO `test`.`flash`(`TIMEDATE`, `XSECOND`, `LATITUDE`, `LONGITUDE`, `PEAKCURRENT`, `MULTIPLICITY`, `HOSTID`, `TDFSUM`, `TDFVALUE`, `TDFVALUESTRING`, `GOODTIME`, `ACCORDANCE`, `MODIFIEDTIMEDATE`, `MEANANGLEERROR`, `ELLIPSESEMIMAJOR`, `ELLIPSESEMIMINOR`, `ELLIPSEANGLE`, `FLAG`, `GUID`, `RAWID`) VALUES ('2021-07-29 15:40:01', 7109960, 30.486849, 121.131300, 7.4, 1, 1, 4, 57471.7, '22-103.106.107|23-110', 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `test`.`flash`(`TIMEDATE`, `XSECOND`, `LATITUDE`, `LONGITUDE`, `PEAKCURRENT`, `MULTIPLICITY`, `HOSTID`, `TDFSUM`, `TDFVALUE`, `TDFVALUESTRING`, `GOODTIME`, `ACCORDANCE`, `MODIFIEDTIMEDATE`, `MEANANGLEERROR`, `ELLIPSESEMIMAJOR`, `ELLIPSESEMIMINOR`, `ELLIPSEANGLE`, `FLAG`, `GUID`, `RAWID`) VALUES ('2021-07-29 15:40:07', 4652077, 30.417373, 121.655155, -92.7, 2, 1, 27, 98707.3, '15-53.54|22-101.104.105.107.108|23-102.103.110.111.112.113.116|24-9.12|32-17|34-109.114|41-101.107.113.115|251-101.104.109.116', 17, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO `test`.`flash`(`TIMEDATE`, `XSECOND`, `LATITUDE`, `LONGITUDE`, `PEAKCURRENT`, `MULTIPLICITY`, `HOSTID`, `TDFSUM`, `TDFVALUE`, `TDFVALUESTRING`, `GOODTIME`, `ACCORDANCE`, `MODIFIEDTIMEDATE`, `MEANANGLEERROR`, `ELLIPSESEMIMAJOR`, `ELLIPSESEMIMINOR`, `ELLIPSEANGLE`, `FLAG`, `GUID`, `RAWID`) VALUES ('2021-07-29 15:40:07', 4971358, 30.413452, 121.671058, -12.6, -1, 1, 9, 48811.7, '22-101.104.105.106.107|23-102.110|251-109.117', 9, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
启动主启动类并访问http://localhost:10010/doc.html,国产swagger接口文档knife(小刀子)
输入查询时间并查看返回数据
项目结构
<?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>com.cawis</groupId> <artifactId>lightning</artifactId> <version>1.0</version> </parent> <groupId>com.cawis</groupId> <artifactId>center-service</artifactId> <version>1.0</version> <name>center-service</name> <description>调用中心服务</description> <dependencies> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> </dependencies> </project>
在lighting命名空间里面新建一个center-service的配置并保存配置信息
nacos中center-service的配置
server: port: 10086 spring: mvc: pathmatch: matching-strategy: ANT_PATH_MATCHER #还原swagger扫描方式 redis: host: 127.0.0.1 port: 6379 password: your密码 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 feign: sentinel: enabled: true #日志配置 logging: level: org: springframework: INFO file: name: /logs/${spring.application.name}.log
本地的bootstrap.yml
spring:
application:
name: center-service #服务名-对应nacos中的Data Id
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: adc3ed94-a259-4ef6-924f-074a63f6e65d #命名空间ID
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${spring.cloud.nacos.discovery.namespace}
file-extension: yml
统一返回对象
package com.cawis.common; import lombok.*; import lombok.experimental.Accessors; import java.io.Serializable; /** * 响应信息主体 * * @param <T> * @author lengleng */ @ToString @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class R<T> implements Serializable { private static final long serialVersionUID = 1L; @Getter @Setter private int code; @Getter @Setter private String msg; @Getter @Setter private T data; public static <T> R<T> ok() { return restResult(null, 0, null); } public static <T> R<T> ok(T data) { return restResult(data, 0, null); } public static <T> R<T> ok(T data, String msg) { return restResult(data, 0, msg); } public static <T> R<T> failed() { return restResult(null, 1, null); } public static <T> R<T> failed(String msg) { return restResult(null, 1, msg); } public static <T> R<T> failed(T data) { return restResult(data, 1, null); } public static <T> R<T> failed(T data, String msg) { return restResult(data, 1, msg); } public static <T> R<T> restResult(T data, int code, String msg) { R<T> apiResult = new R<>(); apiResult.setCode(code); apiResult.setData(data); apiResult.setMsg(msg); return apiResult; } }
各种配置类
package com.cawis.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class Knife4jConfiguration { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).pathMapping("/").select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any()).build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder().title("调用中心服务").description("调用中心服务").version("1.0").contact(new Contact("一剑光寒", "", "")).license("Home").licenseUrl("http://127.0.0.1:19090/doc.html").build(); } }
package com.cawis.config; import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; @Configuration public class RedisConfig { @Bean public RedisTemplate redisTemplate(RedisConnectionFactory factory) { RedisTemplate template = new RedisTemplate(); template.setConnectionFactory(factory); //redis序列化--key采用String的序列化方式,value采用json的序列化方式 // template.setKeySerializer(RedisSerializer.string()); // template.setHashKeySerializer(RedisSerializer.string()); // template.setValueSerializer(RedisSerializer.json()); // template.setHashValueSerializer(RedisSerializer.json()); //Jackson序列化--key采用String的序列化方式,value采用Jackson的序列化方式 // Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); // //序列化包括类型描述 否则反向序列化实体会报错,一律都为JsonObject // ObjectMapper mapper = new ObjectMapper(); // mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); // jackson2JsonRedisSerializer.setObjectMapper(mapper); // template.setKeySerializer(RedisSerializer.string()); // template.setHashKeySerializer(RedisSerializer.string()); // template.setValueSerializer(jackson2JsonRedisSerializer); // template.setHashValueSerializer(jackson2JsonRedisSerializer); //FastJson序列化--key采用String的序列化方式,value采用FastJson的序列化方式 GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer(); template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); template.setValueSerializer(fastJsonRedisSerializer); template.setHashValueSerializer(fastJsonRedisSerializer); template.afterPropertiesSet(); return template; } }
feign客户端
package com.cawis.feign; import com.cawis.common.R; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; @FeignClient("flashquery-service") public interface MyFeignClient { @GetMapping("flashList") R flashList(@RequestParam String startTime, @RequestParam String endTime, @RequestParam Integer current, @RequestParam Integer pageSize); @GetMapping("dataList") R dataList(@RequestParam String lineName, @RequestParam Integer lineId); }
远程调用的controller
package com.cawis.controller; import com.cawis.feign.MyFeignClient; import com.cawis.util.RedisUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @Slf4j @RestController public class MyController { @Resource RedisUtils redisUtils; @Resource MyFeignClient myFeignClient; @GetMapping("/flashList") public Object flashList(@RequestParam(defaultValue = "2021-07-29 15:00:00") String startTime, @RequestParam(defaultValue = "2021-07-30 15:00:00") String endTime, @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer pageSize) { return myFeignClient.flashList(startTime, endTime, current, pageSize); } @GetMapping("/dataList") public Object dataList(String lineName, Integer lineId) { return myFeignClient.dataList(lineName, lineId); } }
主启动类
package com.cawis; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; @EnableFeignClients @SpringBootApplication public class CenterServiceApplication { public static void main(String[] args) { SpringApplication.run(CenterServiceApplication.class, args); } }
启动主启动类并访问http://localhost:10086/doc.html
输入查询时间条件并查看flashquery-service控制台可以看到接口远程调用成功
项目结构
<?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.6.11</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.cawis</groupId> <artifactId>gateway-service</artifactId> <version>1.0</version> <name>gateway-service</name> <description>网关服务</description> <properties> <java.version>8</java.version> <springcloud-version>2021.0.4</springcloud-version> <springcloud-alibaba.version>2021.0.4.0</springcloud-alibaba.version> </properties> <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.18.Final</version> </dependency> <!--gateway依赖于webflux而不是webmvc所以要单独生成pom依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--bootstrap.yml支持--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> <!--openfign和gateway的新负载均衡器--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${springcloud-version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${springcloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
在lighting命名空间里面新建一个gateway-service的配置并保存配置信息
nacos中gateway-service的配置
server: port: 18080 spring: cloud: gateway: routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务] - id: center-service # 当前路由的标识, 要求唯一,可以随便写 uri: lb://center-service # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略 predicates: # 断言(就是路由转发要满足的条件) - Path=/centerservice/** # 当请求路径满足Path指定的规则时,才进行路由转发 filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改 - StripPrefix=1 # 转发之前去掉1层路径 - id: flashquery-service uri: lb://flashquery-service predicates: - Path=/flashqueryservice/** filters: - StripPrefix=1 sentinel: transport: dashboard: 127.0.0.1:8080 discovery: locator: enabled: true #让gateway可以发现nacos中的微服务 lower-case-service-id: true #使用小写服务名,默认是大写 #日志配置 logging: level: org: springframework: INFO file: name: /logs/${spring.application.name}.log #自定义配置 config: excludes: http://127.0.0.1:18080
本地bootstrap.yml
spring:
application:
name: gateway-service #服务名-对应nacos中的Data Id
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: adc3ed94-a259-4ef6-924f-074a63f6e65d #命名空间ID
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${spring.cloud.nacos.discovery.namespace}
file-extension: yml
这里要说一下,这里的网关作者改进了一下,配置了Swagger接口文档的统一访问以及基于网关层面的跨域配置,这是微服务企业级开发中的常规操作
全局过滤配置类
package com.cawis.config; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.ObjectUtils; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.reactive.CorsWebFilter; import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.net.URI; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @Slf4j @Configuration public class GatewayFilter implements GlobalFilter, Ordered { /** * 忽略的URL */ @Value("${config.excludes}") private String[] excludes; /** * 跨域-Origin * * @return */ @Bean public CorsWebFilter corsFilter() { CorsConfiguration cors = new CorsConfiguration(); cors.setAllowedOriginPatterns(Collections.singletonList("*")); for (String exclude : excludes) { cors.addAllowedOrigin(exclude); } cors.addAllowedHeader(CorsConfiguration.ALL); cors.addAllowedMethod(CorsConfiguration.ALL); cors.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", cors); return new CorsWebFilter(source); } /** * 防盗链-Referer * * @param exchange * @param chain * @return */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); Map<String, String> headers = request.getHeaders().toSingleValueMap(); String referer = headers.get(HttpHeaders.REFERER); URI uri = request.getURI(); //已忽略的URL不拦截 if (isExcludeUrl(referer + uri.getPath())) { return chain.filter(exchange); } //是否存在外链请求本站 if ((null != referer && referer.indexOf(uri.getHost()) < 0)) { log.info("Referer过滤器 => 服务器:{} => 当前域名:{} => 当前url:{}", uri.getHost(), referer, uri.getPath()); Map data = new HashMap<>(); data.put("code", 1002); data.put("data", "系统不支持当前域名访问"); DataBuffer dataBuffer = response.bufferFactory().wrap(JSONObject.toJSONString(data).getBytes()); response.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); return response.writeWith(Mono.just(dataBuffer)); } return chain.filter(exchange); } @Override public int getOrder() { return -1; } /** * 判断是否为忽略的URL * * @param url URL路径 * @return true-忽略,false-过滤 */ private boolean isExcludeUrl(String url) { if (ObjectUtils.isEmpty(excludes)) { return false; } return Arrays.asList(excludes).stream().map(pattern -> Pattern.compile("^" + pattern)).map(p -> p.matcher(url)).anyMatch(Matcher::find); } }
Swagger资源配置类
package com.cawis.config; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResourcesProvider; import java.util.ArrayList; import java.util.List; /** * Swagger资源配置 */ @Slf4j @Component @Primary @AllArgsConstructor public class SwaggerResourceConfig implements SwaggerResourcesProvider { private final RouteLocator routeLocator; private final GatewayProperties gatewayProperties; @Override public List<SwaggerResource> get() { List<SwaggerResource> resources = new ArrayList<>(); List<String> routes = new ArrayList<>(); //获取所有路由的ID routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); //过滤出配置文件中定义的路由->过滤出Path Route Predicate->根据路径拼接成api-docs路径->生成SwaggerResource gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> { route.getPredicates().stream() .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())) .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(), predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") .replace("**", "v2/api-docs")))); }); return resources; } private SwaggerResource swaggerResource(String name, String location) { log.info("name:{},location:{}", name, location); SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setName(name); swaggerResource.setLocation(location); swaggerResource.setSwaggerVersion("2.0"); return swaggerResource; } }
Sentinel全局异常捕获类
package com.cawis.handler; import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter; import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler; import com.alibaba.csp.sentinel.slots.block.BlockException; import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException; import com.alibaba.csp.sentinel.slots.block.flow.FlowException; import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException; import com.alibaba.fastjson.JSON; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Hashtable; import java.util.Map; @Configuration public class SentinelExceptionHandler implements BlockExceptionHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception { Map data = new Hashtable(); String msg = "未知异常"; int status = 429; if (e instanceof FlowException) { msg = "请求被限流了"; } else if (e instanceof ParamFlowException) { msg = "请求被热点参数限流"; } else if (e instanceof DegradeException) { msg = "请求被降级了"; } else if (e instanceof AuthorityException) { msg = "没有权限访问"; status = 401; } response.setContentType("application/json;charset=utf-8"); response.setStatus(status); data.put("data", msg); data.put("status", status); response.getWriter().println(JSON.toJSONString(data)); } @Bean @Order(0) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } }
Swagger网关访问控制类
package com.cawis.handler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; import springfox.documentation.swagger.web.*; import java.util.Optional; /** * 自定义Swagger的各个配置节点 */ @RestController public class SwaggerHandler { @Autowired(required = false) private SecurityConfiguration securityConfiguration; @Autowired(required = false) private UiConfiguration uiConfiguration; private final SwaggerResourcesProvider swaggerResources; @Autowired public SwaggerHandler(SwaggerResourcesProvider swaggerResources) { this.swaggerResources = swaggerResources; } /** * Swagger安全配置,支持oauth和apiKey设置 */ @GetMapping("/swagger-resources/configuration/security") public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() { return Mono.just(new ResponseEntity<>( Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK)); } /** * Swagger UI配置 */ @GetMapping("/swagger-resources/configuration/ui") public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() { return Mono.just(new ResponseEntity<>( Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); } /** * Swagger资源配置,微服务中这各个服务的api-docs信息 */ @GetMapping("/swagger-resources") public Mono<ResponseEntity> swaggerResources() { return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); } }
主启动类
package com.cawis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayServiceApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServiceApplication.class, args);
}
}
启动网关主启动类并访问http://localhost:18080/doc.html可以看到网关里面配置的服务的接口都被统一管理起来
调用flashquery-service接口并输入查询条件发现接口调用成功
调用center-service接口并输入查询条件发现接口远程调用成功
写在最后:至此springcloud-alibaba版本整合完成,这个是之前作者实际开发项目升级而来,抽取了其中作者认为最核心的一些模块分享,能给兄弟们带来一点点帮助就很满足了,加油~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。