提示:文章如有错误的地方请指出,以免误人子弟!
提示:以下是本篇文章正文内容,下面案例可供参考
首先没有安装组件的先安装springcloud alibaba(一) 组件安装,然后创建一个空的文件夹,然后用idea打开。
4.0.0
com.wwwh.onlyone.parent
onlyone-parent
1.0.0
onlyone-parent
pom
1.8
1.8
1.8
UTF-8
UTF-8
1.8
3.0.3
2021.1
2.4.2
3.0.5
1.8.2
8.0.26
2.2.0
1.2.6
2.5.5
1.3.1
1.2.78
6.0.0
0.1.54
2.2.11
1.18.20
3.12.0
org.springframework.cloud
spring-cloud-starter-bootstrap
${bootstrap.version}
com.alibaba.cloud
spring-cloud-alibaba-dependencies
${cloud-alibaba.version}
pom
import
org.springframework.boot
spring-boot-dependencies
${boot.version}
pom
import
com.alibaba.csp
sentinel-datasource-nacos
${sentinel-datasource-nacos.vsersion}
org.springframework.cloud
spring-cloud-starter-gateway
${gateway.version}
org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis.version}
mysql
mysql-connector-java
${mysql.version}
com.alibaba
druid-spring-boot-starter
${druid.version}
org.springframework.boot
spring-boot-starter-data-redis
${redis.version}
com.github.pagehelper
pagehelper-spring-boot-starter
${pagehelper.version}
org.activiti
activiti-spring-boot-starter-basic
${activiti.version}
org.springframework.boot
spring-boot-starter-data-jpa
com.jcraft
jsch
${sftp.version}
com.alibaba
fastjson
${fastjson.version}
com.alibaba
easyexcel
${easyexcel.version}
org.projectlombok
lombok
${lombok.version}
org.apache.commons
commons-lang3
${commons-lang3.version}
org.projectlombok
lombok-maven-plugin
1.18.20.0
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
utf-8
true
依然是在最外层的onlyone文件夹创建,不在parent上面创建,其他模块创建也是一样。
这个模块用来存放一些其他模块共用的实体类,共用方法等,因为本项目服务间的调用,用的dubbo插件,所以多了个service文件夹(共用的接口)。
common-pom内容:(需要注意的是
标签的内容是parent模块的pom信息,其他模块也一样)
onlyone-parent
com.wwwh.onlyone.parent
1.0.0
com.wwwh.onlyoa.common
4.0.0
onlyone-common
1.0.0
jar
onlyone-common
公共组件
com.github.pagehelper
pagehelper-spring-boot-starter
com.alibaba
easyexcel
org.projectlombok
lombok
org.apache.commons
commons-lang3
com.fasterxml.jackson.core
jackson-annotations
org.springframework.boot
spring-boot-maven-plugin
2.4.2
com.wwwh.onlyone.common
repackage
org.projectlombok
lombok-maven-plugin
1.18.20.0
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
utf-8
true
该模块用于服务数据提供。
这里parent
与common一样,并且将common模块引入,就可以使用共用方法了。
接着引入nacos包spring-cloud-starter-alibaba-nacos-discovery
,将application.yml配置内容放到nacos的包spring-cloud-starter-alibaba-nacos-config
,douuo包暴露提供方的数据方法spring-cloud-starter-dubbo
,bootstrap.yml 在cloud alibaba 2020.0.0 默认不在加载bootstrap 配置文件
,要用bootstrap 配置文件 需要手动添加spring-cloud-starter-bootstrap
依赖,不然启动项目会报错的,以及一些常规的插件包。
provider-pom 内容:
4.0.0
onlyone-parent
com.wwwh.onlyone.parent
1.0.0
com.wwwh.onlyone.registry
onlyone-registry
1.0.0
jar
onlyone-registry
注册中心
com.wwwh.onlyoa.common
onlyone-common
1.0.0
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-starter-bootstrap
spring-cloud-commons
org.springframework.cloud
spring-cloud-context
org.springframework.cloud
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
com.alibaba.cloud
spring-cloud-starter-dubbo
org.mybatis.spring.boot
mybatis-spring-boot-starter
mysql
mysql-connector-java
com.alibaba
druid-spring-boot-starter
org.springframework.boot
spring-boot-starter-data-redis
com.github.pagehelper
pagehelper-spring-boot-starter
1.3.1
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
asm
org.ow2.asm
org.springframework.boot
spring-boot-maven-plugin
2.4.2
com.wwwh.onlyone.registry
repackage
org.projectlombok
lombok-maven-plugin
1.18.20.0
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
utf-8
true
spring:
profiles:
#开发环境
active: dev
server:
port: 7001
spring:
application:
name: onlyone-registry
cloud:
nacos:
discovery:
#配置中心nacos地址
server-addr: 192.168.96.135:8848
enabled: true
register-enabled: true
#命名空间
namespace: 762988e7-0b5a-4bd2-a4f6-03ae96cf1a8c
config:
#注册中心nacos地址
server-addr: 192.168.96.135:8848
#指定yaml格式的配置
file-extension: yaml
#命名空间
namespace: 762988e7-0b5a-4bd2-a4f6-03ae96cf1a8c
group: ONLYONE_DEV_GROUP
spring.application.name:
配置的名称spring:
# 前后端传输时间相差8小时问题
jackson:
time-zone:
GMT+8
date-format:
yyyy-MM-dd HH:mm:ss
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.96.135:3306/onlyoa?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true& useSSL=false&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8&serverTimezone=Asia/Shanghai
username: root
password: wh0209
redis:
# Redis数据库索引(默认为0)
database: 0
# Redis服务器地址
host: 192.168.96.135
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
password: wh0209
# 连接超时时间(毫秒)
timeout: 3000
mybatis:
configuration:
cache-enabled: false
map-underscore-to-camel-case: true
mapper-locations: classpath:mapping/**/*Mapper.xml
type-aliases-package: com.onlyoa.common.entity
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
page-size-zero: true
dubbo:
cloud:
subscribed-services: onlyone-consumer
scan:
base-packages: com.wwwh.onlyone.registry.Impl #指定 Dubbo 服务实现类的扫描基准包
protocol:
name: dubbo #使用dubbo协议
port: -1 # port 为协议端口( -1 表示自增端口,从 20880 开始)
registry:
address: nacos://192.168.96.135:8848 #配置中心nacos地址
config-center:
namespace: 762988e7-0b5a-4bd2-a4f6-03ae96cf1a8c
consumer:
timeout: 300000
logging:
level:
com.wwwh.onlyone.registry: debug
config: classpath:logback-spring.xml
file:
path: C:/log/myLogs/registry/
服务提供模块暴露的接口方法在 public 命名空间,不知道咋回事。
启动服务数据提供模块看看:
启动成功了!
该模块用于服务数据调用。
pom 文件和上面的provider差不多,多了个sentinel
的包spring-cloud-starter-alibaba-sentinel
,用于接口的限流以及sentinel配置持久化到nacos的包sentinel-datasource-nacos
。
pom 内容:
4.0.0
onlyone-parent
com.wwwh.onlyone.parent
1.0.0
com.wwwh.onlyone.consumer
onlyone-consumer
1.0.0
jar
onlyone-consumer
消费者
com.wwwh.onlyoa.common
onlyone-common
1.0.0
org.springframework.boot
spring-boot-starter-web
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-starter-bootstrap
spring-cloud-commons
org.springframework.cloud
spring-cloud-context
org.springframework.cloud
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-config
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
com.alibaba.csp
sentinel-datasource-nacos
com.alibaba.cloud
spring-cloud-starter-dubbo
com.jcraft
jsch
org.mybatis.spring.boot
mybatis-spring-boot-starter
mysql
mysql-connector-java
com.alibaba
druid-spring-boot-starter
org.apache.commons
commons-lang3
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
asm
org.ow2.asm
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.boot
spring-boot-maven-plugin
2.4.2
com.wwwh.onlyone.consumer
repackage
org.projectlombok
lombok-maven-plugin
1.18.20.0
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
utf-8
true
接下来是yml 配置内容
spring:
profiles:
#开发环境
active: dev
server:
port: 8001
spring:
application:
name: onlyone-consumer
cloud:
nacos:
discovery:
#配置中心nacos地址
server-addr: 192.168.96.135:8848
enabled: true
register-enabled: true
#命名空间
namespace: 762988e7-0b5a-4bd2-a4f6-03ae96cf1a8c
config:
#注册中心nacos地址
server-addr: 192.168.96.135:8848
#指定yaml格式的配置
file-extension: yaml
#命名空间
namespace: 762988e7-0b5a-4bd2-a4f6-03ae96cf1a8c
group: ONLYONE_DEV_GROUP
spring:
# 前后端传输时间相差8小时问题
jackson:
time-zone:
GMT+8
date-format:
yyyy-MM-dd HH:mm:ss
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.96.135:3306/onlyoa?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true& useSSL=false&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8&serverTimezone=Asia/Shanghai
username: root
password: wh0209
redis:
# Redis数据库索引(默认为0)
database: 0
# Redis服务器地址
host: 192.168.96.135
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
password: wh0209
# 连接超时时间(毫秒)
timeout: 3000
cloud:
sentinel:
transport:
#配置Sentinel dashboard地址
dashboard: 192.168.96.135:8858
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直到找到未被占用的端口
port: 8719
datasource:
dsl:
nacos:
server-addr: 192.168.96.135:8848 #配置中心nacos地址
namespace: 762988e7-0b5a-4bd2-a4f6-03ae96cf1a8c #配置nacos地址
dataId: onlyone-consumer-sentinel
groupId: SENTINEL_GROUP
data-type: json
rule-type: flow
dubbo:
registry:
address: nacos://192.168.96.135:8848 #配置中心nacos地址
scan:
base-packages: com.wwwh.onlyoa.consumer.controller #指定 Dubbo 服务实现类的扫描基准包
cloud:
subscribed-services: onlyone-registry,onlyone-provider
application:
qos-enable: false
config-center:
namespace: 762988e7-0b5a-4bd2-a4f6-03ae96cf1a8c
protocol:
name: dubbo #使用dubbo协议
port: -1 # port 为协议端口( -1 表示自增端口,从 20880 开始)
consumer:
timeout: 300000
mybatis:
configuration:
cache-enabled: false
map-underscore-to-camel-case: true
mapper-locations: classpath:mapping/**/*Mapper.xml
type-aliases-package: com.onlyoa.common.entity
sftp:
# 服务器地址
host: 192.168.96.135
# 端口
port: 22
# 账号
userName: root
# 密码
password: wang521
# 图片的根路径
basePath: /home/nginx/image
# 音频的根路径
audioPath: /home/nginx/audio
# 视频的根路径
videoPath: /home/nginx/video
# channel连接超时时间
timeout: 30000
#连接次数
count: 3
#休眠时间
sleepTime: 6000
#服务器头像地址
titleImgsPath: http://192.168.96.135:80/image/
#服务器音频地址
titleAudiosPath: http://192.168.96.135:80/audio/
#服务器视频地址
titleVideosPath: http://192.168.96.135:80/video/
logging:
level:
com.wwwh.onlyone.consumer: debug
config: classpath:logback-spring.xml
file:
path: C:/log/myLogs/consumer/
注意:这里需要注意的就是 sentinel 持久化到 nacos 的配置
注意:这里的 命名空间 组名称,之前的yaml 换成 Json
配置内容:
[
{
"resource": "infof",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
},
{
"resource": "infoe",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
里面的参数对应说明请查看sentinel 官网说明
对应下图的表单里面的字段
启动项目看看
@DubboService
,目前最新的是@DubboService,老版本的是@Service
注意导包。@SentinelResource
value
:对应nacos里面sentinel json配置的"resource": "infof"
。blockHandlerClass
:发生流控时的回调方法。blockHandler
:具体流控回调方法。fallbackClass
:代码发生错误时的回调方法。fallback
:具体错误回调方法。public static String handler(BlockException blockException) {
String ruleLimitApp = blockException.getRuleLimitApp();
return "....被限流了.... "+ruleLimitApp;
}
public static String fallBack() {
return "....系统运行异常....";
}
pom 文件 gateway spring-cloud-starter-gateway
4.0.0
onlyone-parent
com.wwwh.onlyone.parent
1.0.0
com.wwwh.onlyone.gateway
onlyone-gateway
1.0.0
jar
onlyone-gateway
网关
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.springframework.cloud
spring-cloud-starter-gateway
org.springframework.boot
spring-boot-starter-data-redis
org.springframework.cloud
spring-cloud-starter-loadbalancer
3.0.4
org.apache.commons
commons-lang3
org.projectlombok
lombok
org.springframework.boot
spring-boot-maven-plugin
2.4.2
com.wwwh.onlyone.gateway
repackage
org.projectlombok
lombok-maven-plugin
1.18.20.0
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
utf-8
true
用于请求的转发,全局拦截器等
这边我没有把配置放到nacos,感兴趣的可以自己照着上面的模块弄一下。
server:
port: 1109
spring:
application:
name: onlyone-gateway
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
cloud:
nacos:
discovery:
#配置nacos地址
server-addr: 192.168.96.135:8848
#命名空间
namespace: 762988e7-0b5a-4bd2-a4f6-03ae96cf1a8c
# config:
# server-addr: 192.168.40.129:8848 #注册中心nacos地址
# file-extension: yaml #指定yaml格式的配置
# namespace: d2b59ca0-ff9f-4e63-a94c-d7a88b87d2d7 #命名空间
# group: DEV_GROUP
gateway:
httpclient:
connect-timeout: 10000
response-timeout: 5s
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: onlyone_gateway_login #路由id,要求唯一
# uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://onlyone-consumer #匹配注册中心的服务名称
predicates:
- Path=/free/** #断言,路径相匹配进行路由
filters:
- name: IgnoreAuthFilter #本路由跳过全局过滤器
args:
ignoreGlobalFilter: true
redis:
# Redis数据库索引(默认为0)
database: 0
# Redis服务器地址
host: 192.168.96.135
# Redis服务器连接端口
port: 6379
# Redis服务器连接密码(默认为空)
password: wh0209
# 连接超时时间(毫秒)
timeout: 3000
logging:
level:
com.wwwh.onlyone.registry: debug
config: classpath:logback-spring.xml
file:
path: C:/log/myLogs/gateway/
import com.wwwh.onlyone.gateway.utils.RedisUtil;
import org.apache.commons.lang3.StringUtils;
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.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Map;
/**
* description Gateway全局过滤器
* @author Mr.Tiger
* @date 2020/12/28 15:47
*/
@Component
public class MyLogGatewayFilter implements GlobalFilter, Ordered
{
/**
* description: 注入redis的工具类
*/
private final RedisUtil redisUtil;
public MyLogGatewayFilter(RedisUtil redisUtil)
{
this.redisUtil = redisUtil;
}
private static final Logger logger = LoggerFactory.getLogger(MyLogGatewayFilter.class);
/**
* description: token常量
*/
public static final String AUTHORIZE_TOKEN = "token";
/**
* description: 唯一标识,账号常量
*/
public static final String AUTHORIZE_USERID = "userPhone";
public final static String ATTRIBUTE_IGNORE_TEST_GLOBAL_FILTER = "@ignoreTestGlobalFilter";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//不过滤,忽略掉 注册,登录,记住密码,个人信息 等url路径
//指定路由跳过全局拦截器
if (exchange.getAttribute(ATTRIBUTE_IGNORE_TEST_GLOBAL_FILTER) == null) {
//获取请求头中的token和userPhone
String token = exchange.getRequest().getHeaders().getFirst(AUTHORIZE_TOKEN);
logger.info("-------------前台token:"+token);
String userPhone = exchange.getRequest().getHeaders().getFirst(AUTHORIZE_USERID);
//如果token和userPhone为null,则请求参数中尝试再次获取
if (StringUtils.isEmpty(token))
{
logger.error("请求头token 不存在,请重新登陆");
exchange.getRequest().getQueryParams().getFirst(AUTHORIZE_TOKEN);
}
if (StringUtils.isEmpty(userPhone))
{
logger.error("请求头账号 不存在,请重新登陆");
exchange.getRequest().getQueryParams().getFirst(AUTHORIZE_USERID);
}
//如果依然不存在token或者userPhone,则直接返回401状态码
if (StringUtils.isEmpty(token) || StringUtils.isEmpty(userPhone))
{
logger.error("请求头账号或token 不存在,请重新登陆");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
else
{
//从redis里取出token
Object getToken = redisUtil.hget(userPhone, AUTHORIZE_TOKEN);
logger.info("-------------redis--token:"+getToken);
if (getToken == null)
{
//返回没有找到token
logger.error("没有找到 账号对应的 token");
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().setComplete();
}
else
{
if (!token.equals(getToken))
{
//返回参数不被接受
logger.error("请求头里的token和redis里的不一样");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
else
{
String path = exchange.getRequest().getURI().getPath();
Map<String, Object> attributes = exchange.getAttributes();
System.out.println(attributes.toString());
logger.info("截取到的url地址是-------"+path);
}
}
}
}
return chain.filter(exchange);
}
@Override
public int getOrder()
{
return -108;
}
}
里面具体业务不用太过关心。
import com.wwwh.onlyone.gateway.filter.MyLogGatewayFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @Description:
* @Author: Mr.Tiger
* @Date: 2021/5/25 11:38
*/
@Slf4j
@Component
public class IgnoreAuthFilter extends AbstractGatewayFilterFactory<IgnoreAuthFilter.Config> {
public IgnoreAuthFilter() {
super(Config.class);
log.info("IgnoreFilter 进入 IgnoreAuthGatewayFilterFactory ");
}
@Override
public GatewayFilter apply(Config config) {
log.info("IgnoreFilter 进入 apply");
/*return (exchange, chain) -> {
if (!config.isIgnoreGlobalFilter()) {
return chain.filter(exchange);
}
return chain.filter(exchange);
};*/
//===============================注意=================================
//下面的内部类写法,是为了指定过滤器的优先级,要优先于全局过滤器,否则
//容易造成全局过滤器 拦截到指定 局部过滤器的配置内容。
return new InnerFilter(config);
}
/**
* 创建一个内部类,来实现2个接口,指定顺序
* 这里通过Ordered指定优先级
*/
private class InnerFilter implements GatewayFilter, Ordered {
private Config config;
InnerFilter(Config config) {
this.config = config;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
/*System.out.println(" pre 自定义过滤器工厂 AAAA " + this.getClass().getSimpleName());
boolean root = true == config.isIgnoreGlobalFilter();
if (root) {
System.out.println(" is root ");
} else {
System.out.println(" is no root ");
}
// 在then方法里的,相当于aop中的后置通知
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
System.out.println(" post 自定义过滤器工厂 AAAA " + this.getClass().getSimpleName());
}));*/
log.info("进入innerFilter=====" + config.isIgnoreGlobalFilter());
if (config.isIgnoreGlobalFilter() == true) {
exchange.getAttributes().put(MyLogGatewayFilter.ATTRIBUTE_IGNORE_TEST_GLOBAL_FILTER, true);
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1000;
}
}
public static class Config{
boolean ignoreGlobalFilter;
public boolean isIgnoreGlobalFilter() {
return ignoreGlobalFilter;
}
public void setIgnoreGlobalFilter(boolean ignoreGlobalFilter) {
this.ignoreGlobalFilter = ignoreGlobalFilter;
}
}
/**
* description: 这个name方法 用来在yml配置中指定对应的过滤器名称
*
* @return java.lang.String
* @author Mr.Tiger
*/
@Override
public String name() {
return "IgnoreAuthFilter";
}
}
注意:ATTRIBUTE_IGNORE_TEST_GLOBAL_FILTER
这个参数在拦截器里面的配置
测试调用:
希望对你有所帮助!