一个简单的连接器(三)

一.运行机制

1. 上一篇中我们简单的实现了服务器的运行机制,但是,分工可以进一步的细化,上一篇中HTTPServer起到两个作用:1. 连接,2. 处理请求;这里我们将其拆分成两个模块:1.连接器,2.处理器

2. 上一篇中,对请求的获取和解析都是在Request中完成的,这里将其拆分成两个模块:

1.获取工具2.解析工具

3.  另外将独立出处理错误消息的模块,用于处理程序产生的错误信息。

4.  增加一个启动模块,作为程序的入口。

 

这样连接器就成为一个独立的模块,这样就大大减轻请求和响应程序的负载,从而提高程序的效率,提高程序的模块化程度;连接器所完成的三个重要功能:1.连接处理 2解析 3产生Request和Response对象

 

二.实战代码

该应用程序所包含的模块:

1.Model模块:将HTTP请求分别抽象成三个类:1.HTTPRequestLine(请求行)2.HTTPHeader(请求头)3.HttpRequestParameters(请求实体)

2.inter模块:Servlet实现统一的标准:1.Servlet接口 2.ServeltRequest接口 3.ServletResponse接口

    3.Util模块:工具类模块:1.Contants工具类  2.Parse工具类 3.StringManager工具类  4.SocketInputStream工具类

     4.Handeler模块:1.RequestFacade2.ResponseFacade类 3.ServletProcessor4.StaticRescourseProcessor

1. HttpConnetor

package Connector;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
/**
 * 连接器
 * @author JayKing
 *
 */
public class HttpConnector implements Runnable {
	boolean stopped=false;
	private String scheme = "http";

	public String getScheme() {
		return scheme;
	}

	@Override
	public void run() {
		ServerSocket serversocket = null;
		int port = 8080;
		try {
			serversocket = new ServerSocket(port, 100, InetAddress.getByName("127.0.0.1"));
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		while (!stopped) {
			Socket socket = null;
			try {
				socket = serversocket.accept();
			} catch (IOException e) {
				continue;
			}
			HttpProcessor processor = new HttpProcessor(this);//频繁创建对象 通过连接池来解决
			processor.process(socket);
		}
	
	}

	public void start() {
		Thread thread = new Thread(this);
		thread.start();
	}

}

2. HttpProcessor

package Connector;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import Handler.ServletProcessor;
import Handler.StaticResourceProcessor;
import Util.Parse;
import Util.SocketInputStream;
/**
 * 处理器
 * @author JayKing
 *
 */
public class HttpProcessor {
	private HttpConnector httpConnector;
	private HttpRequest request;
	private HttpResponse response;

	public HttpProcessor(HttpConnector httpConnector) {
		this.httpConnector = httpConnector;
	}

	/**
	 * 接受请求 实现分流
	 * 
	 * @param socket
	 */
	public void process(Socket socket) {
		SocketInputStream input = null;
		OutputStream output = null;
		try {
			input = new SocketInputStream(socket.getInputStream(), 2048);
			output = socket.getOutputStream();
			request = new HttpRequest(input);
			response = new HttpResponse(output);
			response.setRequest(request);
			response.setHeader("Server", "Pyrmont Servlet container");
			Parse.parseRequestLine(request, input, output);
			Parse.parseHeaders(request, input);
			if (request.getRequestURI().startsWith("/servlet/")) {
				ServletProcessor processor = new ServletProcessor();
				processor.process(request, response);
			} else {
				StaticResourceProcessor processor = new StaticResourceProcessor();
				processor.process(request, response);
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

3. HttpResponse

package Connector;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import Inter.ServletResponse;

/**
 * 响应
 * @author JayKing
 *
 */
public class HttpResponse implements ServletResponse {

	protected HttpRequest request;
	protected String contentType;
	protected HashMap<String, ArrayList<String>> headers = new HashMap<String, ArrayList<String>>();
	protected boolean committed = false;
	private int contentLength = -1;
	public OutputStream output;

	public HttpResponse(OutputStream output) {
		this.output = output;
	}

	public void setRequest(HttpRequest request) {
		this.request = request;

	}

	public void setHeader(String name, String value) {
		if (isCommitted())
			return;

		ArrayList<String> values = new ArrayList<String>();
		values.add(value);
		synchronized (headers) {
			headers.put(name, values);
		}
		String match = name.toLowerCase();
		if (match.equals("content-length")) {
			try {
				contentLength = Integer.parseInt(value);
			} catch (NumberFormatException e) {
				e.printStackTrace();
			}
			if (contentLength >= 0)
				setContentLength(contentLength);
		} else if (match.equals("content-type")) {
			setContentType(value);
		}

	}

	private void setContentType(String value) {
		if (isCommitted())
			return;
		this.contentType = value;
	}

	private void setContentLength(int length) {
		if (isCommitted())
			return;
		this.contentLength = length;

	}

	public boolean isCommitted() {
		return (committed);
	}

}

4. HttpRequest

package Connector;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import Inter.ServletRequest;
import Model.Cookie;
import Model.HttpRequestParameters;

import Util.SocketInputStream;
/**
 * 请求
 * @author JayKing
 *
 */
public class HttpRequest implements ServletRequest {
	private InputStream input;
	private String requestURI;
	private String method;
	private String protocol;
	protected ArrayList<Cookie> cookies = new ArrayList<Cookie>();
	public  HashMap<String, ArrayList<String>> headers = new HashMap<String, ArrayList<String>>();
	public boolean parsed;
	public HttpRequestParameters parameters;

	public boolean isRequestedSessionIdFromCookie() {

		return false;
	}

	public void setRequestedSessionCookie(boolean b) {

	}

	public void setRequestedSessionURL(boolean b) {

	}

	public void setRequestedSessionId(String password) {

	}

	public void setContentLength(int n) {

	}

	public void setContentType(String value) {

	}

	public void setQueryString(String string) {

	}

	public String getMethod() {
		return method;
	}

	public String getProtocol() {
		return protocol;
	}

	public HttpRequest(SocketInputStream input) {
		this.input = input;
	}

	public String getRequestURI() {
		return requestURI;
	}

	public InputStream getInput() {
		return input;
	}

	public void setInput(InputStream input) {
		this.input = input;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public void setProtocol(String protocol) {
		this.protocol = protocol;
	}

	public void setRequestURI(String normalizedUri) {
		this.requestURI = normalizedUri;
	}


	public void addCookie(Cookie cookie) {
		synchronized (cookies) {
			cookies.add(cookie);
		}
	}

	public void addHeader(String name, String value) {
		name = name.toLowerCase();
		synchronized (headers) {
			ArrayList<String> values = (ArrayList<String>) headers.get(name);
			if (values == null) {
				values = new ArrayList<String>();
				headers.put(name, values);
			}
			values.add(value);
		}
	}

	public String getCharacterEncoding() {
		return null;
	}

	public String getQueryString() {
		return null;
	}

	public String getContentType() {
		
		return null;
	}

	public int getContentLength() {
		
		return 0;
	}

}

5. RequestFacade

package Handler;

import Connector.HttpRequest;
import Inter.ServletRequest;
import Inter.ServletResponse;

public class RequestFacade implements ServletRequest {
	private ServletRequest resquest;

	public RequestFacade(HttpRequest request) {
		this.resquest = resquest;
	}

}

6. ResponseFacade

package Handler;

import Connector.HttpResponse;
import Inter.ServletResponse;

public class ResponseFacade implements ServletResponse{
	private ServletResponse response;

	public ResponseFacade(HttpResponse response) {
		this.response = response;
	}

}

7. ServletProcessor

package Handler;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLStreamHandler;
import java.util.HashMap;

import Connector.HttpRequest;
import Connector.HttpResponse;
import Inter.Servlet;
import Inter.ServletRequest;
import Inter.ServletResponse;
import Util.Contants;

public class ServletProcessor {

	public void process(HttpRequest request, HttpResponse response) {
		String uri = request.getRequestURI();
		String ServletName = uri.substring(uri.lastIndexOf("/") + 1);
		ClassLoader classloader = null;
		Class myClass = null;
		String repository = null;
		URLClassLoader loader = null;
		URL[] urls = new URL[1];
		URLStreamHandler streamhandler = null;
		File classPath = new File(Contants.WEB_ROOT);
		try {
			repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();
			urls[0] = new URL(null, repository, streamhandler);
			loader = new URLClassLoader(urls);
			myClass = loader.loadClass(ServletName);
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Servlet servlet = null;
		RequestFacade requestFacade = new RequestFacade(request);
		ResponseFacade responseFacade = new ResponseFacade(response);
		try {
		
			servlet = (Servlet) myClass.newInstance();
			servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade);
		} catch (InstantiationException | IllegalAccessException e) {
			e.printStackTrace();
		}

	}
}

8. StaticRescourceProcessor

package Handler;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import Connector.HttpRequest;
import Connector.HttpResponse;
import Util.Contants;

public class StaticResourceProcessor {
	private static final int BUFFER_SIZE = 1024;

	public void process(HttpRequest request, HttpResponse response) throws IOException {
		byte[] bytes = new byte[BUFFER_SIZE];
		FileInputStream fis = null;
		try {
			File file = new File(Contants.WEB_ROOT, request.getRequestURI());
			if (file.exists()) {
				fis = new FileInputStream(file);
				int ch = fis.read(bytes, 0, BUFFER_SIZE);
				while (ch != -1) {
					response.output.write(bytes, 0, ch);
					ch = fis.read(bytes, 0, BUFFER_SIZE);
				}
			}
		} catch (FileNotFoundException e) {
			response.output.write(Contants.errorMessage.getBytes());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (fis != null)
				fis.close();
		}
	}

}

9. Servlet

package Inter;

public interface Servlet {
   public void init();
   public void service(ServletRequest servletrequest,ServletResponse servletresposne);
   public void destory();
}

10. ServletRequest

package Inter;

public interface ServletRequest {

}

11. ServletResponse

package Inter;

public interface ServletResponse {

}

12. Cookie

package Model;

/**
 * Cookie菜单
 * @author JayKing
 *
 */
public class Cookie {
	public String name;
	public String password;
		
	public Cookie() {
	}

	public Cookie(String username, String password) {
		this.name = username;
		this.password = password;
	}

	public String getName() {
		return name;
	}

	public void setName(String username) {
		this.name = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	

}

13. HttpHeader

package Model;

/**
 * 请求头
 * 
 * @author JayKing
 *
 */
public class HttpHeader {

	public static final int INITIAL_NAME_SIZE = 32;
	public static final int INITIAL_VALUE_SIZE = 64;
	public static final int MAX_NAME_SIZE = 128;
	public static final int MAX_VALUE_SIZE = 4096;
	public char[] name;
	public int nameEnd;
	public char[] value;
	public int valueEnd;
	protected int hashCode = 0;

	public HttpHeader() {
		this(new char[INITIAL_NAME_SIZE], 0, new char[INITIAL_VALUE_SIZE], 0);
	}

	public HttpHeader(char[] name, int nameEnd, char[] value, int valueEnd) {

		this.name = name;
		this.nameEnd = nameEnd;
		this.value = value;
		this.valueEnd = valueEnd;

	}

	public void recycle() {
		nameEnd = 0;
		valueEnd = 0;
		hashCode = 0;
	}

}

14. HttpREquestLine

package Model;

/**
 * 请求方法
 * 
 * @author JayKing
 *
 */
public class HttpRequestLine {

	public static final int MAX_PROTOCOL_SIZE = 1024;
	public static final int MAX_METHOD_SIZE = 1024;
	public static final int MAX_URI_SIZE = 32768;
	private static final int INITIAL_METHOD_SIZE = 1024;
	private static final int INITIAL_URI_SIZE = 64;
	private static final int INITIAL_PROTOCOL_SIZE = 8;


    public char[] method;
    public int methodEnd;
    public char[] uri;
    public int uriEnd;
    public char[] protocol;
    public int protocolEnd;


	public HttpRequestLine() {

		this(new char[INITIAL_METHOD_SIZE], 0, new char[INITIAL_URI_SIZE], 0, new char[INITIAL_PROTOCOL_SIZE], 0);

	}

	public HttpRequestLine(char[] method, int methodEnd, char[] uri, int uriEnd, char[] protocol, int protocolEnd) {

		this.method = method;
		this.methodEnd = methodEnd;
		this.uri = uri;
		this.uriEnd = uriEnd;
		this.protocol = protocol;
		this.protocolEnd = protocolEnd;

	}

	public void recycle() {
		methodEnd = 0;
		uriEnd = 0;
		protocolEnd = 0;
	}

	public int indexOf(char[] buf) {
		return indexOf(buf, buf.length);
	}

	public int indexOf(char[] buf, int end) {
		char firstChar = buf[0];
		int pos = 0;
		while (pos < uriEnd) {
			pos = indexOf(firstChar, pos);
			if (pos == -1)
				return -1;
			if ((uriEnd - pos) < end)
				return -1;
			for (int i = 0; i < end; i++) {
				if (uri[i + pos] != buf[i])
					break;
				if (i == (end - 1))
					return pos;
			}
			pos++;
		}
		return -1;
	}

	public int indexOf(char c, int start) {
		for (int i = start; i < uriEnd; i++) {
			if (uri[i] == c)
				return i;
		}
		return -1;
	}

	public int indexOf(String str) {
		return indexOf(str.toCharArray(), str.length());
	}

	public char[] getMethod() {
		return method;
	}

	public void setMethod(char[] method) {
		this.method = method;
	}

	public int getMethodEnd() {
		return methodEnd;
	}

	public void setMethodEnd(int methodEnd) {
		this.methodEnd = methodEnd;
	}

	public char[] getUri() {
		return uri;
	}

	public void setUri(char[] uri) {
		this.uri = uri;
	}

	public int getUriEnd() {
		return uriEnd;
	}

	public void setUriEnd(int uriEnd) {
		this.uriEnd = uriEnd;
	}

	public char[] getProtocol() {
		return protocol;
	}

	public void setProtocol(char[] protocol) {
		this.protocol = protocol;
	}

	public int getProtocolEnd() {
		return protocolEnd;
	}

	public void setProtocolEnd(int protocolEnd) {
		this.protocolEnd = protocolEnd;
	}

}

15. HttpRequestParameters

package Model;

import java.util.HashMap;

public class HttpRequestParameters extends HashMap {
	private boolean locked = false;

	public HttpRequestParameters() {

	}

	public void setLocked(boolean locked) {
		this.locked = locked;

	}

}

16. BootStarp

package startup;

import Connector.HttpConnector;

public class Bootstrap {
	public static void main(String[] args) {
	    HttpConnector connector = new HttpConnector();
	    connector.start();
	  }
}

17. Contants

package Util;

import java.io.File;
/**
 * 常量类
 * @author JayKing
 *
 */
public class Contants {
	public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";
	public static final String Package = "JayKing.Connector";
	public static final String Config = System.getProperty("user.dir") + File.separator + "config";
	public static final String errorMessage = "HTTP/1.1 404 File Not Found\r\n" + "Content-Type: text/html\r\n"
			+ "Content-Length: 23\r\n" + "\r\n" + "<h1>File Not Found</h1>";
	public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
	public static final int PROCESSOR_IDLE = 0;
	public static final int PROCESSOR_ACTIVE = 1;

}

18. Parse

package Util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import Connector.HttpRequest;
import Model.Cookie;
import Model.HttpHeader;
import Model.HttpRequestLine;
import Model.HttpRequestParameters;

/**
 * 解析类
 * 
 * @author JayKing
 *
 */
public class Parse {
	private static HttpRequestLine requestLine = new HttpRequestLine();
	private static HttpHeader httpheader = new HttpHeader();
	private static HttpRequestParameters results = new HttpRequestParameters();
	protected static StringManager sm = StringManager.getManager("JayKing.connector");

	/**
	 * 解析请求头
	 * 
	 * @param input
	 * @throws IOException
	 */
	public static void parseHeaders(HttpRequest request, SocketInputStream input) throws IOException {
		while (true) {
			input.readHeader(httpheader);
			if (httpheader.nameEnd == 0) {
				if (httpheader.valueEnd == 0) {
					return;
				} else {
					System.out.println(sm.getString("httpProcessor.parseHeaders.colon"));
				}
			}
			String name = new String(httpheader.name, 0, httpheader.nameEnd);
			String value = new String(httpheader.value, 0, httpheader.valueEnd);
			request.addHeader(name, value);
			if (name.equals("cookie")) {
				Cookie cookies[] = parseCookie(value);
				for (int i = 0; i < cookies.length; i++) {
					if (cookies[i].getName().equals("jsessionid")) {
						if (!request.isRequestedSessionIdFromCookie()) {
							request.setRequestedSessionId(cookies[i].getPassword());
							request.setRequestedSessionCookie(true);
							request.setRequestedSessionURL(false);
						}
					}
					request.addCookie(cookies[i]);
				}
			} else if (name.equals("content-length")) {
				int n = -1;
				try {
					n = Integer.parseInt(value);
				} catch (Exception e) {
					System.out.println(sm.getString("httpProcessor.parseHeaders.contentLength"));
				}
				request.setContentLength(n);
			} else if (name.equals("content-type")) {
				request.setContentType(value);
			}
		}

	}

	/**
	 * 解析Cookie
	 * 
	 * @param value
	 * @return
	 */
	private static Cookie[] parseCookie(String value) {

		return null;
	}

	/**
	 * 解析请求行
	 * 
	 * @param input
	 * @param output
	 * @throws IOException
	 */

	public static void parseRequestLine(HttpRequest request, SocketInputStream input, OutputStream output)
			throws IOException {
		input.readRequestLine(requestLine);
		String method = new String(requestLine.method, 0, requestLine.methodEnd);
		String uri = null;
		String protocol = new String(requestLine.protocol, 0, requestLine.protocolEnd);
		if (method.length() < 1) {
			System.out.println("Missing HTTP request method");
		} else if (requestLine.uriEnd < 1) {
			System.out.println("Missing HTTP request URI");
		}
		int question = requestLine.indexOf("?");
		if (question >= 0) {
			request.setQueryString(new String(requestLine.uri, question + 1, requestLine.uriEnd - question - 1));
			uri = new String(requestLine.uri, 0, question);
		} else {
			request.setQueryString(null);
			uri = new String(requestLine.uri, 0, requestLine.uriEnd);
		}
		if (!uri.startsWith("/")) {
			int pos = uri.indexOf("://");
			if (pos != -1) {
				pos = uri.indexOf('/', pos + 3);
				if (pos == -1) {
					uri = "";
				} else {
					uri = uri.substring(pos);
				}
			}
		}

		String match = ";jsessionid=";
		int semicolon = uri.indexOf(match);
		if (semicolon >= 0) {
			String rest = uri.substring(semicolon + match.length());
			int semicolon2 = rest.indexOf(';');
			if (semicolon2 >= 0) {
				request.setRequestedSessionId(rest.substring(0, semicolon2));
				rest = rest.substring(semicolon2);
			} else {
				request.setRequestedSessionId(rest);
				rest = "";
			}
			request.setRequestedSessionURL(true);
			uri = uri.substring(0, semicolon) + rest;
		} else {
			request.setRequestedSessionId(null);
			request.setRequestedSessionURL(false);
		}
		String normalizedUri = normalize(uri);
		((HttpRequest) request).setMethod(method);
		request.setProtocol(protocol);
		if (normalizedUri != null) {
			((HttpRequest) request).setRequestURI(normalizedUri);
		} else {
			((HttpRequest) request).setRequestURI(uri);
		}

		if (normalizedUri == null) {
			System.out.println("Invalid URI: " + uri + "'");
		}

	}

	/**
	 * 解析参数
	 * 
	 * @param request
	 * @throws UnsupportedEncodingException 
	 */
	protected static void parseParameters(HttpRequest request) throws UnsupportedEncodingException {
		if (request.parsed)
			return;
		results.setLocked(false);
		String encoding = request.getCharacterEncoding();
		if (encoding == null)
			encoding = "ISO-8859-1";
		String queryString = request.getQueryString();
		parseParameters(results, queryString, encoding);
		String contentType = request.getContentType();
		if (contentType == null)
			contentType = "";
		int semicolon = contentType.indexOf(':');
		if (semicolon >= 0) {
			contentType = contentType.substring(0, semicolon).trim();
		} else {
			contentType = contentType.trim();
		}
		if ("POST".equals(request.getMethod()) && (request.getContentLength() > 0)
				&& "application/x-www-form-urlencoded".equals(contentType)) {
			try {
				int max = request.getContentLength();
				int len = 0;
				byte buf[] = new byte[request.getContentLength()];
				InputStream is = request.getInput();
				while (len < max) {
					int next = is.read(buf, len, max - len);
					if (next < 0) {
						break;
					}
					len += next;
				}
				is.close();
				if (len < max) {
					throw new RuntimeException("Content length mismatch");
				}
				parseParameters(results, buf, encoding);
			} catch (UnsupportedEncodingException ue) {
				ue.printStackTrace();
			} catch (IOException e) {
				throw new RuntimeException("Content read fail");
			}
		}
		results.setLocked(true);
		request.parsed = true;
		request.parameters = results;
	}

	private static void parseParameters(HttpRequestParameters results, byte[] data, String encoding) throws UnsupportedEncodingException {
		if (data != null && data.length > 0) {
			int pos = 0;
			int ix = 0;
			int ox = 0;
			String key = null;
			String value = null;
			while (ix < data.length) {
				byte c = data[ix++];
				switch ((char) c) {
				case '&':
					value = new String(data, 0, ox, encoding);
					if (key != null) {
						putMapEntry(results, key, value);
						key = null;
					}
					ox = 0;
					break;
				case '=':
					key = new String(data, 0, ox, encoding);
					ox = 0;
					break;
				case '+':
					data[ox++] = (byte) ' ';
					break;
				case '%':
					data[ox++] = (byte) ((convertHexDigit(data[ix++]) << 4) + convertHexDigit(data[ix++]));
					break;
				default:
					data[ox++] = c;
				}
			}

			if (key != null) {
				value = new String(data, 0, ox, encoding);
				putMapEntry(results, key, value);
			}
		}

	}

	private static byte convertHexDigit(byte b) {
		if ((b >= '0') && (b <= '9'))
			return (byte) (b - '0');
		if ((b >= 'a') && (b <= 'f'))
			return (byte) (b - 'a' + 10);
		if ((b >= 'A') && (b <= 'F'))
			return (byte) (b - 'A' + 10);
		return 0;
	}

	private static void parseParameters(HttpRequestParameters results, String data, String encoding) throws UnsupportedEncodingException {
		if ((data != null) && (data.length() > 0)) {
			int len = data.length();
			byte[] bytes = new byte[len];
			data.getBytes(0, len, bytes, 0);
			parseParameters(results, bytes, encoding);
		}

	}

	private static void putMapEntry(Map map, String name, String value) {
		String[] newValues = null;
		String[] oldValues = (String[]) map.get(name);
		if (oldValues == null) {
			newValues = new String[1];
			newValues[0] = value;
		} else {
			newValues = new String[oldValues.length + 1];
			System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
			newValues[oldValues.length] = value;
		}
		map.put(name, newValues);
	}

	/**
	 * 标准化
	 * 
	 * @param path
	 * @return
	 */
	private static String normalize(String path) {
		if (path == null)
			return null;
		String normalized = path;
		if (normalized.startsWith("/%7E") || normalized.startsWith("/%7e"))
			normalized = "/~" + normalized.substring(4);
		if ((normalized.indexOf("%25") >= 0) || (normalized.indexOf("%2F") >= 0) || (normalized.indexOf("%2E") >= 0)
				|| (normalized.indexOf("%5C") >= 0) || (normalized.indexOf("%2f") >= 0)
				|| (normalized.indexOf("%2e") >= 0) || (normalized.indexOf("%5c") >= 0)) {
			return null;
		}

		if (normalized.equals("/."))
			return "/";

		if (normalized.indexOf('\\') >= 0)
			normalized = normalized.replace('\\', '/');
		if (!normalized.startsWith("/"))
			normalized = "/" + normalized;

		while (true) {
			int index = normalized.indexOf("//");
			if (index < 0)
				break;
			normalized = normalized.substring(0, index) + normalized.substring(index + 1);
		}

		while (true) {
			int index = normalized.indexOf("/./");
			if (index < 0)
				break;
			normalized = normalized.substring(0, index) + normalized.substring(index + 2);
		}

		while (true) {
			int index = normalized.indexOf("/../");
			if (index < 0)
				break;
			if (index == 0)
				return (null);
			int index2 = normalized.lastIndexOf('/', index - 1);
			normalized = normalized.substring(0, index2) + normalized.substring(index + 3);
		}

		if (normalized.indexOf("/...") >= 0)
			return (null);

		return (normalized);

	}

}

19. SocketInputStream

package Util;

import java.io.IOException;
import java.io.InputStream;

import Model.HttpHeader;
import Model.HttpRequestLine;

/**
 * 读取类
 * 
 * @author JayKing
 *
 */
public class SocketInputStream extends InputStream {
	private static final byte CR = (byte) '\r';// 首部
	private static final byte LF = (byte) '\n';// 换行 \r\n回到首部换行
	private static final byte SP = (byte) ' ';
	private static final byte HT = (byte) '\t';
	private static final byte COLON = (byte) ':';
	private static final int LC_OFFSET = 'A' - 'a';
	protected byte buf[];// 字节数组
	protected int count = 0;// buf的长度
	protected int pos;// buf的指针
	protected InputStream is;
	protected static StringManager sm = StringManager.getManager(Contants.Package);

	public SocketInputStream(InputStream is, int bufferSize) {

		this.is = is;
		buf = new byte[bufferSize];

	}

	/**
	 * 读取请求头
	 * 
	 * @param header
	 * @throws IOException
	 */
	public void readHeader(HttpHeader header) throws IOException {
		if (header.nameEnd != 0)
			header.recycle();
		int chr = read();
		if ((chr == CR) || (chr == LF)) {
			if (chr == CR)
				read();
			header.nameEnd = 0;
			header.valueEnd = 0;
			return;
		} else {
			pos--;
		}
		int maxRead = header.name.length;
		int readStart = pos;
		int readCount = 0;
		boolean colon = false;
		while (!colon) {
			if (readCount >= maxRead) {
				if ((2 * maxRead) <= HttpHeader.MAX_NAME_SIZE) {
					char[] newBuffer = new char[2 * maxRead];
					System.arraycopy(header.name, 0, newBuffer, 0, maxRead);
					header.name = newBuffer;
					maxRead = header.name.length;
				} else {
					System.out.println(sm.getString("requestStream.readline.toolong"));
				}
			}

			if (pos >= count) {
				int val = read();
				if (val == -1) {
					System.out.println(sm.getString("requestStream.readline.error"));
				}
				pos = 0;
				readStart = 0;
			}
			if (buf[pos] == COLON) {
				colon = true;
			}
			char val = (char) buf[pos];
			if ((val >= 'A') && (val <= 'Z')) {
				val = (char) (val - LC_OFFSET);
			}
			header.name[readCount] = val;
			readCount++;
			pos++;
		}
		header.nameEnd = readCount - 1;
		maxRead = header.value.length;
		readStart = pos;
		readCount = 0;
		int crPos = -2;
		boolean eol = false;
		boolean validLine = true;
		while (validLine) {
			boolean space = true;
			while (space) {
				if (pos >= count) {
					int val = read();
					if (val == -1)
						throw new IOException(sm.getString("requestStream.readline.error"));
					pos = 0;
					readStart = 0;
				}
				if ((buf[pos] == SP) || (buf[pos] == HT)) {
					pos++;
				} else {
					space = false;
				}
			}
			while (!eol) {
				if (readCount >= maxRead) {
					if ((2 * maxRead) <= HttpHeader.MAX_VALUE_SIZE) {
						char[] newBuffer = new char[2 * maxRead];
						System.arraycopy(header.value, 0, newBuffer, 0, maxRead);
						header.value = newBuffer;
						maxRead = header.value.length;
					} else {
						System.out.println(sm.getString("requestStream.readline.toolong"));
					}
				}
				if (pos >= count) {
					int val = read();
					if (val == -1)
						System.out.println(sm.getString("requestStream.readline.error"));
					pos = 0;
					readStart = 0;
				}
				if (buf[pos] == CR) {
				} else if (buf[pos] == LF) {
					eol = true;
				} else {
					int ch = buf[pos] & 0xff;
					header.value[readCount] = (char) ch;
					readCount++;
				}
				pos++;
			}
			int nextChr = read();
			if ((nextChr != SP) && (nextChr != HT)) {
				pos--;
				validLine = false;
			} else {
				eol = false;
				if (readCount >= maxRead) {
					if ((2 * maxRead) <= HttpHeader.MAX_VALUE_SIZE) {
						char[] newBuffer = new char[2 * maxRead];
						System.arraycopy(header.value, 0, newBuffer, 0, maxRead);
						header.value = newBuffer;
						maxRead = header.value.length;
					} else {
						System.out.println(sm.getString("requestStream.readline.toolong"));
					}
				}
				header.value[readCount] = ' ';
				readCount++;
			}
		}
		header.valueEnd = readCount;
	}

	/**
	 * 读取请求行
	 * 
	 * @param requestLine
	 * @throws IOException
	 */

	public void readRequestLine(HttpRequestLine requestLine) throws IOException {
		if (requestLine.methodEnd != 0)
			requestLine.recycle();
		int chr = 0;
		do {
			try {
				chr = read();

			} catch (Exception e) {
				chr = -1;
				System.out.println(sm.getString("requestStream.readline.error"));
			}
		} while ((chr == CR) && (chr == LF));
		pos--;
		int maxRead = requestLine.method.length;
		int readStart = pos;
		int readCount = 0;
		boolean space = false;
		while (!space) {
			if (readCount >= maxRead) {
				if ((2 * maxRead) <= HttpRequestLine.MAX_METHOD_SIZE) {
					char[] newBuffer = new char[2 * maxRead];
					System.arraycopy(requestLine.method, 0, newBuffer, 0, maxRead);
					requestLine.method = newBuffer;
					maxRead = requestLine.method.length;
				} else {
					System.out.println(sm.getString("requestStream.readline.toolong"));
				}
			}
			if (pos >= count) {
				int val = read();
				if (val == -1) {
					System.out.println(sm.getString("requestStream.readline.error"));
				}
				pos = 0;
				readStart = 0;
			}
			if (buf[pos] == SP) {
				space = true;
			}
			requestLine.method[readCount] = (char) buf[pos];
			readCount++;
			pos++;
		}
		requestLine.methodEnd = readCount - 1;
		maxRead = requestLine.uri.length;
		readStart = pos;
		readCount = 0;
		space = false;
		boolean eol = false;
		while (!space) {
			if (readCount >= maxRead) {
				if ((2 * maxRead) <= HttpRequestLine.MAX_URI_SIZE) {
					char[] newBuffer = new char[2 * maxRead];
					System.arraycopy(requestLine.uri, 0, newBuffer, 0, maxRead);
					requestLine.uri = newBuffer;
					maxRead = requestLine.uri.length;
				} else {
					System.out.println(sm.getString("requestStream.readline.toolong"));
				}
			}
			if (pos >= count) {
				int val = read();
				if (val == -1)
					System.out.println(sm.getString("requestStream.readline.error"));
				pos = 0;
				readStart = 0;
			}
			if (buf[pos] == SP) {
				space = true;
			} else if ((buf[pos] == CR) || (buf[pos] == LF)) {
				eol = true;
				space = true;
			}
			requestLine.uri[readCount] = (char) buf[pos];
			readCount++;
			pos++;
		}
		requestLine.uriEnd = readCount - 1;
		maxRead = requestLine.protocol.length;
		readStart = pos;
		readCount = 0;
		while (!eol) {
			if (readCount >= maxRead) {
				if ((2 * maxRead) <= HttpRequestLine.MAX_PROTOCOL_SIZE) {
					char[] newBuffer = new char[2 * maxRead];
					System.arraycopy(requestLine.protocol, 0, newBuffer, 0, maxRead);
					requestLine.protocol = newBuffer;
					maxRead = requestLine.protocol.length;
				} else {
					System.out.println(sm.getString("requestStream.readline.toolong"));
				}
			}
			if (pos >= count) {
				int val = read();
				if (val == -1)
					System.out.println(sm.getString("requestStream.readline.error"));
				pos = 0;
				readStart = 0;
			}
			if (buf[pos] == CR) {
			} else if (buf[pos] == LF) {
				eol = true;
			} else {
				requestLine.protocol[readCount] = (char) buf[pos];
				readCount++;
			}
			pos++;
		}
		requestLine.protocolEnd = readCount;
	}

	/**
	 * 读取一个buf数组,并做判断 必须进行重写
	 */
	public int read() throws IOException {
		if (pos >= count) {
			fill();
			if (pos >= count)
				return -1;
		}
		return buf[pos++] & 0xff;// byte类型转换成int类型保持二进制数一致性
	}

	/**
	 * 读取一个buf数组
	 * 
	 * @throws IOException
	 */
	public void fill() throws IOException {
		pos = 0;
		count = 0;
		int nRead = is.read(buf);
		if (nRead > 0) {
			count = nRead;
		}
	}

	public int available() throws IOException {
		return (count - pos) + is.available();
	}

	public void close() throws IOException {
		if (is == null)
			return;
		is.close();
		is = null;
		buf = null;
	}
}

20. StringManager

package Util;
/**
 * 字符串获取类
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Properties;
public class StringManager {
	private String packagename;
	private static Hashtable managers = new Hashtable();

	private StringManager(String packagename) {
		this.packagename = packagename;
	}

	public synchronized static StringManager getManager(String packagename) {
		StringManager mgr = (StringManager) managers.get(packagename);
		if (mgr == null) {
			mgr = new StringManager(packagename);
		}
		return mgr;
	}

	public String getString(String string) throws IOException {
		Properties p = new Properties();
		InputStream in = new FileInputStream(Contants.Config + File.separator + "LocalStrings.properties");
		p.load(in);
		return p.getProperty(string);
	}

}

三.运行程序

静态资源:打开浏览器在地址栏中输入URL:Http://localhost:8080/index.html

Servlet资源:打开浏览器在地址栏中输入URL:Http://localhost:8080/Servlet/MyServlet




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值