0%

下面描述三种类型

  1. application/x-www-form-urlencoded
  2. multipart/form-data:上传文件
  3. application/json;charset=UTF-8

Post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Slf4j
public class RestTemplateUtils {
private static final RestTemplate REST_TEMPLATE;

static {
REST_TEMPLATE = new RestTemplate();
}
/**
* application/x-www-form-urlencoded
*/
public void post(String serverUrl){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
String bodys = "id=1&name=maxzhao";
HttpEntity<String> httpEntity = new HttpEntity<>(bodys, headers);
ResponseEntity<JSONObject> response = REST_TEMPLATE.postForEntity(serverUrl, httpEntity, JSONObject.class);
}
/**
* multipart/form-data
*/
public void post(String serverUrl){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("id","1");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<String> httpEntity = new HttpEntity<>(bodys, headers);
ResponseEntity<JSONObject> response = REST_TEMPLATE.postForEntity(serverUrl, httpEntity, JSONObject.class);
}
/**
* application/json;charset=UTF-8
*/
public void post(String serverUrl){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
MultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
requestBody.add("id","1");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<String> httpEntity = new HttpEntity<>(bodys, headers);
ResponseEntity<JSONObject> response = REST_TEMPLATE.postForEntity(serverUrl, httpEntity, JSONObject.class);
}
}

解析结果

1
2
3
4
5
JSONObject body = response.getBody();
if (HttpStatus.OK.equals(response.getStatusCode()) && body != null) {
// 处理结果
}
// 错误会抛出异常 HttpServerErrorException

自定义异常处理器

1
2
3
4
5
6
7
8
9
REST_TEMPLATE.setErrorHandler(new DefaultResponseErrorHandler() {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
/*错误请求不为 400 时,抛出异常*/
if (!HttpStatus.BAD_REQUEST.equals(response.getStatusCode())) {
super.handleError(response);
}
}
});

本文地址: https://github.com/maxzhao-it/blog/post/63856b15/

引入 HttpClient

1
2
3
4
5
6
7
8
9
10
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Slf4j
public class RestTemplateUtils {
private static final RestTemplate REST_TEMPLATE;

static {
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
try {
httpComponentsClientHttpRequestFactory.setHttpClient(generateCloseableHttpClient());
} catch (Exception e) {
log.error("生成 HttpClient 失败", e);
}
httpComponentsClientHttpRequestFactory.setConnectTimeout(60 * 1000);
httpComponentsClientHttpRequestFactory.setReadTimeout(30 * 100);
REST_TEMPLATE = new RestTemplate(httpComponentsClientHttpRequestFactory);
}
}

自定义异常处理器

1
2
3
4
5
6
7
8
9
REST_TEMPLATE.setErrorHandler(new DefaultResponseErrorHandler() {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
/*错误请求不为 400 时,抛出异常*/
if (!HttpStatus.BAD_REQUEST.equals(response.getStatusCode())) {
super.handleError(response);
}
}
});

本文地址: https://github.com/maxzhao-it/blog/post/63856b15/

前言

Word 文档内容识别主要由两部分:docdocx

docx 文档内容识别的难点在于:

  1. 格式不规范。
  2. 内容出现的规律

下面记录解析段落格式及内容。

一、docx内容提取

1、提取全文

提取全文内容相对简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class FileParsingService {
/**
* 解析 docx 的存文本内容
*
* @param file 文件
* @return 存文本内容
*/
public String parsingWordContent(Resource file) {
InputStream is = null;
try {
is = file.getInputStream();
XWPFDocument document = new XWPFDocument(is);
/*word 纯文本内容*/
return new XWPFWordExtractor(document).getText();
} catch (Exception e) {
log.warn("解析 word 失败,fileName={}", file.getFilename(), e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
log.warn("请关注输出入关闭失败", e);
}
}
}
return null;
}
}

2、提取有格式的内容

2.1、 基本原理

提取有格式的内容是按照段的方式提取的。

2.2、 获取所有段落

1
2
3
4
5
6
7
8
9
public class FileParsingService {
/*******************************/
public List<String> parsingWordOpinion(Resource file) throws Exception{
InputStream is = file.getInputStream();
XWPFDocument document = new XWPFDocument(is);
/*段落集合*/
List<IBodyElement> bodyElements = document.getBodyElements();
}
}

2.3、 处理段落

常用的几种段类型:

  • XWPFSDT 目录
  • XWPFParagraph 段落
  • XWPFTable 表格

2.3.1、XWPFSDT 目录

对于目录,直接获取目录内容就可以了

1
((XWPFSDT) bodyElement).getContent().getText()

2.3.2、XWPFParagraph 段落(重点)

作为段落的内容,又可以分为:

  • 标题
  • 序列(有序列、无序列)
  • 正文
2.3.2.1、提取段落正文
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class FileParsingUtil {
private final static boolean concatenatePhoneticRuns = true;
/**
* 输出超文本链接=false
*/
private final static boolean fetchHyperlinks = false;

/**
* 只提取段落内容
*
* @param document 文档
* @param paragraph 段落 (XWPFParagraph) bodyElement;
* @return 内容
*/

public static String extractParagraphText(XWPFDocument document, XWPFParagraph paragraph) {
StringBuilder text = new StringBuilder();
for (IRunElement run : paragraph.getIRuns()) {
if (run instanceof XWPFSDT) {
text.append(((XWPFSDT) run).getContent().getText());
} else if (!concatenatePhoneticRuns && run instanceof XWPFRun) {
text.append(((XWPFRun) run).text());
} else {
text.append(run);
}
/*提取超链接的链接*/
if (run instanceof XWPFHyperlinkRun && fetchHyperlinks) {
XWPFHyperlink link = ((XWPFHyperlinkRun) run).getHyperlink(document);
if (link != null)
text.append(" <").append(link.getURL()).append(">");
}
}
return text.toString();
}
}
2.3.2.2、提取段落的格式
1
2
XWPFParagraph paragraphTemp = (XWPFParagraph) bodyElement;
paragraphTemp.getStyleID()

格式有很多,比如:

  • 标题
    • Heading 1
    • Heading 2
    • RegHChG
    • RegH1G
    • RegH2G
  • 序列的合适
    • ListParagraph
    • RegSingleTxtG
    • RegSingleTxtG2

备注:但是需要的判断方式不是序列的格式,因为格式是不固定的。

格式内容在 wps样式和格式中都能看到。

2.3.2.3、判断是否为序列
1
2
3
4
XWPFParagraph paragraphTemp = (XWPFParagraph) bodyElement;
if(paragraphTemp.getNumID()!=null){
// 当前为序列
}

需要有两个重要属性

  • NumLevelText 序列值的格式化方式
    • %1、,根据序列的类型,可以为 1、一、a、
    • (%1),根据序列的类型,可以为 (1)(一)(a)
    • 暂未发现 %1%2 的区别——TODO
  • NumFmt 序列的类型
    • chineseCounting 中文
    • decimal 数字
    • decimalEnclosedCircleChinese 圆圈中的数字
    • upperLetter 大写字母
    • lowerLetter 小写字母
    • lowerRoman 小写罗马
    • upperRoman 大写罗马
    • bullet 无序(不用识别出方的、圆的和菱形的,没有意义)
    • 其它

2.3.3、XWPFTable 表格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class FileParsingUtil {
/**
* 解析表格内容
*
* @param table 表格 (XWPFTable) bodyElement
* @return 表格内容
*/
public static String appendTableText(XWPFTable table) {
StringBuilder text = new StringBuilder();
//this works recursively to pull embedded tables from tables
for (XWPFTableRow row : table.getRows()) {
List<ICell> cells = row.getTableICells();
for (int i = 0; i < cells.size(); i++) {
ICell cell = cells.get(i);
if (cell instanceof XWPFTableCell) {
text.append(((XWPFTableCell) cell).getTextRecursively());
} else if (cell instanceof XWPFSDTCell) {
text.append(((XWPFSDTCell) cell).getContent().getText());
}
if (i < cells.size() - 1) {
text.append("\t");
}
}
text.append('\n');
}
return text.toString();
}
}

一段话:

在识别出内容出现的规律后,对于规范的格式,需要识别的内容也是多种多样的,需要打开 worddocx推荐用wps打开),然后打开样式和格式,对每个段落内容进行分析。

本文地址: https://github.com/maxzhao-it/blog/post/cb38f68c/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import java.util.HashMap;
import java.util.Map;

/**
* 罗马数字与十进制计算工具
*
* @author maxzhao
* @since 2022-12-19 09:29
*/
public class RomanSerialNumberUtil {
/**
* 罗马数字对应的十进制
*/
private static final Map<String, Integer> ROMAN_SERIAL_NUMBER_MAP;
/**
* 数字间隔计算,从大到小
*/
private static final int[] DIGITS = new int[13];
/**
* 数字对应小写的罗马数字
*/
private static final Map<Integer, String> NUM_TO_LOWER_ROMAN_SERIAL_NUMBER = new HashMap<>();
/**
* 数字对应大写的罗马数字
*/
private static final Map<Integer, String> NUM_TO_UPPER_ROMAN_SERIAL_NUMBER = new HashMap<>();

static {
ROMAN_SERIAL_NUMBER_MAP = new HashMap<>(32);
ROMAN_SERIAL_NUMBER_MAP.put("I", 1);
ROMAN_SERIAL_NUMBER_MAP.put("i", 1);
ROMAN_SERIAL_NUMBER_MAP.put("V", 5);
ROMAN_SERIAL_NUMBER_MAP.put("v", 5);
ROMAN_SERIAL_NUMBER_MAP.put("X", 10);
ROMAN_SERIAL_NUMBER_MAP.put("x", 10);
ROMAN_SERIAL_NUMBER_MAP.put("L", 50);
ROMAN_SERIAL_NUMBER_MAP.put("l", 50);
ROMAN_SERIAL_NUMBER_MAP.put("C", 100);
ROMAN_SERIAL_NUMBER_MAP.put("c", 100);
ROMAN_SERIAL_NUMBER_MAP.put("D", 500);
ROMAN_SERIAL_NUMBER_MAP.put("d", 500);
ROMAN_SERIAL_NUMBER_MAP.put("M", 1000);
ROMAN_SERIAL_NUMBER_MAP.put("m", 1000);
ROMAN_SERIAL_NUMBER_MAP.put("IV", 4);
ROMAN_SERIAL_NUMBER_MAP.put("iv", 4);
ROMAN_SERIAL_NUMBER_MAP.put("IX", 9);
ROMAN_SERIAL_NUMBER_MAP.put("ix", 9);
ROMAN_SERIAL_NUMBER_MAP.put("XL", 40);
ROMAN_SERIAL_NUMBER_MAP.put("xl", 40);
ROMAN_SERIAL_NUMBER_MAP.put("XC", 90);
ROMAN_SERIAL_NUMBER_MAP.put("xc", 90);
ROMAN_SERIAL_NUMBER_MAP.put("CD", 400);
ROMAN_SERIAL_NUMBER_MAP.put("cd", 400);
ROMAN_SERIAL_NUMBER_MAP.put("CM", 900);
ROMAN_SERIAL_NUMBER_MAP.put("cm", 900);
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(1, "i");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(5, "v");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(10, "x");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(50, "l");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(100, "c");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(500, "d");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(1000, "m");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(4, "iv");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(9, "ix");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(40, "xl");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(90, "xc");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(400, "cd");
NUM_TO_LOWER_ROMAN_SERIAL_NUMBER.put(900, "cm");


NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(1, "I");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(5, "V");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(10, "X");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(50, "L");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(100, "C");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(500, "D");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(1000, "M");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(4, "IV");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(9, "IX");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(40, "XL");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(90, "XC");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(400, "CD");
NUM_TO_UPPER_ROMAN_SERIAL_NUMBER.put(900, "CM");

DIGITS[0] = 1000;
DIGITS[1] = 900;
DIGITS[2] = 500;
DIGITS[3] = 400;
DIGITS[4] = 100;
DIGITS[5] = 90;
DIGITS[6] = 50;
DIGITS[7] = 40;
DIGITS[8] = 10;
DIGITS[9] = 9;
DIGITS[10] = 5;
DIGITS[11] = 4;
DIGITS[12] = 1;
}

/**
* 数字转小写罗马字符串
*
* @param num 字符串
* @return 数字
*/
public static String toLowerRomanSerialNumber(int num) {
return toRomanSerialNumber(num, true);
}
/**
* 数字转大写罗马字符串
*
* @param num 字符串
* @return 数字
*/
public static String toUpperRomanSerialNumber(int num) {
return toRomanSerialNumber(num, false);
}
/**
* 数字转罗马字符串
*
* @param num 字符串
* @return 数字
*/
public static String toRomanSerialNumber(int num,boolean lowerChar) {
Map<Integer, String> chars = lowerChar ? NUM_TO_LOWER_ROMAN_SERIAL_NUMBER : NUM_TO_UPPER_ROMAN_SERIAL_NUMBER;
String res = "";
while (num > 0) {
for (int digit : DIGITS) {
if (num >= digit) {
res += chars.get(digit);
num -= digit;
break;
}
}
}
return res;
}

/**
* 罗马字符串转 数字
*
* @param roman 字符串
* @return 数字
*/
public static int getLowerRomanSerialNumber(String roman) {
int res = 0;
int idx = 0;
while (idx < roman.length()) {
if (idx + 1 < roman.length() && ROMAN_SERIAL_NUMBER_MAP.containsKey(roman.substring(idx, idx + 2))) {
res += ROMAN_SERIAL_NUMBER_MAP.get(roman.substring(idx, idx + 2));
idx += 2;
} else {
res += ROMAN_SERIAL_NUMBER_MAP.get(roman.substring(idx, idx + 1));
idx++;
}

}
return res;
}
}

本文地址: https://github.com/maxzhao-it/blog/post/b87a95cb/

SpringCloudGateway 全局过滤器需要实现 org.springframework.cloud.gateway.filter.GlobalFilter 接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

@Component
public class AuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpRequest.Builder mutate = request.mutate();
/*获取请求头*/
String contentType = request.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
/*添加、或更新*/
mutate.header(HttpHeaders.CONTENT_TYPE, URLEncoder.encode(MediaType.APPLICATION_JSON_VALUE, Constants.UTF8));
/*删除*/
mutate.headers(httpHeaders -> httpHeaders.remove(name)).build();
return chain.filter(exchange.mutate().request(mutate.build()).build());
}

@Override
public int getOrder() {
return -200;
}
}

本文地址: https://github.com/maxzhao-it/blog/post/5fd3d0d2/

Sentinel 官方配置记录了一部分,在 sentinel-core 的源码里都可以找到。

配置修改

sentinel-dashbord 控制台

这里使用 sentinel-dashboard-1.8.6.jar

官方参考

这里建议使用外部化配置:

1
java -Dcsp.sentinel.config.file=./application.properties -jar sentinel-dashboard.jar

配置文件在 sentinel-dashboard.jar:/BOOT-INF/classes/application.properties,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 新增
# 服务端口
server.port=48080
# 项目名
project.name=sentinel-dashboard
# 客户端发送心跳的地址
csp.sentinel.dashboard.server=localhost:48080
# 日志文件的地址
csp.sentinel.log.dir=./logs/
#spring settings
server.servlet.encoding.force=true
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true

#cookie name setting
server.servlet.session.cookie.name=sentinel_dashboard_cookie

#logging settings
logging.level.org.springframework.web=INFO
logging.file.name=./logs/csp/sentinel-dashboard.log
logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n

#auth settings
auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version
auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png
# If auth.enabled=false, Sentinel console disable login
auth.username=sentinel
auth.password=sentinel

# Inject the dashboard version. It's required to enable
# filtering in pom.xml for this resource file.
sentinel.dashboard.version=1.8.6

sentinel 客户端

日志配置 sentinel.properties 加载是在 LogConfigLoader 下,加载方式有

  • 环境变量(CSP_SENTINEL_CONFIG_FILE)指定
  • 配置属性(csp.sentinel.config.file)指定
  • 默认(classpath:sentinel.properties

我们可以使用默认配置,在 resources 下创建 sentinel.properties 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 没有配置时,默认读取当前文件,可以通过 -Dcsp.sentinel.config.file 配置
# 指定应用的名称
project.name=gateway
# 未指定时,取project.name
csp.sentinel.app.name=gateway
# 指定应用的类型
csp.sentinel.app.type=10
# 单个监控日志文件的大小 long
csp.sentinel.metric.file.single.size=52428800
# 监控日志文件的总数上限 int 6
csp.sentinel.metric.file.total.count=1 6
# 最大的有效响应时长(ms),超出此值则按照此值记录
csp.sentinel.statistic.max.rt=5000
# SPI 加载时使用的 ClassLoader
#csp.sentinel.spi.classloader=context
csp.sentinel.metric.flush.interval=1
# 日志配置
csp.sentinel.log.dir=./logs/sentinel/
# 输出至文件,默认
csp.sentinel.log.output.type=file
# 日志文件 使用进程ID
csp.sentinel.log.use.pid=true

如果使用 SpringCloudAlibaba可以参考官方 Sentinel 说明

本文地址: https://github.com/maxzhao-it/blog/post/6c42980c/

这里使用SpringCloud

依赖

父类依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- <spring-cloud.version>2021.0.4</spring-cloud.version> -->
<!-- <spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version> -->
<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>

<!-- SpringCloud Alibaba 微服务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

基础依赖

1
2
3
4
5
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

sentinel 使用 nacos 做配置中心

1
2
3
4
5
<!-- Sentinel Datasource Nacos -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

sentinelgateway 依赖

1
2
3
4
5
<!-- SpringCloud Alibaba Sentinel Gateway -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

配置

配置文件配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# Spring
spring:
cloud:
# 当前配置可以放在 nacos 中
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
# 认证中心
- id: auth
uri: lb://auth
predicates:
- Path=/auth/**
filters:
- StripPrefix=1
nacos:
discovery:
# nacos 服务注册地址
server-addr: 127.0.0.1:8848
config:
# nacos 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-dev.${spring.cloud.nacos.config.file-extension}
sentinel:
# 取消控制台懒加载
eager: true
transport:
# 接收限流规则
port: 8719
# 控制台地址
dashboard: 127.0.0.1:48080
# nacos配置持久化
datasource:
# 动态数据源
ds1:
# NacosDataSourceProperties
nacos:
server-addr: 127.0.0.1:8848
dataId: sentinel-gateway
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow

规则的种类(ruleType):

  • flow: 流量控制
  • degrade: 熔断降级
  • system:系统保护
  • authority:访问控制
  • param-flow:热点

官方规则种类配置说明

flow的配置

nacos配置中心就可以添加网关流量控制规则:

1
2
3
4
5
6
7
8
9
10
[
{
"resource": "auth",
"count": 500,
"grade": 1,
"limitApp": "default",
"strategy": 0,
"controlBehavior": 0
}
]

网关限流规则:GatewayFlowRule

本文地址: https://github.com/maxzhao-it/blog/post/8a4e05d0/

nginx.confhttp 下加入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 开启gzip压缩
gzip on;
# 大于1K的才压缩
gzip_min_length 1k;
# 压缩缓冲区
gzip_buffers 16 64K;
# 压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_http_version 1.1;
# 压缩级别,1-10,数字越大压缩的越好,时间也越长
gzip_comp_level 5;
# 进行压缩的文件类型
gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
# 跟Squid等缓存服务有关,on的话会在Header里增加"Vary: Accept-Encoding"
gzip_vary on;
# 排除IE6
gzip_disable "MSIE [1-6]\.";

本文地址: https://github.com/maxzhao-it/blog/post/cbe2108c/