资讯专栏INFORMATION COLUMN

实现一个spring webservice服务端四:服务端、客户端以及httpclient调用spr

oneasp / 2372人阅读

摘要:执行结果如下中华田园犬测试我认为所有使用协议的,都能使用测试。下面是我写的测试代码旺财需要增加一个包测试结果返回值如下中华田园犬写法稍微有点麻烦的是,需要拼接请求参数,参数少的话还好,多的话就很烦不过这种方法不用生成一大堆客户端代码。

经过前段时间的学习,已经实现一个有返回值的spring-ws服务,那接下来,就要试试能不能通过不同方式的调用,要实现一下几种方式的测试:

spring-ws服务端测试

spring-ws客户端测试

httpclient

spring-ws服务端测试

我对spring-test 和spring-ws-test,几乎没有什么了解,只好按照文档来写spring-ws服务端测试的,这是测试代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("spring-ws-servlet.xml")
public class WebserviceTest {
    
    @Autowired
    private ApplicationContext applicationContext;
    
    private MockWebServiceClient client;
    
    @Before
    public void createClient() {
        client = MockWebServiceClient.createClient(applicationContext);
    }
    
    
    @Test
    public void holidayTest() {
    
        Source requestPayload = new StringSource(
            
                "" +
                    
                        "旺财" +
                    
                        "");
    
        Source responsePayload = new StringSource(
            
                "" +
                        "中华田园犬" +
                        "5" +
                       "");
    
    
        client.sendRequest(RequestCreators.withPayload(requestPayload)).andExpect(ResponseMatchers
                .payload
                (responsePayload));
        
    }
}

需要添加jar包:

        
            junit
            junit
            4.12
        
        
            org.springframework.ws
            spring-ws-test
            2.4.0.RELEASE
        
        
            org.springframework
            spring-test
            4.2.7.RELEASE
        

执行测试方法,一直报下面这个错误:

failed to load applicationcontext

因为我没有配置日志,所以不知道具体错误是什么,只好又去配置log4j2,配置完之后,具体的错误信息可以看到了:

Caused by: java.io.FileNotFoundException: class path resource [spring-ws-servlet.xml] cannot be opened because it does not exist
    at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:172)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:330)
    ... 36 more

可以看到,是因为找不到配置文件【spring-ws-servlet.xml】,我找到了出错的代码:

public URL getResource(String name) {
        URL url;
        if (parent != null) {
            url = parent.getResource(name);
        } else {
            url = getBootstrapResource(name);
        }
        if (url == null) {
            url = findResource(name);
        }
        return url;
    }

name就是spring-ws-servlet.xml, parent就是Classloader,只是不知道为什么找不到;

我只好把路径修改为@ContextConfiguration("classpath:spring-ws-servlet.xml"),为了能够在classpath下找到这个文件,又把spring-ws-servlet.xml 和hr.xsd文件复制到src/main/resource下面,可能有人会疑惑为什么是复制过去一份,而不是把WEB-INF下的文件转移到src/main/resource下面,因为spring 的默认加载位置就是wWEB-INF下的文件,而我又没有找到读取classpath路径文件的配置,就是这个:


    spring-ws
    org.springframework.ws.transport.http.MessageDispatcherServlet
    
      transformWsdlLocations
      true
    
  

所以只好改成这样,虽然看着奇怪,但是不再报找不到文件的错误了。

改完之后,继续测试,可是又有报错了:

[different] Expected namespace URI "http://mycompany.com/hr/webservice" but was "null" - comparing  at /holidayResponse[1] to  at /holidayResponse[1]

Payload: 中华田园犬5

起初,以为是哪里错了,后来,认真看了下信息,才发现,报错是因为期望返回值中有xmlns="http://mycompany.com/hr/webse...",但是实际返回值是:

中华田园犬5

和期望的值不一样,所以才报了这个错,把期望值修改了一下:

Source responsePayload = new StringSource(
            
                "" +
                        "中华田园犬" +
                        "5" +
                       "");

这样再测试,就不报错了。
至此,spring-ws服务端测试通过。

spring-ws客户端测试

spring-ws参考文档上关于服务端测试,给出了几种方式,有http、jms、eamil等,因为我的测试服务端是http的,所以就使用http的测试;

关于http测试webservice的方式,spring-ws首先给出的要求是要有消息工厂【messageFactory】,就像下面的配置一样:





 

 


spring-ws提供了两种消息工厂,分别为:

SaajSoapMessageFactory ------saaj 支持多

AxiomSoapMessageFactory ------axis2 适合数据多

我参考文档写的测试代码是:

import org.junit.Test;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.xml.transform.StringSource;

import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

/**
 * Created by nyl
 * 2017/6/23
 */
public class SpringClient {
    
    private final WebServiceTemplate client = new WebServiceTemplate();
    
    
    @Test
    public void sptingTest() {
        
        client.setDefaultUri("http://www.ningyongli.site:8080/webservicelearn/holidayService");
    
        StreamSource source =  new StringSource(
        
                "" +
                
                        "旺财" +
                
                        "");
    
        try {
            JAXBContext unmarshaller = JAXBContext.newInstance(HolidayResponse.class);
            JAXBResult jaxbResult = new JAXBResult(unmarshaller);
            
            //StreamResult result = new StreamResult(System.out);
            client.sendSourceAndReceiveToResult(source, jaxbResult);
            HolidayResponse holidayResponse = (HolidayResponse) jaxbResult.getResult();
            System.out.println(holidayResponse.toString());
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    
        
        
    }
    
}

代码中并没有设置messageFactory,于是我去看源码,发现:

public WebServiceTemplate() {
        initDefaultStrategies();
    }

    /**
     * Creates a new {@code WebServiceTemplate} based on the given message factory.
     *
     * @param messageFactory the message factory to use
     */
    public WebServiceTemplate(WebServiceMessageFactory messageFactory) {
        setMessageFactory(messageFactory);
        initDefaultStrategies();
    }

 还有···········

WebServiceTemplate 提供了很多中构造方法,无参构造方法会加载默认的配置(initDefaultStrategies),默认配置如下:

org.springframework.ws.client.core.FaultMessageResolver=org.springframework.ws.soap.client.core.SoapFaultMessageResolver
org.springframework.ws.WebServiceMessageFactory=org.springframework.ws.soap.saaj.SaajSoapMessageFactory
org.springframework.ws.transport.WebServiceMessageSender=org.springframework.ws.transport.http.HttpUrlConnectionMessageSender

也就是说,默认的就是SaajSoapMessageFactory这个,知道了,我就不管这个了。

WebServiceTemplate 有很多用于请求的方法

我用的是这个sendSourceAndReceiveToResult(source, result),这些方法的参数请求参数顶级接口Source ,返回数据顶级接口Result,回调方法等;只要根据接口要求,实现子类,放进方法里执行即可。
执行结果如下:

HolidayResponse{ name=中华田园犬, age=5}
httpclient测试

我认为所有使用http协议的,都能使用httpclient测试。
我在学习spring-ws之前遇到了几次webservice的问题,其中一个让我印象深刻,第三方公司给我一个wsdl文件,我根据文件生成客户端代码,发现返回值是boolean类型的数据,但是他给我的soap ui测试截图上,返回的是一个复杂的对象,我以为我客户端代码生成错了,于是尝试了axis 、axis2 、cxf等jar包,生成的返回值都一样,于是我就去看wsdl文件(那时候基本上还看不懂),发现wsdl中返回值就是boolean类型,于是和对接人员沟通希望给出正确的wsdl文件,结果对方不认为wsdl有问题,反正soap ui 测通了,让我自己想办法。
于是就有了httpclient调用webservice的经历。

下面是我写的测试代码:

    @Test
    public void httpclientTest() {
        CloseableHttpClient closeableHttpClient = null;
        CloseableHttpResponse closeableHttpResponse = null;
        String  result = null;
        try {
            
            String requestStr = "" +
                    "" +
                    ""+
                    "" +
                    "旺财" +
                    "" +
                    "" +
                    "";
                
            HttpPost httpPost = new HttpPost("http://www.ningyongli.site:8080/webservicelearn/holidayService");
            httpPost.setHeader("Content-Type", "text/xml;charset=utf-8");
            //httpPost.setHeader("SOAPAction", "hollidayService");
    
            System.out.println(requestStr);
            StringEntity entity = new StringEntity(requestStr, "UTF-8");
            httpPost.setEntity(entity);
        
            closeableHttpClient = HttpClients.createDefault();
            closeableHttpResponse = closeableHttpClient.execute(httpPost);
            result = EntityUtils.toString(closeableHttpResponse.getEntity());
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                closeableHttpResponse.close();
                closeableHttpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

需要增加一个jar包:

   
      org.apache.httpcomponents
      httpclient
      4.5.3
    

测试结果返回值如下:


    
    
        
            中华田园犬
            5
        
    

写法稍微有点麻烦的是,需要拼接请求参数,参数少的话还好,多的话就很烦;不过这种方法不用生成一大堆客户端代码。

总结

总体而言,测试实现要比服务端实现要简单一些,基本都很快调通了。

本来还想用axis、axis2调用测试一下的,但是突然发现spring-ws生成的wsdl路径和它们要求的有点不一样,这两种要求路径都是这样的http://ip:port/name/servicena...,和我用spring-ws有点不一样,尝试了一下常用的调用方式都无法实现。以后对axis和axis2有一定了解了,再来看这个问题

客户端测试源码在这里

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70168.html

相关文章

  • WebService就是这么简单

    摘要:它使用方式,接收和响应外部系统的某种请求。回顾我们在学习基础网络编程章节已经知道了这么一个连接了。使用指定名称的命名空间。名词简单对象访问协议作为一个基于语言的协议用于有网上传输数据。以的根元素出现。代理这么一个概念就更加清晰了。 WebService介绍 首先我们来谈一下为什么需要学习webService这样的一个技术吧.... 问题一 如果我们的网站需要提供一个天气预报这样一个需求...

    SwordFly 评论0 收藏0
  • Java 远程通讯技术及原理分析

    摘要:对于与而言,则可以看做是消息传递技术的一种衍生或封装。在生产者通知消费者时,传递的往往是消息或事件,而非生产者自身。通过消息路由,我们可以配置路由规则指定消息传递的路径,以及指定具体的消费者消费对应的生产者。采用和来进行远程对象的通讯。 消息模式 归根结底,企业应用系统就是对数据的处理,而对于一个拥有多个子系统的企业应用系统而言,它的基础支撑无疑就是对消息的处理。与对象不同,消息本质上...

    rozbo 评论0 收藏0
  • 分布式服务框架之远程通讯技术及原理分析

    摘要:微软的虽然引入了事件机制,可以在队列收到消息时触发事件,通知订阅者。由微软作为主要贡献者的,则对以及做了进一层包装,并能够很好地实现这一模式。 在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,这些名词之间到底是些什么关系呢,它们背后到底是基...

    sorra 评论0 收藏0
  • 分布式服务框架之远程通讯技术及原理分析

    摘要:微软的虽然引入了事件机制,可以在队列收到消息时触发事件,通知订阅者。由微软作为主要贡献者的,则对以及做了进一层包装,并能够很好地实现这一模式。 在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在Java领域中有很多可实现远程通讯的技术,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,这些名词之间到底是些什么关系呢,它们背后到底是基...

    0xE7A38A 评论0 收藏0
  • Java系统WebServiceSpring与CXF的集成

    摘要:我们再使用这样的来查看这个服务具体的定义这个用以通过查看服务也就是我们开头所说的用通用格式来描述的功能入参和返回值,使我们的调用者明白服务的使用方法具体详情可以查看我们的这个服务的页面。 WebService是什么呢?顾名思义,是Web系统提供的服务,其目的呢,往大了说:是系统实现多异构模块协同合作,服务实现SOA(Services oriented Architecture面向服务的...

    waterc 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<