Skip to content

Commit 6118ca8

Browse files
committed
feat: add Jakarta EE Servlet 6.0 adapter module (#2998)
Add sentinel-web-servlet-jakarta module to support Jakarta EE Servlet 6.0 (Spring Boot 3.x, JDK 17+). Changes: - New module: sentinel-adapter/sentinel-web-servlet-jakarta - All javax.servlet imports replaced with jakarta.servlet - jakarta.servlet-api 6.0.0 (replacing javax.servlet-api 3.1.0) - Spring Boot 3.2.0 for tests (replacing 1.5.17.RELEASE) - Added new module to sentinel-adapter/pom.xml Usage: <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-web-servlet-jakarta</artifactId> </dependency> Fixes #2998
1 parent 872bbf8 commit 6118ca8

12 files changed

Lines changed: 813 additions & 0 deletions

File tree

sentinel-adapter/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
<modules>
1818
<module>sentinel-web-servlet</module>
19+
<module>sentinel-web-servlet-jakarta</module>
1920
<module>sentinel-dubbo-adapter</module>
2021
<module>sentinel-apache-dubbo-adapter</module>
2122
<module>sentinel-apache-dubbo3-adapter</module>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<groupId>com.alibaba.csp</groupId>
8+
<artifactId>sentinel-adapter</artifactId>
9+
<version>2.0.0-alpha2-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>sentinel-web-servlet-jakarta</artifactId>
13+
<packaging>jar</packaging>
14+
<description>Sentinel adapter for Jakarta EE Servlet 6.0 (Spring Boot 3.x)</description>
15+
16+
<properties>
17+
<jakarta.servlet-api.version>6.0.0</jakarta.servlet-api.version>
18+
<skip.spring.v6x.test>false</skip.spring.v6x.test>
19+
</properties>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>com.alibaba.csp</groupId>
24+
<artifactId>sentinel-core</artifactId>
25+
</dependency>
26+
27+
<dependency>
28+
<groupId>jakarta.servlet</groupId>
29+
<artifactId>jakarta.servlet-api</artifactId>
30+
<version>${jakarta.servlet-api.version}</version>
31+
<scope>provided</scope>
32+
</dependency>
33+
34+
<dependency>
35+
<groupId>junit</groupId>
36+
<artifactId>junit</artifactId>
37+
<scope>test</scope>
38+
</dependency>
39+
<dependency>
40+
<groupId>org.springframework.boot</groupId>
41+
<artifactId>spring-boot-starter-web</artifactId>
42+
<version>3.2.0</version>
43+
<scope>test</scope>
44+
</dependency>
45+
<dependency>
46+
<groupId>org.springframework.boot</groupId>
47+
<artifactId>spring-boot-starter-test</artifactId>
48+
<version>3.2.0</version>
49+
<scope>test</scope>
50+
</dependency>
51+
</dependencies>
52+
53+
<build>
54+
<plugins>
55+
<plugin>
56+
<groupId>org.apache.maven.plugins</groupId>
57+
<artifactId>maven-surefire-plugin</artifactId>
58+
<version>${maven.surefire.version}</version>
59+
<configuration>
60+
<skipTests>${skip.spring.v6x.test}</skipTests>
61+
</configuration>
62+
</plugin>
63+
</plugins>
64+
</build>
65+
66+
</project>
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
* Copyright 1999-2018 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.servlet;
17+
18+
import java.io.IOException;
19+
20+
import jakarta.servlet.Filter;
21+
import jakarta.servlet.FilterChain;
22+
import jakarta.servlet.FilterConfig;
23+
import jakarta.servlet.ServletException;
24+
import jakarta.servlet.ServletRequest;
25+
import jakarta.servlet.ServletResponse;
26+
import jakarta.servlet.http.HttpServletRequest;
27+
import jakarta.servlet.http.HttpServletResponse;
28+
29+
import com.alibaba.csp.sentinel.Entry;
30+
import com.alibaba.csp.sentinel.EntryType;
31+
import com.alibaba.csp.sentinel.ResourceTypeConstants;
32+
import com.alibaba.csp.sentinel.SphU;
33+
import com.alibaba.csp.sentinel.Tracer;
34+
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
35+
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner;
36+
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
37+
import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig;
38+
import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil;
39+
import com.alibaba.csp.sentinel.context.ContextUtil;
40+
import com.alibaba.csp.sentinel.slots.block.BlockException;
41+
import com.alibaba.csp.sentinel.util.StringUtil;
42+
43+
/**
44+
* Servlet filter that integrates with Sentinel.
45+
*
46+
* @author youji.zj
47+
* @author Eric Zhao
48+
* @author zhaoyuguang
49+
*/
50+
public class CommonFilter implements Filter {
51+
52+
/**
53+
* Specify whether the URL resource name should contain the HTTP method prefix (e.g. {@code POST:}).
54+
*/
55+
public static final String HTTP_METHOD_SPECIFY = "HTTP_METHOD_SPECIFY";
56+
/**
57+
* If enabled, use the default context name, or else use the URL path as the context name,
58+
* {@link WebServletConfig#WEB_SERVLET_CONTEXT_NAME}. Please pay attention to the number of context (EntranceNode),
59+
* which may affect the memory footprint.
60+
*
61+
* @since 1.7.0
62+
*/
63+
public static final String WEB_CONTEXT_UNIFY = "WEB_CONTEXT_UNIFY";
64+
65+
private final static String COLON = ":";
66+
67+
private boolean httpMethodSpecify = false;
68+
private boolean webContextUnify = true;
69+
70+
@Override
71+
public void init(FilterConfig filterConfig) {
72+
httpMethodSpecify = Boolean.parseBoolean(filterConfig.getInitParameter(HTTP_METHOD_SPECIFY));
73+
if (filterConfig.getInitParameter(WEB_CONTEXT_UNIFY) != null) {
74+
webContextUnify = Boolean.parseBoolean(filterConfig.getInitParameter(WEB_CONTEXT_UNIFY));
75+
}
76+
}
77+
78+
@Override
79+
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
80+
throws IOException, ServletException {
81+
HttpServletRequest sRequest = (HttpServletRequest) request;
82+
Entry urlEntry = null;
83+
84+
try {
85+
String target = FilterUtil.filterTarget(sRequest);
86+
// Clean and unify the URL.
87+
// For REST APIs, you have to clean the URL (e.g. `/foo/1` and `/foo/2` -> `/foo/:id`), or
88+
// the amount of context and resources will exceed the threshold.
89+
UrlCleaner urlCleaner = WebCallbackManager.getUrlCleaner();
90+
if (urlCleaner != null) {
91+
target = urlCleaner.clean(target);
92+
}
93+
94+
// If you intend to exclude some URLs, you can convert the URLs to the empty string ""
95+
// in the UrlCleaner implementation.
96+
if (!StringUtil.isEmpty(target)) {
97+
// Parse the request origin using registered origin parser.
98+
String origin = parseOrigin(sRequest);
99+
String contextName = webContextUnify ? WebServletConfig.WEB_SERVLET_CONTEXT_NAME : target;
100+
ContextUtil.enter(contextName, origin);
101+
102+
if (httpMethodSpecify) {
103+
// Add HTTP method prefix if necessary.
104+
String pathWithHttpMethod = sRequest.getMethod().toUpperCase() + COLON + target;
105+
urlEntry = SphU.entry(pathWithHttpMethod, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
106+
} else {
107+
urlEntry = SphU.entry(target, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
108+
}
109+
}
110+
chain.doFilter(request, response);
111+
} catch (BlockException e) {
112+
HttpServletResponse sResponse = (HttpServletResponse) response;
113+
// Return the block page, or redirect to another URL.
114+
WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse, e);
115+
} catch (IOException | ServletException | RuntimeException e2) {
116+
Tracer.traceEntry(e2, urlEntry);
117+
throw e2;
118+
} finally {
119+
if (urlEntry != null) {
120+
urlEntry.exit();
121+
}
122+
ContextUtil.exit();
123+
}
124+
}
125+
126+
private String parseOrigin(HttpServletRequest request) {
127+
RequestOriginParser originParser = WebCallbackManager.getRequestOriginParser();
128+
String origin = EMPTY_ORIGIN;
129+
if (originParser != null) {
130+
origin = originParser.parseOrigin(request);
131+
if (StringUtil.isEmpty(origin)) {
132+
return EMPTY_ORIGIN;
133+
}
134+
}
135+
return origin;
136+
}
137+
138+
@Override
139+
public void destroy() {
140+
141+
}
142+
143+
private static final String EMPTY_ORIGIN = "";
144+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright 1999-2018 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.servlet;
17+
18+
import java.io.IOException;
19+
20+
import jakarta.servlet.Filter;
21+
import jakarta.servlet.FilterChain;
22+
import jakarta.servlet.FilterConfig;
23+
import jakarta.servlet.ServletException;
24+
import jakarta.servlet.ServletRequest;
25+
import jakarta.servlet.ServletResponse;
26+
import jakarta.servlet.http.HttpServletRequest;
27+
import jakarta.servlet.http.HttpServletResponse;
28+
29+
import com.alibaba.csp.sentinel.Entry;
30+
import com.alibaba.csp.sentinel.ResourceTypeConstants;
31+
import com.alibaba.csp.sentinel.SphU;
32+
import com.alibaba.csp.sentinel.Tracer;
33+
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
34+
import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig;
35+
import com.alibaba.csp.sentinel.context.ContextUtil;
36+
import com.alibaba.csp.sentinel.slots.block.BlockException;
37+
38+
/***
39+
* Servlet filter for all requests.
40+
*
41+
* @author youji.zj
42+
*/
43+
public class CommonTotalFilter implements Filter {
44+
45+
public static final String TOTAL_URL_REQUEST = "total-url-request";
46+
47+
@Override
48+
public void init(FilterConfig filterConfig) {
49+
50+
}
51+
52+
@Override
53+
public void doFilter(ServletRequest request, ServletResponse response,
54+
FilterChain chain) throws IOException, ServletException {
55+
HttpServletRequest sRequest = (HttpServletRequest)request;
56+
57+
Entry entry = null;
58+
try {
59+
ContextUtil.enter(WebServletConfig.WEB_SERVLET_CONTEXT_NAME);
60+
entry = SphU.entry(TOTAL_URL_REQUEST, ResourceTypeConstants.COMMON_WEB);
61+
chain.doFilter(request, response);
62+
} catch (BlockException e) {
63+
HttpServletResponse sResponse = (HttpServletResponse)response;
64+
WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse, e);
65+
} catch (IOException | ServletException | RuntimeException e2) {
66+
Tracer.trace(e2);
67+
throw e2;
68+
} finally {
69+
if (entry != null) {
70+
entry.exit();
71+
}
72+
ContextUtil.exit();
73+
}
74+
}
75+
76+
@Override
77+
public void destroy() {
78+
79+
}
80+
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 1999-2018 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.servlet.callback;
17+
18+
import java.io.IOException;
19+
20+
import jakarta.servlet.http.HttpServletRequest;
21+
import jakarta.servlet.http.HttpServletResponse;
22+
23+
import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil;
24+
import com.alibaba.csp.sentinel.slots.block.BlockException;
25+
26+
/***
27+
* The default {@link UrlBlockHandler}.
28+
*
29+
* @author youji.zj
30+
*/
31+
public class DefaultUrlBlockHandler implements UrlBlockHandler {
32+
33+
@Override
34+
public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex)
35+
throws IOException {
36+
// Directly redirect to the default flow control (blocked) page or customized block page.
37+
FilterUtil.blockRequest(request, response);
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 1999-2018 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.servlet.callback;
17+
18+
/***
19+
* @author youji.zj
20+
*/
21+
public class DefaultUrlCleaner implements UrlCleaner {
22+
23+
@Override
24+
public String clean(String originUrl) {
25+
return originUrl;
26+
}
27+
}

0 commit comments

Comments
 (0)