webservice(五)有关Soap协议的客户端和服务器端的实例代码(基础与进阶)

服务器端代码:

package org.sid.service;


import java.util.List;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;


@WebService(targetNamespace="http://www.sid.com/webservice")
public interface IMyService {
	@WebResult(name="add")
	public int add(@WebParam(name="a")int a,@WebParam(name="b")int b);

	@WebResult(name="user")
	public User addUser(@WebParam(name="user")User user);

	@WebResult(name="user")
	public User login(@WebParam(name="username")String username,
			@WebParam(name="password")String password) throws UserException;

	/**
	 * 设置验证信息
	 * 并且验证信息已头的方式来进行传递,不通过body来传递
	 * @param authInfo
	 * @return
	 */
	@WebResult(name="user")
	public List<User> list(@WebParam(header=true,name="authInfo")String authInfo);
}
package org.sid.service;

import java.util.ArrayList;
import java.util.List;

import javax.jws.HandlerChain;
import javax.jws.WebService;


@WebService(targetNamespace="http://www.sid.com/webservice",endpointInterface="org.sid.service.IMyService")
@HandlerChain(file="handler_chain.xml")
public class MyServiceImpl implements IMyService {
	private static List<User> users =  new ArrayList<User>();
	
	public MyServiceImpl(){
		users.add(new User(1, "admin", "管理员", "admin"));
	}

	@Override
	public int add(int a, int b) {
		System.out.println("a+b="+(a+b));
		return a+b;
	}

	@Override
	public User addUser(User user) {
		users.add(user);
		return user;
	}

	@Override
	public User login(String username, String password) throws UserException{
		for (User user : users) {
			if (username.equals(user.getUsername())&&password.equals(user.getPassword())) {
				return user;
			}
		}
		throw new UserException("用户不存在");
	}

	@Override
	public List<User> list(String authInfo) {
		System.out.println(authInfo);
		return users;
	}

}
package org.sid.service;

import javax.xml.ws.Endpoint;

public class MyServer {

	public static void main(String[] args) {
		Endpoint.publish("http://localhost:8989/ms", new MyServiceImpl());
	}
}
package org.sid.service;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class User {

	private int id;
	private String username;
	private String nickname;
	private String password;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getNickname() {
		return nickname;
	}
	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public User(int id, String username, String nickname, String password) {
		super();
		this.id = id;
		this.username = username;
		this.nickname = nickname;
		this.password = password;
	}
	public User() {
		super();
	}
	
	
}

package org.sid.service;

public class UserException extends Exception {

	public UserException() {
		super();
	}

	public UserException(String arg0, Throwable arg1, boolean arg2, boolean arg3) {
		super(arg0, arg1, arg2, arg3);
	}

	public UserException(String arg0, Throwable arg1) {
		super(arg0, arg1);
	}

	public UserException(String arg0) {
		super(arg0);
	}

	public UserException(Throwable arg0) {
		super(arg0);
	}

}

package org.sid.test;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URL;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPFaultException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.junit.Test;
import org.sid.service.User;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * SAAJ
 * 没有之前的client是因为;之前的是将soap包装了,而这个方法是更底层的soap
 * Soap attachment api for java
 *
 */
public class TestSoap {
	String ns = "http://www.sid.com/webservice";
	String wsdlUrl = "http://localhost:8989/ms?wsdl";

	/**
	 * soap消息的分析和创建
	 */
	@Test
	public void test01(){
		try {
			//1.创建消息工厂
			MessageFactory factory = MessageFactory.newInstance();
			//2.根据消息工厂创建soapMessage
			SOAPMessage message = factory.createMessage();
			//3.创建SoapPart
			SOAPPart part = message.getSOAPPart();
			//4.获取SOAPEnvelope
			SOAPEnvelope envelope = part.getEnvelope();
			//5.可以通过soapEnvelope有效的获取相应的body和header等信息
			SOAPBody body = envelope.getBody();
			//6.根据Qname创建相应的节点(Qname就是一个带有命名空间的节点)
			QName qname = new QName(ns, "add", "ns");
			body.addBodyElement(qname).setValue("123123");
			//如果用一下方式进行设置会将<>转换为<和>
//			body.addBodyElement(qname).setValue("<a>2</a><a>2</a>");
			SOAPBodyElement ele = body.addBodyElement(qname);
			ele.addChildElement("a").setValue("11");
			ele.addChildElement("b").setValue("22");
			//打印消息
			message.writeTo(System.out);
			
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * soap消息的传递和处理
	 * 加入了schema的命名空间问题
	 */
	@Test
	public void test02(){
		try {
			//1.创建服务(Service)
			URL url = new URL(wsdlUrl);
			QName qname = new QName(ns, "MyServiceImplService");
			Service service = Service.create(url, qname);
			
			//2.创建Dispatch
			//Service.Mode.MESSAGE会将<>转换了
			Dispatch<SOAPMessage> dispatch = service.createDispatch(new QName(ns,"MyServiceImplPort"), 
					SOAPMessage.class, Service.Mode.MESSAGE);
			
			//3.创建SOAPMessage
			SOAPMessage msg = MessageFactory.newInstance().createMessage();
			SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
			SOAPBody body = envelope.getBody();
			
			//4.创建Qname来制定消息中传递的数据
			QName ename = new QName(ns,"add","nn");//<nn:add xmlns="xx">
			SOAPBodyElement ele = body.addBodyElement(ename);
			ele.addChildElement("a").setValue("22");
			ele.addChildElement("b").setValue("33");
			msg.writeTo(System.out);
			
			System.out.println("\n invoking……");
			//5.通过Dispatch传递消息
			SOAPMessage response = dispatch.invoke(msg);
			response.writeTo(System.out);
			
			//将响应的消息转换为dom对象
			Document doc = response.getSOAPPart().getEnvelope().getBody().extractContentAsDocument();
			String str = doc.getElementsByTagName("add").item(0).getTextContent();
			System.out.println("\n"+str);
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * payload方式
	 * add用户
	 */
	@Test
	public void test03(){
		try {
			//1.创建服务(Service)
			URL url = new URL(wsdlUrl);
			QName qname = new QName(ns, "MyServiceImplService");
			Service service = Service.create(url, qname);
			
			//2.创建Dispatch,通过Source方式传递
			Dispatch<Source> dispatch = service.createDispatch(new QName(ns,"MyServiceImplPort"), 
					Source.class, Service.Mode.PAYLOAD);
			
			//3.根据用户对象创建相应的xml
			User user = new User(3,"zhangsan","张三","zhangsan");
			JAXBContext ctx = JAXBContext.newInstance(User.class);
			Marshaller mar = ctx.createMarshaller();
			StringWriter writer = new StringWriter();
			//去掉startDocument和endDocument
			mar.setProperty(Marshaller.JAXB_FRAGMENT, true);
			mar.marshal(user, writer);
			
			//4.封装相应的part addUser
			String payload = "<nn:addUser xmlns:nn=\""+ns+"\">"+writer.toString()+"</nn:addUser>";
			System.out.println(payload);
			StreamSource rs = new StreamSource(new StringReader(payload));
			
			//5.通过dispatch传递payload
			Source response = dispatch.invoke(rs);
			
			//6.将Source转换为DOM进行操作,使用Transform对象转换
			Transformer tran = TransformerFactory.newInstance().newTransformer();
			DOMResult result = new DOMResult();
			tran.transform(response, result);

			//7.处理响应信息
			XPath xPath = XPathFactory.newInstance().newXPath();
			NodeList nl = (NodeList) xPath.evaluate("//user", result.getNode(),XPathConstants.NODESET);
			System.out.println(nl.item(0).getNodeName());
			//反编排
			User ru = (User) ctx.createUnmarshaller().unmarshal(nl.item(0));
			System.out.println(ru.getNickname());
			
		} catch (IOException e) {
			e.printStackTrace();
		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		}
	}


	/**
	 * message方式处理list
	 */
	@Test
	public void test04(){
		try {
			//1.创建服务(Service)
			URL url = new URL(wsdlUrl);
			QName qname = new QName(ns, "MyServiceImplService");
			Service service = Service.create(url, qname);
			
			//2.创建Dispatch
			//Service.Mode.MESSAGE会将<>转换了
			Dispatch<SOAPMessage> dispatch = service.createDispatch(new QName(ns,"MyServiceImplPort"), 
					SOAPMessage.class, Service.Mode.MESSAGE);
			
			//3.创建SOAPMessage
			SOAPMessage msg = MessageFactory.newInstance().createMessage();
			SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
			SOAPBody body = envelope.getBody();
			//处理header信息
			SOAPHeader header = envelope.getHeader();
			if (header==null) {
				header = envelope.addHeader();
			}
			QName hname = new QName(ns,"authInfo","nn");
			header.addHeaderElement(hname).setValue("USER");
			
			//4.创建Qname来制定消息中传递的数据
			QName ename = new QName(ns,"list","nn");//<nn:add xmlns="xx">
			SOAPBodyElement ele = body.addBodyElement(ename);
			msg.writeTo(System.out);
			System.out.println("\n invoking……");
			
			//5.通过Dispatch传递消息
			SOAPMessage response = dispatch.invoke(msg);
			response.writeTo(System.out);
			
			//将响应的消息转换为dom对象
			Document doc = response.getSOAPBody().extractContentAsDocument();
			NodeList nl = doc.getElementsByTagName("user");
			JAXBContext ctx = JAXBContext.newInstance(User.class);
			for (int i = 0; i < nl.getLength(); i++) {
				Node n = nl.item(i);
				User u = (User) ctx.createUnmarshaller().unmarshal(n);
				System.out.println(u.getNickname());
			}
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}


	/**
	 * message方式处理login
	 * 加入异常处理方式
	 * 异常这样加入和定义:
	 * <fault message="tns:UserException" name="UserException" wsam:Action="http://www.sid.com/webservice/IMyService/login/Fault/UserException"/>
	 * fault标签要位于output标签之后
	 * 
	 */
	@Test
	public void test05(){
		try {
			//1.创建服务(Service)
			URL url = new URL(wsdlUrl);
			QName qname = new QName(ns, "MyServiceImplService");
			Service service = Service.create(url, qname);
			
			//2.创建Dispatch
			//Service.Mode.MESSAGE会将<>转换了
			Dispatch<SOAPMessage> dispatch = service.createDispatch(new QName(ns,"MyServiceImplPort"), 
					SOAPMessage.class, Service.Mode.MESSAGE);
			
			//3.创建SOAPMessage
			SOAPMessage msg = MessageFactory.newInstance().createMessage();
			SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
			SOAPBody body = envelope.getBody();
			
			//4.创建Qname来制定消息中传递的数据
			QName ename = new QName(ns,"login","nn");//<nn:add xmlns="xx">
			SOAPBodyElement ele = body.addBodyElement(ename);
			ele.addChildElement("username").setValue("ss");
			ele.addChildElement("password").setValue("ss");
			msg.writeTo(System.out);
			System.out.println("\n invoking……");
			
			//5.通过Dispatch传递消息
			SOAPMessage response = dispatch.invoke(msg);
			response.writeTo(System.out);
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SOAPFaultException e) {
			System.out.println(e.getMessage());;
		}
	}
}

服务器端加入handler:

package org.sid.handler;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;

import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class LicenseHandler implements SOAPHandler<SOAPMessageContext> {
	String ns = "http://www.sid.com/webservice";

	@Override
	public void close(MessageContext context) {
	}

	@Override
	public boolean handleFault(SOAPMessageContext context) {
		return false;
	}

	@Override
	public boolean handleMessage(SOAPMessageContext context) {
		System.out.println("=========Server handleMessage=========");
		try {
			//往服务器发信息
			Boolean out = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
			if (!out) {
				SOAPMessage message = context.getMessage();
				//1.判断message中是否存在header
				SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
				SOAPHeader header = envelope.getHeader();
				SOAPBody body = envelope.getBody();
				Node bn = body.getChildNodes().item(0);
				//获取part的name
				String partName = bn.getLocalName();
				if ("list".equals(partName)||"addUser".equals(partName)) {
					System.out.println("list or addUser");
					Iterator<SOAPHeaderElement> iterator = header.examineAllHeaderElements();
					if (header==null||!iterator.hasNext()) {
						//添加一个错误信息
						SOAPFault fault = body.addFault();
						fault.setFaultString("头部信息不能为空");
						throw new SOAPFaultException(fault);
					}else{
						while (iterator.hasNext()) {
							SOAPHeaderElement ele = iterator.next();
							System.out.println(ele.getTextContent());
						}
					}
					message.writeTo(System.out);
				}
			}
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	@Override
	public Set<QName> getHeaders() {
		return null;
	}

}

handler_chain.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains 
	xmlns:javaee="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<javaee:handler-chain>
		<javaee:handler>
			<javaee:handler-class>org.sid.handler.LicenseHandler</javaee:handler-class>
		</javaee:handler>
	</javaee:handler-chain>
</javaee:handler-chains>


客户端代码实例:

先wsimport之后,加入client测试

package com.sid.test;


import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Holder;
import javax.xml.ws.soap.SOAPFaultException;

import com.sid.webservice.IMyService;
import com.sid.webservice.MyServiceImplService;
import com.sid.webservice.User;

public class SoapClient {
	public static void main(String[] args) throws Exception {
		URL url = new URL("http://localhost:9898/ms?wsdl");
		QName qname = new QName("http://www.sid.com/webservice", "MyServiceImplService");
		MyServiceImplService mis = new MyServiceImplService(url,qname);
		IMyService ms = mis.getMyServiceImplPort();
		try {
//			ms.login("admin","admin");
			User u = new User();
			u.setId(1); u.setUsername("123"); u.setPassword("23"); u.setNickname("23");
			Holder<User> user = new Holder<User>(u);
			ms.addUser(user);
		} catch (SOAPFaultException e) {
			System.out.println(e.getMessage());
		}
	}
}

在客户端加入handler,对header进行处理:

package org.sid.handler;

import java.io.IOException;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.w3c.dom.Node;

public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {
	String ns = "http://www.sid.com/webservice";

	@Override
	public void close(MessageContext arg0) {
	}

	@Override
	public boolean handleFault(SOAPMessageContext context) {
		return false;
	}

	/**
	 * 
	 * LogicalHandler只能获得SOAPBody信息
	 * SOAPHandler可以获取SOAPMessage信息
	 * 客户端先处理LogicalHandler
	 * 服务器端先处理SOAPHandler
	 * 1.创建一个类实现SOAPHandler(并加入<SOAPMessageContext>)
	 * 2.在handlerMessage中编写代码
	 * 3.配置Handler
	 * 4.在服务上开启handler(在客户端MyServiceImplService中加上@HandlerChain(file="handler_chain.xml"))
	 * 
	 * 服务器获取
	 * 1.编写handler
	 * 2.在服务器端显示声明一个变量(基于契约优先)
	 */
	@Override
	public boolean handleMessage(SOAPMessageContext context) {
		System.out.println("=========handleMessage=========");
		try {
			//往服务器发信息
			Boolean out = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
			if (out) {
				SOAPMessage message = context.getMessage();
				//1.判断message中是否存在header
				SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
				//2.获取body,判断是partName
				SOAPBody body = envelope.getBody();
				Node node = body.getChildNodes().item(0);
				String partname = node.getLocalName();
				if ("list".equals(partname)||"addUser".equals(partname)) {
					System.out.println("list or addUser");
					SOAPHeader header = envelope.getHeader();
					if (header==null) {
						header = envelope.addHeader();
					}
					QName qname = new QName(ns, "licenseInfo","nn");
					header.addHeaderElement(qname).setValue("123123");
					message.writeTo(System.out);
					System.out.println();
				}
			}
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	@Override
	public Set<QName> getHeaders() {
		return null;
	}

}

名字在wsimport之后的服务器实现(MyServiceImplService)类名之上中添加:

@HandlerChain(file="handler_chain.xml")

handler_chain.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains 
	xmlns:javaee="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<javaee:handler-chain>
		<javaee:handler>
			<javaee:handler-class>org.sid.handler.HeaderHandler</javaee:handler-class>
		</javaee:handler>
	</javaee:handler-chain>
</javaee:handler-chains>










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值