A-A+

WebService开发记录

2015年12月03日 技术 暂无评论 阅读 2,906 次

自打去年被BMC的Web Service整的非常凄惨之后,我就对Java平台下的Web Service开发敬而远之,实在受不了各种莫名其妙的问题,还有开发的配置调试过程。但是今年的这个时间,我又不得不硬着头皮把Web Service嵌入一个老的项目里面,于是各种麻烦铺面而来。

先是想使用Axis2来开发,网络上的一篇篇文章说实话简直是没什么营养,我怀疑这帮人是不是只成功过一次,还是说有前置条件但是却没写出来,总之如果按照这些千篇一律的文章是不可能顺顺当当就配置成功的。通过反复的试探大概了解了其配置,总体上感觉太复杂,对于一般的中小型、老旧项目不太适用,如果使用Axis2来开发,耗费的开发、调试时间得不偿失,所以干脆直接放弃,同时也摆脱了那些味同嚼蜡的水文。

接着就寻求比较简单的框架,一般来说易于自己理解的就是简单的框架,看上CXF一眼就对其一见钟情,不过对于从未接触此框架的人来说,如果只是按照网络上的文章去做还是有些困难,这里不说如何配置,只是说不能完全按照那些文章去做,因为或多或少都有些瑕疵,需要反复调试。

开发环境为:eclipse,JDK1.7,tomcat8,SpringMVC4.1,cxf3.1。

声明一个接口,使用WebService进行注解:

  1. package com.xnck.ws.server;
  2. import javax.jws.WebService;
  3. @WebService
  4. public interface ITestWebService {
  5.     public boolean test(String userId);
  6. }

实现这个接口:

  1. package com.xnck.ws.server.impl;
  2. import javax.jws.WebService;
  3. import org.apache.log4j.Logger;
  4. import com.xnck.ws.server.ITestWebService;
  5. @WebService(endpointInterface = "com.xnck.ws.server.ITestWebService")
  6. public class TestWebService implements ITestWebService{
  7.     private static final Logger log = Logger.getLogger(TestWebService.class);
  8.     public boolean test(String userId) {
  9.         return false;
  10.     }
  11. }

WEB-INF/classes内添加cxf.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.     xmlns:context="http://www.springframework.org/schema/context"
  4.     xmlns:jaxws="http://cxf.apache.org/jaxws"
  5.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans
  7.         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  8.         http://www.springframework.org/schema/context
  9.         http://www.springframework.org/schema/context/spring-context-3.0.xsd
  10.         http://cxf.apache.org/jaxws
  11.         http://cxf.apache.org/schemas/jaxws.xsd">
  12.     <import resource="classpath:META-INF/cxf/cxf.xml" />
  13.     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
  14.     <bean id="test" class="com.xnck.ws.server.impl.TestWebService" />
  15.     <jaxws:endpoint id="testWebService" implementor="#test" address="/test">
  16.     </jaxws:endpoint>
  17. </beans>

WEB.xml中的部分配置内容为:

  1. <!-- contextconfig -->
  2.   <context-param>
  3.     <param-name>contextConfigLocation</param-name>
  4.     <param-value>
  5.         classpath:spring-common.xml,classpath:cxf.xml
  6.     </param-value>
  7.   </context-param>
  8.   <listener>
  9.     <listener-class>
  10.             org.springframework.web.context.ContextLoaderListener
  11.     </listener-class>
  12.   </listener>
  13.   <!-- spring servlet -->
  14.   <servlet>
  15.     <servlet-name>Spring-Servlet</servlet-name>
  16.     <servlet-class> org.springframework.web.servlet.DispatcherServlet</servlet-class>
  17.     <init-param>
  18.       <param-name>contextConfigLocation</param-name>
  19.       <param-value>
  20.             classpath:spring-servlet.xml
  21.       </param-value>
  22.     </init-param>
  23.     <load-on-startup>1</load-on-startup>
  24.   </servlet>
  25.   <servlet-mapping>
  26.     <servlet-name>Spring-Servlet</servlet-name>
  27.     <url-pattern>*.do</url-pattern>
  28.   </servlet-mapping>
  29.   <servlet-mapping>
  30.     <servlet-name>Spring-Servlet</servlet-name>
  31.     <url-pattern>*.shtml</url-pattern>
  32.   </servlet-mapping>
  33.   <!-- cxf servlet -->
  34.   <servlet>
  35.        <servlet-name>CXFServlet</servlet-name>
  36.        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
  37.        <load-on-startup>2</load-on-startup>
  38.    </servlet>
  39.    <servlet-mapping>
  40.        <servlet-name>CXFServlet</servlet-name>
  41.        <url-pattern>/webservice/*</url-pattern>
  42.    </servlet-mapping>

然后启动tomcat,访问http://localhost:8080/yourwebstie/webservice,就可以看到正常的WSDL输出信息了,到这里没有什么问题,即使有点问题也是小问题。

但是,使用SoapUI来对上文开发的TestWebService测试时,就出错了,具体的错误为:Cannot create a secure XMLInputFactory。去互联网上搜索,千篇一律的解决办法又出现了,各种搞定后来其实是搞不定。一般在互联网上通过5分钟的搜索无法解决问题时,那这个问题就十分棘手了,有可能卡主很长时间。不停的打开这些前篇一律的帖子,终于发现有几篇有营养的,首先:

http://blog.csdn.net/wuxuguang123/article/details/43676265这个帖子从cxf的源代码进行分析,给出了令人眼前一亮的解决办法,通过设定常量“ALLOW_INSECURE_PARSER”的值来解决办法,但是并没有非常明确的说明该如何解决,只是比较模糊的给出了方向。

再继续搜索发现了两个帖子,分别是http://codego.net/584909/http://shangliang57.iteye.com/blog/2048380,第一个帖子想通过Spring声明Bean来改变这个常量的值,我在尝试的时候失败了,应该是某些配置或者框架版本不一样,第二个帖子是通过cxf的拦截器来设置这个常量的值,尝试后成功了。关于cxf拦截器的说明介绍,可以看这里http://lavasoft.blog.51cto.com/62575/167288/

造的拦截器代码如下:

  1. package com.xnck.authorize.interceptor;
  2. import org.apache.cxf.interceptor.Fault;
  3. import org.apache.cxf.message.Message;
  4. import org.apache.cxf.phase.AbstractPhaseInterceptor;
  5. import org.apache.cxf.phase.Phase;
  6. public class CxfWssJSystemEnvIntercepter extends AbstractPhaseInterceptor<Message>{
  7.     public CxfWssJSystemEnvIntercepter(String phase) {
  8.             super(phase);
  9.     }
  10.     public CxfWssJSystemEnvIntercepter(){
  11.         super(Phase.RECEIVE);
  12.     }
  13.     @Override
  14.     public void handleMessage(Message message) throws Fault {
  15.       if(null==System.getProperty("org.apache.cxf.binding.soap.messageFactoryClassName")
  16.          ||"".equals(System.getProperty("org.apache.cxf.binding.soap.messageFactoryClassName"))
  17.       ){
  18.             System.setProperty("org.apache.cxf.stax.allowInsecureParser","1");
  19.         }
  20.     }
  21. }

这样在符合条件的时候,访问任何一个cxf的web service都会触发这个拦截器,从而更改常量“ALLOW_INSECURE_PARSER”的值。在cxf.xml里面发布web service时的配置就变成:

  1. <bean id="task" class="com.ceservice.ws.server.impl.TaskWebService" />
  2. <jaxws:endpoint id="taskWebService" implementor="#task" address="/task">
  3.         <jaxws:inInterceptors>
  4.            <bean class="com.ceservice.authorize.interceptor.CxfWssJSystemEnvIntercepter"></bean>
  5.     </jaxws:inInterceptors>
  6. </jaxws:endpoint>

再运行进行测试,我这里是没有再报错了。

给我留言

Copyright © 字痕随行 保留所有权利.   Theme  Ality

用户登录

分享到: