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:server是指定的地址,是在我的接口中指定的带有注释beans.xml retrieve的服务路径。@Path

(抱歉:我无法提供上述 XML 文档。)

4

1 回答 1

0

我认为这是一个 CXF 错误,它为安静的 Web 服务获取了不正确的基本 URL。

类“org.apache.cxf.transport.servlet.ServletController”调用类“org.apache.cxf.transport.servlet.BaseUrlHelper”的方法“getBaseURL ”。

它从请求 URL 中获取基本 URL,并忽略参数部分。这对于 SOAP Web 服务是正确的,因为 SOAP Web 服务 URL 就像:http://host:port/basepath?para=a。不幸的是,对于 RESTful 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 只是在第一次时才将 Base URL 设置为 EndpointInfo 的地址。这意味着,您必须在第一时间访问正确的基本 URL!:(

解决方法是:覆盖“org.apache.cxf.transport.servlet.ServletController”的方法“getBaseURL(HttpServletRequest request)”,让它返回正确的base URL。

例如,第 1 步:扩展 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:使用派生类 RestfulServletController 代替 CXFNonSpringServlet。不要忘记,您应该将“basePath”配置为 /Rest/rest。

希望这可以帮到你。

于 2013-01-29T09:00:23.027 回答