我正在使用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文档。)
答案 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"作为/休息/休息。
希望这可以帮到你。