JaxWs基于消息编程

JaxWs 基于消息编程

1     两种消息模式

2     三种数据类型

2.1     Source

2.2     SOAPMessage

2.3     DataSource

3     服务端访问底层信息

4     客户端访问底层消息

4.1     Dispatch的三种请求方式

5     统一入口

6     注意

6.1     MESSAGE和PAYLOAD的区别

通过SEI(Service Endpoint Interface)在服务端和客户端进行操作时,我们是直接使用的对应实现类或代理类对象。表面上看我们是使用的对象在服务端和客户端进行通讯,而实际上底层还是通过发送消息和解析消息进行的。有时候我们可能会希望或者需要直接访问这些消息,这个时候我们就可以通过Provider和Dispatch来实现了。Provider是应用在服务端的,而Dispatch是应用在客户端的。

1       两种消息模式

在使用Provider和Dispatch时,我们可以使用两种消息模式,MESSAGE和PAYLOAD。

当使用MESSAGE模式时我们可以访问整个的消息,包括绑定的任何header和wrapper。而使用PAYLOAD模式时我们仅仅可以访问payload的消息。如当我们的Dispatch在以PAYLOAD模式工作时,它只能访问到返回的SOAPMessage的body部分,而binding层将处理任何绑定的header和wrapper。

2       三种数据类型

Provider和Dispatch在进行信息传递时只能使用三种数据类型:

l  javax.xml.transform.Source

l  javax.xml.soap.SOAPMessage

l  javax.activation.DataSource

2.1     Source

Source是一个接口,它持有一个XML文档对象。每一个Source接口的实现类都提供了一系列的方法来访问和操纵其持有的XML文档的内容。Source接口的实现类有DOMSource、SAXSource和StreamSource等。

2.2     SOAPMessage

SOAPMessage是一个抽象类,使用SOAPMessage的时候需要满足两个条件:

第一:Provider实现类使用的是SOAP绑定,即SOAPBinding;

第二:Provider实现类使用的是MESSAGE Mode。

SOAPMessage持有一个SOAP消息。

2.3     DataSource

DataSource是一个接口,使用时需要满足以下两个条件:

第一:Provider实现类使用的是Http绑定,即HttpBinding;

第二:Provider实现使用的是MESSAGE Mode。

DataSource是对数据集合的抽象,在适当的时候可以通过InputStream和OutputStream的形式提供对该数据的访问。其实现类有FileDataSource和URLDataSource。

3       服务端访问底层信息

服务端访问底层信息是通过Provider接口进行的。通过实现Provider接口并且把实现类发布为一个WebService,我们就可以在客户端发起请求时访问到其发送过来的底层消息对象,Source、SOAPMessage或者DataSource。Provider接口只定义了一个invoke方法,该方法接收一个消息对象,并返回一个同类型的消息对象,而且消息对象的类型只能是上面介绍的三种类型之一。

在使用Provider的时候我们需要在其实现类上使用@WebServiceProvider进行标记(使用@WebService标记好像也行),并且Provider<T>指定的消息对象类型必须是上面提到的三种数据类型之一。WebService使用的消息模式默认为PAYLOAD,我们可以在Provider实现类上使用@ServiceMode来指定其它值,如@ServiceMode(Service.Mode.MESSAGE)。

下面我们来看一个使用Provider的例子:

Java代码  

  1. import javax.xml.soap.SOAPMessage;
  2. import javax.xml.ws.Provider;
  3. import javax.xml.ws.Service.Mode;
  4. import javax.xml.ws.ServiceMode;
  5. import javax.xml.ws.WebServiceProvider;
  6. @WebServiceProvider(serviceName = "SOAPMessageService", portName = "SOAPMessagePort", targetNamespace = "http://provider.jaxws.sample.cxftest.tiantian.com/")
  7. @ServiceMode(Mode.MESSAGE)
  8. public class SOAPMessageModeProvider implements Provider<SOAPMessage> {
  9. public SOAPMessage invoke(SOAPMessage request) {
  10. SOAPMessage response = null;
  11. try {
  12. System.out.println("客户端以SOAPMessage通过MESSAGE Mode请求如下: ");
  13. request.writeTo(System.out);
  14. response = MessageUtil.getInstance().create(null, "/provider/SOAPMessageResp.xml");
  15. } catch (Exception ex) {
  16. ex.printStackTrace();
  17. }
  18. return response;
  19. }
  20. }

在上面代码中,我们的SOAPMessageModeProvider:

l  实现了Provider接口;

l  通过Provider接口定义的泛型指定使用的消息对象数据类型为SOAPMessage;

l  通过@WebServiceProvider标注其为一个WebService,并指定了serviceName等属性;

l  通过@ServiceMode指定其使用的消息模式为MESSAGE;

l  在invoke方法中接收了一个SOAPMessage,并返回了一个SOAPMessage。

其中MessageUtil类的代码为:

Java代码  

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import javax.xml.soap.MessageFactory;
  4. import javax.xml.soap.MimeHeaders;
  5. import javax.xml.soap.SOAPException;
  6. import javax.xml.soap.SOAPMessage;
  7. public class MessageUtil {
  8. private static MessageUtil instance = new MessageUtil();
  9. private MessageFactory factory;
  10. private MessageUtil() {
  11. try {
  12. factory = MessageFactory.newInstance();
  13. } catch (SOAPException e) {
  14. e.printStackTrace();
  15. thrownew RuntimeException(e);
  16. }
  17. }
  18. public static MessageUtil getInstance() {
  19. returninstance;
  20. }
  21. /**
  22. * 创建一个默认的SOAPMessage
  23. * @return
  24. * @throws SOAPException
  25. */
  26. public SOAPMessage create() throws SOAPException {
  27. returnfactory.createMessage();
  28. }
  29. /**
  30. * 根据MimeHeaders和soap格式文件路径创建一个SOAPMessage
  31. * @param headers
  32. * @param filePath
  33. * @return
  34. * @throws IOException
  35. * @throws SOAPException
  36. */
  37. public SOAPMessage create(MimeHeaders headers, String filePath) throws IOException, SOAPException {
  38. InputStream is = MessageUtil.class.getResourceAsStream(filePath);
  39. SOAPMessage message = factory.createMessage(headers, is);
  40. is.close();
  41. return message;
  42. }
  43. /**
  44. * 获取MessageFactory
  45. * @return
  46. */
  47. public MessageFactory getMessageFactory() {
  48. returnfactory;
  49. }
  50. }

文件SOAPMessageResp.xml的内容为:

Xml代码  

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <SOAP-ENV:Envelope
  3. xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  4. xmlns:xs="http://www.w3.org/2001/XMLSchema"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  6. <SOAP-ENV:Body>
  7. <ns4:sayHiResponse xmlns:ns4="http://provider.jaxws.sample.cxftest.tiantian.com/">
  8. <ns4:responseType>SOAPMessage Response</ns4:responseType>
  9. </ns4:sayHiResponse>
  10. </SOAP-ENV:Body>
  11. </SOAP-ENV:Envelope>

有了Provider实现类之后我们就可以把它发布为一个WebService了,如:

Java代码  

  1. Object service = new SOAPMessageModeProvider();
  2. Endpoint.publish("http://localhost:8080/test/jaxws/services/SOAPMessage", service);

4       客户端访问底层消息

客户端访问底层消息是通过Dispatch接口进行的,跟服务端的Provider接口一样,Dispatch接口中同样定义了一个invoke方法,该方法负责向服务端发送一种数据类型的消息,并返回一个对应类型的消息。不同的是Dispatch接口的实现类可以不需要我们自己定义和实现。我们可以通过创建代表服务端对应WebService对象的Service对象来创建一个Dispatch对象。Service类中定义了一系列的createDispatch重载方法,但比较常用的还是如下方法:

Java代码  

  1. public <T> Dispatch<T> createDispatch(QName portName, Class<T> type, Mode mode)

该方法接收三个参数:

l  第一个参数QName类型的portName代表目标Service中对应的portName;

l  第二个参数表示底层发送和接收消息时使用的数据类型,根据配置的不同可以是前面提到的三种数据类型中的一种;

l  第三个参数表示使用的消息模式。

下面我们来看一个创建Dispatch,并使用它来与服务端进行交互的例子:

Java代码  

  1. public static void main(String args[]) throws Exception {
  2. //定义serviceName对应的QName,第一个参数是对应的namespace
  3. QName serviceName = new QName("http://provider.jaxws.sample.cxftest.tiantian.com/", "SOAPMessageService");
  4. //定义portName对应的QName
  5. QName portName = new QName("http://provider.jaxws.sample.cxftest.tiantian.com/", "SOAPMessagePort");
  6. //使用serviceName创建一个Service对象,该对象还不能直接跟WebService对象进行交互
  7. Service service = Service.create(serviceName);
  8. //创建一个port,并指定WebService的地址,指定地址后我们就可以创建Dispatch了。
  9. service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, "http://localhost:8080/test/jaxws/services/SOAPMessage");
  10. //创建一个Dispatch对象
  11. Dispatch<SOAPMessage> dispatch = service.createDispatch(portName, SOAPMessage.class, Mode.MESSAGE);
  12. //创建一个SOAPMessage
  13. SOAPMessage request = MessageUtil.getInstance().create(null, "/dispatch/SOAPMessageReq.xml");
  14. //调用Dispatch的invoke方法,发送一个SOAPMessage请求,并返回一个SOAPMessage响应。
  15. SOAPMessage response = dispatch.invoke(request);
  16. System.out.println("服务端返回如下: ");
  17. response.writeTo(System.out);
  18. }

在上面的代码中,我们先通过serviceName创建了一个Service对象,然后再通过addPort方法指定其对应的WebService地址。其实,我们也可以像下面这样,通过WebService对应的wsdl文件和serviceName创建对应的Service对象。

Java代码  

  1. //指定wsdl文件的位置
  2. URL wsdl = new URL("http://localhost:8080/test/jaxws/services/SOAPMessage?wsdl");
  3. Service service = Service.create(wsdl, serviceName);

上述例子中对应的SOAPMessageReq.xml文件的内容如下:

Xml代码  

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  3. xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  4. <SOAP-ENV:Body>
  5. <ns4:sayHi xmlns:ns4="http://provider.jaxws.sample.cxftest.tiantian.com/">
  6. <ns4:requestType>SOAPMessage Request</ns4:requestType>
  7. </ns4:sayHi>
  8. </SOAP-ENV:Body>
  9. </SOAP-ENV:Envelope>

4.1         Dispatch的三种请求方式

同步请求

上述Dispatch的invoke方法请求是同步的,也就是阻塞式的,程序在调用了invoke方法之后会一直等待服务端的返回。

异步请求

异步请求是通过Dispatch的invokeAsync方法进行的。Dispatch的异步请求有两种方式,一种是通过定期轮询Dispatch调用invokeAsync方法返回的Response对象是否已经可以返回,另一种是通过回调函数的形式。所以,针对于这两种方式,Dispatch的invokeAsync有两个重载方法:

Java代码  

  1. public Response<T> invokeAsync(T msg);
  2. public Future<?> invokeAsync(T msg, AsyncHandler<T> handler);

使用定期轮询的方式时,我们在执行完invokeAsync之后会返回一个Response对象,该对象会定期轮询判断invokeAsync方法是否已经完成。当invokeAsync方法调用完成之后,Response对象的isDone()方法会返回true,但是这种调用的完成并不一定是成功的完成,有可能是出异常了,或者其他什么问题。在调用完成,也就是isDone()方法的结果为true之后,我们就可以通过Response对象的get()方法尝试获取对应的返回对象了,之所以说是尝试获取,是因为我们的invokeAsync方法不一定是正常的完成了,如果没有正常完成,调用get()方法将抛出异常。上面Dispatch调用的例子如果我们把它改为定期轮询的异步请求的话,其调用过程的代码可以是这样子:

Java代码  

  1. SOAPMessage request = MessageUtil.getInstance().create(null, "/dispatch/SOAPMessageReq.xml");
  2. Response<SOAPMessage> response = dispatch.invokeAsync(request);
  3. System.out.println("开始判断调用是否已完成");
  4. while (!response.isDone()) {
  5. Thread.sleep(200l);
  6. }
  7. SOAPMessage responseMsg = null;
  8. try {
  9. responseMsg = response.get();
  10. } catch (Exception e) {
  11. System.out.println("调用失败");
  12. }
  13. if (responseMsg != null) {
  14. System.out.println("服务端返回如下: ");
  15. responseMsg.writeTo(System.out);
  16. }

使用回调函数的方式时,我们需要给invokeAsync方法传递一个AsyncHandler接口的实现类作为回调对象。AsyncHandler接口中定义了一个handleResponse方法可以处理服务端返回的结果。当请求完成以后,Dispatch后端的线程会调用AsyncHandler对象的handleResponse方法。前面Dispatch调用的例子如果我们把它改为使用回调函数异步调用的话,其核心代码可以是如下这个样子:

Java代码  

  1. SOAPMessage request = MessageUtil.getInstance().create(null, "/dispatch/SOAPMessageReq.xml");
  2. uture<?> future = dispatch.invokeAsync(request, new AsyncHandler<SOAPMessage>() {
  3. @Override
  4. public void handleResponse(Response<SOAPMessage> res) {
  5. try {
  6. System.out.println("回调函数被调用了……");
  7. SOAPMessage responseMsg = res.get();
  8. responseMsg.writeTo(System.out);
  9. } catch (Exception e) {
  10. e.printStackTrace();
  11. }
  12. }
  13. });
  14. System.out.println("可以开始做其他事情了……");
  15. while (!future.isDone()) {
  16. System.out.println("在请求完成之前,整个程序不能结束,否则回调函数不会被调用");
  17. Thread.sleep(200l);
  18. }

注意,在使用回调函数方式使用Dispatch的异步请求时,请求结果未返回前整个程序不能停止。如果在请求结果返回以前,整个程序结束了,回调函数不会被调用。当然这种情况只会出现在如上单次执行的测试环境下,我们经常使用的Web环境是不会出现此问题的。由此看来,回调函数应该是被Dispatch内部的守护线程调用的。

一次请求

一次请求是通过invokeOneWay方法来进行的。它表示我们的客户端只需要发送请求,而不需要等待服务端的返回。

Java代码  

  1. SOAPMessage request = MessageUtil.getInstance().create(null, "/dispatch/SOAPMessageReq.xml");
  2. dispatch.invokeOneWay(request);

5       统一入口

JaxWs基于消息编程的一个好处是我们可以在服务端使用一个Provider来接收和处理所有的WebService请求,使用一个Dispatch或多个Dispatch来发送请求,从而达到对WebService的统一管理;另一个好处是客户端可以不定义或者说是不需要使用SEI接口及其相关的类。下面我们来看一个客户端和服务端之间直接通过消息编程的简单示例。

在服务端定义一个Provider<DOMSource>的实现类UniteServiceProvider。

Java代码  

  1. @WebServiceProvider(serviceName="UniteService", portName="UniteServicePort", targetNamespace="http://provider.jaxws.sample.cxftest.tiantian.com/")
  2. @ServiceMode(Service.Mode.MESSAGE)
  3. @BindingType(HTTPBinding.HTTP_BINDING)
  4. public class UniteServiceProvider implements Provider<DOMSource> {
  5. @Override
  6. public DOMSource invoke(DOMSource request) {
  7. DOMSource response = null;
  8. MessageUtil.getInstance().printSource(request);
  9. Document requestDoc = (Document)request.getNode();
  10. Element commandEle = (Element)requestDoc.getElementsByTagName("command").item(0);
  11. Element paramEle = (Element)requestDoc.getElementsByTagName("param").item(0);
  12. String command = commandEle.getTextContent();
  13. try {
  14. response = this.getResponse(command, paramEle);
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. MessageUtil.getInstance().printSource(response);
  19. return response;
  20. }
  21. /**
  22. * 根据指令和对应的参数进行相关操作并返回对应的操作结果
  23. * @param command
  24. * @param paramEle
  25. * @return
  26. * @throws Exception
  27. */
  28. private DOMSource getResponse(String command, Element paramEle) throws Exception {
  29. String responseContent = "<response><product><id>1</id><name>Apple</name></product></response>";
  30. InputStream is = new ByteArrayInputStream(responseContent.getBytes("UTF-8"));
  31. Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
  32. DOMSource response = new DOMSource(doc);
  33. return response;
  34. }
  35. }

在上述代码中我们的服务端接收到一个DOMSource的request请求之后,通过DOMSource的getNode方法取到存放在其中的Document对象。之后我们对该Document的内容作了一个解析,然后把对应的返回结果封装成一个DOMSource进行返回。

上述使用到的MessageUtil类里面的printSource方法的代码为:

Java代码  

  1. /**
  2. * 输出Source的内容
  3. * @param source
  4. */
  5. public void printSource(Source source) {
  6. StreamResult result = new StreamResult(System.out);
  7. try {
  8. TransformerFactory.newInstance().newTransformer().transform(source, result);
  9. System.out.println();
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }

发布上述Provider的过程这里就不再赘述了。接着来看一下客户端调用的代码:

Java代码  

  1. public class UniteServiceClient {
  2. public static void main(String args[]) throws Exception {
  3. String requestContent = "<request><command>10001</command><parameter><id>1</id></parameter></request>";
  4. InputStream is = new ByteArrayInputStream(requestContent.getBytes("UTF-8"));
  5. Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
  6. DOMSource requestMsg = new DOMSource(doc);
  7. MessageUtil.getInstance().printSource(requestMsg);
  8. QName serviceName = new QName("http://provider.jaxws.sample.cxftest.tiantian.com/", "UniteService");
  9. QName portName = new QName("http://provider.jaxws.sample.cxftest.tiantian.com/", "UniteServicePort");
  10. Service service = Service.create(serviceName);
  11. //指定绑定方式为HTTPBinding
  12. service.addPort(portName, HTTPBinding.HTTP_BINDING, "http://localhost:8080/test/jaxws/services/UniteService");
  13. Dispatch<DOMSource> dispatch = service.createDispatch(portName, DOMSource.class, Mode.MESSAGE);
  14. DOMSource responseMsg = dispatch.invoke(requestMsg);
  15. System.out.println("服务端返回来的信息是:");
  16. MessageUtil.getInstance().printSource(responseMsg);
  17. }
  18. }

6       注意

6.1     MESSAGE和PAYLOAD的区别

在文章的开始部分介绍了两种消息模式,以及它们之间的区别。MESSAGE模式是访问的整个消息,而PAYLOAD模式访问的只是消息的部分内容。我们也知道,当我们使用DOMSource作为消息对象时我们可以使用MESSAGE和PAYLOAD这两种模式。所以接下来我们就来说说使用DOMSource作为消息对象时使用MESSAGE模式和PAYLOAD模式的区别。

为了具有可比性,我们指定使用的BindingType为SOAPBinding,(未指定BindingType时默认也为SOAPBinding),下面来看看使用MESSAGE模式和PAYLOAD模式的区别。

MESSAGE模式

使用MESSAGE模式,我们在发送DOMSource消息对象时,如果我们的DOMSource消息对象里面持有的Document不是一个SOAPPart(SOAPPart是一个实现了Document接口的抽象类),那么系统会先生成一个SOAPPart,然后把我们的DOMSource里面持有的Document作为SOAPPart关联的SOAPEnvelope对象的SOAPBody部分。然后再把该SOAPPart作为DOMSource持有的Document对象。这个时候如果我们只想获取到最原始的document,也就是SOAPBody包裹的那一段文档,我们得这样来取:

Java代码  

  1. public DOMSource invoke(DOMSource request) {
  2. SOAPPart soapPart = (SOAPPart) request.getNode();
  3. try {
  4. SOAPEnvelope soapEnvelop= soapPart.getEnvelope();
  5. SOAPBody soapBody = soapEnvelop.getBody();
  6. Document preDoc = soapBody.extractContentAsDocument();
  7. } catch (SOAPException e1) {
  8. e1.printStackTrace();
  9. }
  10. returnnull;
  11. }

如果DOMSource本身持有的Document对象就是一个SOAPPart的话就可以直接发送了,不需要再做转换了。当我们的DOMSource持有的不是一个SOAPPart时,系统在生成SOAPPart时很可能会抛出异常信息:HIERARCHY_REQUEST_ERR: 尝试在不允许的位置插入节点。所以当我们配合使用SOAPBinding、DOMSource消息对象和MESSAGE模式时,我们最好给DOMSource传入一个SOAPPart对象或者是SOAPPart格式的Document对象。

PAYLOAD模式

使用PAYLOAD模式时,我们发送的DOMSource消息会直接发送过去。对方接收到的内容和发送时的内容是一样的,注意只是内容是一样的,其持有的Document对象还是会当做一个普通的Document对象处理,如DocumentImpl。比如发送的时候DOMSource持有的是一个SOAPPart,那么接收的时候接收到的DOMSource里面的Document的内容还是发送时SOAPPart的内容,但是对象却是一个普通的Document对象,而不是发送时的SOAPPart对象;而如果发送的时候发送的是一个普通的Document对象,那么接收到的内容也只是一个普通Document的内容,不会像MESSAGE模式那样会有多余的SOAPHeader等信息。

时间: 2024-11-03 18:44:34

JaxWs基于消息编程的相关文章

基于消息的软件架构模型演变

一个优秀的架构师总是能对各种解决方案的优点和对应成本之间取得良好的平衡,而这种能力背后是架构师丰富的经验和广阔的知识体系.基于消息的软件建构模型则是架构师必备的知识点,本文将详细描述该模型的演变过程. 还记得第一次跟公司的软件架构师打交道,他问我"Hi ABC,你的功能设计的怎么样了?"我有点不以为然,不就是个很小的功能么,为什么要用"设计"一词,为什么不是"你的代码写的怎么样了?".我后来明白了,"设计"一词代表了他对软件的

TCP/IP网络编程 基于Linux编程_2 --I/O流分离的半关闭问题

理论基础 流:调用fopen打开文件后进行文件读写操作会创建流,套接字网络通信也会创建流,流是以数据收发为目的的一种桥梁,其实就是指数据的流动,我们可以理解为数据收发的路径. I/O流分离:是指把数据的发送与接收流分开处理,由2个不同对象控制而不是交个1个对象.我们之前讲过2种I/O流分离的方法,第一种:通过调用fork函数创建子进程,父进程负责接收数据,子进程负责发送数据(学习笔记_11).第二种:通过2次fdopen函数的调用,创建读模式FILE指针与写模式FILE指针(基于Linux编程_

基于消息的异步套接字

Windows套接字在两种模式下执行I/O操作,阻塞模式和非阻塞模式.在阻塞模式下,执行操作的函数会一直等待,不会立即返回,知道发送完数据或者接受完数据为止.这在一定条件下是对性能的浪费,例如recvfrom函数没有收到数据的时候吧就会一直等待下去. 为了提高系统的性能,Winsock提供了基于消息的异步socket.下面介绍主要的Socket异步通信函数. <1>int       WSASyncSelect(SOCKET s,HWND hwnd,unsigned int uMsg,long

WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化

在本篇文章中,我们将讨论WCF四大契约(服务契约.数据契约.消息契约和错误契约)之一的消息契约(Message Contract).服务契约关注于对服务操作的描述,数据契约关注于对于数据结构和格式的描述,而消息契约关注的是类型成员与消息元素的匹配关系. 我们知道只有可序列化的对象才能通过服务调用在客户端和服务端之间进行传递.到目前为止,我们知道的可序列化类型有两种:一种是应用了System.SerializableAttribute特性或者实现了System.Runtime.Serializat

基于对象编程与面向对象编程(表达式计算器3)

基于对象编程与面向对象编程 我们的最终目的是用C++设计一个面向对象的表达式计算器,所以非常有必要弄清楚,什么是基于对象编程和面向对象的编程.而要弄清楚这一点,又要先弄明白什么是值语言,什么是对象语义 值语义:对象的拷贝与原对象无关,拷贝后与原对象脱离关系,互不影响.这种拷贝叫深拷贝.拷贝之后脱离关系,只要在拷贝的时候都为对象分配内存空间就行了.某种些情况下算是一种对资源的浪费 值语义例子 class Test { private: int * pNum_; public: Test(int n

C++学习之路: 线程封装(基于对象编程)

引言: 此次我们重新封装线程, 采用基于对象编程的方式,不用于面向对象编程中重定义虚函数的方式,这里我们用回调函数的方式. Thread.h 1 #ifndef THREAD_H_ 2 #define THREAD_H_ 3 4 #include <boost/noncopyable.hpp> 5 #include <functional> 6 #include <pthread.h> 7 8 class Thread : boost::noncopyable 9 {

基于消息系统架构设计

近期在弄一个业务系统,这个业务系统原本是有一个架构的,可是在后期扩展时发现问题多多.关键扩展非常不方便,并且由于业务系统安全规格较高.数据网络连接须要通过多个闸口传递才可,并且业务系统可能须要多地系统联合组网.共享业务数据,可是各地系统又必须相互独立. 用户希望改动架构,让系统可扩展性添加,同一时候要满足系统相互独立方便升级和兴许开发. 依照用户的要求我考虑使用一个基于消息传递的架构设计来满足需求. 所谓基于消息,就是通过消息中转server,中转全部系统间连接数据,同一时候管理数据路由,由消息

分享一个自己用的基于mvc编程工作管理

前言: 最近在家没事学习下mvc,正好把以前用webform写的一个帮助自己编码的工具重构成了mvc,另外根据自己的编程工作感悟添加了公司常用软件维护 ,数据库操作记录这些新功能. 技术没什么高深的技术,就是mvc+jquery easyUi+简单的三层,生成文档的模板引擎用的Razor. 主要还是解决沟通成本太高的问题,都是根据工作中遇到的问题慢慢解决的,至少很多功能可以解决小型软件团队很多流程问题,自己摸索真是又痛苦又快乐.相信也有很多朋友和我一样没有去过大型软件公司,很多问题只能看别人的文

《Essential C++》读书笔记 之 基于对象编程风格

<Essential C++>读书笔记 之 基于对象编程风格 2014-07-13 4.1 如何实现一个class 4.2 什么是Constructors(构造函数)和Destructors(析构函数) 4.3 何谓mutable(可变)和const(不变) 4.4 什么是this指针 4.5 Static Class Member(静态的类成员) 4.6 打造一个Iterator Class 4.7 合作关系必须建立在友谊的基础上 4.8 实现一个copy assignment operat