40

URL が

http://example.com/restfullPath

そしてそうではない

http://example.com/rest/restfullPath

アプリケーションの注釈をこれから切り替えました

@ApplicationPath("/rest/*")

これに

@ApplicationPath("/*")

しかし、 /index.html などのファイルの提供を引き継いでいるようです

ルート アプリケーション コンテキストで JAX-RS を実行する方法はありますが、静的ページを提供していますか?

これはJBOSSフォーラムで以前に質問されたようですが、解決策は実際には実用的ではありません

4

5 に答える 5

45

これはおそらくバグではなく、サーブレット仕様の制限です。JAX-RS の@ApplicationPath処理方法の詳細は実装に固有であり、すべての実装について話すことはできませんが、典型的なアプローチは単にサーブレット URL パターンとして使用することだと思います。ジャージーの ServletContainerInitializer 実装を一例として見てみると、addServletWithApplication()メソッドがサーブレットの作成とリクエストを処理するためのマッピングを担当していることがわかります。実際に、ジャージー サーブレット@ApplicationPathコンテナーのマップとしてのパスを使用していることがわかります。道。

残念なことに、太古の昔から、サーブレットの仕様では、サーブレットを URL パスにマッピングする方法はほんの一握りしか許可されていませんでした。仕様のセクション 12.2 に記載されている Servlet 3.0 の現在のオプション-- 残念ながら PDF としてのみ利用可能であり、セクションごとにリンクすることはできません -- は次のとおりです。

  • /.../*ここで、イニシャル/...は 0 個以上のパス要素です
  • *.<ext><ext>一致する拡張子はどこですか
  • 空のパス/コンテキスト ルートにのみマップされる空の文字列
  • /、単一のスラッシュ。コンテキスト内の「デフォルト」サーブレットを示し、他のものと一致しないものをすべて処理します
  • 一致するリテラル値として扱われるその他の文字列

仕様の同じセクションには、一致するルールが適用される順序に関する特定のルールもありますが、短いバージョンは次のとおりです。リソース クラスがコンテキスト ルートでリクエストに応答するようにするには、パスとして/またはを使用する必要があります。/*を使用する/と、コンテナのデフォルト サーブレットが置き換えられます。これは通常、静的リソースの処理を担当します。を使用する/*と、貪欲になりすぎて、常にすべてに一致する必要があり、デフォルトのサーブレットが呼び出されることはありません。

したがって、サーブレットの URL パターンの制限によって決まるボックス内にいることを受け入れると、オプションはかなり制限されます。ここに私が考えることができるものがあります:

1) を使用@ApplicationPath("/")し、静的リソースを名前または拡張子でコンテナのデフォルト サーブレット (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");
    }
}

マッチング ルールの記述方法により、拡張パターンがデフォルトのサーブレットに優先するため、静的ファイル拡張子ごとにマッピングを追加するだけで済みます。あなたのAPI。これは、リンクしたフォーラムの投稿で言及されている望ましくないオプションにかなり近いものです。完全を期すために言及し、ServletContextInitializer 部分を追加します。

2) API を にマップしたままにし/rest/*、フィルターを使用して API の要求を識別し、そのパスに転送します。このようにして、サーブレットの 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_rewriteTuckey 書き換えフィルターocpsoft Rewriteなどの既存の実装を使用します。

于 2013-05-25T06:57:58.250 に答える
2

内部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 仕様/実装の一部であるかどうかは疑問です。

于 2013-06-12T23:13:19.293 に答える
1

*.html、*.jsp などのページ ファイルを処理するためDefaultServletに、サーブレット コンテナーを探して手動でサーブレット マッピングを追加することができます。web.xml

たとえば、Tomcat 5.5 については、http: //tomcat.apache.org/tomcat-5.5-doc/default-servlet.htmlで説明されています。

于 2012-06-04T11:18:21.510 に答える
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 を使用して、この動的 Web プロジェクトを as という名前の WAR ファイルにエクスポートhelloservice.warし、ローカル マシンで実行されている WildFly にデプロイしました。その URL: http://localhost:8080/helloservice/hello.

このリンクにアクセスすると、以下が返されました。

hello
于 2015-08-06T17:19:18.717 に答える
0

別の投稿から @damo for Jersey 2.0 を引用

「あるいは、ある種のリダイレクトで何かを引き出すことができるかもしれません。たとえば、Pre-matching Filterを使用します。私はこのようなことをしたことはありませんが、ドキュメントでは「リクエスト URI を変更することもできる」と示唆しています。 "

于 2013-06-26T22:02:00.670 に答える