jaxws 完美融合 tomcat+spring,共用一个端口,科科。。。
主要是包含jaxws模式实验。
目前,在网络上主要是包含两种模式
1.jaxws+tomcat 模式
但是,这种方式 不能使用spring的自动注入功能,在实际项目中难于使用。
2.jaxws+spring 模式
这种模式,每一个webservice要配置专门的banding。实际使用麻烦。
那么jaxws有没有一种类似CXF的实现方式呢,咳咳。。。
经过这段时间反复查看源代码,查看资料。总算发现如下办法,其效率有待验证。。。
1.通过配置web.xml,使得jaxws配置所有/ws/*路径
<listener>
<!-- 固定值:使用jaxws-ri中的监听器 -->
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>JaxWsServlet</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>JaxWsServlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
2.配置WEB-INF/sun-jaxws.xml
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
<!-- implementation:对外开放WebServices接口的实现类 -->
<!-- url-pattern:浏览器访问后缀 -->
<endpoint name="webservice1"
implementation="com.jadyer.service.HelloServiceImpl"
url-pattern="/ws/webservice1"/>
</endpoints>
通过配置1的通配符,配置2中所有的webservice都要被匹配到。
TODO:这个地方可以省略掉/ws/就好了。嗯,下次研究下,问题不大
3.WSServletContextListener 会遍历sun-jaxws.xml 配置的所有endpoint。并封装为EndService,放到adapters里面。
最后,wsservielt.getDelegate.getAdapters,可以拿到所有的adapter,根据url_pattern,匹配到对应的 adapter,加以处理。
这里的关键问题是 没法使用 autowired。查资料发现spring官网发现SpringBeanAutowiringSupport可以支持,但是只有简单描述没有demo。崩溃。。。
通过查看SpringBeanAutowiringSupport的源代码,发现ContextLoader.getCurrentWebApplicationContext()获取的对象WebApplicationContext为空。
根据listener -> filter -> servlet 加载顺序,org.springframework.web.context.ContextLoaderListener 优先加载,然后是com.sun.xml.ws.transport.http.servlet.WSServletContextListener,
然后是org.springframework.web.servlet.DispatcherServlet,最后是com.sun.xml.ws.transport.http.servlet.WSServlet。
当我看到ContextLoader.getCurrentWebApplicationContext()的ContextLoader属于spring-web-4.2.4.RELEASE.jar中,果断猜测ContextLoader应该是在org.springframework.web.servlet.DispatcherServlet
中初始化的,所以通过com.sun.xml.ws.transport.http.servlet.WSServletContextListener去加载@WebService且extends SpringBeanAutowiringSupport的类时,当然不能注入,因为这时springmvc都还没有初始化。
所以我果断实现com.huimark.jaxws.WSSpringServlet2 完全复制 WSServletContextListener的逻辑,只是从Listener换位Servlet实现了,而且 顺序在DispatcherServlet之后(重要),
在 com.sun.xml.ws.transport.http.servlet.WSServlet 之前。(这个应该无所谓,懒得测试了)
后记:
后来我发现com.sun.xml.ws.transport.http.servlet.WSServletContextListener这个类始终会执行,这是由于jaxws-rt-2.2.10.jar/META-INF/services中配置了
javax.servlet.ServletContainerInitializer。删掉即可。
通过链接1,访问实现 数字+1
http://localhost:8080/jaxws-tomcat-spring/add.do
通过account.wsdl右键访问,实现 数字+1.
发现两种访问方式 可以实现 数字 持续增长,证明 访问的是同一个 计数器