Springboot整合 Spring Cloud Gateway

1.Gateway介绍

1.是spring cloud官方推出的响应式的API网关框架,旨在为微服务架构提供一种简单有效的API路由的管理方式,并基于Filter的方式提供网关的基本功能,例如:安全认证,监控,限流等等。
2.功能特征:动态路由:能够匹配任何请求属性。支持路径重写可集成Naocs,Sentinel。可以对路由指定易于编写的predicate(断言)和Filter(过滤器)。
3.核心概念:路由(route):路由是网关中最基础的部分,路由信息包括一个ID,一个目的URL,一组断言工厂,一组Filter组成。如果断言为真,则说明请求的url和配置的路由匹配。断言(predicates):断言函数允许开发者去定义匹配Http request中的任何信息,比如请求头和参数等。过滤器(Filter):分为Gateway filter和Global filter。filter可以对请求和响应进行处理。

2.整合Gateway

1.引入依赖
<!--查看是否引入SpringCloud 版本依赖-->
<dependencyManagement><dependencies><!-- SpringCloud 版本依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement><dependencies><!--spring cloud gateway--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency>
</dependencies>
2.yml配置
路由规则:id:路由唯一标识,不要使用  -uri:需要转发的地址predicates:断言规则,用于路由规则的匹配filters:过滤器
# 开发环境配置
server:# 服务器的HTTP端口,默认为8080port: 9005##注册到nacos的服务名
spring:application:name: @artifactId@profiles:active: ${profiles.active}cloud:#gateway配置gateway:#路由规则routes:- id: auth_route #路由唯一标识,不要使用  -uri: http://localhost:9000 #需要转发的地址predicates: #断言规则,用于路由规则的匹配- Path=/initialAuth/** #如果请求路径中存在initialAuth 则自动匹配到auth服务filters:- StripPrefix=1 #转发之前去除第一层路径,将断言规则中的initialAuth去除
验证测试结果:
通过访问路由端口拼接断言规则,访问auth服务的testUser接口
由此可见通过以上路由配置:成功转发到:http://localhost:9000/testUser

在这里插入图片描述

3.Gateway集成Naocs

1.引入Nacos依赖(nacos版本以及SpringCloud Alibaba 微服务 版本管理)这里不多赘述,之前的文档里都有。
2.springcloud在Hoxton.M2 RELEASED版本之后舍弃Ribbon。需手动引入spring-cloud-loadbalancer
如果不引入spring-cloud-loadbalancer 。则uri: lb://initial-auth 请求时使用负载均衡策略会报 503。

在这里插入图片描述

<!-- SpringCloud Alibaba Nacos -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency><!-- SpringCloud Alibaba Nacos Config -->
<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-loadbalancer</artifactId>
</dependency>
2.yml修改(加入nacos配置)
# 开发环境配置
server:# 服务器的HTTP端口,默认为8080port: 9005##注册到nacos的服务名
spring:application:name: @artifactId@profiles:active: ${profiles.active}cloud:nacos:discovery:server-addr: 127.0.0.1:8848config:server-addr: ${spring.cloud.nacos.discovery.server-addr}#gateway配置gateway:#路由规则routes:- id: auth_route #路由唯一标识,不要使用  -uri: lb://initial-auth #需要转发的已注册到nacos的服务名 lb:使用nacos的负载均衡策略predicates: #断言规则,用于路由规则的匹配- Path=/initialAuth/** #如果请求路径中存在initialAuth 则自动匹配到auth服务filters:- StripPrefix=1 #转发之前去除第一层路径,将断言规则中的initialAuth去除config:import:- optional:nacos:initial-stage-common.yml- optional:nacos:initial-stage-openFeign-${profiles.active}.yml- optional:nacos:initial-stage-${profiles.active}.yml
验证测试结果:

在这里插入图片描述

3.路由断言工厂配置

作用:当请求gateway的时候,使用断言对请求进行匹配,如果匹配成功就路由转发,如果匹配失败就返回404。
类型:内置。自定义。
3.1)内置路由断言工厂
官网地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.RELEASE/single/spring-cloud-gateway.html#gateway-request-predicates-factories
3.1.1)时间断言:
	AfterRouterPredicateFactory:接收一个日期参数,判断请求日期是否晚于指定日期。BeforeRouterPredicateFactory:接收一个日期参数,判断请求日期是否早于指定日期。BetweenRouterPredicateFactory:接收两个日期参数,判断请求日期是否在指定时间断内。
#AfterRouterPredicateFactory
spring:cloud:gateway:routes:- id: after_routeuri: http://example.orgpredicates:- After=2017-01-20T17:42:47.789-07:00[America/Denver]
#BeforeRouterPredicateFactory
spring:cloud:gateway:routes:- id: before_routeuri: http://example.orgpredicates:- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
#BetweenRouterPredicateFactory
spring:cloud:gateway:routes:- id: between_routeuri: http://example.orgpredicates:- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
3.1.2)Cookie断言:
CookieRouterPredicateFactory:两个参数 第一个代表Cookie中的一个key,第二个代表这个key的值(可以是正则表达式)。
spring:cloud:gateway:routes:- id: cookie_routeuri: http://example.orgpredicates:- Cookie=chocolate, ch.p
3.1.3)请求头断言:
HeaderRouterPredicateFactory:根据请求头里的某个参数进行匹配,第一个代表请求头里的某个参数,第二个代表这个参数的值(可以是正则表达式)。
spring:cloud:gateway:routes:- id: header_routeuri: http://example.orgpredicates:- Header=X-Request-Id, \d+
3.1.4)域名断言:
HostRouterPredicateFactory:根据域名进行匹配
spring:cloud:gateway:routes:- id: host_routeuri: http://example.orgpredicates:- Host=**.somehost.org,**.anotherhost.org
3.1.5)请求方式断言:
MethodRouterPredicateFactory:根据请求方式进行匹配,多个用逗号分开
spring:cloud:gateway:routes:- id: method_routeuri: http://example.orgpredicates:- Method=GET
3.1.6)请求路径断言:
PathRouterPredicateFactory:根据请求路径进行匹配,{segment}占位符
spring:cloud:gateway:routes:- id: host_routeuri: http://example.orgpredicates:- Path=/foo/{segment},/bar/{segment}
3.1.7)查询参数断言:
QueryRouterPredicateFactory:根据查询参数进行断言
请求地址的参数中要包含baz这个参数。
请求地址的参数中要包含foo这个参数,并且值等于ba。
spring:cloud:gateway:routes:- id: query_routeuri: http://example.orgpredicates:- Query=bazspring:cloud:gateway:routes:- id: query_routeuri: http://example.orgpredicates:- Query=foo, ba.
3.1.8)客户端ip断言:
RemoteAddrRouterPredicateFactory:根据客户端ip进行断言。
spring:cloud:gateway:routes:- id: remoteaddr_routeuri: http://example.orgpredicates:- RemoteAddr=192.168.1.1
3.2)自定义路由断言工厂
可以模仿内置路由断言工厂

在这里插入图片描述

1.必须是Spring组件bean (类上面添加@Component)
2.类名必须加上RoutePredicateFactory作为结尾
3.必须继承AbstractRoutePredicateFactory
4.在类中必须声明静态内部类(Config),声明属性来接收yml配置文件中对应的断言信息(yml几个参数,Config就声明几个属性)
5.需要结合shortcutFieldOrder方法进行绑定
6.通过apply进行逻辑判断, true匹配成功,false匹配失败。
package com.initial.gateway.predicate;import jakarta.validation.constraints.NotEmpty;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;@Component
public class CheckSignRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckSignRoutePredicateFactory.Config> {public CheckSignRoutePredicateFactory() {super(Config.class);}@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("param");}@Overridepublic Predicate<ServerWebExchange> apply(final Config config) {return new GatewayPredicate() {public boolean test(ServerWebExchange exchange) {if (config.getParam().equals("sign")) {return true;}return false;}public Object getConfig() {return config;}};}@Validatedpublic static class Config {private @NotEmpty String param;public Config() {}public String getParam() {return this.param;}public void setParam(String param) {this.param = param;}}
}
测试结果:
正常加入CheckSign断言:CheckSign=sign

在这里插入图片描述
在这里插入图片描述

加入任意CheckSign断言的值:CheckSign=sign1111

在这里插入图片描述
在这里插入图片描述

4.过滤器工厂配置

作用:当请求gateway的时候,使用过滤器工厂可以进行一些业务逻辑处理,比如去除请求某几层路径。
官网地址:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.RELEASE/single/spring-cloud-gateway.html#_gatewayfilter_factories
因为有很多,这里就不全做整理了,	可以在官网中查看用法。
4.1)内置过滤器工厂
4.1.1)AddRequestHeader:在请求头中添加X-Request-Foo属性,值为Bar
spring:cloud:gateway:routes:- id: add_request_header_routeuri: http://example.orgfilters:- AddRequestHeader=X-Request-Foo, Bar
4.1.2)PrefixPath:为匹配的路由添加前缀,对应服务需要配置context-path
相对应的服务yml中配置
server:servlet:context-path: /mypath 
spring:cloud:gateway:routes:- id: prefixpath_routeuri: http://example.orgfilters:- PrefixPath=/mypath 
4.1.3)AddRequestParameter:为匹配的路由添加foo参数,值为bar
spring:cloud:gateway:routes:- id: add_request_parameter_routeuri: http://example.orgfilters:- AddRequestParameter=foo, bar
4.2)自定义过滤器工厂
可以模仿 AddRequestHeaderGatewayFilterFactory 继承了AbstractNameValueGatewayFilterFactory 继承了AbstractGatewayFilterFactory

在这里插入图片描述

可以模仿 PrefixPathGatewayFilterFactory

在这里插入图片描述

1.必须是Spring组件bean (类上面添加@Component)
2.类名必须加上GatewayFilterFactory作为结尾
3.必须继承AbstractGatewayFilterFactory
4.在类中必须声明静态内部类(Config),声明属性来接收yml配置文件中对应的断言信息(yml几个参数,Config就声明几个属性)
5.需要结合shortcutFieldOrder方法进行绑定
6.通过apply进行逻辑判断。

5.全局过滤器配置

对所有配置的路由进行过滤。
在全局过滤器中,过滤的类需要去实现GlobalFilter接口。
package com.initial.gateway.filter;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Component
public class LogFilter implements GlobalFilter {Logger logger = LoggerFactory.getLogger(LogFilter.class);@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {logger.info(exchange.getRequest().toString());return chain.filter(exchange);}
}
测试结果:请求进入过滤器断点。

在这里插入图片描述

6.Gateway跨域处理

spring:application:name: @artifactId@profiles:active: ${profiles.active}cloud:#gateway配置gateway:#路由规则routes:- id: auth_route #路由唯一标识,不要使用  -uri: lb://initial-auth #需要转发的已注册到nacos的服务名 lb:使用nacos的负载均衡策略predicates: #断言规则,用于路由规则的匹配- Path=/initialAuth/** #如果请求路径中存在initialAuth 则自动匹配到auth服务- CheckSign=signfilters:- StripPrefix=1 #转发之前去除第一层路径,将断言规则中的initialAuth去除#跨域配置globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true # 解决浏览器向服务器发options请求被拦截问题,这样网关就不拦截这个请求了corsConfigurations:'[/**]': # 拦截一切请求
#            allowedOrigins: # 允许哪些网站的跨域请求
#              - "http://localhost:8090"allowedOrigins: '*'allowedMethods: # 允许的跨域ajax的请求方式- "GET"- "POST"- "DELETE"- "PUT"- "OPTIONS"allowedHeaders: "*" # 允许在请求中携带的头信息,这里是允许所有的请求头maxAge: 360000 # 这次跨域检测的有效期

7.Gateway整合sentinel流控降级

网关层的限流可以简单的针对不同路由进行限流,也可针对业务的接口进行限流,或者根据接口的特征分组限流。1.gateway项目pom.xml添加依赖:
<!--sentinel整合gateway--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
2.gateway项目yml文件添加:
spring:application:name: @artifactId@profiles:active: ${profiles.active}cloud:sentinel:transport:#添加sentinel控制台地址dashboard: 127.0.0.1:8088
3.通过网关访问接口:
sentinel会将访问的路由注册进去:auth_routeRoute ID:根据选择的路由id进行流控。

在这里插入图片描述

 API 分组 :在api管理中维护api分组,然后选择api分组进行流控。

在这里插入图片描述
在这里插入图片描述

间隔: QPS按每秒请求量,比如1秒请求2次。这里的间隔设置为 当前QPS 1秒钟请求2次,当间隔为2秒则为当前QPS 2秒中请求2次。
Burst size:宽容次数。如果设置为1,则QPS阈值+1。
针对请求属性:参数属性:Client IP:根据id进行限流Remote Host:域名Header:请求头。Header 名称 :对请求头中含有某个key-value的进行限流。比如Header 名称:sign,匹配模式:精确 匹配串:1当一个请求头中含有sign并且这个值等1的进行流控。URL 参数:请求地址参数。URL 参数名称:对请求地址中含有某个参数的进行限流。比如URL 参数名称:name,匹配模式:精确 匹配串:1当一个请求连接的参数中含有name并且这个值等1的进行流控。Cookie:Cookie。Cookie 名称:对Coolie中含有某个key-value的进行限流。属性值匹配:匹配模式:精确: 一个具体的值。 比如设置为127.0.0.1 则对127.0.0.1这个ip访问进行限流子串:模糊匹配正则: 正则表达式4.测试流控:根据路由id进行流控。

在这里插入图片描述

5.gateway项目中自定义全局限流信息。
package com.initial.gateway.config;import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;@Configuration
public class GatewaySentinelConfig {@PostConstructpublic void init(){BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {Map<String,String> map = new HashMap<>();map.put("code",HttpStatus.TOO_MANY_REQUESTS.toString());map.put("msg","服务器繁忙,请稍后再试");return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(map));}};GatewayCallbackManager.setBlockHandler(blockRequestHandler);}}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/837199.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【逆天OP懒狗的JAVA自学笔记--5.判断和循环】第二阶段始篇

文章目录 前言一、流程控制语句1.顺序结构&#xff08;最简单&#xff09;2.分支结构2.1 if 语句2.1.1 if语句的三种格式2.1.2 if 的注意事项 2.2 switch 语句2.2.1switch 的扩展知识 3.循环结构3.1 for 循环 扩展小点&#xff1a;//1.求和的变量不能定义在循环的里面&#xff…

解决finalshell无法连接,一直提示登陆密码

问题描述 在使用FinalShell连接配置虚拟机时&#xff0c;无法正常连接&#xff0c;一直提示输入登录密码&#xff0c;即使输入的密码是正确的。 切换到root 模式,输入密码 su root 此时需要输入root账户的密码&#xff0c;但是我们又不知道root的密码&#xff0c;怎么办&…

嵌入式STM32中I2C控制器外设详解

STM32中的I2C外设主要负责IIC协议与外界进行通信,就像USART外设一样,我们在学习的过程中,需要抓住I2C应用的重点。 STM32在使用I2C协议时,可以通过两种方式, 一是软件模拟协议 意思是使用CPU直接控制通讯引脚的电平,产生出符合通讯协议标准的逻辑。例如,像点亮LED那样…

绝地求生:经典艾伦格即将回归!绝地求生艾伦格进化史

29.2版本经典艾伦格地图将会回归&#xff0c;让我回顾一下艾伦格地图的改动历史吧&#xff01; 回归时间 2016年早期A测 A测 4.1版本&#xff1a;艾伦格-新视界 主要区域变动 Military Base(军事基地) Military Base Mylta Power&#xff08;大电&#xff09; Mylta Power …

微信小程序开发题库

一. 单选题&#xff08;共12题&#xff0c;60分&#xff09; 1. (单选题) 有如下HTML代码&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>Document</title> <style> ul,li{ margin:0; p…

【计算机网络】数据链路层 组帧 习题4

组帧 发送方根据一定的规则将网络层递交的分组封装成帧(也称为组帧)。 组帧时&#xff0c;既要加首部&#xff0c;也要加尾部&#xff0c;原因是&#xff0c;在网络信息中&#xff0c;帧是以最小单位传输的。所以接收方要正确地接收帧&#xff0c;就必须清楚该帧在一串比特串中…

EasyExcel 中实体类的注解@ExcelProperty

ExcelProperty(value "职务", index 0) value 与index 的优先级, 实测得出下面结论. 1、只有value : 按照value 的匹配 2、只有index: 按照index 的匹配 3、 同时有value和index: 按照index的匹配. 结果: 按照index的匹配, 找到的数据 {"administrat…

大模型管理工具:SWIFT

目录 一、SWIFT 介绍 二、SWIFT 安装 2.0 配置环境(可选) 2.1 使用pip进行安装 2.2 源代码安装 2.3 启动 WEB-UI 三、部署模型 3.0 deploy命令参数 3.1 原始模型 3.2 微调后模型 一、SWIFT 介绍 SWIFT&#xff08;Scalable lightWeight Infrastructure for Fine-Tuni…

MySQL8.0就地升级到MySQL8.4.0

MySQL8.0就地升级到MySQL8.4.0 升级需求&#xff1a;将8.0.35升级到8.4.0,以In-Place方式直接升级到MySQL8.4.0。 数据库版本 操作系统版本 原版本 8.0.35 Centos7.9 x86_64 新版本 8.4.0 Centos7.9 x86_64 关闭现有版本MySQL&#xff0c;将二进制或包替换成新版本并…

对比学习笔记

这里写目录标题 什么是对比学习计算机视觉中的对比学习对比学习在NLP中的应用 什么是对比学习 对比学习是在没有标签的前提下学习样本之间的是否相似&#xff0c;其实和二分类比较相似&#xff0c;判断两个图像是不是属于同一个类别。换句话来说就是把相近的分布推得更近&…

用Arm CCA解锁数据的力量

安全之安全(security)博客目录导读 目录 CCA将如何改变Arm架构呢? 在实践中部署CCA 释放数据和人工智能的全部力量和潜力 早期计算中最大的挑战之一是管理计算资源&#xff0c;以最大化计算效率同时提供给不同程序或用户分配资源的分离。这导致了我们今天大多数使用的时间…

MinIO学习笔记

MINIO干什么用的&#xff1a; AI数据基础设施的对象存储 为人工智能系统提供数据支持&#xff0c;数据存储&#xff1b;对象存储&#xff08;Object Storage&#xff09;是一种数据存储架构&#xff0c;它以对象为单位来处理、存储和检索数据&#xff0c;每个对象都包含了数据本…

ModuleSim 仿真找不到模块 module is not defined

提示如下&#xff1a; # vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L cycloneive_ver -L rtl_work -L work -voptargs""acc"" pulse_generator_tb # Start time: 14:26:25 on May 10,2024 # ** Note: (…

开关电源功率测试方法:输入、输出功率测试步骤

在现代电子设备中&#xff0c;开关电源扮演着至关重要的角色&#xff0c;其效率和稳定性直接影响到整个系统的性能。因此&#xff0c;对开关电源进行功率测试成为了电源管理的重要环节。本文将详细介绍如何使用DC-DC电源模块测试系统对开关电源的输入输出功率进行准确测量&…

网络安全之OSPF进阶

该文针对OSPF进行一个全面的认识。建议了解OSPF的基础后进行本文的一个阅读能较好理解本文。 OSPF基础的内容请查看&#xff1a;网络安全之动态路由OSPF基础-CSDN博客 OSPF中更新方式中的触发更新30分钟的链路状态刷新。是因为其算法决定的&#xff0c;距离矢量型协议是边算边…

Python | Leetcode Python题解之第87题扰乱字符串

题目&#xff1a; 题解&#xff1a; class Solution:def isScramble(self, s1: str, s2: str) -> bool:cachedef dfs(i1: int, i2: int, length: int) -> bool:"""第一个字符串从 i1 开始&#xff0c;第二个字符串从 i2 开始&#xff0c;子串的长度为 le…

5.13号模拟前端面试10问

1.介绍箭头函数和普通函数的区别 箭头函数和普通函数在JavaScript中有一些重要的区别。以下是关于这些区别的详细解释&#xff1a; 语法结构上的差异&#xff1a; 箭头函数使用更简洁的语法&#xff0c;它不需要使用function关键字&#xff0c;而是使用一个箭头&#xff08;…

第三方组件element-ui

1、创建 选vue2 不要快照 vue2于vue3差异 vue2main。js import Vue from vue import App from ./App.vueVue.config.productionTip falsenew Vue({render: h > h(App), }).$mount(#app)vue3 main.js vue2不能有多个跟组件&#xff08;div&#xff09;

牛客网刷题 | BC82 乘法表

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 输出九九乘法表&am…

ASP.NET医药进销存系统

摘 要 目前&#xff0c;大中型城市的多数药品店已经实现了商品管理、客户管理、销售管理及销售管理等的信息化和网络化&#xff0c;提高了管理效率。但是&#xff0c;在大多数小药品店&#xff0c;药品店管理仍然以传统人工管理为主&#xff0c;特别是在药品的采购、销售、库…