WebService:SpringBoot整合CXF实现WebService接口

依赖引入

引入依赖jar包

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>3.1.11</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.1.11</version>
</dependency>

创建配置类


import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import javax.xml.ws.Endpoint;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

@Configuration
public class CxfConfig {


    //解决跨域问题,跨域过滤
    @Bean
    public CorsFilter corsFilter(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",corsConfiguration());
        return  new CorsFilter(source);
    }
    private CorsConfiguration corsConfiguration(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setMaxAge(36001l);
        return  corsConfiguration;
    }
    
    /**
     * webservice配置后,controller不能使用,需要在配置一个DispatcherServlet来扫描Controller
     * @return
     */
    @Bean
    public ServletRegistrationBean restServlet(){
        //注解扫描上下文
        AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        //controller的文件夹路径
        applicationContext.scan("com.brinfo.java.controller");
        //通过构造函数指定dispatcherServlet的上下文
        DispatcherServlet rest_dispatcherServlet = new DispatcherServlet(applicationContext);
        //用ServletRegistrationBean包装servlet
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(rest_dispatcherServlet);
        //优先级
        registrationBean.setLoadOnStartup(1);
        //指定urlmapping
        registrationBean.addUrlMappings("/*");
        //指定name,如果不指定默认为dispatcherServlet
//        registrationBean.setName("rest");
        return registrationBean;
    }
    
     /**
     * 配置webservice的前缀路径
     * @return
     */
    @Bean
    public ServletRegistrationBean dispatcherServlet() {
        return new ServletRegistrationBean(new CXFServlet(),"/all/*");
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus springBus() {
        return new SpringBus();
    }

    /**
     * 配置webservice接口路径
     * @return
     */
    @Bean
    public AllServiceImpl AllServiceImpl() {
        return new AllServiceImpl();
    }

    @Bean
    public Endpoint endpoint() {
        EndpointImpl endpoint = new EndpointImpl(springBus(), AllServiceImpl());
        endpoint.publish("/");
        return endpoint;
    }
}

创建WebService接口类

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import java.text.ParseException;

// targetNamespace的值就是包路径
@WebService(name = "AllService",targetNamespace = "http://api.webController/")
@SOAPBinding(style= SOAPBinding.Style.RPC)
public interface AllService {

    /**
     * 测试方法
     * @return
     */
    @WebMethod(operationName = "sayHello")
    public void sayHello(String str) throws Exception;

}

创建WebService接口实现类

package com.brinfo.base.interfaces.webController.Impl;

import com.brinfo.base.interfaces.config.FtpParamsConfig;
import com.brinfo.base.interfaces.feignApi.ScheduleServiceFeign;
import com.brinfo.base.interfaces.webController.api.AllService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.jws.WebService;
import java.text.ParseException;
import java.util.*;

/**
 * 测试方法
 */
@WebService(name = "AllService", endpointInterface = "com.brinfo.base.interfaces.webController.api.AllService", targetNamespace = "http://api.webController/")
public class AllServiceImpl implements AllService {
    private static final Logger logger = LoggerFactory.getLogger(AllServiceImpl.class);

    @Autowired
    ScheduleServiceFeign scheduleServiceFeign;
    @Autowired
    FtpParamsConfig ftpParamsConfig;

    /**
     * 测试方法
     * @return
     */
    @Override
    public void sayHello(String str) throws Exception {
        try {
            System.out.println(str);
        } catch (JAXBException e) {
            e.printStackTrace();
        } catch (NullPointerException e){
            e.printStackTrace();
        }
    }
    
}

调用测试

JaxWsDynamicClientFactory

 简介:只要指定服务器端wsdl文件的位置,然后指定要调用的方法和方法的参数即可,不关心服务端的实现方式。

public class Client3 {  
    
public static void main(String[] args) throws Exception {  
        //方法名
        String method = "sayHello"
        //参数
        String param = "KEVIN"
         //实例化JaxWsDynamicClientFactory
        JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();  
        //通过wsdl路径生成客户端实体
        Client client = clientFactory.createClient("http://localhost:9090/AllService?wsdl");  
        //调用方法传参
        Object[] result = client.invoke(method, param);  
        //打印回值
        System.out.println(result[0]);  
    }  

}

webservie报错:远程主机强迫关闭了一个现有的连接。

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> System.IO.IOException: Unable to read data from the transport connection:远程 主机强迫关闭了一个现有的连接。. ---> System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接。
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
   --- End of inner exception stack trace ---
   at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
   at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request)
   at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
   at EnterpriseServerBase.WebService.DynamicWebCalling.HdyyElectronicService.doDownloadRecipeInfo(String userName, String password, String senderCode)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at XmlTrans.Core.WSHelperCore.InvokeWebServiceMethod(String methodname, Object[] args)

原因:

经验证,如果数据稍微大点,比如3-4M,有时候可以通过稍微调大等待超时时长来解决问题,但是如果数据偏大的话,比如10M,调大等待超时时长也无济于事,Socket连接很快会被干掉,只要数据一直这么大,连接就会被不断的干掉。

总结:

webservice只适用于小数据的传输,不要尝试使用webservice进行大数据的传输。

解决办法:

public class Client3 {  
    
public static void main(String[] args) throws Exception {  
        //方法名
        String method = "sayHello"
        //参数
        String param = "KEVIN"
         //实例化JaxWsDynamicClientFactory
        JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();  
        //通过wsdl路径生成客户端实体
        Client client = clientFactory.createClient("http://localhost:9090/helloWorldService?wsdl");  
       
        HTTPConduit http = (HTTPConduit)client.getConduit();
        //策略
        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        //连接超时(1分钟)
        httpClientPolicy.setConnectionTimeout(1 * 60000);
        httpClientPolicy.setAllowChunking(false);
        //响应超时(1分钟)
        httpClientPolicy.setReceiveTimeout(1 * 60000);
        http.setClient(httpClientPolicy);
        //调用方法传参
        Object[] result = client.invoke(method, param);  
        //打印回值
        System.out.println(result[0]);  
    }  

}

 

参考:https://www.cnblogs.com/langtianya/p/4939098.html

posted @ 2020-05-13 21:48  怒吼的萝卜  阅读(15519)  评论(1编辑  收藏  举报