我认为这是一个 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。
希望这可以帮到你。