通过springboot发布WebService接口并调用方式
作者:大乐哥。
SpringBoot集成cxf步骤记录
1.什么是cxf
Apache CXF是一个开源的Service框架,简化用户的service开发,基于CXF开发的应用可提供SOAP、XML/HTTP、RESTFUL HTTP或CORBA等服务。CXF底层页可以使用不同的传输协议,包括HTTP、JMS或JBI等。
cxf特性
支持大量的Web Service标准:包括SOAP、WS-I Basic Profile、WSDL、WS-Addressing、WS-Policy、WS-ReliableMessaging和WS-Security。
支持大量的前端(frontend)编程模型。CXF实现了标准的JAX-WS API,它也包括一种被称为简单前端(simple frontend)的模型,这种模型无需annotation支持。
CXF支持web service的两种开发模式:
- 规则(contract)优先: 通过编写WSDL来开发web service;
- 代码优先: 通过编写java代码来开发webservice.
2.集成引入
<!-- cxf start --> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-spring-boot-starter-jaxws</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-features-logging</artifactId> <version>3.3.0</version> </dependency> <!-- cxf end -->
注意事项:cxf版本需要与SpringBoot的版本对应,不然因版本问题, 整合cxf-spring-boot-starter-jaxws的启动项目会出现异常。
具体对应关系上仓库进行查看下
https://mvnrepository.com/artifact/org.apache.cxf/cxf-spring-boot-starter-jaxws查找到jaxws的各种版本,进入之后可以看到对应的springboot版本
3.服务端
3.1 CXF配置类
package com.mrxu.config; import org.apache.cxf.Bus; import org.apache.cxf.bus.spring.SpringBus; import org.apache.cxf.ext.logging.LoggingFeature; import org.springframework.context.annotation.Bean; /** * <b>功能描述:CXF配置类</b><br> * * @author newzhong * @version 1.0.0 * @since JDK 1.8 */ public class CxfConfig { @Bean(name = Bus.DEFAULT_BUS_ID) public SpringBus springBus() { SpringBus bus = new SpringBus(); bus.getFeatures().add(new LoggingFeature()); return bus; } }
3.2 服务的发布
自定义注解标注要发布的服务类,发布出去
package com.mrxu.config; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * <p>description:自动发布接口地址注解</p> * * @author newzhong * @version 1.0 */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface AutoPublish { /** *<p>description:发布地址</p> * @return String * @author newzhong */ String publishAddress(); }
package com.mrxu.config; import lombok.extern.slf4j.Slf4j; import org.apache.cxf.Bus; import org.apache.cxf.bus.spring.SpringBus; import org.apache.cxf.jaxws.EndpointImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import org.springframework.web.context.WebApplicationContext; @Component @Slf4j public class PublishEndpoint implements ApplicationRunner { @Autowired private WebApplicationContext applicationConnect; @Autowired() @Qualifier(Bus.DEFAULT_BUS_ID) private SpringBus bus; @SuppressWarnings("resource") @Override public void run(ApplicationArguments applicationArguments) throws Exception { log.info("开始进行自动发布webService接口"); String[] beanNames = applicationConnect.getBeanNamesForAnnotation(AutoPublish.class); for(String beanName : beanNames) { String publishAddr = applicationConnect.getType(beanName).getAnnotation(AutoPublish.class).publishAddress(); EndpointImpl endpoint = new EndpointImpl(bus, applicationConnect.getBean(beanName)); endpoint.publish(publishAddr); log.info(String.format("发布接口地址:[%s]", publishAddr)); } log.info("weBservice接口自动发布结束"); } }
3.3 发布的地址yml,nacos配置
cxf:
path: /cxf
原本默认的默认端口号后 +拼接 /service,现在可以根据需求进行修改
3.4. 新增服务接口
在接口上添加@WebService注解
- @WebParam表示方法的参数,如果不加此注解,方法的参数都从arg0,开始,随着参数增多,name不断增加为arg1,arg2…;
- @WebResult表示方法的返回值, 没有此注解 返回值名字为return
package com.mrxu.service; import javax.jws.WebParam; import javax.jws.WebService; /** * <b>功能描述:webService测试接口</b><br> * @author newzhong * @version 1.0.0 * @since JDK 1.8 * * @Note * <b>创建时间:</b> 2021-03-27 14:32 */ @WebService(targetNamespace = "http://service.mrxu.com/") public interface IWebServiceTest { String getDept(@WebParam(name = "jsonStr")String jsonStr); }
3.5 新增服务接口实现类
- serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service。缺省值为 Java 类的简单名称 + Service。(字符串)
- endpointInterface: 服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口
- name:此属性的值包含XML Web Service的名称。在默认情况下,该值是实现XML Web Service的类的名称,wsdl:portType 的名称。缺省值为 Java 类或接口的非限定名称。(字符串
- portName: wsdl:portName。缺省值为 WebService.name+Port。
- targetNamespace:指定你想要的名称空间,认是使用接口实现类的包名的反缀
- wsdlLocation:指定用于定义 Web Service 的 WSDL 文档的 Web 地址。Web 地址可以是相对路径或绝对路径。(字符串)
注意:实现类上可以不添加Webservice注解 ,加在接口上
package com.mrxu.service.impl; import com.mrxu.common.domain.Phone; import com.mrxu.config.AutoPublish; import com.mrxu.dao.PhoneMapper; import com.mrxu.service.IWebServiceTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.jws.WebService; import java.util.List; @Service("WebServiceTest") @AutoPublish(publishAddress = "test") @WebService(endpointInterface = "com.mrxu.service.IWebServiceTest", serviceName = "WebServiceTest", targetNamespace = "http://service.mrxu.com/" ) public class WebServiceTest implements IWebServiceTest { @Autowired public PhoneMapper phoneMapper; @Override public String getDept(String jsonStr) { List<Phone> phones = phoneMapper.selectPhone(); String s = phones.toString(); return s; } }
3.6 验证服务发布
通过浏览器访问wsdl,wsdl路径即为发布的路径加上?wsdl
http://127.0.0.1:[端口号]/cxf/test?wsdl
可以看到接口就成功了。
测试webservice接口
1.新建一个controller
package com.mrxu.controller; import com.mrxu.service.TestWebService; import io.swagger.annotations.Api; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Api(tags = "webser") @RestController @RequestMapping("/wbser") public class WebServiceController { private static final long CONNECT_TIMEOUT = 10 * 1000; private static final long RECEIVE_TIMEOUT = 60 * 1000; private static final String ACTINFO_WSDL = "http://175.2.70.225:9002/cxf/test?wsdl"; private TestWebService service = getProxyService(ACTINFO_WSDL, TestWebService.class); @PostMapping("/wbser") public String wbeser(String id){ String userService = service.getDept("1"); return userService; } public static <T> T getProxyService(String wsdl, Class<T> serviceClass) { JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(serviceClass); factory.setAddress(wsdl); T service = (T) factory.create(); org.apache.cxf.endpoint.Client proxy = ClientProxy.getClient(service); HTTPConduit conduit = (HTTPConduit) proxy.getConduit(); HTTPClientPolicy policy = new HTTPClientPolicy(); policy.setConnectionTimeout(CONNECT_TIMEOUT); policy.setReceiveTimeout(RECEIVE_TIMEOUT); conduit.setClient(policy); return service; } }
2.新建一个WebService接口
package com.mrxu.service; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; @WebService(targetNamespace="http://service.mrxu.com/") public interface TestWebService { @WebMethod @WebResult String getData(@WebParam String requestData); @WebMethod @WebResult String getData1(@WebParam String requestData); @WebMethod @WebResult String getDept(@WebParam(name = "jsonStr")String id); }
最后可以通过swagger进行测试
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。