【问题标题】:Multiple context paths in one jetty-web.xml for JAX-RS application running on a Tomcat server一个 jetty-web.xml 中的多个上下文路径,用于在 Tomcat 服务器上运行的 JAX-RS 应用程序
【发布时间】:2020-02-22 04:31:17
【问题描述】:

我已经看到了这个问题的版本,甚至multiple years ago 的一个版本正是我要问的,但是很可惜,那个问题没有答案。就这样吧:我有一个基于 tomcat 的 Web 应用程序,它可以根据一些嵌入式 JSON 文件的设置采用许多不同的形式。我想要完成的是使用 URL 作为基础来通知应用程序使用哪个版本,而不是为每个不同的配置创建多个应用程序实例。

当前:

http://<server>/Version1,http://<server>/Version2,http://<server>/Version3

相同的应用程序,三个 WAR 文件,只是相互重命名/每个服务器上下文路径

首选:

http://<server>/Version1,http://<server>/Version2,http://<server>/Version3

一个应用程序/一个 WAR 文件/三个服务器上下文路径

这可能吗?如果是这样,它是如何实现的?如果没有,有没有人有一个聪明的主意?

注意:Maven 和 Gradle 均未使用。

【问题讨论】:

    标签: tomcat jax-rs war contextpath


    【解决方案1】:

    您确定要多个上下文路径?

    即使您有 1 个战争和 3 个上下文路径,该战争也会被加载 3 次,并且每一个都将彼此隔离(类加载器、对象实例、会话、cookie、资源等)

    另一方面,您可以在单个 web 应用程序之前执行一些自定义 URI 操作。

    这是一个在根上下文 (/) 上加载的单个 WebApp (war) 的示例,仅加载一次,然后是一个 HandlerWrapper(一个 Jetty 概念),它执行 URI 版本识别和 URI 操作,并带有一个请求用于将版本传达回 webapp 及其 servlet 的属性。

    package jetty;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.PrintWriter;
    import java.net.HttpURLConnection;
    import java.net.URI;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.eclipse.jetty.server.Request;
    import org.eclipse.jetty.server.Server;
    import org.eclipse.jetty.server.handler.HandlerWrapper;
    import org.eclipse.jetty.util.IO;
    import org.eclipse.jetty.util.resource.PathResource;
    import org.eclipse.jetty.webapp.WebAppContext;
    
    import static java.nio.charset.StandardCharsets.UTF_8;
    
    /**
     * This is a single Webapp on root, and a Handler that identifies a URI pattern
     * and informs the webapp what version to use.
     */
    public class UriIdentifiedBehaviorDemo
    {
        public static void main(String[] args) throws Exception
        {
            Server server = new Server(8080);
    
            WebAppContext webapp = createWebApp();
            webapp.setContextPath("/"); // root
    
            UriVersionHandler uriVersionHandler = new UriVersionHandler();
            uriVersionHandler.setHandler(webapp);
    
            server.setHandler(uriVersionHandler);
            server.start();
    
            try
            {
                // direct access
                demoCall(server.getURI().resolve("/demo/"));
                // attempt at version, but missing number
                demoCall(server.getURI().resolve("/version/demo/"));
                // versioned
                demoCall(server.getURI().resolve("/version1/demo/"));
                demoCall(server.getURI().resolve("/version99/demo/"));
            }
            finally
            {
                server.stop();
            }
        }
    
        private static void demoCall(URI destUri) throws IOException
        {
            HttpURLConnection http = (HttpURLConnection)destUri.toURL().openConnection();
            int statusCode = http.getResponseCode();
            System.out.printf("GET [%s] resulted in Response Status Code [%d]%n", 
                destUri, statusCode);
    
            if (statusCode != HttpURLConnection.HTTP_OK)
            {
                return;
            }
    
            try (InputStream in = http.getInputStream())
            {
                String responseBody = IO.toString(in, UTF_8);
                System.out.printf("Response Body: %s%n", responseBody);
            }
        }
    
        private static WebAppContext createWebApp()
        {
            WebAppContext webapp = new WebAppContext();
            Path warPath = Paths.get("src/main/wars/webapp-a.war");
            webapp.setBaseResource(new PathResource(warPath));
    
            webapp.addServlet(DemoServlet.class, "/demo/*");
    
            return webapp;
        }
    
        public static class DemoServlet extends HttpServlet
        {
            @Override
            protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException
            {
                resp.setContentType("text/plain");
                resp.setCharacterEncoding("utf-8");
                PrintWriter out = resp.getWriter();
                out.printf("Version (header) is [%s]%n", 
                    req.getAttribute("my.uri.version"));
            }
        }
    
        public static class UriVersionHandler extends HandlerWrapper
        {
            @Override
            public void handle(String target, 
                               Request baseRequest, 
                               HttpServletRequest request, 
                               HttpServletResponse response) 
                throws IOException, ServletException
            {
                String actualTarget = target;
                String requestPath = baseRequest.getHttpURI().getPath();
                Pattern pat = Pattern.compile("^\\/version([0-9]+)\\/");
                Matcher mat = pat.matcher(requestPath);
                if (mat.find())
                {
                    // we are in a version identified syntax!
                    String version = mat.group(1);
                    request.setAttribute("my.uri.version", version);
                    actualTarget = requestPath.substring(mat.end(1));
                }
    
                getHandler().handle(actualTarget, baseRequest, request, response);
            }
        }
    
    }
    

    显示以下输出...

    GET [http://127.0.1.1:8080/demo/] resulted in Response Status Code [200]
    Response Body: Version (header) is [null]
    
    GET [http://127.0.1.1:8080/version/demo/] resulted in Response Status Code [404]
    GET [http://127.0.1.1:8080/version1/demo/] resulted in Response Status Code [200]
    Response Body: Version (header) is [1]
    
    GET [http://127.0.1.1:8080/version99/demo/] resulted in Response Status Code [200]
    Response Body: Version (header) is [99]
    
    

    仅供参考,这种投机性问题最好在jetty-users mailing list 上,或作为Eclipse Jetty Issue tracker 上的问题(作为问题)。

    【讨论】:

    • 这几乎就是我要找的。抱歉不够明确,但您在这里展示的是嵌入式服务器,而我正在运行的是 Tomcat 服务器,而不是嵌入式。因此,我无法将 UriHandler 包裹在不存在的服务器周围。
    • 如果您使用jetty-home(或旧的jetty-distribution),您可以通过插入的自定义处理程序(通过xml)和正常的webapp(war)部署来完成此操作。
    • 没有jetty-home。这是一个运行许多不同 WAR 文件的 tomcat 服务器,我的只是其中之一。
    • 我不明白,你的标题中有jetty-web.xml,标签中有jetty。这些对tomcat的提及令人困惑。同样是的,您仍然可以在多 webapp Jetty 独立服务器(非嵌入式)上为某些(不是全部)webapps 提供自定义处理程序。
    • 我应该声明“Java API for RESTful Web Services”(JAX-RS),它使用了一个 jetty-web.xml 文件。它不是一个真正的基于码头的应用程序,仅使用码头独立服务器进行调试,而不是在部署中。
    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-03
    • 2013-01-01
    • 2011-12-19
    • 2016-05-11
    • 2018-05-06
    相关资源
    最近更新 更多