当前位置: 首页 > 面试题库 >

在根上下文上的JAX-RS应用程序-如何完成?

惠志
2023-03-14
问题内容

我想让我的JAX-RX应用程序从根上下文开始,所以我的URL是

http://example.com/restfullPath

并不是

http://example.com/rest/restfullPath

我从这里切换了我的应用程序的注释

@ApplicationPath("/rest/*")

对此

@ApplicationPath("/*")

但随后看来,它接管了/index.html等文件

有没有一种方法可以在根应用程序上下文上运行JAX-RS,但仍提供静态页面?

似乎以前在JBOSS论坛上曾问过这个问题,但是该解决方案并不实际


问题答案:

它可能不是Servlet规范的局限性,而是错误。如何@ApplicationPath处理JAX-
RS的细节是特定于实现的,我不能说所有的实现,但是我猜典型的方法是将其简单地用作servlet
URL模式。以Jersey的ServletContainerInitializer实现为例,您将发现该addServletWithApplication()方法负责创建Servlet和映射以处理请求,并且您可以看到它确实使用@ApplicationPath了Jersey
ServletContainer的映射路径。路径。


不幸的是,自远古以来,Servlet规范仅允许使用少量方法将Servlet映射到URL路径。在规范的12.2节中给出的Servlet 3.0的当前选项(几乎只能以PDF格式提供,因此不能按节链接)是:

  • /.../*初始/...为零或更多路径元素
  • *.<ext>``<ext>匹配的扩展名在哪里
  • 空字符串,仅映射到空路径/上下文根
  • /,单斜杠,表示上下文中的“默认” servlet,它处理与其他不匹配的任何内容
  • 任何其他字符串,将其视为要匹配的文字值

规范的同一部分还对匹配规则的应用顺序有特定的规则,但是简短的版本是这样的:要使资源类在上下文根处回答请求,您必须使用//*作为路径。如果使用/,那么您将替换容器的默认servlet,该默认servlet通常负责处理静态资源。如果您使用/*,那么您会使它过于贪婪,并说它应该一直与所有内容匹配,并且永远不会调用默认servlet。

因此,如果我们接受由Servlet URL模式的限制所决定的范围之内,那么我们的选择就相当有限。这是我能想到的:

1)使用@ApplicationPath("/"),并通过名称或扩展名将您的静态资源显式映射到容器的默认servlet(在Tomcat和Jetty中命名为“默认”,对其他不确定)。在web.xml中,它看起来像

<!-- All html files at any path -->
<servlet-mapping>   
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>
<!-- Specifically index.html at the root -->
<servlet-mapping>   
    <servlet-name>default</servlet-name>
    <url-pattern>/index.html</url-pattern>
</servlet-mapping>

或使用ServletContextInitializer,例如

public class MyInitializer implements ServletContainerInitializer {
    public void onStartup(Set<Class<?>> c, ServletContext ctx) {
        ctx.getServletRegistration("default").addMapping("*.html");
        ctx.getServletRegistration("default").addMapping("/index.html");
    }
}

由于编写了匹配规则的方式,扩展模式将胜过默认servlet,因此,只要静态文件扩展名与任何扩展名之间不存在重叠,您只需添加一个映射即可。您的API。这与您链接的论坛帖子中提到的不受欢迎的选项非常接近,我只是为了完整起见提及它,并添加了ServletContextInitializer部分。

2)将您的API映射到/rest/*,并使用过滤器识别对API的请求,并将其转发到该路径。这样,您便突破了servlet
URL模式框,并可以按任何方式匹配URL。例如,假设您所有的REST调用都以“ / foo”开头或正好为“ /
bar”的路径,而所有其他请求都应转到静态资源,则类似于:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.regex.Pattern;

@WebFilter(urlPatterns = "/*")
public class PathingFilter implements Filter {
    Pattern[] restPatterns = new Pattern[] {
            Pattern.compile("/foo.*"),
            Pattern.compile("/bar"),
    };

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        if (request instanceof HttpServletRequest) {
            String path = ((HttpServletRequest) request).getServletPath();
            for (Pattern pattern : restPatterns) {
                if (pattern.matcher(path).matches()) {
                    String newPath = "/rest/" + path;
                    request.getRequestDispatcher(newPath)
                        .forward(request, response);
                    return;
                }
            }
        }
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void destroy() {}
}

使用以上内容,您基本上可以按以下方式转换请求:

http://example.org/foo          -> http://example.org/rest/foo
http://example.org/foox         -> http://example.org/rest/foox
http://example.org/foo/anything -> http://example.org/rest/foo/anything
http://example.org/bar          -> http://example.org/rest/bar
http://example.org/bart         -> http://example.org/bart
http://example.org/index.html   -> http://example.org/index.html

3)意识到先前的选择基本上是URL重写,并使用现有的实现,例如Apache的mod_rewrite,Tuckey重写过滤器或ocpsoft
Rewrite。



 类似资料:
  • 问题内容: JAX-RS 1.1规范在第6页上说: 如果不存在Application子类,则必须将添加的servlet命名为: 添加的servlet是什么?可以是任意servlet吗? 如果存在Application子类,并且已经定义了一个servlet,该servlet的servlet初始化参数为: 同样,这里的“ servlet”是什么? 如果存在不由现有Servlet处理的Applicati

  • 我知道我需要在servlet上下文中注册用注释的类,以使webapp可访问。通常,我会按照以下方式来做: 我添加到根应用程序上下文中的所有其他配置类。下面是我的dispatcher初始值设定项通常的样子: 但是当我开始使用WebSockets时,事情变得更有趣了。要使websockets工作,必须将WebSoketConfig.class放到servlet上下文中。下面是我的WebSocketCo

  • 我正在使用RAD和WAS7.0.23,并尝试在其中部署jax-rs。但是我在部署描述符(web.xml)中发现了以下错误。 错误404:javax.Servlet.unavailableException:SRVE0200E:Servlet[com.ibm.websphere.jaxrs.server.ibmrestServlet]:找不到所需的类-class java.lang.ClassNot

  • 我在Netbean中创建了名为TestA的新war应用程序。然后,我创建了新的Glassfish部署描述符glassfish-web.xml,内容如下: 然后我将我的应用程序部署到GF。上下文根仍然 /TestA,而不是 /new_context_root.为什么? Glassfish版本为3.1.2.2 断续器 如果我通过自动部署文件夹进行部署,则上下文根会正常更改,但不会从web-admin更

  • 14:32:42,537错误[org.jboss.msc.service.fail](ServerService线程池--316)MSC000001:未能启动服务jboss.web.deployment.default-host./search-rest:org.jboss.msc.msc.service.startException.匿名服务中的服务jboss.web.deployment.de

  • 让spring boot 1.3.x应用程序在application.properties中定义server.context-path=/myPath,并按照Java spring boot中定义重定向请求:如何将我的应用程序根(“/”)映射到index.html? 使用viewControllerRegistry.addViewController(“/”).setViewName(“forwa