我想让我的JAX-RX应用程序从根上下文开始,所以我的URL将是
http://example.com/restfullPath
而不是
http://example.com/rest/restfullPath
我从此
切换了我的应用程序注释@ApplicationPath("/rest/*")
到这个
@ApplicationPath("/*")
但似乎它接管了服务文件,例如/index.html
有没有办法在根应用程序上下文中运行JAX-RS但仍然提供静态页面?
在JBOSS论坛上看来这是asked before,但解决方案并不实用
答案 0 :(得分:38)
这可能不是Servlet规范限制的错误。有关如何处理JAX-RS @ApplicationPath
的详细信息是特定于实现的,我不能代表所有实现,但我猜想典型的方法是将其用作servlet URL模式。看看Jersey的ServletContainerInitializer实现作为一个例子,你会发现addServletWithApplication()
method负责创建servlet和映射来处理请求,你可以看到它确实使用了来自{的路径。 {1}}作为Jersey ServletContainer的映射路径。
不幸的是,从远古时代开始,Servlet规范只允许少数几种将servlet映射到URL路径的方法。在Section 12.2 of the spec中给出的Servlet 3.0的当前选项 - 遗憾的是仅作为PDF提供,因此不能按部分链接 - 是:
@ApplicationPath
,其中初始/.../*
为零个或多个路径元素/...
其中*.<ext>
是匹配<ext>
,单斜杠,表示上下文中的“默认”servlet,它处理与其他任何内容不匹配的任何内容规范的相同部分对匹配规则应该应用的顺序也有特定的规则,但是短版本是这样的:要在上下文根处创建资源类应答请求,您必须使用{{ 1}}或/
作为路径。如果使用/
,那么您将替换容器的默认servlet,它通常负责处理静态资源。如果你使用/*
,那么你就太贪婪了,并说它应该始终匹配所有的东西,并且永远不会调用默认的servlet。
因此,如果我们接受我们在由servlet URL模式的限制确定的框内,我们的选项相当有限。以下是我能想到的:
1)使用/
,并通过名称或扩展名将静态资源显式映射到容器的默认servlet(Tomcat和Jetty中名为“default”,不确定其他人)。在web.xml中,它看起来像
/*
@ApplicationPath("/")
由于编写匹配规则的方式,扩展模式胜过默认的servlet,因此只需要在每个静态文件扩展名之间添加映射,只要这些扩展模块与任何“扩展”之间没有重叠即可。可能出现在您的API中。这非常接近您链接的论坛帖子中提到的不受欢迎的选项,我只是提到它的完整性并添加了ServletContextInitializer部分。
2)将您的API映射到<!-- 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>
,并使用过滤器来识别API请求并将其转发到该路径。这样,您就可以打破servlet URL模式框,并以任何方式匹配URL。例如,假设您所有的REST调用都是以“/ foo”开头或完全是“/ bar”的路径,而所有其他请求都应该转到静态资源,那么就像:
public class MyInitializer implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx) {
ctx.getServletRegistration("default").addMapping("*.html");
ctx.getServletRegistration("default").addMapping("/index.html");
}
}
通过上述内容,您基本上可以按如下方式翻译请求:
/rest/*
3)意识到上一个选项基本上是URL重写并使用现有的实现,例如Apache's mod_rewrite,Tuckey rewrite filter或ocpsoft Rewrite。
答案 1 :(得分:1)
您可以尝试查找servlet容器的DefaultServlet
并在web.xml
中手动添加servlet-mapping来处理页面文件,例如* .html,* .jsp或其他任何内容。
E.g。对于Tomcat 5.5,它在这里描述:http://tomcat.apache.org/tomcat-5.5-doc/default-servlet.html。
答案 2 :(得分:1)
我找到了另一个涉及内部Jersey类的解决方案,我认为它可能还不是JAX-RS规范的一部分。 (基于:http://www.lucubratory.eu/simple-jerseyrest-and-jsp-based-web-application/)
<强>的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>
<强> WEB-INF / JSP / index.jsp的强>
<%@ page contentType="text/html; charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello ${it.foo}!</h2>
</body>
</html>
<强> 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);
}
}
这似乎有效,但我想知道它是否是/将成为JAX-RS规范/实现的一部分。
答案 3 :(得分:0)
从另一篇文章引用@damo for Jersey 2.0
“或者,您可以通过某种重定向来解决问题。例如,使用Pre-matching Filter。我从未做过这样的事情,但文档建议”您甚至可以修改请求URI“。”
答案 4 :(得分:0)
改为使用@ApplicationPath("/")
(不使用星号)。它会对你的情况有所帮助。
以下是REST Web服务示例:
1. JaxRsActivator.java
package com.stackoverflow;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/")
public class JaxRsActivator extends Application {
}
2. HelloService.java
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将此Dynamic Web项目导出到名为helloservice.war
的WAR文件,并将其部署到在本地计算机上运行的WildFly。其网址为:http://localhost:8080/helloservice/hello
。
访问此链接时,它返回:
hello