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
| /**
* 日誌攔截器
*/
@Component
public class LoggingInterceptor implements ClientHttpRequestInterceptor {
private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
@Override
public ClientHttpResponse intercept(
HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution) throws IOException {
logRequest(request, body);
long startTime = System.currentTimeMillis();
ClientHttpResponse response = execution.execute(request, body);
long duration = System.currentTimeMillis() - startTime;
logResponse(response, duration);
return response;
}
private void logRequest(HttpRequest request, byte[] body) {
logger.info("===========================request begin================================================");
logger.info("URI : {}", request.getURI());
logger.info("Method : {}", request.getMethod());
logger.info("Headers : {}", request.getHeaders());
logger.info("Request body: {}", new String(body, StandardCharsets.UTF_8));
logger.info("==========================request end================================================");
}
private void logResponse(ClientHttpResponse response, long duration) throws IOException {
logger.info("============================response begin==========================================");
logger.info("Status code : {}", response.getStatusCode());
logger.info("Status text : {}", response.getStatusText());
logger.info("Headers : {}", response.getHeaders());
logger.info("Duration : {} ms", duration);
logger.info("=======================response end=================================================");
}
}
/**
* 認證攔截器
*/
@Component
public class AuthenticationInterceptor implements ClientHttpRequestInterceptor {
private final TokenService tokenService;
public AuthenticationInterceptor(TokenService tokenService) {
this.tokenService = tokenService;
}
@Override
public ClientHttpResponse intercept(
HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution) throws IOException {
// 獲取並設置認證 token
String token = tokenService.getCurrentToken();
if (token != null) {
request.getHeaders().set("Authorization", "Bearer " + token);
}
return execution.execute(request, body);
}
}
/**
* 重試攔截器
*/
@Component
public class RetryInterceptor implements ClientHttpRequestInterceptor {
private static final Logger logger = LoggerFactory.getLogger(RetryInterceptor.class);
private final int maxRetries;
private final long retryDelay;
public RetryInterceptor(@Value("${rest-client.retry.max-attempts:3}") int maxRetries,
@Value("${rest-client.retry.delay:1000}") long retryDelay) {
this.maxRetries = maxRetries;
this.retryDelay = retryDelay;
}
@Override
public ClientHttpResponse intercept(
HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution) throws IOException {
IOException lastException = null;
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try {
ClientHttpResponse response = execution.execute(request, body);
// 檢查是否需要重試(例如:5xx 錯誤)
if (shouldRetry(response) && attempt < maxRetries) {
logger.warn("Request failed with status {}, retrying... (attempt {}/{})",
response.getStatusCode(), attempt, maxRetries);
// 等待後重試
try {
Thread.sleep(retryDelay * attempt); // 指數退避
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Interrupted during retry delay", e);
}
continue;
}
return response;
} catch (IOException e) {
lastException = e;
if (attempt < maxRetries) {
logger.warn("Request failed, retrying... (attempt {}/{}) - {}",
attempt, maxRetries, e.getMessage());
try {
Thread.sleep(retryDelay * attempt);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new IOException("Interrupted during retry delay", ie);
}
} else {
logger.error("Request failed after {} attempts", maxRetries, e);
}
}
}
throw lastException;
}
private boolean shouldRetry(ClientHttpResponse response) throws IOException {
HttpStatus status = response.getStatusCode();
return status.is5xxServerError() || status == HttpStatus.REQUEST_TIMEOUT;
}
}
|
留言討論