sponseMessage("OK");
String res = response.serializeResponseToString("utf-8");
System.out.println(res);
return response;
}
?
}
在下面的代码中,你能看到ServiceRequest 和DBServiceRequest的执行。请注意随着DBService-Request还提供了一个额外的构造器,它将ServiceRequest作为一个自变量。这就允许我们把原始请求的XML 文档作为当前文档来使用,从而向现有的数据提供一个额外的应用程序特有的界面:
public class ServiceRequest
{
public final static String REQUEST_TYPE_TAG_NAME = "requestType";
public final static String REQUEST_TAG_NAME = "request";
public final static String ROOT_TAG_NAME = "http-request";
protected Document dom;
public ServiceRequest(Document request)
{
dom = request;
}
public ServiceRequest()
{
dom = new DocumentImpl();
initializeRequest();
}
//initializes an empty request
private void initializeRequest()
{
Element root = dom.createElement(ROOT_TAG_NAME);
dom.appendChild(root);
Element eRequestType =
dom.createElement(REQUEST_TYPE_TAG_NAME);
eRequestType.appendChild(dom.createTextNode(""));
root.appendChild(eRequestType);
Element eRequest =
dom.createElement(REQUEST_TAG_NAME);
root.appendChild(eRequest);
}
public String getRequestType()
throws HttpServiceException
{
try
{
return getTextAttribute(REQUEST_TYPE_TAG_NAME);
}
catch(Exception ex)
{
ex.printStackTrace(System.err);
throw new HttpServiceException("Invalid Request Format.");
}
}
public void setRequestType(String requestType)
throws HttpServiceException
{
try
{
setTextAttribute(REQUEST_TYPE_TAG_NAME,requestType);
}
catch(Exception ex)
{
ex.printStackTrace(System.err);
throw new HttpServiceException("Invalid Request Format.");
}
}
public Node getRequest()
throws HttpServiceException
{
try
{
Node request =
((NodeList)dom.getElementsByTagName(REQUEST_TAG_NAME)).item(0);
return request.getFirstChild().cloneNode(true);
}
catch(Exception ex)
{
ex.printStackTrace(System.err);
throw new HttpServiceException("Invalid Request Format.");
}
}
public Element createElementNode(String elementName)
{
return dom.createElement(elementName);
}
public Text createTextNode(String value)
{
return dom.createTextNode(value);
}
public void setRequest(Node request)
throws HttpServiceException
{
try
{
Node requestElement =
((NodeList)dom.getElementsByTagName(REQUEST_TAG_NAME)).item(0);
Node oldRequest =
requestElement.getFirstChild();
if(oldRequest != null)
requestElement.removeChild(oldRequest);
requestElement.appendChild(request);
}
catch(Exception ex)
{
ex.printStackTrace(System.err);
throw new HttpServiceException("Invalid Request Format.");
}
}
public byte[] serializeRequestToByteArray(String encoding)
throws HttpServiceException
{
try
{
return serializeDOM(encoding).toByteArray();
}
catch(Exception ex)
{
ex.printStackTrace(System.err);
throw new HttpServiceException("Error during serialization");
}
}
public String serializeRequestToString(String encoding)
throws HttpServiceException
{
try
{
return serializeDOM(encoding).toString();
}
catch(Exception ex)
{
ex.printStackTrace(System.err);
throw new HttpServiceException(
"Error during serialization");
}
}
private ByteArrayOutputStream serializeDOM(String encoding)
throws HttpServiceException
{
try
{
ByteArrayOutputStream bytes =
new ByteArrayOutputStream (4096);
PrintWriter out = new PrintWriter (new OutputStreamWriter (bytes,encoding),true) ;
OutputFormat of =
new OutputFormat(dom,encoding,true);
XMLSerializer serializer = new XMLSerializer(out,of);
serializer.serialize(dom);
out.close();
return bytes;
}
catch(Exception ex)
{
ex.printStackTrace(System.err);
throw new HttpServiceException("Error during serialization");
}
}
protected String getTextAttribute(String name)
{
Node textAttributeNode = ((NodeList)dom.getElementsByTagName(name)).item(0);
Node textAttribute = textAttributeNode.getFirstChild();
if(textAttribute.getNodeType() == Node.TEXT_NODE)
return textAttribute.getNodeValue();
else
return null;
}
protected void setTextAttribute(String name, String value)
{
if (value == null)
value ="";
Node textAttributeNode =((NodeList)dom.getElementsByTagName(name)).item(0);
Node textAttribute =
textAttributeNode.getFirstChild();
textAttribute.setNodeValue(value);
}
}
public class DBServiceRequest extends ServiceRequest
{
public final static String SERVICE_NAME = "DBService";
public final static String SQL_STATEMENT_TAG_NAME = "sql-statement";
public DBServiceRequest()
{
super();
initializeParameters();
}
public DBServiceRequest(Document request)
{
super(request);
}
public DBServiceRequest(ServiceRequest request)
{
dom = request.dom;
}
public void setSqlStatement(String sql)
{
setTextAttribute(SQL_STATEMENT_TAG_NAME,sql);
}
public String getSqlStatement()
{
return getTextAttribute(SQL_STATEMENT_TAG_NAME);
}
private void initializeParameters()
{
Element eDBRequest = null;
//not very nice but this should never fail
try
{
setRequestType(SERVICE_NAME);
eDBRequest = createElementNode(SQL_STATEMENT_TAG_NAME);
}
catch(Exception ex)
{}
eDBRequest.appendChild(dom.createTextNode(""));
try
{
setRequest(eDBRequest);
}
catch(Exception ex)
{
}
}
扩展框架结构
我们可以对这个框架进行扩展,从而处理任何类型的服务。要想创建一个新的服务,首先必须要定义XML请求和响应的语法。然后,创建ServiceRequest和ServiceResponse的一个子类,它们将帮助处理服务特有的数据。最后,创建Http-ServiceHandler的一个新子类,它将处理请求并生成适当的响应。整个过程就是这样。
虽然这个框架包含了一些功能,但是如果不增加一些更多功能的话,它在实际应用情况下还不是很实用。我有意识地省略了这些功能,以使框架结构保持简单,并将注意力集中到了最重要的细节上。为了完整起见,现在我们来简要分析这个框架结构的一些局限性以及应该如何去克服这些局限性。
首先,这个框架结构不能限制对服务的访问。这就意味着知道如何访问这个服务的每个人都能够进行访问。在你允许对服务的访问之前,请求某种证明可以解决这个问题。你可以用这同一个框架来创建一个证明服务,这样就能确认用户并生成一个唯一的ID,当用户访问任何其它服务时,都会被要求这个ID。系统会将这个ID存储在某些类型的访问列表中,并且要求在一个有限时间内,每个请求都必须通过一个有效ID才能访问服务。
另外,每次用户访问服务时,服务都要创建一个与数据库的连接。将服务与一个连接pooling框架组合起来可以解决这个问题,这样就将给请求分配一个现有连接,而不是每次都创建新连接。
最后一个局限是缺乏session的管理。由于我们是通过一个socket 直接访问servlet,因此不能使用特别有用的HttpSession对象。由于在Web 服务器与浏览器相互作用的过程中,在客户计算机上没有生成session cookie ,因此不能管理自动session。为了克服这个局限,我们可以执行我们自己的session管理。一个session可以是一个与唯一ID相关联的对象,它可以存储其它对象。例如,你可以有一个上下文hash信号表格,在其中存储session对象,使用唯一的ID 作为关键字。这个session对象还可以包含一个hash信号表格,它存储了你想在session中坚持使用的每个对象。
这个框架利用HTTP隧道技术,允许一个桌面应用程序访问防火墙后面的服务,对其进行扩展后还提供对其它类型服务的简易访问。
上一页 [1] [2]