Java 根上下文上的JAX-RS应用程序-如何实现?

Java 根上下文上的JAX-RS应用程序-如何实现?,java,jax-rs,Java,Jax Rs,我想让我的JAX-RX应用程序在根上下文中启动,这样我的URL就会 而不是 我将我的应用程序的注释从这个 @ApplicationPath("/rest/*") 对此 @ApplicationPath("/*") 但是,它似乎接管了/index.html等文件的服务 有没有办法在根应用程序上下文上运行JAX-RS,但仍然提供静态页面 这似乎是在JBOSS论坛上,但解决方案并不实用您可以尝试查找servlet容器的DefaultServlet,并手动在web.xml中为其添加servlet

我想让我的JAX-RX应用程序在根上下文中启动,这样我的URL就会

而不是

我将我的应用程序的注释从这个

@ApplicationPath("/rest/*")
对此

@ApplicationPath("/*")
但是,它似乎接管了/index.html等文件的服务

有没有办法在根应用程序上下文上运行JAX-RS,但仍然提供静态页面


这似乎是在JBOSS论坛上,但解决方案并不实用

您可以尝试查找servlet容器的
DefaultServlet
,并手动在
web.xml
中为其添加servlet映射,以处理诸如*.html、*.jsp或任何其他页面文件


例如,对于Tomcat 5.5,这里描述了:。

与其说它是一个bug,不如说它是Servlet规范的一个限制。关于如何处理JAX-RS
@ApplicationPath
的细节是特定于实现的,我不能说它适用于所有实现,但我想典型的方法是简单地将其用作Servlet URL模式。以Jersey的ServletContainerInitializer实现为例,您会发现负责创建servlet和映射以处理请求,并且您可以看到它确实使用了来自
@ApplicationPath
的路径作为Jersey ServletContainer的映射路径

不幸的是,自远古以来,Servlet规范只允许将Servlet映射到URL路径的少数方法。Servlet 3.0中的当前选项(遗憾的是,该选项仅以PDF格式提供,因此无法按节链接)如下所示:

  • /…/*
    其中初始的
    /…
    是零个或多个路径元素
  • *。
    其中
    是要匹配的扩展名
  • 空字符串,仅映射到空路径/上下文根
  • /
    ,单斜杠,表示上下文中的“默认”servlet,它处理与其他内容不匹配的任何内容
  • 任何其他字符串,它被视为要匹配的文本值
规范的同一部分还针对匹配规则的应用顺序制定了特定的规则,但简短的版本是:要使资源类在上下文根目录下应答请求,必须使用
/
/*
作为路径。如果您使用
/
,那么您将替换容器的默认servlet,该servlet通常负责处理静态资源。如果您使用
/*
,那么您会使它过于贪婪,并说它应该始终匹配所有内容,并且将永远不会调用默认的servlet

因此,如果我们接受servlet URL模式的局限性决定了我们的处境,那么我们的选择就相当有限。以下是我能想到的:

1) 使用
@ApplicationPath(“/”
),并通过名称或扩展显式地将静态资源映射到容器的默认servlet(在Tomcat和Jetty中命名为“default”,不确定其他servlet)。在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>
通过以上步骤,您可以将请求转换为以下内容:

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重写,并使用现有的实现,例如,或。

我发现了另一个涉及内部Jersey类的解决方案,我假设它可能还不是JAX-RS规范的一部分。(基于:)

web.xml

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name>jersey-rest-jsp-frame-1</display-name>

  <filter>
    <filter-name>jersey</filter-name>
    <filter-class>
      com.sun.jersey.spi.container.servlet.ServletContainer
    </filter-class>
    <init-param>
      <param-name>
        com.sun.jersey.config.property.JSPTemplatesBasePath
      </param-name>
      <param-value>/WEB-INF/jsp</param-value>
    </init-param>
    <init-param>
      <param-name>
        com.sun.jersey.config.property.WebPageContentRegex
      </param-name>
      <param-value>
        (/(image|js|css)/?.*)|(/.*\.jsp)|(/WEB-INF/.*\.jsp)|
        (/WEB-INF/.*\.jspf)|(/.*\.html)|(/favicon\.ico)|
        (/robots\.txt)
      </param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>jersey</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

jersey-rest-jsp-frame-1
运动衫
com.sun.jersey.spi.container.servlet.ServletContainer
com.sun.jersey.config.property.JSPTemplatesBasePath
/WEB-INF/jsp
com.sun.jersey.config.property.WebPageContentRegex
(/(image | js | css)/?*)(/.*\.jsp)|(/WEB-INF/.*\.jsp)|
(/WEB-INF/*\.jspf)|(/.*\.html)|(/favicon\.ico)|
(/robots\.txt)
运动衫
/*
WEB-INF/jsp/index.jsp

<%@ page contentType="text/html; charset=UTF-8" language="java" %>

<html>
<body>
<h2>Hello ${it.foo}!</h2>
</body>
</html>

你好${it.foo}!
IndexModel.java

package example;

import com.sun.jersey.api.view.Viewable;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.net.URI;
import java.util.HashMap;

@Path("/")
@Produces(MediaType.TEXT_HTML)
public class IndexModel {

    @GET
    public Response root() {
      return Response.seeOther(URI.create("/index")).build();
    }

    @GET
    @Path("index")
    public Viewable index(@Context HttpServletRequest request) {
      HashMap<String, String> model = new HashMap<String, String>();
      model.put("foo","World");
      return new Viewable("/index.jsp", model);
    }
}
包示例;
导入com.sun.jersey.api.view.view;
导入javax.servlet.http.HttpServletRequest;
导入javax.ws.rs.GET;
导入javax.ws.rs.Path;
导入javax.ws.rs.products;
导入javax.ws.rs.core.Context;
导入javax.ws.rs.core.MediaType;
导入javax.ws.rs.core.Response;
导入java.net.URI;
导入java.util.HashMap;
@路径(“/”)
@生成(MediaType.TEXT\u HTML)
公共类索引模型{
@得到
公共响应根(){
返回Response.seeOther(URI.create(“/index”).build();
}
@得到
@路径(“索引”)
公共可查看索引(@Context-HttpServletRequest){
HashMap模型=新的HashMap();
模型看跌期权(“foo”、“World”);
返回新的可视文件(“/index.jsp”,model);
}
}

这似乎可行,但我想知道它是否是/将成为JAX-RS规范/实现的一部分。

引用另一篇文章中的@damo for Jersey 2.0

“或者,您也可以通过某种重定向来完成一些事情。例如,使用.I从未做过类似的事情,但文档建议“您甚至可以修改请求URI”。

使用
@ApplicationPath(“/”)
)(不带星号)。这对你有帮助

下面是一个示例REST web服务:

1。jaxractivator.java

package com.stackoverflow;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/")
public class JaxRsActivator extends Application {
}
package com.stackoverflow;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class HelloService {
    @GET
    @Produces(MediaType.TEXT_HTML)
    public String hello() {
        return "hello";
    }
}
2。HelloService.java

package com.stackoverflow;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/")
public class JaxRsActivator extends Application {
}
package com.stackoverflow;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class HelloService {
    @GET
    @Produces(MediaType.TEXT_HTML)
    public String hello() {
        return "hello";
    }
}
我使用Eclipse将这个动态Web项目导出到名为
helloservice.WAR
的WAR文件中,并将其部署到本地机器上运行的WildFly。其URL:
http://localhost:8080/helloservice/hello

访问此链接时,它返回:

hello

我看不出这是如何解决这个问题的。但如果有人好奇的话,下面是这个答案的代码来自的博客:我是根据我的经验写的。你的链接没有任何你认为与我的代码相同的代码。我的代码是一个通用的t