Jax-Rs服务未被调用



我正在使用ApacheCXF开发JAX-RSRest服务。在将它部署到Tomcat7服务器之后,如果我键入URL http://localhost:8080/Rest/rest?_wadl,它将显示WADL。但是如果我输入URL http://localhost:8080/Rest/rest/retrieve,它会给我404错误。

在以上URL中:Rest是我的项目名称/rest是在web.xml中指定的我的CXFServlet的url模式/是在beans.xml中指定的jaxrs:server的地址retrieve是在我的接口中指定的带有@Path注释的服务路径。

(我很抱歉:我不能提供上面提到的XML文档。)

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

类"org.apache.cxf.transport.servlet.ServletController"调用类"org.apache.cxf.ttransport.servole.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只在第一次将基本URL设置为EndpointInfo的地址。这意味着,您必须在第一时间访问正确的基本URL!:(

解决方案是:覆盖"org.apache.cxf.transport.servlet.ServletController"的方法"getBaseURL(HttpServlet请求)",让它返回正确的基本URL。

例如,步骤1:扩展Servlet控制器。

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());
    }
}

步骤2:扩展CXFNonSpringServlet并在子类中使用RestfulServlet控制器

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:使用派生类RestfulServlet控制器,而不是CXFNonSpringServlet。别忘了,您应该将"basePath"配置为/Rest/Rest。

希望这能帮助到你。

最新更新