SocketInputStream input = null;
OutputStream output = null;
// Construct and initialize the objects we will need
try {
input = new SocketInputStream(socket.getInputstream(),
connector.getBufferSize());
}
catch (Exception e) {
ok = false;
}
try {
if (ok) {
parseConnection(socket);
parseRequest(input, output);
if (!request.getRequest().getProtocol().startsWith("HTTP/0"))
parseHeaders(input);
parseConnection方法获得协议的值,像HTTP0.9, HTTP1.0或HTTP1.1。如果协议是HTTP1.0,keepAlive设置为false,因为HTTP1.0不支持持久连接。如果在HTTP请求里边找到Expect: 100-continue的头部信息,则parseHeaders方法将把sendAck设置为true。
如果协议是HTTP1.1,并且web客户端发送头部Expect: 100-continue的话,通过调用ackRequest方法它将响应这个头部。它将会测试组块是否是允许的。
if (http11) {
// Sending a request acknowledge back to the client if requested.
ackRequest(output);
// If the protocol is HTTP/1.1, chunking is allowed.
if (connector.isChunkingAllowed())
response.setAllowChunking(true);
}
ackRequest方法测试sendAck的值,并在sendAck为true的时候发送下面的字符串:
if ( "close".equals(response.getHeader("Connection")) ) {
keepAlive = false;
}
// End of request processing
status = Constants.PROCESSOR_IDLE;
// Recycling the request and the response objects
request.recycle();
response.recycle();
}
standard HTTP request headers in character arrays:
static final char[] AUTHORIZATION_NAME = "authorization".toCharArray();
static final char[] ACCEPT_LANGUAGE_NAME = "accept-language".toCharArray();
static final char[] COOKIE_NAME = "cookie".toCharArray();
...
if (header.equals(DefaultHeaders.AUTHORIZATION_NAME)) {
request.setAuthorization(value);
}
else if (header.equals(DefaultHeaders.ACCEPT_LANGUAGE_NAME)) {
parseAcceptLanguage(value);
}
else if (header.equals(DefaultHeaders.COOKIE_NAME)) {
// parse cookie
}
else if (header.equals(DefaultHeaders.CONTENT_LENGTH_NAME)) {
// get content length
}
else if (header.equals(DefaultHeaders.CONTENT_TYPE_NAME)) {
request.setContentType(value);
}
else if (header.equals(DefaultHeaders.HOST_NAME)) {
// get host name
}
else if (header.equals(DefaultHeaders.CONNECTION_NAME)) {
if (header.valueEquals(DefaultHeaders.CONNECTION_CLOSE_VALUE)) {
keepAlive = false;
response.setHeader("Connection", "close");
}
}
else if (header.equals(DefaultHeaders.EXPECT_NAME)) {
if (header.valueEquals(DefaultHeaders.EXPECT_100_VALUE))
sendAck = true;
else
throw new ServletException(sm.getstring
("httpProcessor.parseHeaders.unknownExpectation"));
}
else if (header.equals(DefaultHeaders.TRANSFER_ENCODING_NAME)) {
//request.setTransferEncoding(header);
}
request.nextHeader(); 简单容器的应用程序
本章的应用程序的主要目的是展示默认连接器是怎样工作的。它包括两个类:
ex04.pyrmont.core.SimpleContainer和ex04 pyrmont.startup.Bootstrap。类
SimpleContainer实现了org.apache.catalina.container接口,所以它可以和连接器关联。类Bootstrap是用来启动应用程序的,我们已经移除了第3章带的应用程序中的连接器模块,类ServletProcessor和
StaticResourceProcessor,所以你不能请求一个静态页面。
类SimpleContainer展示在Listing 4.3.
Listing 4.3: The SimpleContainer class
package ex04.pyrmont.core;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
import java.io.File;
import java.io.IOException;
import javax.naming.directory.DirContext;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.catalina.Cluster;
import org.apache.catalina.Container;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Loader;
import org.apache.catalina.Logger;
import org.apache.catalina.Manager;
import org.apache.catalina.Mapper;
import org.apache.catalina.Realm;
import org.apache.catalina.Request;
import org.apache.catalina.Response;
public class SimpleContainer implements Container {
public static final String WEB_ROOT =
System.getProperty("user.dir") + File.separator + "webroot";
public SimpleContainer() { }
public String getInfo() {
return null;
}
public Loader getLoader() {
return null;
}
public void setLoader(Loader loader) { }
public Logger getLogger() {
return null;
}
public void setLogger(Logger logger) { }
public Manager getManager() {
return null;
}
public void setManager(Manager manager) { }
public Cluster getCluster() {
return null;
}
public void setCluster(Cluster cluster) { }
public String getName() {
return null;
}
public void setName(String name) { }
public Container getParent() {
return null;
}
public void setParent(Container container) { }
public ClassLoader getParentClassLoader() {
return null;
}
public void setParentClassLoader(ClassLoader parent) { }
public Realm getRealm() {
return null;
}
public void setRealm(Realm realm) { }
public DirContext getResources() {
return null;
}
public void setResources(DirContext resources) { }
public void addChild(Container child) { }
public void addContainerListener(ContainerListener listener) { }
public void addMapper(Mapper mapper) { }
public void addPropertyChangeListener(
PropertyChangeListener listener) { }
public Container findchild(String name) {
return null;
}
public Container[] findChildren() {
return null;
}
public ContainerListener[] findContainerListeners() {
return null;
}
public Mapper findMapper(String protocol) {
return null;
}
public Mapper[] findMappers() {
return null;
}
public void invoke(Request request, Response response)
throws IoException, ServletException {
string servletName = ( (Httpservletrequest)
request).getRequestURI();
servletName = servletName.substring(servletName.lastIndexof("/") +
1);
URLClassLoader loader = null;
try {
URL[] urls = new URL[1];
URLStreamHandler streamHandler = null;
File classpath = new File(WEB_ROOT);
string repository = (new URL("file",null,
classpath.getCanonicalpath() + File.separator)).toString();
urls[0] = new URL(null, repository, streamHandler);
loader = new URLClassLoader(urls);
}
catch (IOException e) {
System.out.println(e.toString() );
}
Class myClass = null;
try {
myClass = loader.loadclass(servletName);
}
catch (classNotFoundException e) {
System.out.println(e.toString());
}
servlet servlet = null;
try {
servlet = (Servlet) myClass.newInstance();
servlet.service((HttpServletRequest) request,
(HttpServletResponse) response);
}
catch (Exception e) {
System.out.println(e.toString());
}
catch (Throwable e) {
System.out.println(e.toString());
}
}
public Container map(Request request, boolean update) {
return null;
}
public void removeChild(Container child) { }
public void removeContainerListener(ContainerListener listener) { }
public void removeMapper(Mapper mapper) { }
public void removoPropertyChangeListener(
PropertyChangeListener listener) {
}
}
我只是提供了SimpleContainer类的invoke方法的实现,因为默认连接器将会调用这个方法。invoke方法创建了一个类加载器,加载servlet类,并调用它的service方法。这个方法和第3章的ServletProcessor类在哦个的process方法非常类似。
Bootstrap类在Listing 4.4在列出.
Listing 4.4: The ex04.pyrmont.startup.Bootstrap class
package ex04.pyrmont.startup;
import ex04.pyrmont.core.simplecontainer;
import org.apache.catalina.connector.http.HttpConnector;
public final class Bootstrap {
public static void main(string[] args) {
HttpConnector connector = new HttpConnector();
SimpleContainer container = new SimpleContainer();
connector.setContainer(container);
try {
connector.initialize();
connector.start();
// make the application wait until we press any key.
System in.read();
}
catch (Exception e) {
e.printStackTrace();
}
}
}