我想以编程方式向tomcat发布web服务.
例如JAX-WS或Apache CXF
与Endpoint.publish(…)类似.
例如JAX-WS或Apache CXF
与Endpoint.publish(…)类似.
- //how to tell this tomcat?
- Endpoint.publish("http://0.0.0.0:8080/SimpleService",serviceImpl);
- //or better something like this:
- Endpoint.publish("/SimpleService",serviceImpl);
无需使用web.xml和/或sun-jaxws.xml(对于每个服务)
题:
有没有任何已知的方法来实现它(使用JAX-WS或Apache CXF或……)?
(我知道已经发布了类似的问题.但是他们都没有回答我的问题.)
解决方法
这是我自己的问题.
我设法在Apache CXF的帮助下[以编程方式将webservice发布到tomcat].
我设法在Apache CXF的帮助下[以编程方式将webservice发布到tomcat].
这是一个简化的工作示例:
我将一个CXFNonSpringServlet子类化并在web.xml中注册:
- <servlet>
- <servlet-name>MyCXFServlet</servlet-name>
- <display-name>CXF Servlet</display-name>
- <servlet-class>de.test.MyCXFServlet</servlet-class>
- <load-on-startup>2</load-on-startup>
- <async-supported>true</async-supported>
- </servlet>
- <servlet-mapping>
- <servlet-name>MyCXFServlet</servlet-name>
- <url-pattern>/soap/*</url-pattern>
- </servlet-mapping>
这是我的子类CXFNonSpringServlet:
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
- import java.util.HashSet;
- import java.util.Set;
- import javax.jws.WebMethod;
- import javax.servlet.ServletConfig;
- import org.apache.cxf.endpoint.Server;
- import org.apache.cxf.frontend.Serverfactorybean;
- import org.apache.cxf.service.factory.ReflectionServicefactorybean;
- import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
- public class MyCXFServlet extends CXFNonSpringServlet
- {
- @Override
- protected void loadBus(ServletConfig sc)
- {
- super.loadBus(sc);
- publishServices();
- }
- private void publishServices()
- {
- Set<Class> serviceInterfaces = new HashSet<>();
- serviceInterfaces.add(de.test.IUserService.class);
- serviceInterfaces.add(de.test.ILoginService.class);
- for (Class aSVCInterface : serviceInterfaces)
- {
- final String serviceName = aSVCInterface.getSimpleName();
- try
- {
- ReflectionServicefactorybean reflectionFactory = new ReflectionServicefactorybean(){
- @Override
- protected boolean isValidMethod(Method method)
- {
- boolean ret = super.isValidMethod(method);
- WebMethod wm = method.getAnnotation(WebMethod.class);
- if (wm != null && wm.exclude())
- ret = false;
- return ret;
- }
- @Override
- protected String getServiceName() //Override for custom service name
- {
- return serviceName;
- }
- };
- reflectionFactory.setServiceClass(aSVCInterface);
- Object proxiedServiceObject = Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[]{aSVCInterface},new de.test.MyWebServiceInvocationHandler(aSVCInterface));
- Serverfactorybean factory = new Serverfactorybean(reflectionFactory);
- factory.setBus(getBus());
- factory.setServiceClass(aSVCInterface);
- factory.setServiceBean(proxiedServiceObject);
- factory.setAddress("/" + serviceName);
- Server svr = factory.create();
- svr.getEndpoint().getInInterceptors().add(new de.test.MyServiceInterceptor());
- }
- catch (Exception exception)
- {
- exception.printStackTrace();
- }
- }
- }
- }
上面的Servlet将发布2个简单的接口作为SOAP-WebService.
实现是动态的(代理)
这是我的MyServiceInterceptor:
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Proxy;
- import org.apache.cxf.binding.soap.SoapMessage;
- import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
- import org.apache.cxf.endpoint.Endpoint;
- import org.apache.cxf.interceptor.Fault;
- import org.apache.cxf.message.Exchange;
- import org.apache.cxf.phase.Phase;
- import org.apache.cxf.service.Service;
- import org.apache.cxf.service.invoker.BeanInvoker;
- import org.apache.cxf.service.invoker.Invoker;
- public class MyServiceInterceptor extends AbstractSoapInterceptor
- {
- public MyServiceInterceptor()
- {
- super(Phase.PRE_INVOKE);
- }
- @Override
- public void handleMessage(SoapMessage p_message) throws Fault
- {
- final Exchange exchange = p_message.getExchange();
- final Endpoint endpoint = exchange.get(Endpoint.class);
- final Service service = endpoint.getService();
- final Invoker invoker = service.getInvoker();
- if (invoker instanceof BeanInvoker)
- {
- BeanInvoker bi = (BeanInvoker)invoker;
- Object serviceObj = bi.getServiceObject(null);
- if (Proxy.isProxyClass(serviceObj.getClass()))
- {
- InvocationHandler ih = Proxy.getInvocationHandler(serviceObj);
- if (ih instanceof MyWebServiceInvocationHandler)
- {
- MyWebServiceInvocationHandler h = (MyWebServiceInvocationHandler)ih;
- h.setSoapMessage(p_message);
- }
- }
- }
- }
- }
MyServiceInterceptor-Class主要用于将当前SOAPMessage注入MyWebServiceInvocationHandler.
我的MyWebServiceInvocationHandler(我认为,这里不需要代码)负责调用真正的Service-Method.它只是实现了InvocationHandler并且有一个Soap-Message字段(参见MyServiceInterceptor).这是获取SOAPMessage-Details(如Header)所必需的.
希望这可以帮助.干杯!