**
其中User为wenservice传输的bean,两端bean中的属性相同
此处使用springboot,所用pom如下
org.springframework.boot
spring-boot-starter-test
test
org.apache.httpcomponents
httpclient
com.alibaba
fastjson
1.1.41
org.springframework.boot
spring-boot-devtools
true
org.apache.cxf
cxf-spring-boot-starter-jaxws
3.1.11
webservice接口:
@WebService(targetNamespace="http://service.webservice.modular.anyu.com")
public interface TestUserService {
@WebMethod//标注该方法为webservice暴露的方法,用于向外公布,它修饰的方法是webservice方法,去掉也没影响的,类似一个注释信息。
@WebMethod
List getUserByAll();
}
webservice接口实现类:
@WebService(serviceName="TestUserService",//对外发布的服务名
targetNamespace="http://service.webservice.modular.anyu.com",//指定你想要的名称空间,通常使用使用包名反转
endpointInterface="com.anyu.modular.webservice.service.TestUserService")//服务接口全路径, 指定做SEI(Service EndPoint Interface)服务端点接口
@Component
public class TestUserServiceImpl implements TestUserService{
@Autowired
BreastCureNodeDao breastCureNodeDao;//dao层,数据库查询
public List getUserByAll(){
return breastCureNodeDao.selectUserByAll();
}
}
BreastCureNode 类 (bean):
@XmlRootElement(name="User")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(propOrder= {""})
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String userName;
private Integer age;
private String six;
private String school;
private Date brithday;
//.......get ....set ....toString省略
}
webservice配置config
@Configuration
public class CxfConfig {
@Autowired
private Bus bus;
@Autowired
TestUserService testUserService;
/**
* 此方法作用是改变项目中服务名的前缀名,此处127.0.0.1或者localhost不能访问时,请使用ipconfig查看本机ip来访问
* wsdl访问地址为:http://127.0.0.1:8080/soap/user?wsdl
* 不用此方法,则访问 : http://127.0.0.1:8080/services/user?wsdl
*/
// @SuppressWarnings("all")
// @Bean
// public ServletRegistrationBean dispatcherServlet() {
// return new ServletRegistrationBean(new CXFServlet(), "/soap/*");
// }
/**
* 方法一
*/
// @Bean(name = Bus.DEFAULT_BUS_ID)
// public SpringBus springBus() {
// return new SpringBus();
// }
//
// @Bean
// public TestUserService testUserService() {
// return new TestUserServiceImpl();
// }
//
// @Bean
// public Endpoint endpoint() {
// EndpointImpl endpoint = new EndpointImpl(springBus(), testUserService());
// endpoint.publish("/user");
// return endpoint;
// }
/**
* 方法二
* 若有多个webservice,将下面方法复制,修改service和publish即可
**/
@Bean
public Endpoint endpoint() {
EndpointImpl endpoint = new EndpointImpl(bus, testUserService);
endpoint.publish("/user/breast");
endpoint.getInInterceptors().add(new AuthInterceptor());//添加用户密码验证,去掉则客户端不需要用户密码验证
return endpoint;
}
}
AuthInterceptor 用户名密码验证:
public class AuthInterceptor extends AbstractPhaseInterceptor{
private static final Logger logger = LoggerFactory.getLogger(AuthInterceptor.class);
private SAAJInInterceptor saa = new SAAJInInterceptor();
private static final String USER_NAME = "admin";
private static final String USER_PASSWORD = "admin";
public AuthInterceptor() {
super(Phase.PRE_PROTOCOL);
getAfter().add(SAAJInInterceptor.class.getName());
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
SOAPMessage mess = message.getContent(SOAPMessage.class);
if (mess == null) {
saa.handleMessage(message);
mess = message.getContent(SOAPMessage.class);
}
SOAPHeader head = null;
try {
head = mess.getSOAPHeader();
} catch (Exception e) {
logger.error("getSOAPHeader error: {}",e.getMessage(),e);
}
if (head == null) {
throw new Fault(new IllegalArgumentException("找不到Header,无法验证用户信息"));
}
NodeList users = head.getElementsByTagName("username");
NodeList passwords = head.getElementsByTagName("password");
if (users.getLength() < 1) {
throw new Fault(new IllegalArgumentException("找不到用户信息"));
}
if (passwords.getLength() < 1) {
throw new Fault(new IllegalArgumentException("找不到密码信息"));
}
String userName = users.item(0).getTextContent().trim();
String password = passwords.item(0).getTextContent().trim();
//可以从数据库获取用户名密码验证,也可以使用固定的用户名,密码
//根据项目需要选择
//固定的用户名和密码 此处为admin admin
if(USER_NAME.equals(userName) && USER_PASSWORD.equals(password)){
logger.debug("admin auth success");
} else {
SOAPException soapExc = new SOAPException("认证错误");
logger.debug("admin auth failed");
throw new Fault(soapExc);
}
}
}
客户端代码:
public class CxfClient {
public static void main(String[] args) {
CxfClient.main1();
CxfClient.main2();
}
/**
* 1.代理类工厂的方式,需要拿到对方的接口地址
*/
public static void main1() {
try {
// 接口地址
String address = "http://192.168.0.100:8081/services/user/breast?wsdl";
// 代理工厂
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
// 设置代理地址
jaxWsProxyFactoryBean.setAddress(address);
// 设置接口类型
jaxWsProxyFactoryBean.setServiceClass(TestUserService.class);
// 创建一个代理接口实现
TestUserService us = (TestUserService) jaxWsProxyFactoryBean.create();
// 数据准备
// 调用代理接口的方法调用并返回结果
String result = us.getUserByAll();
System.err.println("返回结果:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 2:动态调用
*/
public static void main2() {
// 创建动态客户端
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://192.168.0.100:8081/services/user/breast?wsdl");
// 需要密码的情况需要加上用户名和密码
client.getOutInterceptors().add(new ClientLoginInterceptor("admin", "admin"));
Object[] objects = new Object[0];
try {
// invoke("方法名",参数1,参数2,参数3....);
objects = client.invoke("getUserByAll");
List users = (List)objects[0];
for (User user : users) {
System.out.println(user.toString());
}
System.err.println("main2 : 动态调用 : 返回数据:" + objects[0]);
} catch (java.lang.Exception e) {
e.printStackTrace();
}
}
}
客户端User类:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String userName;
private Integer age;
private String six;
private String school;
private Date brithday;
//.......get ....set ....toString省略
}
ClientLoginInterceptor 验证用户名,密码的类:
public class ClientLoginInterceptor extends AbstractPhaseInterceptor
{
public ClientLoginInterceptor(String username, String password)
{
super(Phase.PREPARE_SEND);
this.username = username;
this.password = password;
}
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void handleMessage(SoapMessage soap) throws Fault
{
List headers = soap.getHeaders();
Document doc = DOMUtils.createDocument();
Element auth = doc.createElement("authrity");
Element username = doc.createElement("username");
Element password = doc.createElement("password");
username.setTextContent(this.username);
password.setTextContent(this.password);
auth.appendChild(username);
auth.appendChild(password);
headers.add(0, new Header(new QName("tiamaes"),auth));
}
}
此时基本代码书写完成,启动服务端,输入:http://localhost:8081/services/user/breast?wsdl则可以出现如下页面:
启动客户端: 则会报以下错误:
java.lang.ClassCastException: com.xima.webservice.service.User cannot be cast to com.xima.breast.vo.User
at com.example.demo.CxfClient.main2(CxfClient.java:79)
at com.example.demo.CxfClient.main(CxfClient.java:26)
两个bean类的路径不同,导致映射失败;
将客户端User的路径改为com.xima.webservice.service.User即成功在客户端输出User数据