From 26e4227acee3bba9819245f50c4741e87d37978f Mon Sep 17 00:00:00 2001 From: Xiong Neng Date: Fri, 15 Jun 2018 18:40:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AAcxf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- springboot-cxf/.gitignore | 14 +++ springboot-cxf/LICENSE | 20 ++++ springboot-cxf/README.md | 29 +++++ springboot-cxf/pom.xml | 106 ++++++++++++++++++ springboot-cxf/run.sh | 72 ++++++++++++ .../com/xncoding/webservice/Application.java | 12 ++ .../xncoding/webservice/config/CxfConfig.java | 38 +++++++ .../webservice/model/BaseResponse.java | 60 ++++++++++ .../com/xncoding/webservice/model/User.java | 47 ++++++++ .../webservice/service/ICommonService.java | 27 +++++ .../service/impl/CommonServiceImpl.java | 32 ++++++ .../xncoding/webservice/util/JacksonUtil.java | 45 ++++++++ .../src/main/resources/application.yml | 33 ++++++ springboot-cxf/src/main/resources/banner.txt | 23 ++++ .../xncoding/webservice/ApplicationTests.java | 97 ++++++++++++++++ 15 files changed, 655 insertions(+) create mode 100644 springboot-cxf/.gitignore create mode 100644 springboot-cxf/LICENSE create mode 100644 springboot-cxf/README.md create mode 100644 springboot-cxf/pom.xml create mode 100644 springboot-cxf/run.sh create mode 100644 springboot-cxf/src/main/java/com/xncoding/webservice/Application.java create mode 100644 springboot-cxf/src/main/java/com/xncoding/webservice/config/CxfConfig.java create mode 100644 springboot-cxf/src/main/java/com/xncoding/webservice/model/BaseResponse.java create mode 100644 springboot-cxf/src/main/java/com/xncoding/webservice/model/User.java create mode 100644 springboot-cxf/src/main/java/com/xncoding/webservice/service/ICommonService.java create mode 100644 springboot-cxf/src/main/java/com/xncoding/webservice/service/impl/CommonServiceImpl.java create mode 100644 springboot-cxf/src/main/java/com/xncoding/webservice/util/JacksonUtil.java create mode 100644 springboot-cxf/src/main/resources/application.yml create mode 100644 springboot-cxf/src/main/resources/banner.txt create mode 100644 springboot-cxf/src/test/java/com/xncoding/webservice/ApplicationTests.java diff --git a/springboot-cxf/.gitignore b/springboot-cxf/.gitignore new file mode 100644 index 0000000..1e3c5bb --- /dev/null +++ b/springboot-cxf/.gitignore @@ -0,0 +1,14 @@ +# 此为注释– 将被Git 忽略 +# /结尾表示是目录,忽略目录和目录下的所有件 +# /开头表示根目录,否则是.gitignore的相对目录 +# !开头表示反选 +.idea/ +target/ +*.iml +*.ipr +*.iws +*.log +.svn/ +.project +rebel.xml +.rebel-remote.xml.* diff --git a/springboot-cxf/LICENSE b/springboot-cxf/LICENSE new file mode 100644 index 0000000..83cd47d --- /dev/null +++ b/springboot-cxf/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2018 Xiong Neng + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/springboot-cxf/README.md b/springboot-cxf/README.md new file mode 100644 index 0000000..eab02d4 --- /dev/null +++ b/springboot-cxf/README.md @@ -0,0 +1,29 @@ +## 实现WebService + +利用Apache CXF实现WebService + +启动之后,wsdl访问链接: + +## 客户端动态代理调用 + +这个在单元测试类ApplicationTests中有演示 + +## 生产客户端代码 + +apache的wsdl2java工具,使用`-autoNameResolution`自动处理 + +``` +wsdl2java -autoNameResolution http://xxx?wsdl +``` + +JDK自带的工具 + +``` +wsimport -p com.enzhico.land.client -keep http://xxx?wsdl -s d:/ws -B-XautoNameResolution +``` + +## 许可证 + +Copyright (c) 2018 Xiong Neng + +基于 MIT 协议发布: diff --git a/springboot-cxf/pom.xml b/springboot-cxf/pom.xml new file mode 100644 index 0000000..eb7e706 --- /dev/null +++ b/springboot-cxf/pom.xml @@ -0,0 +1,106 @@ + + + 4.0.0 + + com.xncoding + springboot-cxf + 1.0.0-SNAPSHOT + jar + + springboot-restful + CXF实现WebService + + + org.springframework.boot + spring-boot-starter-parent + 1.5.10.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-jetty + + + + + org.apache.cxf + cxf-spring-boot-starter-jaxws + 3.2.4 + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.hamcrest + hamcrest-all + 1.3 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20 + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + src/main/resources + + + src/main/java + + **/*.xml + + + + + + \ No newline at end of file diff --git a/springboot-cxf/run.sh b/springboot-cxf/run.sh new file mode 100644 index 0000000..955efb1 --- /dev/null +++ b/springboot-cxf/run.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# 项目自动更新脚本 +# 先clone相应的分支下来: +# git clone ssh://git@120.24.173.142:7999/xxx.git +# 远程调试启动: +# nohup java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 & + +function start { + profile="$1" + echo "启动环境profile=${profile}" + jarfile=$(ls target/*.jar) + if [[ "$?" == "0" ]]; then + stop $profile $jarfile + fi + branch=$(git branch |awk '{print $2}') + git pull origin ${branch} + echo "更新完代码开始重新打包" + mvn clean && mvn clean && mvn package -DskipTests=true + if [[ "$?" != "0" ]]; then + echo "编译出错,退出!" + exit 1 + fi + echo "nohup java -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 &" + nohup java -Xms512m -Xmx1024m -jar -Dspring.profiles.active=${profile} ${jarfile} >/dev/null 2>&1 & + echo "启动应用中,请查看日志文件..." +} + +function stop { + profile="$1" + jarfile="$2" + ps aux | grep "${jarfile}" | grep "spring.profiles.active=${profile}" | grep -v grep > /dev/null + if [[ "$?" == "0" ]]; then + echo "该应用还在跑,我先停了它" + pid=$(ps aux | grep "${jarfile}" | grep "spring.profiles.active=${profile}" | grep -v grep |awk '{print $2}') + if [[ "$pid" != "" ]]; then + kill -9 $pid + fi + echo "停止应用成功..." + fi +} + +if [[ "$1" == "start" ]]; then + if [[ "$#" < 2 ]]; then + echo "请输入正确参数:./epay.sh start {profile}" + exit 1 + fi + profile="$2" + if [[ "$profile" != "dev" && "$profile" != "test" && "$profile" != "show" && "$profile" != "production" ]]; then + echo "参数错误,请输入正确的profile参数,使用方法:" + echo "./epay.sh start {profile} ==> 启动应用,{profile}取值:dev|test|show|production" + exit 1 + fi + start "${profile}" +elif [[ "$1" == "stop" ]]; then + if [[ "$#" < 2 ]]; then + echo "请输入正确参数:./epay.sh stop {profile}" + exit 1 + fi + profile="$2" + if [[ "$profile" != "dev" && "$profile" != "test" && "$profile" != "show" && "$profile" != "production" ]]; then + echo "参数错误,请输入正确的profile参数,使用方法:" + echo "./epay.sh stop {profile} ==> 停止应用,{profile}取值:dev|test|show|production" + exit 1 + fi + jarfile=$(ls target/*.jar) + stop $profile $jarfile +else + echo "参数错误,使用方法:{}参数是必填的,[]参数可选" + echo "./epay.sh start {profile} ==> 启动应用,{profile}取值:dev|test|show|production" + echo "./epay.sh stop {profile} ==> 停止应用,{profile}取值:dev|test|show|production" + exit 1 +fi diff --git a/springboot-cxf/src/main/java/com/xncoding/webservice/Application.java b/springboot-cxf/src/main/java/com/xncoding/webservice/Application.java new file mode 100644 index 0000000..2b63d98 --- /dev/null +++ b/springboot-cxf/src/main/java/com/xncoding/webservice/Application.java @@ -0,0 +1,12 @@ +package com.xncoding.webservice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/springboot-cxf/src/main/java/com/xncoding/webservice/config/CxfConfig.java b/springboot-cxf/src/main/java/com/xncoding/webservice/config/CxfConfig.java new file mode 100644 index 0000000..87f8c43 --- /dev/null +++ b/springboot-cxf/src/main/java/com/xncoding/webservice/config/CxfConfig.java @@ -0,0 +1,38 @@ +package com.xncoding.webservice.config; + +import javax.xml.ws.Endpoint; + +import org.apache.cxf.Bus; +import org.apache.cxf.jaxws.EndpointImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import com.xncoding.webservice.service.ICommonService; +import org.springframework.context.annotation.Configuration; + +/** + * 默认服务在 Host:port/services/*** 路径下 + * 这里相当于把Commonservice接口发布在了路径/services/CommonService下 + * wsdl文档路径为http://localhost:8080/services/CommonService?wsdl + * + * @author XiongNeng + * @version 1.0 + * @since 2018/6/15 + */ +@Configuration +public class CxfConfig { + @Autowired + private Bus bus; + + @Autowired + ICommonService commonService; + + /** + * JAX-WS + **/ + @Bean + public Endpoint endpoint() { + EndpointImpl endpoint = new EndpointImpl(bus, commonService); + endpoint.publish("/CommonService"); + return endpoint; + } +} diff --git a/springboot-cxf/src/main/java/com/xncoding/webservice/model/BaseResponse.java b/springboot-cxf/src/main/java/com/xncoding/webservice/model/BaseResponse.java new file mode 100644 index 0000000..ccc36ca --- /dev/null +++ b/springboot-cxf/src/main/java/com/xncoding/webservice/model/BaseResponse.java @@ -0,0 +1,60 @@ +package com.xncoding.webservice.model; + +/** + * 基础返回类 + * + * @author XiongNeng + * @version 1.0 + * @since 2018/1/7 + */ +public class BaseResponse { + /** + * 是否成功 + */ + private boolean success; + + /** + * 说明 + */ + private String msg; + + /** + * 返回数据 + */ + private T data; + + public BaseResponse() { + + } + + public BaseResponse(boolean success, String msg, T data) { + this.success = success; + this.msg = msg; + this.data = data; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + +} diff --git a/springboot-cxf/src/main/java/com/xncoding/webservice/model/User.java b/springboot-cxf/src/main/java/com/xncoding/webservice/model/User.java new file mode 100644 index 0000000..a5ce00a --- /dev/null +++ b/springboot-cxf/src/main/java/com/xncoding/webservice/model/User.java @@ -0,0 +1,47 @@ +package com.xncoding.webservice.model; + +/** + * 用户 + * + * @author XiongNeng + * @version 1.0 + * @since 2018/3/4 + */ +public class User { + private Long id; + private String name; + private Integer age; + + public User() { + } + + public User(Long id, String name, Integer age) { + this.id = id; + this.name = name; + this.age = age; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } +} diff --git a/springboot-cxf/src/main/java/com/xncoding/webservice/service/ICommonService.java b/springboot-cxf/src/main/java/com/xncoding/webservice/service/ICommonService.java new file mode 100644 index 0000000..d498f2e --- /dev/null +++ b/springboot-cxf/src/main/java/com/xncoding/webservice/service/ICommonService.java @@ -0,0 +1,27 @@ +package com.xncoding.webservice.service; + +import com.xncoding.webservice.model.User; + +import javax.jws.WebMethod; +import javax.jws.WebParam; +import javax.jws.WebService; + +/** + * ICommonService + * + * @author XiongNeng + * @version 1.0 + * @since 2018/6/15 + */ +@WebService(name = "CommonService", // 暴露服务名称 + targetNamespace = "http://model.webservice.xncoding.com/"// 命名空间,一般是接口的包名倒序 +) +public interface ICommonService { + @WebMethod +// @WebResult(name = "String", targetNamespace = "") + public String sayHello(@WebParam(name = "userName") String name); + + @WebMethod +// @WebResult(name = "String", targetNamespace = "") + public User getUser(@WebParam(name = "userName") String name); +} diff --git a/springboot-cxf/src/main/java/com/xncoding/webservice/service/impl/CommonServiceImpl.java b/springboot-cxf/src/main/java/com/xncoding/webservice/service/impl/CommonServiceImpl.java new file mode 100644 index 0000000..73159d3 --- /dev/null +++ b/springboot-cxf/src/main/java/com/xncoding/webservice/service/impl/CommonServiceImpl.java @@ -0,0 +1,32 @@ +package com.xncoding.webservice.service.impl; + +import com.xncoding.webservice.model.User; +import com.xncoding.webservice.service.ICommonService; +import org.springframework.stereotype.Component; + +import javax.jws.WebService; + +/** + * CommonServiceImpl + * + * @author XiongNeng + * @version 1.0 + * @since 2018/6/15 + */ +@WebService(serviceName = "CommonService", // 与接口中指定的name一致 + targetNamespace = "http://model.webservice.xncoding.com/", // 与接口中的命名空间一致,一般是接口的包名倒 + endpointInterface = "com.xncoding.webservice.service.ICommonService"// 接口地址 +) +@Component +public class CommonServiceImpl implements ICommonService { + + @Override + public String sayHello(String name) { + return "Hello ," + name; + } + + @Override + public User getUser(String name) { + return new User(1000L, name, 23); + } +} diff --git a/springboot-cxf/src/main/java/com/xncoding/webservice/util/JacksonUtil.java b/springboot-cxf/src/main/java/com/xncoding/webservice/util/JacksonUtil.java new file mode 100644 index 0000000..1cb864d --- /dev/null +++ b/springboot-cxf/src/main/java/com/xncoding/webservice/util/JacksonUtil.java @@ -0,0 +1,45 @@ +package com.xncoding.webservice.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; + +/** + * JacksonUtil + * + * @author XiongNeng + * @version 1.0 + * @since 2018/3/4 + */ +public class JacksonUtil { + private static ObjectMapper mapper = new ObjectMapper(); + + public static String bean2Json(Object obj) { + try { + return mapper.writeValueAsString(obj); + } catch (JsonProcessingException e) { + e.printStackTrace(); + return null; + } + } + +// public static T json2Bean(String jsonStr, Class objClass) { +// try { +// return mapper.readValue(jsonStr, objClass); +// } catch (IOException e) { +// e.printStackTrace(); +// return null; +// } +// } + + public static T json2Bean(String jsonStr, TypeReference typeReference) { + try { + return mapper.readValue(jsonStr, typeReference); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/springboot-cxf/src/main/resources/application.yml b/springboot-cxf/src/main/resources/application.yml new file mode 100644 index 0000000..dafde37 --- /dev/null +++ b/springboot-cxf/src/main/resources/application.yml @@ -0,0 +1,33 @@ +########################################################## +################## 所有profile共有的配置 ################# +########################################################## + +################### 项目启动端口 ################### +server.port: 8092 + +################### spring配置 ################### +spring: + profiles: + active: dev + +cxf: + path: /services # 替换默认的/services路径 + +logging: + level: + org.springframework.web.servlet: ERROR + +--- + +##################################################################### +######################## 开发环境profile ########################## +##################################################################### +spring: + profiles: dev + +logging: + level: + ROOT: INFO + com: + xncoding: DEBUG + file: E:/logs/app.log diff --git a/springboot-cxf/src/main/resources/banner.txt b/springboot-cxf/src/main/resources/banner.txt new file mode 100644 index 0000000..859b78f --- /dev/null +++ b/springboot-cxf/src/main/resources/banner.txt @@ -0,0 +1,23 @@ + + _____ _______ _____ _____ + /\ \ /::\ \ /\ \ /\ \ + /::\____\ /::::\ \ /::\____\ /::\ \ + /:::/ / /::::::\ \ /:::/ / /::::\ \ + /:::/ / /::::::::\ \ /:::/ / /::::::\ \ + /:::/ / /:::/~~\:::\ \ /:::/ / /:::/\:::\ \ + /:::/ / /:::/ \:::\ \ /:::/____/ /:::/__\:::\ \ + /:::/ / /:::/ / \:::\ \ |::| | /::::\ \:::\ \ + /:::/ / /:::/____/ \:::\____\ |::| | _____ /::::::\ \:::\ \ + /:::/ / |:::| | |:::| | |::| | /\ \ /:::/\:::\ \:::\ \ +/:::/____/ |:::|____| |:::| | |::| | /::\____\/:::/__\:::\ \:::\____\ +\:::\ \ \:::\ \ /:::/ / |::| | /:::/ /\:::\ \:::\ \::/ / + \:::\ \ \:::\ \ /:::/ / |::| | /:::/ / \:::\ \:::\ \/____/ + \:::\ \ \:::\ /:::/ / |::|____|/:::/ / \:::\ \:::\ \ + \:::\ \ \:::\__/:::/ / |:::::::::::/ / \:::\ \:::\____\ + \:::\ \ \::::::::/ / \::::::::::/____/ \:::\ \::/ / + \:::\ \ \::::::/ / ~~~~~~~~~~ \:::\ \/____/ + \:::\ \ \::::/ / \:::\ \ + \:::\____\ \::/____/ \:::\____\ + \::/ / ~~ \::/ / + \/____/ \/____/ + diff --git a/springboot-cxf/src/test/java/com/xncoding/webservice/ApplicationTests.java b/springboot-cxf/src/test/java/com/xncoding/webservice/ApplicationTests.java new file mode 100644 index 0000000..fd5124b --- /dev/null +++ b/springboot-cxf/src/test/java/com/xncoding/webservice/ApplicationTests.java @@ -0,0 +1,97 @@ +package com.xncoding.webservice; + +import com.xncoding.webservice.model.User; +import com.xncoding.webservice.service.ICommonService; +import org.apache.cxf.endpoint.Client; +import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; +import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class ApplicationTests { + @LocalServerPort + private Integer port; + /** + * 接口地址 + */ + private String wsdlAddress; + + @Before + public void prepare() { + wsdlAddress = "http://localhost:" + port + "/services/CommonService?wsdl"; + } + + /** + * 方式1.代理类工厂的方式,需要拿到对方的接口 + */ + @Test + public void cl1() { + try { + // 接口地址 + // 代理工厂 + JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean(); + // 设置代理地址 + jaxWsProxyFactoryBean.setAddress(wsdlAddress); + // 设置接口类型 + jaxWsProxyFactoryBean.setServiceClass(ICommonService.class); + // 创建一个代理接口实现 + ICommonService cs = (ICommonService) jaxWsProxyFactoryBean.create(); + // 数据准备 + String userName = "Leftso"; + // 调用代理接口的方法调用并返回结果 + String result = cs.sayHello(userName); + System.out.println("返回结果:" + result); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 方式2. 动态调用方式 + */ + @Test + public void cl2() { + // 创建动态客户端 + JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); + Client client = dcf.createClient(wsdlAddress); + // 需要密码的情况需要加上用户名和密码 + // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME, PASS_WORD)); + Object[] objects; + try { + // invoke("方法名",参数1,参数2,参数3....); + objects = client.invoke("sayHello", "Leftso"); + System.out.println("返回类型:" + objects[0].getClass()); + System.out.println("返回数据:" + objects[0]); + } catch (java.lang.Exception e) { + e.printStackTrace(); + } + } + + /** + * 方式2. 动态调用方式,返回对象User + */ + @Test + public void cl3() { + // 创建动态客户端 + JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance(); + Client client = dcf.createClient(wsdlAddress); + Object[] objects; + try { + // invoke("方法名",参数1,参数2,参数3....); + objects = client.invoke("getUser", "张三"); + System.out.println("返回类型:" + objects[0].getClass()); + System.out.println("返回数据:" + objects[0]); + User user = (User) objects[0]; + System.out.println("返回对象User.name=" + user.getName()); + } catch (java.lang.Exception e) { + e.printStackTrace(); + } + } + +}