diff --git a/core/pom.xml b/core/pom.xml
index 784a9053d5..b5303545f5 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -153,6 +153,17 @@
caffeine
+
+ org.webjars
+ webjars-locator-lite
+
+
+
+ org.webjars
+ jquery
+ test
+
+
jakarta.servletjakarta.servlet-api
diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java
index 0e9ca4fc31..e76fac4e5d 100644
--- a/core/src/main/java/org/apache/struts2/StrutsConstants.java
+++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java
@@ -195,6 +195,16 @@ public final class StrutsConstants {
*/
public static final String STRUTS_UI_STATIC_CONTENT_PATH = "struts.ui.staticContentPath";
+ /**
+ * Whether WebJars support is enabled (serving and URL building)
+ */
+ public static final String STRUTS_WEBJARS_ENABLED = "struts.webjars.enabled";
+
+ /**
+ * Optional comma-separated allowlist of WebJar names permitted to be served (empty = all)
+ */
+ public static final String STRUTS_WEBJARS_ALLOWLIST = "struts.webjars.allowlist";
+
/**
* A global flag to enable/disable html body escaping in tags, can be overwritten per tag
*/
@@ -434,6 +444,11 @@ public final class StrutsConstants {
*/
public static final String STRUTS_STATIC_CONTENT_LOADER = "struts.staticContentLoader";
+ /**
+ * The {@link org.apache.struts2.webjars.WebJarUrlProvider} implementation class
+ */
+ public static final String STRUTS_WEBJARS_URL_PROVIDER = "struts.webjars.urlProvider";
+
/**
* The {@link org.apache.struts2.UnknownHandlerManager} implementation class
*/
diff --git a/core/src/main/java/org/apache/struts2/components/WebJar.java b/core/src/main/java/org/apache/struts2/components/WebJar.java
new file mode 100644
index 0000000000..c18538a42a
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/components/WebJar.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.struts2.components;
+
+import jakarta.servlet.http.HttpServletRequest;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.struts2.inject.Inject;
+import org.apache.struts2.util.ValueStack;
+import org.apache.struts2.views.annotations.StrutsTag;
+import org.apache.struts2.views.annotations.StrutsTagAttribute;
+import org.apache.struts2.webjars.WebJarUrlProvider;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Optional;
+
+/**
+ *
Resolves a version-less WebJar resource path to a servable URL and writes it to the output
+ * (or stores it in a variable when {@code var} is set). Compose it with {@code }/{@code }
+ * or a raw {@code }/{@code