学习目标:
在项目中出现异常是在所难免的,但是出现异常后怎么处理?
默认我们需要service层的异常需要抛出,而servcie层被Spring管理,默认Spring的事务回滚只对RunTimeException起作用,所以我们要把service层的编译器异常转换为运行时异常抛出。
只有这种异常不需要影响业务,或者通过这种异常可以执行其他业务,我们才需要try
我们预设这样一个场景,假如我们做新增商品,需要接收下面的参数:
price:价格 name:名称
在gmall-model
中编写实体类,该实体类无实际业务仅为测试使用:
@Data
public class Item {
private Integer id;
private String name;
private Long price;
}
controller:
package com.atguigu.gmall.product.controller;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.product.model.Item;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("admin")
public class ItemController {
@PostMapping("item")
public Result<Item> saveItem(Item item) {
// 模拟业务执行出现异常
int i = 1/0;
// 保存业务
System.out.println("保存成功");
return Result.build(item, ResultCodeEnum.SUCCESS);
}
}
项目开发中肯定会设置全局异常处理,不管系统发生了任何不可知的异常信息,都应该给用户返回友好提示信息。
在service-util
模块中新建类:GlobalExceptionHandler
package com.atguigu.gmall.common.config;
import com.atguigu.gmall.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理
* 作用:拦截到controller层异常,将异常结果统一进行友好返回 返回表中响应结果Result
*
* @author: atguigu
* @create: 2022-12-23 10:38
*/
@Slf4j
@RestControllerAdvice // @ControllerAdvice+@ResponseBody
public class GlobalExceptionHandler {
/**
* 处理运行时异常
*
* @param e
* @return
*/
@ExceptionHandler(RuntimeException.class)
public Result error(RuntimeException e) {
log.error("全局运行时异常,{}", e);
return Result.fail();
}
/**
* 处理异常
*
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public Result error(Exception e) {
log.error("全局异常,{}", e);
return Result.fail();
}
}
在业务微服务模块中启动类所在包为:com.atguigu.gmall 会自动的扫描到service-util
模块中全局异常处理类。
一定要保证启动类能够扫描service-util模块中全局异常处理类,否则会出现全局异常捕获失效。
不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:
以上这些问题可以借助网关解决。
网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 网关来做,这样既提高业务灵活性又不缺安全性,典型的架构图如图所示:
优点如下:
总结:微服务网关就是一个系统,通过暴露该微服务网关系统,方便我们进行相关的鉴权,安全控制,日志统一处理,易于监控的相关功能。
实现微服务网关的技术有很多,
我们使用gateway这个网关技术,无缝衔接到基于spring cloud的微服务开发中来。
gateway官网:
https://spring.io/projects/spring-cloud-gateway
点击gmall-parent
,选择New–>Module,操作如下
点击下一步
点击下一步
点击完成
修改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">
<parent>
<artifactId>gmall-parent</artifactId>
<groupId>com.atguigu.gmall</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gmall-gateway</artifactId>
<dependencies>
<dependency>
<groupId>com.atguigu.gmall</groupId>
<artifactId>common-util</artifactId>
<version>1.0</version>
</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>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
</project>
启动类:
package com.atguigu.gmall;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author: atguigu
* @create: 2022-12-23 10:50
*/
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApp {
public static void main(String[] args) {
SpringApplication.run(GatewayApp.class, args);
}
}
在resources 目录下新建配置文件:application.yml
server:
port: 80
spring:
application:
name: server-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.200.128:8848
gateway:
discovery: #是否与服务发现组件进行结合,通过 serviceId(必须设置成大写) 转发到具体的服务实例。默认为false,设为true便开启通过服务中心的自动根据 serviceId 创建路由的功能。
locator: #路由访问方式:http://Gateway_HOST:Gateway_PORT/大写的serviceId/**,其中微服务应用名默认大写访问。
enabled: true
routes:
- id: service-product
uri: lb://service-product
predicates:
- Path=/*/product/** # 路径匹配
拷贝配套资料中的前端项目页面,放入一个没有中文目录的文件下
这是一个用nodejs构建的项目,解压后进入项目根目录,打开cmd窗口执行:
npm install [安装依赖 node_modules] 项目库中有node_modules 就不需要执行npm install(已有)
npm run dev
将两个配置文件 注:第一个为网关地址,第二个为项目访问地址
/config/dev.env.js http://127.0.0.1或者http://api.gmall.com
/config/index.js host: 'localhost', port: 8888
在idea里引入工程,需要idea中配置
注意:如果出现未找到node-sass模块,只需要在窗口中运行
npm install node-sass 即可,然后重新npm install node-sass,npm run dev 运行项目的时候,没有提示node-sass 模块未找到,需要看一下当前的nodejs 版本
node -v : 建议v10.14.3
可以通过8888端口即可访问:
进入首页后,点击左侧菜单"基本信息管理"->"平台属性列表"发现页面没有如期显示分类以及属性信息,打开浏览器调试工具查看console
选项查看控制台报错信息如下:原因为跨域问题
跨域:浏览器对于javascript的同源策略的限制 。
以下情况都属于跨域:
跨域原因说明 | 示例 |
---|---|
域名不同 | www.jd.com 与 www.taobao.com |
域名相同,端口不同 | www.jd.com:8080 与 www.jd.com:8081 |
二级域名不同 | item.jd.com 与 miaosha.jd.com |
如果域名和端口都相同,但是请求路径不同,不属于跨域,如:
www.jd.com/item
www.jd.com/goods
http和https也属于跨域
而我们刚才是从manager.gmall.com
去访问api.gmall.com
,这属于域名不同,跨域了。
跨域不一定都会有跨域问题。
因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能与当前页域名相同的路径,这能有效的阻止跨站攻击。
因此:跨域问题 是针对ajax的一种限制。
但是这却给我们的开发带来了不便,而且在实际生产环境中,肯定会有很多台服务器之间交互,地址和端口都可能不同,怎么办?
目前比较常用的跨域解决方案有3种:
最早的解决方案,利用script标签可以跨域的原理实现。
限制:
只能发起GET请求
nginx反向代理
思路是:利用nginx把跨域反向代理为不跨域,支持各种请求方式
缺点:需要在nginx进行额外配置,语义不清晰
规范化的跨域请求解决方案,安全可靠。
优势:
缺点:
我们这里会采用cors的跨域方案。
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
目前,所有浏览器都支持该功能(IE10以下不行)。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。
CORS通信与AJAX没有任何差别,因此你不需要改变以前的业务逻辑。只不过,浏览器会在请求中携带一些头信息,我们需要以此判断是否允许其跨域,然后在响应头中加入一些信息即可。这一般通过过滤器完成即可。
预检请求
跨域请求会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错。
一个“预检”请求的样板:
OPTIONS /cors HTTP/1.1
Origin: http://localhost:1000
Access-Control-Request-Method: GET
Access-Control-Request-Headers: X-Custom-Header
User-Agent: Mozilla/4.0...
Origin:会指出当前请求属于哪个域(协议+域名+端口)。服务会根据这个值决定是否允许其跨域。
Access-Control-Request-Method:接下来会用到的请求方式,比如PUT
Access-Control-Request-Headers:会额外用到的头信息
预检请求的响应
服务的收到预检请求,如果许可跨域,会发出响应:
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://miaosha.jd.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 1728000
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
如果服务器允许跨域,需要在返回的响应头中携带下面信息:
有关cookie:
要想操作cookie,需要满足3个条件:
虽然原理比较复杂,但是前面说过:
事实上,SpringCloudGateway中只需要注册过滤器对象,内部已经实现了刚才所讲的判定逻辑。我们只需编写跨域规则即可:
package com.atguigu.gmall.gateway.filter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
/**
* 配置CORS过滤器,解决跨域问题
*
* @author: atguigu
* @create: 2022-12-23 14:08
*/
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
//1.配置CORS跨域规则
CorsConfiguration corsConfiguration = new CorsConfiguration();
//1.1设置允许哪些域名可以跨域访问 * 开发测试中方便 上线有改为真实服务器地址
corsConfiguration.addAllowedOrigin("*");
//1.2设置是否允许提交cookie
corsConfiguration.setAllowCredentials(true);
//1.3设置允许提交方法 PUT DELETE POST GET
corsConfiguration.addAllowedMethod("*");
//1.4设置允许提交头信息
corsConfiguration.addAllowedHeader("*");
//1.5设置预检请求有效期
corsConfiguration.setMaxAge(3600L);
//2.注册CORS配置
UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
//第一个参数:设置过滤器拦截请求 第二个参数:Cors跨域规则
configurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsWebFilter(configurationSource);
}
}
在后台管理页面中测试:
mybatis-plus-code
模块导入到idea中CodeGenerator
中生成方法数据库中的表!
YAPI接口地址:http://192.168.200.128:3000/project/11/interface/api/211
新建BaseAttrInfoController
中增加方法处理保存属性方法
package com.atguigu.gmall.product.controller;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.product.model.BaseAttrInfo;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.atguigu.gmall.product.service.BaseAttrInfoService;
import org.springframework.web.bind.annotation.RestController;
/**
* 属性表 前端控制器
* @author atguigu
* @since 2022-12-12
*/
@RestController
@RequestMapping("admin/product")
@Api(tags = "属性表控制器")
public class BaseAttrInfoController{
@Autowired
private BaseAttrInfoService baseAttrInfoService;
/**
* 保存平台属性方法
* @param baseAttrInfo
* @return
*/
@PostMapping("saveAttrInfo")
public Result saveAttrInfo(@RequestBody BaseAttrInfo baseAttrInfo) {
// 前台数据都被封装到该对象中baseAttrInfo
baseAttrInfoService.saveAttrInfo(baseAttrInfo);
return Result.ok();
}
}
业务层接口BaseAttrInfoService中新增方法
package com.atguigu.gmall.product.service;
import com.atguigu.gmall.product.model.BaseAttrInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* 属性表 业务接口类
* @author atguigu
* @since 2022-12-12
*/
public interface BaseAttrInfoService extends IService<BaseAttrInfo> {
/**
* 保存平台属性方法
* @param baseAttrInfo
*/
void saveAttrInfo(BaseAttrInfo baseAttrInfo);
}
业务层实现类BaseAttrInfoServiceImpl
实现方法
package com.atguigu.gmall.product.service.impl;
import com.atguigu.gmall.product.mapper.BaseAttrInfoMapper;
import com.atguigu.gmall.product.mapper.BaseAttrValueMapper;
import com.atguigu.gmall.product.model.BaseAttrInfo;
import com.atguigu.gmall.product.model.BaseAttrValue;
import com.atguigu.gmall.product.service.BaseAttrInfoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.List;
/**
* @author: atguigu
* @create: 2022-12-21 16:42
*/
@Service
public class BaseAttrInfoServiceImpl extends ServiceImpl<BaseAttrInfoMapper, BaseAttrInfo> implements BaseAttrInfoService {
@Autowired
private BaseAttrInfoMapper baseAttrInfoMapper;
@Autowired
private BaseAttrValueMapper baseAttrValueMapper;
/**
* 根据分类ID 获取平台属性列表
* 1.平台属性可以挂在一级,二级,或者是三级分类下
* 2.查询一级分类下包含平台属性列表, 传参:category1ID, null(二级分类ID),null(三级分类ID)
* 3.查询一级分类,以及二级分类 下包含平台属性列表, 传参:category1ID, category2ID,null(三级分类ID)
* 4.查询一级分类,以及二级分类,以及三级分类 下包含平台属性列表, 传参:category1ID, category2ID,category3ID(三级分类ID)
* 不可能存在 直接根据二级或者三级分类查询
*
* @param category1Id
* @param category2Id
* @param category3Id
* @return
*/
@Override
public List<BaseAttrInfo> attrInfoList(Long category1Id, Long category2Id, Long category3Id) {
return baseAttrInfoMapper.attrInfoList(category1Id, category2Id, category3Id);
}
/**
* 新增平台属性包含属性值,关联到某个分类下
*
* @param baseAttrInfo
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void saveAttrInfo(BaseAttrInfo baseAttrInfo) {
//1.判断做新增还是修改 新增:新增平台属性记录
if (baseAttrInfo.getId() == null) {
//如果提交的平台属性ID为null 执行 新增
baseAttrInfoMapper.insert(baseAttrInfo);
} else {
//提交平台属性ID有值 执行 修改
baseAttrInfoMapper.updateById(baseAttrInfo);
}
//根据平台属性ID查询平台属性值列表 将旧的关联到平台属性值全部删除(逻辑删除)
LambdaQueryWrapper<BaseAttrValue> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(BaseAttrValue::getAttrId, baseAttrInfo.getId());
baseAttrValueMapper.delete(queryWrapper);
//2.平台属性值 新增:获取到平台属性集合批量新增
List<BaseAttrValue> attrValueList = baseAttrInfo.getAttrValueList();
if (!CollectionUtils.isEmpty(attrValueList)) {
for (BaseAttrValue baseAttrValue : attrValueList) {
//2.1将平台属性ID关联到平台属性值
baseAttrValue.setAttrId(baseAttrInfo.getId());
baseAttrValueMapper.insert(baseAttrValue);
}
}
}
/**
* 根据平台属性Id 获取到平台属性值集合
*
* @param attrId
* @return
*/
@Override
public List<BaseAttrValue> getAttrValueList(Long attrId) {
LambdaQueryWrapper<BaseAttrValue> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(BaseAttrValue::getAttrId, attrId);
return baseAttrValueMapper.selectList(queryWrapper);
}
}
注意:实现类方法添加:@Transactional
YAPI接口地址:
- http://192.168.200.128:3000/project/11/interface/api/275 根据平台属性ID查询平台属性值集合
接口选中准修改数据 , 根据该attrId 去查找AttrInfo,该对象下 List !
所以在返回的时候,需要返回BaseAttrInfo
在BaseAttrInfoController
中增加方法处理*查询平台属性集合方法
/**
* 根据平台属性ID查询平台属性值集合
* @param attrId
* @return
*/
@GetMapping("getAttrValueList/{attrId}")
public Result<List<BaseAttrValue>> getAttrValueList(@PathVariable("attrId") Long attrId) {
BaseAttrInfo baseAttrInfo = baseAttrInfoService.getAttrInfo(attrId);
List<BaseAttrValue> baseAttrValueList = baseAttrInfo.getAttrValueList();
return Result.ok(baseAttrValueList);
}
业务层接口BaseAttrInfoService
中新增方法
/**
* 根据attrId 查询平台属性对象
* @param attrId
* @return
*/
BaseAttrInfo getAttrInfo(Long attrId);
业务层实现类BaseAttrInfoServiceImpl
实现方法
@Override
public BaseAttrInfo getAttrInfo(Long attrId) {
BaseAttrInfo baseAttrInfo = baseAttrInfoMapper.selectById(attrId);
// 查询到最新的平台属性值集合数据放入平台属性中!
baseAttrInfo.setAttrValueList(getAttrValueList(attrId));
return baseAttrInfo;
}
/**
* 根据属性id获取属性值
* @param attrId
* @return
*/
private List<BaseAttrValue> getAttrValueList(Long attrId) {
// select * from baseAttrValue where attrId = ?
LambdaQueryWrapper<BaseAttrValue> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(BaseAttrValue::getAttrId, attrId);
List<BaseAttrValue> baseAttrValueList = baseAttrValueMapper.selectList(queryWrapper);
return baseAttrValueList;
}
1,重新安装nacos,nacos数据保存至mysql,先删除已安装的nacos,再安装
2,资源库获取nacos数据库表结构并且导入数据库
3,更改nacos启动配置参数
docker run -d
-e MODE=standalone
-e PREFER_HOST_MODE=hostname
-e SPRING_DATASOURCE_PLATFORM=mysql
-e MYSQL_SERVICE_HOST=192.168.200.128
-e MYSQL_SERVICE_PORT=3306
-e MYSQL_SERVICE_USER=root
-e MYSQL_SERVICE_PASSWORD=123456
-e MYSQL_SERVICE_DB_NAME=nacos_config
-p 8848:8848 --name nacos --restart=always
nacos/nacos-server:1.4.1
在gmall-gateway
,还有gmall-service
父模块添加依赖
<!-- 配置-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
说明:搭建环境是我们注释了的,现在打开
删除之前的配置文件application.yml
添加配置文件:bootstrap.properties
spring.application.name=service-product
spring.profiles.active=dev
spring.cloud.nacos.discovery.server-addr=192.168.200.128:8848
spring.cloud.nacos.config.server-addr=192.168.200.128:8848
spring.cloud.nacos.config.prefix=${spring.application.name}
spring.cloud.nacos.config.file-extension=yaml
spring.cloud.nacos.config.shared-configs[0].data-id=common.yaml
说明:
配置文件统一配置到nacos配置中心
common.yaml为公共配置,后续有需要的service模块都可直接引用,避免重复配置
Nacos配置列表中新增配置common.yaml配置文件如下(已完成):
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*Mapper.xml
feign:
sentinel:
enabled: true
client:
config:
default:
readTimeout: 3000
connectTimeout: 1000
spring:
# zipkin:
# base-url: http://192.168.200.128:9411
# discovery-client-enabled: false
# sender:
# type: web
cloud:
sentinel:
transport:
dashboard: http://192.168.200.128:8080
rabbitmq:
host: 192.168.200.128
port: 5672
username: admin
password: admin
publisher-confirm-type: correlated
publisher-returns: true
listener:
simple:
acknowledge-mode: manual #默认情况下消息消费者是自动确认消息的,如果要手动确认消息则需要修改确认模式为manual
prefetch: 1 # 消费者每次从队列获取的消息数量。此属性当不设置时为:轮询分发,设置为1为:公平分发
redis:
host: 192.168.200.128
port: 6379
database: 0
timeout: 1800000
lettuce:
pool:
max-active: 20 #最大连接数
max-wait: -1 #最大阻塞等待时间(负数表示没限制)
max-idle: 5 #最大空闲
min-idle: 0 #最小空闲
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
Nacos配置列表中新增商品模块配置文件service-product-dev.yaml
server:
port: 8206
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/gmall_product?characterEncoding=utf-8&useSSL=false
username: root
password: root
hikari:
connection-test-query: SELECT 1 # 自动检测连接
connection-timeout: 60000 #数据库连接超时时间,默认30秒
idle-timeout: 500000 #空闲连接存活最大时间,默认600000(10分钟)
max-lifetime: 540000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
maximum-pool-size: 12 #连接池最大连接数,默认是10
minimum-idle: 10 #最小空闲连接数量
pool-name: SPHHikariPool # 连接池名称
说明:其实配置属性还是以前项目的配置属性,只是变化了文件命名规则,配置项不变。
删除之前的配置文件application.yml
添加配置文件bootstrap.properties
spring.application.name=server-gateway
spring.profiles.active=dev
spring.cloud.nacos.discovery.server-addr=192.168.200.128:8848
spring.cloud.nacos.config.server-addr=192.168.200.128:8848
spring.cloud.nacos.config.prefix=${spring.application.name}
spring.cloud.nacos.config.file-extension=yaml
Nacos配置列表中新增配置 server-gateway-dev.yaml配置文件如下(已完成):
server:
port: 80
spring:
application:
name: server-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.200.128:8848
ip: 127.0.0.1
gateway:
discovery: #是否与服务发现组件进行结合,通过 serviceId(必须设置成大写) 转发到具体的服务实例。默认为false,设为true便开启通过服务中心的自动根据 serviceId 创建路由的功能。
locator: #路由访问方式:http://Gateway_HOST:Gateway_PORT/大写的serviceId/**,其中微服务应用名默认大写访问。
enabled: true
routes:
- id: service-product
uri: lb://service-product
predicates:
- Path=/*/product/** # 路径匹配
说明:其他服务配置文件统一已经在Nacos提供。或者配套资料中也有配置文件压缩包Nacos中直接导入即可