几种RPC模型的使用与比较(4)

假设我想在有一个Spring应用,我需要把一个Pojo或者一部分方法导出为Web Service。
但这会有一个问题——Endpoint的生命周期是由JAX-WS runtime来管理(The lifecycle of such an endpoint instance will be managed by the JAX-WS runtime),
Spring context中的Bean无法autowire到Endpoint中,而我要导出的那些东东都用到了Spring管理的Bean。


对此,我们有两个解决方法:

org.springframework.web.context.support.SpringBeanAutowiringSupport

JaxWsServiceExporter


我上面括号中的那段话是引用的SpringBeanAutowiringSupport的javaDoc。
使用该类的典型案例就是bean注入到JAX-WS endpoint类中(人家注释上写的),任何一个生命周期不是由Spring来管理的场景都可以用到他。
而我们只需要继承这个类,也就是说创建一个实例时会调用父类的无参构造方法,我们来看看他的构造方法:

/** * This constructor performs injection on this instance, * based on the current web application context. * <p>Intended for use as a base class. * @see #processInjectionBasedOnCurrentContext */ public SpringBeanAutowiringSupport() { processInjectionBasedOnCurrentContext(this); } /** * Process {@code @Autowired} injection for the given target object, * based on the current web application context. * <p>Intended for use as a delegate. * @param target the target object to process * @see org.springframework.web.context.ContextLoader#getCurrentWebApplicationContext() */ public static void processInjectionBasedOnCurrentContext(Object target) { Assert.notNull(target, "Target object must not be null"); WebApplicationContext cc = ContextLoader.getCurrentWebApplicationContext(); if (cc != null) { AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); bpp.setBeanFactory(cc.getAutowireCapableBeanFactory()); bpp.processInjection(target); } else { if (logger.isDebugEnabled()) { logger.debug("Current WebApplicationContext is not available for processing of " + ClassUtils.getShortName(target.getClass()) + ": " + "Make sure this class gets constructed in a Spring web application. Proceeding without injection."); } } }


那就试试看:

@Service @WebService(serviceName="testMyService") public class MyServiceEndpoint extends SpringBeanAutowiringSupport{ @Autowired MyService myService; @WebMethod public String sayHiFarAway(String name){ return myService.sayHiTo(name); } }

接着发布一下:

ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext*.xml"); Endpoint.publish("http://localhost:8080/myservices", (MyServiceEndpoint)context.getBean(MyServiceEndpoint.class));


调用:

javax.xml.ws.Service service = javax.xml.ws.Service.create(url, new QName("http://endpoint.king.pac/","testMyService")); QName q = new QName("http://endpoint.king.pac/","MyServiceEndpointPort"); MyClientService client = service.getPort(q,MyClientService.class); System.out.println(client.sayHiFarAway("King"));


写一个EndPoint还要继承和业务无关的类,让人不爽...而且发布和调用都麻烦。
那试试SimpleJaxWsServiceExporter,只需要简单的配置就可以导出一个EndPoint。
但是他也有需要注意的地方,引用一下该类的javaDoc:

Note that this exporter will only work if the JAX-WS runtime actually supports publishing with an address argument, i.e. if the JAX-WS runtime ships an internal HTTP server. This is the case with the JAX-WS runtime that's inclued in Sun's JDK 1.6 but not with the standalone JAX-WS 2.1 RI.


SimpleJaxWsServiceExporter会自动detect所有被WebService注解的类,因此只需要在配置中声明即可;此时Endpoint地址直接使用默认的localhost:8080:

<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter" />


接着改善一下客户端的调用,使用JaxWsPortProxyFactoryBean:

<bean id="clientSide" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean" p:wsdlDocumentUrl="http://localhost:8080/testMyService?wsdl" p:serviceName="testMyService" p:portName="MyServiceEndpointPort" p:serviceInterface="pac.king.endpoint.MyClientService" p:namespaceUri="http://endpoint.king.pac/" />

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2eaf27a13bb9bd1a56b67589e2f91611.html