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]); } }
-----------------------------------
作者:怒吼的萝卜
链接:http://www.cnblogs.com/nhdlb/
-----------------------------------