天天看点

jaxws-tomcat-spring

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.

发现两种访问方式 可以实现 数字 持续增长,证明 访问的是同一个 计数器