项目中要用到webservice,刚听到的时候还挺开心的,因为我之前接触过,想来应该不是很难,。
谁料,事实不是这样的....,让我费了个好劲啊。
不说了,下面上代码,这是入门级的,所以会比较详细,仔细看:
服务器端:
1、接口+实现类
//接口
package com.ekservice.service;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import com.ek.entry.user.User;
/**
* @author Administrator
* 类说明
*/
@WebService(targetNamespace="http://jeeek-dp/", name="ExampleService")
public interface ExampleService {
@WebResult(name="password")
@WebMethod(action="http://jeeek-dp/ExampleService/getStr")
public User getStr(@WebParam(name="name")String userName);
}
//实现类
package com.ekservice.impl;
import javax.jws.WebService;
import com.ek.entry.user.User;
import com.ekservice.service.ExampleService;
/**
* @author Administrator
* 类说明
*/
@WebService(targetNamespace="http://jeeek-dp/", serviceName="ExampleService", name="ExampleService")
public class ExampleServiceImpl implements ExampleService {
public User getStr(String userName) {
User user = new User();
user.setAddress("北京市海淀区222号");
user.setMobilePhone("010-1101111");
return user;
}
}
2、WS-Security 安全验证 - 过滤器
package com.ekservice.interceptor;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityException;
/**
* @author Administrator
* 类说明
*/
public class ExampleServiceInterceptor implements CallbackHandler{
private Map passwords = new HashMap();
public ExampleServiceInterceptor() {
passwords.put("admin", "password");//此处的对应的是验证信息-用户名+密码,必须与客户端一致才可验证通过
}
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
String identifier = pc.getIdentifier();//用户名
int usage = pc.getUsage();//验证方式
if (usage == WSPasswordCallback.USERNAME_TOKEN) {// 密钥方式USERNAME_TOKEN
if (!passwords.containsKey(identifier)) {
try {
throw new WSSecurityException("User not match - "+identifier);
} catch (WSSecurityException e) {
e.printStackTrace();
}
}
// username token pwd...
// ▲这里的值必须和客户端设的值相同,从cxf2.4.x后校验方式改为cxf内部实现校验,不必自己比较password是否相同
// 请参考:http://cxf.apache.org/docs/24-migration-guide.html的Runtime
// Changes片段
pc.setPassword(passwords.get(identifier));// ▲【这里非常重要】▲
// ▲PS 如果和客户端不同将抛出org.apache.ws.security.WSSecurityException:
// The
// security token could not be authenticated or
// authorized异常,服务端会认为客户端为非法调用
}else if (usage == WSPasswordCallback.SIGNATURE) {// 密钥方式SIGNATURE
if (!passwords.containsKey(identifier)) {
try {
throw new WSSecurityException("User not match - "+identifier);
} catch (WSSecurityException e) {
e.printStackTrace();
}
}
// set the password for client's keystore.keyPassword
// ▲这里的值必须和客户端设的值相同,从cxf2.4.x后校验方式改为cxf内部实现校验,不必自己比较password是否相同;
// 请参考:http://cxf.apache.org/docs/24-migration-guide.html的Runtime
// Changes片段
pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
// ▲PS:如果和客户端不同将抛出org.apache.ws.security.WSSecurityException:The
// security token could not be authenticated or
// authorized异常,服务端会认为客户端为非法调用
}
}
}
}
3、Spring配置文件
4、User.java
package com.ek.entry.user;
import java.io.Serializable;
import java.util.Date;
/**
* @包名 ek.entry.user.po
* @文件名 User.java
* @版本 V 1.0
*/
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String userName; //用户名
private String passWord; //密码
private String address;
private String mobilePhone;
private Date entryTime; //录入时间
private Date updateTime; //更新时间
private String entryUserId; //录入人ID
private String validFlag; //有效标识
private Integer access;
/**
* @return the userName
*/
public String getUserName() {
return userName;
}
/**
* @param userName the userName to set
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* @return the passWord
*/
public String getPassWord() {
return passWord;
}
/**
* @param passWord the passWord to set
*/
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getMobilePhone() {
return mobilePhone;
}
public void setMobilePhone(String mobilePhone) {
this.mobilePhone = mobilePhone;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
/**
* @return the entryTime
*/
public Date getEntryTime() {
return entryTime;
}
/**
* @param entryTime the entryTime to set
*/
public void setEntryTime(Date entryTime) {
this.entryTime = entryTime;
}
/**
* @return the updateTime
*/
public Date getUpdateTime() {
return updateTime;
}
/**
* @param updateTime the updateTime to set
*/
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
/**
* @return the entryUserId
*/
public String getEntryUserId() {
return entryUserId;
}
/**
* @param entryUserId the entryUserId to set
*/
public void setEntryUserId(String entryUserId) {
this.entryUserId = entryUserId;
}
/**
* @return the validFlag
*/
public String getValidFlag() {
return validFlag;
}
/**
* @param validFlag the validFlag to set
*/
public void setValidFlag(String validFlag) {
this.validFlag = validFlag;
}
/**
* @return the id
*/
public int getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(int id) {
this.id = id;
}
public User() {
super();
this.entryTime = new Date();
this.updateTime = new Date();
this.validFlag = "1";
}
/**
* @return the access
*/
public Integer getAccess() {
return access;
}
/**
* @param access the access to set
*/
public void setAccess(Integer access) {
this.access = access;
}
}
至此,服务器端开发完成,启动tomcat即可访问接口,http://localhost:8080/jeeek-dp/services/ExampleService?wsdl
客户端:
1、使用wsdl2java命令生成客户端代码,只保留生成的javabean跟接口即可,其他的文件可以全部删去,,我留下的文件。
2、编写客户端接口访问验证拦截器,只要确保用户名密码与服务器相同即可(我的理解),代码:
package com.ek.client.interceptor;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityException;
/**
* @author
* 类说明
*/
public class ExampleServiceClientInterceptor implements CallbackHandler{
private Map passwords = new HashMap();
public ExampleServiceClientInterceptor() {
passwords.put("admin", "password");
}
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
String identifier = pc.getIdentifier();
int usage = pc.getUsage();
if (usage == WSPasswordCallback.USERNAME_TOKEN) {// 密钥方式USERNAME_TOKEN
System.out.println(passwords.containsKey(identifier)+"="+passwords.get(identifier)+"-"+identifier);
if (!passwords.containsKey(identifier)) {
try {
throw new WSSecurityException("User not match - "+identifier);
} catch (WSSecurityException e) {
e.printStackTrace();
}
}
pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
}else if (usage == WSPasswordCallback.SIGNATURE) {// 密钥方式SIGNATURE
if (!passwords.containsKey(identifier)) {
try {
throw new WSSecurityException("User not match - "+identifier);
} catch (WSSecurityException e) {
e.printStackTrace();
}
}
pc.setPassword(passwords.get(identifier));// //▲【这里非常重要】▲
}
}
}
}
package com.ek.client.call;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ek.client.services.example.ExampleService;
import com.ek.client.services.example.User;
/**
* @author
* 类说明
*/
public class ExampleServiceClient {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-cxf-client.xml");
ExampleService es = (ExampleService) ctx.getBean("service");
User u = es.getStr("ssss");
System.out.println(u.getAddress);
}
}
因为整这个东西费了很多时间,坐下记录。
共勉!