0

Apache CXF を使用して JAX-RS Rest サービスを開発しています。Tomcat 7 サーバーにデプロイした後、URL を入力http://localhost:8080/Rest/rest?_wadlすると、WADL が表示されます。しかし、URL を入力するhttp://localhost:8080/Rest/rest/retrieveと 404 エラーが発生します。

上記の URL:Restは私のプロジェクトの名前です はで指定された/rest私の URL パターンです はでCXFServlet指定されたweb.xml /アドレスですは注釈付きのインターフェースで指定されたサービスのパスです。jaxrs:serverbeans.xml retrieve@Path

(申し訳ありませんが、上記の XML ドキュメントを提供することはできません。)

4

1 に答える 1

0

これは、安静な Web サービスのベース URL が正しくない CXF のバグだと思います。

クラス「org.apache.cxf.transport.servlet.ServletController」は、クラス「org.apache.cxf.transport.servlet.BaseUrlHelper」のメソッド「getBaseURL」を呼び出します。

リクエスト URL からベース URL を取得し、パラメーター部分は無視します。SOAP Web サービスの URL はhttp://host:port/basepath?para=a. 残念ながら、安静な Web サービスの場合、URL は のようになりますhttp://host:port/basepath/method/parameter。正しいベース URL は であるはずですがhttp://host:port/basepath、実際には BaseUrlHelper によって が返されますhttp://host:port/basepath/method/parameter。「?」の前に URL を指定するだけです。にアクセスしたときの結果が正しいのはそのためです。http://localhost:8080/Rest/rest?_wadlこの場合、正しいベース URL が得られますhttp://localhost:8080/Rest

http://localhost:8080/Rest/rest?_wadl最初にアクセスしてから にアクセスすれhttp://localhost:8080/Rest/rest/retrieveば正解です。そのため、CXF は初回のみベース URL を EndpointInfo のアドレスとして設定します。つまり、最初は正しいベース URL にアクセスする必要があります。:(

解決策は次のとおりです。「org.apache.cxf.transport.servlet.ServletController」のメソッド「getBaseURL(HttpServletRequest request)」をオーバーライドし、正しいベース URL を返すようにします。

たとえば、step1: ServletController を拡張します。

public class RestfulServletController extends ServletController {
    private final String basePath;

    public RestfulServletController(DestinationRegistry destinationRegistry, ServletConfig config,
            HttpServlet serviceListGenerator, String basePath) {
        super(destinationRegistry, config, serviceListGenerator);
        this.basePath = basePath;
    }

    @Override
    protected String getBaseURL(HttpServletRequest request) {
        // Fixed the bug of BaseUrlHelper.getBaseURL(request) for restful service.
        String reqPrefix = request.getRequestURL().toString();
        int idx = reqPrefix.indexOf(basePath);
        return reqPrefix.substring(0, idx + basePath.length());
    }
}

step2: CXFNonSpringServlet を拡張し、サブクラスで RestfulServletController を使用する

public class RestfulCXFServlet extends CXFNonSpringServlet {
    ... ...
    private ServletController createServletController(ServletConfig servletConfig) {
        HttpServlet serviceListGeneratorServlet = new ServiceListGeneratorServlet(destinationRegistry, bus);
        ServletController newController = new RestfulServletController(destinationRegistry, servletConfig,
            serviceListGeneratorServlet, basePath);
        return newController;
    }
}

step3: CXFNonSpringServlet の代わりに、派生クラス RestfulServletController を使用します。「basePath」を /Rest/rest として構成する必要があることを忘れないでください。

これがあなたを助けることを願っています。

于 2013-01-29T09:00:23.027 に答える