SpringCloudAlibaba注册中心与配置中心之利器Nacos实战与源码分析(中)
Nacos配置中心示例
配置SpringBoot日志
日志我们使用SpringBoot默认的logback,在库存模块的根目录下创建conf文件夹,将logback.xml放在下面,logback.xml内容如下
<?xml version="1.0" encoding="UTF-8" ?> <configuration debug="false"> <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> <springProperty scope="context" name="APP_HOME" source="spring.application.name"/> <property name="LOG_HOME" value="${LOG_PATH:-.}" /> <!-- 控制台输出设置 --> <!-- 彩色日志格式,magenta:洋红,boldMagenta:粗红,yan:青色,·⊱══> --> <property name="CONSOLE_LOG_PATTERN" value="%boldMagenta([%d{yyyy-MM-dd HH:mm:ss.SSS}]) %cyan([%X{requestId}]) %boldMagenta(%-5level) %blue(%logger{15}) %red([%thread]) %magenta(·⊱══>) %cyan(%msg%n)"/> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <charset>utf8</charset> </encoder> </appender> <!-- 按天输出日志设置 --> <appender name="DAY_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志文件输出的文件名 --> <FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}_${APP_HOME}.%i.log</FileNamePattern> <!-- 日志文件保留天数 --> <MaxHistory>7</MaxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>50MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <!-- 设置拦截的对象为INFO级别日志 --> <onMatch>ACCEPT</onMatch> <!-- 当遇到了INFO级别时,启用改段配置 --> <onMismatch>DENY</onMismatch> <!-- 没有遇到INFO级别日志时,屏蔽改段配置 --> </filter> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 按天输出WARN级别日志设置 --> <appender name="DAY_WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志文件输出的文件名 --> <FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}_${APP_HOME}_warn.%i.log</FileNamePattern> <!-- 日志文件保留天数 --> <MaxHistory>7</MaxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>50MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>WARN</level> <!-- 设置拦截的对象为INFO级别日志 --> <onMatch>ACCEPT</onMatch> <!-- 当遇到了INFO级别时,启用改段配置 --> <onMismatch>DENY</onMismatch> <!-- 没有遇到INFO级别日志时,屏蔽改段配置 --> </filter> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 按天输出ERROR级别日志设置 --> <appender name="DAY_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 日志文件输出的文件名 --> <FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}_${APP_HOME}_error.%i.log</FileNamePattern> <!-- 日志文件保留天数 --> <MaxHistory>7</MaxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>50MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <!-- 设置拦截的对象为ERROR级别日志 --> <onMatch>ACCEPT</onMatch> <!-- 当遇到了ERROR级别时,启用改段配置 --> <onMismatch>DENY</onMismatch> <!-- 没有遇到ERROR级别日志时,屏蔽改段配置 --> </filter> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!-- 格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 日志输出级别,OFF level > FATAL > ERROR > WARN > INFO > DEBUG > ALL level --> <logger name="com.sand" level="INFO"/> <logger name="com.apache.ibatis" level="INFO"/> <logger name="java.sql.Statement" level="INFO"/> <logger name="java.sql.Connection" level="INFO"/> <logger name="java.sql.PreparedStatement" level="INFO"/> <logger name="org.springframework" level="WARN"/> <logger name="com.baomidou.mybatisplus" level="WARN"/> <!-- 开发环境:打印控制台和输出到文件 --> <springProfile name="dev"> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="DAY_FILE"/> <appender-ref ref="DAY_WARN_FILE"/> <appender-ref ref="DAY_ERROR_FILE"/> </root> </springProfile> <!-- 生产环境:打印控制台和输出到文件 --> <springProfile name="pro"> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="DAY_FILE"/> <appender-ref ref="DAY_WARN_FILE"/> <appender-ref ref="DAY_ERROR_FILE"/> </root> </springProfile> </configuration>
配置使用
创建配置
创建库存微服务的Nacos配置,点击发布
编辑配置,增加库存微服务数据库的配置和日志配置文件路径和保存路径
ecom-storage-service-dev.yaml的配置内存如下
server: port: 4080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://192.168.50.95:3308/storage?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource druid: max-active: 1000 min-idle: 5 initial-size: 10 mybatis-plus: global-config: db-config: id-type: auto logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 configuration: map-underscore-to-camel-case: on call-setters-on-nulls: on log-impl: org.apache.ibatis.logging.stdout.StdOutImpl logging: file: path: ./ecom_storage/logs config: ./ecom_storage/conf/logback.xml
如果配置中心和redis是共用的,所有服务都放在一个ecom-group组下,commons-dev.yaml的内容如下
spring: cloud: nacos: discovery: server-addr: ${spring.cloud.nacos.server-addr} group: ecom-group namespace: a2b1a5b7-d0bc-48e8-ab65-04695e61db01 username: itsx password: itxs123 redis: cluster: nodes: 192.168.50.196:5001,192.168.50.196:5002,192.168.50.196:5003,192.168.50.196:5004,192.168.50.196:5005,192.168.50.196:5006 max-redirects: 6 password: PushBz28
创建extension-priority-dev.yaml(组为extension-group)和shared-priority-dev.yaml(组为shared-priority-dev.yaml)来演示读取多配置文件及配置的优先级。
简单配置文件以配置完毕
读取配置示例
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
客户端spring-cloud-starter-alibaba-nacos-config在加载配置的时候,不仅仅加载了以 dataid 为
${spring.application.name}.${file-extension:properties}为前缀的基础配置,还加载了dataid为
${spring.application.name}-${profile}.${file-extension:properties}的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以通过Spring 提供的
${spring.profiles.active}这个配置项来配置,这里使用spring.profiles.active=dev,自定义 namespace 的配置和支持自定义 Group 的配置,此外可以通过使用extension-configs或shared-configs支持读取多个 Data Id 的配置场景。
库存模块的bootstrap.yml文件内容如下
spring: application: name: ecom-storage-service profiles: active: dev main: allow-circular-references: true cloud: nacos: # 注册中心信息放在配置中心上,每个程序一般只配置配置中心的信息 server-addr: 192.168.50.95:8848 config: server-addr: ${spring.cloud.nacos.server-addr} file-extension: yaml namespace: a2b1a5b7-d0bc-48e8-ab65-04695e61db01 group: storage-group extension-configs: - dataId: extension-priority-dev.yaml group: extension-group refresh: true - dataId: commons-dev.yaml group: commons-group refresh: true shared-configs: - dataId: shared-priority-dev.yaml group: shared-group refresh: true username: itsx password: itxs123 enabled: true # 默认为true,设置false 来完全关闭 Spring Cloud Nacos Config refresh-enabled: true # 默认为true,当变更配置时,应用程序中能够获取到最新的值,设置false来关闭动态刷新,我们使用注册中心场景大部分就是动态感知,因此基本使用默认的
创建读取配置NacosConfigDemoComtroller.java
package cn.itxs.ecom.storage.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @Name :NacosConfigDemoComtroller * @Description :Nacos配置读取示例控制器 * @Author :itxs * @Date :2022/4/10 11:06 * @Version :1.0 * @History : */ @RestController @RefreshScope public class NacosConfigDemoComtroller { //直接通过@Value注解就能获取nacos配置中心的数据,但这种写法不能实现动态更新,需要配合@RefreshScope注解来使@Value注解的内容动态刷新 @Value(value = "${user.name}") private String userName; @Value(value = "${user.age}") private String userAge; @Autowired private ConfigurableApplicationContext applicationContext; @RequestMapping("/read_config") public String readConfig(){ return "ApplicationContext get userName=" + applicationContext.getEnvironment().getProperty("user.name") + ",ApplicationContext get userAge=" + applicationContext.getEnvironment().getProperty("user.age") + ",Value get userName=" + userName + ",Value get userAge="+userAge; } }
库存模块读取配置示例框架如下
访问http://localhost:4080/read_config
首先ecom-storage-service-dev.yaml微服务主配置读取到了,服务的端口为我们配置4080,其次目前user的值获取到的是extension-priority-dev.yaml里的
修改Nacos中extension-priority-dev.yaml的值,继续访问
在 Nacos Spring Cloud 中,
dataId的完整格式如下:{prefix}-.$
prefix
默认为spring.application.name
的值,也可以通过配置项spring.cloud.nacos.config.prefix
来配置。spring.profiles.active
即为当前环境对应的 profile,当spring.profiles.active
为空时,对应的连接符-
也将不存在,dataId 的拼接格式变成${prefix}.${file-extension}
file-exetension
为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension
来配置。目前只支持properties
和yaml
类型。
直接通过@Value注解就能获取nacos配置中心的数据,但这种写法不能实现动态更新,通过 Spring Cloud 原生注解
@RefreshScope来使@Value注解的内容动态刷新,至此配置都可以动态更新。
配置优先级
从上小节之后继续进行多个示例,包括在主配置文件增加user的值,在extension-priority-dev.yaml和shared-priority-dev.yaml内部多个文件顺序的,验证 Spring Cloud Alibaba Nacos Config三种配置能力从 Nacos 拉取相关的配置的优先级。
- A: 通过
spring.cloud.nacos.config.shared-configs .data-id
支持多个共享 Data Id 的配置 - B: 通过
spring.cloud.nacos.config.extension-configs .data-id
的方式支持多个扩展 Data Id 的配置 - C: 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置
优先级关系是:shared-configs < extension-configs < 主配置(应用名、应用名+ Profile )自动生成相关的 Data Id 配置)
而extension-configs内部配置多个 Data Id 时,优先级关系是
spring.cloud.nacos.config.extension-configs .data-id其中 n 的值越大,优先级越高。
Nacos Spring Boot
使用
@NacosPropertySource加载 指定
dataId的配置源,并开启自动更新,并通过 Nacos 的
@NacosValue注解设置属性值。
OpenAPI
Nacos也提供了OpenAPI供开发者进行灵活定制开发
通过官网提供接口定义测试获取配置
curl -X GET 'http://192.168.50.95:8848/nacos/v1/cs/configs?tenant=a2b1a5b7-d0bc-48e8-ab65-04695e61db01&dataId=ecom-storage-service-dev.yaml&group=storage-group'
监听配置变化
如果需要感知配置的变化,可以添加一个监听器来监听配置的变化
Nacos注册中心示例
概述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vgbqH7Bo-1649608118605)(F:\creation\markdown\article\SpringCloudAlibaba注册中心与配置中心之利器Nacos实战与源码分析\SpringCloudAlibaba注册中心与配置中心之利器Nacos实战与源码分析.assets\image-20220410175620221.png)]
进行远程调用首先需要知道远程服务的地址,spring-cloud-starter-alibaba-nacos-discovery客户端提供服务名的方式去调用远程的服务的功能,首先解决找服务的问题,其次也提供客户端软件负载均衡器,支持设置负载均衡算法和自定义扩展负载均衡算法,目前最新版本的负载均衡器已不再使用Spring Cloud Netflix Ribbon,而是使用spring-cloud-loadbalancer,关于spring-cloud-loadbalancer的使用详细可以查阅官网,spring-cloud-loadbalancer文档归在spring-cloud-commons里,https://docs.spring.io/spring-cloud-commons/docs/3.1.1/reference/html/#spring-cloud-loadbalancer。调用HTTP 服务Spring Boot提供RestTemplate方式,但是这种使用我们需要拼接url和参数,显然不太符合方法调用的思维,这时我们再使用Spring Cloud OpenFeign(以声明式REST客户端:Feign创建了一个动态实现的接口,该接口用JAX-RS或Spring MVC注解装饰),以Spring MVC使用方式进行服务调用。
服务注册
将spring-cloud-loadbalancer加入到commons的pom文件里,服务注册与发现客户端依赖spring-cloud-starter-alibaba-nacos-discovery前面已加入了
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency>
前面在Nacos中的commons-dev.yaml中已包含Nacos注册中心的配置,接着先初始化库存数据,新建commodityCode为1001的库存数据999,在commons模块创建库存实体和库存接口
package cn.itxs.ecom.commons.entity; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @Data @TableName("storage_tbl") public class Storage { private Integer id; private String commodityCode; private Integer count; }
package cn.itxs.ecom.commons.service; public interface StorageService { /** * 扣除存储数量 */ String deduct(String commodityCode, int count); }
库存微服务中建立StorageMapper.java
package cn.itxs.ecom.storage.dao; import cn.itxs.ecom.commons.entity.Storage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface StorageMapper extends BaseMapper<Storage> { }
增加MyBatis-Plus配置类MyBatisPlusConfig.java,配置Mapper的扫描目录
package cn.itxs.ecom.storage.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; @MapperScan("cn.itxs.ecom.storage.dao") @EnableTransactionManagement @Configuration public class MyBatisPlusConfig { /** * 配置新版乐观锁插件,新版分页插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); //乐观锁插件 mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); //分页插件 mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return mybatisPlusInterceptor; } }
增加库存服务实现类
package cn.itxs.ecom.storage.service.impl; import cn.itxs.ecom.commons.service.StorageService; import cn.itxs.ecom.storage.dao.StorageMapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class StorageServiceImpl implements StorageService { @Autowired StorageMapper storageMapper; @Override public String deduct(String commodityCode, int count) { UpdateWrapper updateWrapper = new UpdateWrapper(); updateWrapper.setSql("count = count - " + count); updateWrapper.eq("commodity_code", commodityCode); storageMapper.update(null,updateWrapper); return "1"; } }
最后创建库存控制器,提供扣减库存方法
package cn.itxs.ecom.storage.controller; import cn.itxs.ecom.commons.service.StorageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class StorageController { @Autowired StorageService storageService; @RequestMapping("/deduct/{commodityCode}/{count}") public String deduct(@PathVariable("commodityCode") String commodityCode, @PathVariable("count") int count){ return storageService.deduct(commodityCode,count); } }
启动库存微服务,在Nacos控制台中查看库存服务模块已注册到Nacos
访问扣减库存的接口,http://localhost:4080/deduct/1001/1 ,查看数据库库存表1001商品库存已减1,至此库存服务注册已完成
服务发现
建立订单微服务模块,同样在conf目录下复制前面logback.xml文件,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"> <parent> <artifactId>simple-ecommerce</artifactId> <groupId>cn.itxs</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>ecom-order-service</artifactId> <packaging>jar</packaging> <version>1.0</version> <name>ecom-order-service</name> <description>a simple electronic commerce platform demo tutorial for order service</description> <dependencies> <dependency> <groupId>cn.itxs</groupId> <artifactId>ecom-commons</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>3.0.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <!-- 指定该Main Class为全局的唯一入口 --> <mainClass>cn.itxs.ecom.order.OrderServiceApplication</mainClass> <layout>ZIP</layout> </configuration> <executions> <execution> <goals> <goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中--> </goals> </execution> </executions> </plugin> </plugin> </plugins> </build> </project>
bootstrap.yml内容如下
spring: application: name: ecom-order-service profiles: active: dev main: allow-circular-references: true cloud: nacos: # 注册中心信息放在配置中心上,每个程序一般只配置配置中心的信息 server-addr: 192.168.50.95:8848 config: server-addr: ${spring.cloud.nacos.server-addr} file-extension: yaml namespace: a2b1a5b7-d0bc-48e8-ab65-04695e61db01 group: order-group username: itsx password: itxs123 extension-configs: - dataId: commons-dev.yaml group: commons-group refresh: true enabled: true # 默认为true,设置false 来完全关闭 Spring Cloud Nacos Config refresh-enabled: true # 默认为true,当变更配置时,应用程序中能够获取到最新的值,设置false来关闭动态刷新,我们使用注册中心场景大部分就是动态感知,因此基本使用默认的
在commons模块创建订单实体和订单接口和库存OpenFeign接口
package cn.itxs.ecom.commons.entity; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @Data @TableName("order_tbl") public class Order { private Integer id; private String userId; private String commodityCode; private Integer count; private Integer money; }
package cn.itxs.ecom.commons.service; import cn.itxs.ecom.commons.entity.Order; public interface OrderService { /** * 创建订单 */ Order create(String userId, String commodityCode, int orderCount); }
package cn.itxs.ecom.commons.service.openfeign; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @FeignClient("ecom-storage-service") public interface StorageFeignService { /** * deduct 方法在 Spring MVC 请求映射的方式与 nacos-discovery-provider 中的 ServiceController 基本相同, * 唯一区别在于 @PathVariable 注解指定了 value 属性 commodityCode和count, * 这是因为默认情况,Java 编译器不会讲接口方法参数名添加到 Java 字节码中。 */ @RequestMapping("/deduct/{commodityCode}/{count}") String deduct(@PathVariable("commodityCode") String commodityCode, @PathVariable("count") int count); }
同样在订单创建Mapper接口和配置类
package cn.itxs.ecom.order.dao; import cn.itxs.ecom.commons.entity.Order; import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface OrderMapper extends BaseMapper<Order> { }
package cn.itxs.ecom.order.config; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.annotation.EnableTransactionManagement; @MapperScan("cn.itxs.ecom.order.dao") @EnableTransactionManagement @Configuration public class MyBatisPlusConfig { /** * 配置新版乐观锁插件,新版分页插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); //乐观锁插件 mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); //分页插件 mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return mybatisPlusInterceptor; } }
增加订单接口实现类
package cn.itxs.ecom.order.service.impl; import cn.itxs.ecom.commons.entity.Order; import cn.itxs.ecom.commons.service.OrderService; import cn.itxs.ecom.order.dao.OrderMapper; import cn.itxs.ecom.commons.service.openfeign.StorageFeignService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class OrderServiceImpl implements OrderService { @Autowired private StorageFeignService storageFeignService; @Autowired OrderMapper orderMapper; @Override public Order create(String userId, String commodityCode, int orderCount) { storageFeignService.deduct(commodityCode,orderCount); Order order = new Order(); order.setUserId(userId); order.setCommodityCode(commodityCode); order.setCount(orderCount); order.setMoney(orderCount*10); orderMapper.insert(order); return order; } }
最后增加订单控制器和订单微服务启动类,注意需要@EnableFeignClients和配置扫描Feign接口
package cn.itxs.ecom.order.controller; import cn.itxs.ecom.commons.service.OrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class OrderController { @Autowired OrderService orderService; @RequestMapping("/create/{userId}/{commodityCode}/{count}") public String create(@PathVariable("userId") String userId,@PathVariable("commodityCode") String commodityCode, @PathVariable("count") int count){ return orderService.create(userId,commodityCode,count).toString(); } }
package cn.itxs.ecom.order; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @EnableFeignClients(basePackages = {"cn.itxs.ecom.commons.service.openfeign"}) // 激活 @FeignClient @ComponentScan(basePackages = {"cn.itxs.ecom.order","cn.itxs.ecom.commons.config","cn.itxs.ecom.commons.utils"}) public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
启动订单的微服务,查看库存和订单微服务都已注册到Nacos中
执行创建订单服务,http://localhost:4070/create/a1001/1001/3 ,成功返回结果
数据库中订单和库存数据表记录也已经正确更新
**本人博客网站 **IT小神 www.itxiaoshen.com
- zookeeper配置中心实战--solrcloud zookeeper配置中心原理及源码分析
- zookeeper配置中心实战--solrcloud zookeeper配置中心原理及源码分析
- Spring Cloud 微服务开发:入门、进阶与源码剖析 —— 11.3 Nacos 服务配置入门实战
- Nacos:配置中心原理分析
- 19.SpringCloud实战项目-SpringCloud整合Alibaba-Nacos配置中心
- Spring Cloud 微服务实战——nacos 服务注册中心搭建(附源码)
- SpringCloud实战 | 第三篇:SpringCloud整合Nacos实现配置中心
- nacos作为配置中心使用的长轮询是怎么一回事及长轮询重要源码解读
- Nacos配置中心设计分析-客户端
- [Abp 源码分析]四、模块配置
- Nacos学习(六):Nacos配置中心服务端设置与客户端的调用
- springboot2.x +kafka使用和源码分析二(topic配置)
- C++STL内存配置的设计思想与关键源码分析
- Servlet容器Tomcat中web.xml中url-pattern的配置详解[附带源码分析]
- Tiny210(S5PV210) U-BOOT(三)----配置时钟频率源码分析
- Dubbo实战(三)多注册中心配置
- Android逆向之旅---反编译利器Apktool和Jadx源码分析以及错误纠正
- 分布式事务中间件 TCC-Transaction 源码分析 —— 项目实战
- LoRaWAN实战 LinkADR命令的源码分析
- Nacos的集群搭建 和 服务配置中心的 使用