Jax-Rs服务没有被调用

时间:2012-08-18 08:30:00

标签: cxf jax-rs tomcat7

我正在使用Apache CXF开发JAX-RS Rest服务。将其部署到Tomcat 7服务器后,如果我输入URL http://localhost:8080/Rest/rest?_wadl,它会显示WADL。但如果我输入网址http://localhost:8080/Rest/rest/retrieve,则会给我404错误。

在上述网址中:Rest是我的项目名称 /rest是我CXFServlet的网址格式,在web.xml中指定 /jaxrs:server中指定的地址beans.xml retrieve是我的界面中使用@Path注释指定的服务路径。

(道歉:我无法提供上面提到的XML文档。)

1 个答案:

答案 0 :(得分: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。不幸的是,对于宁静的Web服务,URL就像http://host:port/basepath/method/parameter一样。正确的基本网址应为http://host:port/basepath,但实际上,BaseUrlHelper会为您提供http://host:port/basepath/method/parameter。它只是在"?"之前给出了URL。这就是访问http://localhost:8080/Rest/rest?_wadl时结果正确的原因,在这种情况下,它会提供正确的基本网址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;
    }
}

步骤3:使用派生类RestfulServletController代替CXFNonSpringServlet。 别忘了,你应该配置" basePath"作为/休息/休息。

希望这可以帮到你。