@WebService @SOAPBinding(style=Style.RPC) public interface IHelloWorld { public String sayHelloWorld(String name); public List<String> getStringList(List<String> strList); public List<User> getUserList(List<User> userList); @XmlJavaTypeAdapter(XMLMapAdapter.class) public Map<String,Object> getMapData(@XmlJavaTypeAdapter(XMLMapAdapter.class) Map<String,Object> data); }
@Repository @WebService(endpointInterface = "net.log_cd.ws.IHelloWorld") public class HelloWorldImpl implements IHelloWorld { @Override public String sayHelloWorld(String name) { return "hi " + name + ", Hello World!"; } @Override public List<String> getStringList(List<String> strList) { return strList; } @Override public List<User> getUserList(List<User> userList) { return userList; } @Override public Map<String, Object> getMapData(Map<String,Object> data) { return data; } }
二、相关POJO
@XmlRootElement(name = "user") @XmlAccessorType(XmlAccessType.FIELD) public class User implements Serializable{ private static final long serialVersionUID = 1L; private String id; private String name; private String password; private Address address; @XmlJavaTypeAdapter(XMLTimestampAdapter.class) private Timestamp registerDate; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Timestamp getRegisterDate() { return registerDate; } public void setRegisterDate(Timestamp registerDate) { this.registerDate = registerDate; } @Override public String toString(){ return "ID:"+this.getId()+"-Name:"+this.getName()+"-Password:"+this.getPassword() +"-Address:"+this.getAddress().toString()+"-RegisterDate:"+this.getRegisterDate(); } }
public class Address implements Serializable { private static final long serialVersionUID = 1L; private String street; private String postcode; public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getPostcode() { return postcode; } public void setPostcode(String postcode) { this.postcode = postcode; } @Override public String toString(){ return this.street+","+this.postcode; } }
@XmlType(name = "MapConvertor") @XmlAccessorType(XmlAccessType.FIELD) public class MapConvertor { private List<MapEntry> entries = new ArrayList<MapEntry>(); public void addEntry(MapEntry entry) { entries.add(entry); } public List<MapEntry> getEntries() { return entries; } public static class MapEntry { private String key; private Object value; public MapEntry() { super(); } public MapEntry(String key, Object value) { super(); this.key = key; this.value = value; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } } }
三、类型转换适配器
/** * adapter: Timestamp to String */ public class XMLTimestampAdapter extends XmlAdapter<String, Timestamp>{ private static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss"; @Override public String marshal(Timestamp time) throws Exception { Date date = new Date(time.getTime()); return new SimpleDateFormat(DEFAULT_FORMAT).format(date); } @Override public Timestamp unmarshal(String timeStr) throws Exception { Date date = new SimpleDateFormat(DEFAULT_FORMAT).parse(timeStr); return new Timestamp(date.getTime()); } }
/** * 通过继承XmlAdapter<ValueType,BoundType>类型,将CXF不能处理的类型进行转换 * valuType是能够处理的类型,boundType是不能处理的类型: * 转化的实质是将不能处理的类型,如Map,定义一个类来模拟Map。 */ public class XMLMapAdapter extends XmlAdapter<MapConvertor, Map<String, Object>> { @Override public MapConvertor marshal(Map<String, Object> map) throws Exception { MapConvertor convertor = new MapConvertor(); for (Map.Entry<String, Object> entry : map.entrySet()) { MapConvertor.MapEntry e = new MapConvertor.MapEntry(entry.getKey(), entry.getValue()); convertor.addEntry(e); } return convertor; } @Override public Map<String, Object> unmarshal(MapConvertor map) throws Exception { Map<String, Object> result = new HashMap<String, Object>(); for (MapConvertor.MapEntry e : map.getEntries()) { result.put(e.getKey(), e.getValue()); } return result; } }
四、发布WebService
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <context:component-scan base-package="net.log_cd.ws"/> <jaxws:server id="helloWorldWebService" serviceClass="net.log_cd.ws.IHelloWorld" address="/helloWorld"> <jaxws:serviceBean> <ref bean="helloWorldImpl"/> </jaxws:serviceBean> </jaxws:server> </beans>
五、配置spring客户端
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <context:component-scan base-package="com.log_cd.ws" /> <!-- org.apache.cxf.bus.spring.SpringBus: under bean name 'cxf' just bound one --> <jaxws:client id="helloClient" serviceClass="net.log_cd.ws.IHelloWorld" address="http://localhost:8080/cxf/ws/helloWorld" /> </beans>
六、测试代码
@ContextConfiguration("classpath:cxf-ws-client.xml") public class CXFWebServiceTest extends AbstractJUnit4SpringContextTests { @Resource private IHelloWorld helloClient; @Ignore public void testInvokeWithJaxWsProxyFactory() { JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(IHelloWorld.class); factory.setAddress("http://localhost:8080/cxf/ws/helloWorld"); IHelloWorld service = (IHelloWorld) factory.create(); System.out.println(service.sayHelloWorld("JaxWsProxyFactory")); } @Ignore public void testInvokeFromApplicationContext() { System.out.println(helloClient.sayHelloWorld("ApplicationContext")); } @Ignore public void testStringList() { List<String> strList = new ArrayList<String>(); strList.addAll(Arrays.asList("lucy,lily,frank,steve".split(","))); List<String> retStrList = helloClient.getStringList(strList); for (String str : retStrList) { System.out.println(str); } } @Ignore public void testUserList() { List<User> userList = new ArrayList<User>(); for (int i = 1; i <= 10; i++) { User user = new User(); user.setId("" + i); user.setName("user_" + i); user.setPassword("password_" + i); user.setRegisterDate(new Timestamp(System.currentTimeMillis())); Address address = new Address(); address.setStreet("street_" + i); address.setPostcode(String.valueOf(Math.round((Math.random() * 1000000f)))); user.setAddress(address); userList.add(user); } List<User> retList = helloClient.getUserList(userList); for (User user : retList) { System.out.println(user.toString()); } } @Test public void testMapData() { Map<String, Object> data = new HashMap<String, Object>(); data.put("name", "vajra"); data.put("weight", "70KG"); data.put("height", "165cm"); data.put("descript", "fat man"); Map<String, Object> retMap = helloClient.getMapData(data); for (Map.Entry<String, Object> entry : retMap.entrySet()) { System.out.println(entry.getKey() + "=" + entry.getValue()); } } }