Java模拟实现服务器(Version _1.0)

自己动手写一个服务器,不能说水平会有多大的提升,但是让我知道servlet是如何与服务器进行交互的。现在将简单的模拟实现记录下来。(此处记录的是服务器模拟的简易版本,以后还会写一个利用注解实现的服务器版本)

分析图:

 Request代码:

public class Request {

	private static final String BLANK=" ";
	private static final String CRLF="\r\n";
	
	private String reqInfo;
	private String method;
	private String url;
	private Map<String,List<String>> paremters=new HashMap<>();
	
	public Request(Socket client) throws IOException{
		this(client.getInputStream());
	}
	public Request(InputStream is) throws IOException{
		
		byte[] buf=new byte[1024*1024];
		
		int len=is.read(buf);
		this.reqInfo=new String(buf,0,len);
		
		//解析传入的数据信息
		parseInfo();
	}
	private void parseInfo() {
		//获取第一行数据
		String fristLine=reqInfo.substring(0, reqInfo.indexOf(CRLF)).trim();
		
		//获取请求方式
		this.method=fristLine.substring(0,fristLine.indexOf(BLANK)).trim();
		//声明变量存放请求参数
		String paremter="";
		if("post".equalsIgnoreCase(method)){
			//post
			this.url=fristLine.substring(fristLine.indexOf("/"),fristLine.indexOf("HTTP/1.1")).trim();
			paremter=reqInfo.substring(reqInfo.lastIndexOf(CRLF)).trim();
		}else if("get".equalsIgnoreCase(method)){
			if(fristLine.contains("favicon.ico")){
				return;//此种情况不做处理
			}
			this.url=fristLine.substring(fristLine.indexOf("/"),fristLine.indexOf("?"));
			paremter=fristLine.substring(fristLine.indexOf("?")+1,fristLine.indexOf("HTTp/1.1")).trim();
		}
		//判定参数
		if(paremter==null){
			return;
		}
		//将参数放入map集合中
		parseParemter(paremter);
		
		
	}
	/**
	 * 解析参数,将参数放入集合中
	 * @param paremter
	 */
	private void parseParemter(String paremter) {
		String[] elements=paremter.split("&");
		for(String element:elements){
			String[] kvs=element.split("=");
			String key=kvs[0];
			List<String> values=null;
			if(paremters.containsKey(key)){
				values=paremters.get(key);
				values.add(kvs[1]);
			}else{
				values=new ArrayList<>();
				values.add(kvs[1]);
				paremters.put(key, values);
			}
			
		}
	}
	
	public String getUrl(){
		return url;
	}
	public String getMethod(){
		return method;
	}
	public List<String> getParamters(String name){
		if(paremters.containsKey(name)){
			return paremters.get(name);
		}
		return null;
	}
	 public String getParamter(String name){
		 if(paremters.containsKey(name)){
			 return paremters.get(name).get(0);
		 }
		 return null;
	 }
	
}

Response代码:

public class Response {

	private static final String BLANK="";
	private static final String CRLF="\r\n";
	
	private static OutputStream os=null;
	
	private StringBuffer respHandler;//响应头
	private StringBuffer respContext;//响应实体
	private int len;//响应实体内容的字节数
	
	public Response(Socket client) throws IOException{
		this(client.getOutputStream());
	}
	
	public Response(OutputStream os){
		this.os=os;
		respHandler=new StringBuffer();
		respContext=new StringBuffer();
	}
	/*
	 * 拼装响应头
	 */
	private void createHandler(int code){
		respHandler.append("HTTP1.1").append(BLANK).append(String.valueOf(code)).append(BLANK);
		
		switch (code) {
			case 200:
				respHandler.append("OK");
				break;
			case 404:
				respHandler.append("NOT FOUND");
			case 500:
				respHandler.append("SERVER ERROR");
		}
		
		respHandler.append(CRLF);
		respHandler.append("Content-Type:text/html; charset=GBK").append(CRLF);
		respHandler.append("Date:").append(new Date()).append(CRLF);
		respHandler.append("Server:LAOXUEServer").append(CRLF);
		respHandler.append("Content-Length:").append(this.len).append(CRLF);
		respHandler.append(CRLF);
	}
	/*
	 * 要显示到浏览器上的内容
	 */
	public Response print(String respContext){
		len+=respContext.getBytes().length;
		this.respContext.append(respContext);
		return this;
	}
	/**
	 * 通过流将封装好的响应内容写出到浏览器
	 * @param code
	 * @throws IOException
	 */
	public void pushToClient(int code) throws IOException{
		createHandler(code);
		this.respHandler.append(respContext);
		os.write(respHandler.toString().getBytes());
	}
	
}

 Servlet代码:

public abstract class Servlet {

	public void Service(Request req,Response resp) {
		this.doGet(req, resp);
		this.doPost(req, resp);
	}

	public abstract void doGet(Request req,Response resp);
	public abstract void doPost(Request req,Response resp);
}

WebApp代码:

public class WebApp {

	private Map<String,String> mapping;
	private Map<String,String> servlet;
	public WebApp() {
		mapping =new HashMap<>();
		servlet=new HashMap<>();
		
	}
	public Map<String, String> getMapping() {
		return mapping;
	}
	public void setMapping(Map<String, String> mapping) {
		this.mapping = mapping;
	}
	public Map<String, String> getServlet() {
		return servlet;
	}
	public void setServlet(Map<String, String> servlet) {
		this.servlet = servlet;
	}
}

ServletContext代码:

public class ServletContext {

	//测试数据
	private static WebApp app=new WebApp();
	static{
		app.getMapping().put("/login", "abc");
		app.getMapping().put("/log","abc");
		
		app.getServlet().put("abc","tomcat.controller.LoginServlet");
		
		
	}
	
	public Servlet getServlet(String url) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
		//使用反射技术创建对应的对象
		return (Servlet) Class.forName(app.getServlet().get(app.getMapping().get(url))).newInstance();
	}
}

Server代码:

public class Server {

	public static void main(String[] args) throws IOException {
		//创建server对象
		ServerSocket server=new ServerSocket(8888);
		
		while(true){
			//获取客户端Socket
			Socket client=server.accept();
			new Thread(new Dispatcher(client)).start();
		}
	}
	
}

Dispacher代码:

public class Dispatcher implements Runnable {

	private Request req;
	private Response resp;
	private ServletContext context;
	public Dispatcher(Socket client) {
		try {
			req = new Request(client);
			resp = new Response(client);
			context = new ServletContext();
		} catch (Exception e) {
		}
	}
	@Override
	public void run() {
		String url=req.getUrl();
		if(url!=null && !("".equals(url))){
			try {
				context.getServlet(req.getUrl()).Service(req, resp);
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}
	
}

LoginServlet代码:

public class LoginServlet extends Servlet{

	@Override
	public void doGet(Request req, Response resp) {
		String name=req.getParamter("uname");
		resp.print("<!DOCTYPE html><html><head></head><body><h1>欢迎"+name+"登陆</h1></body></html>");
		try {
			resp.pushToClient(200);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void doPost(Request req, Response resp) {
		
	}

}

代码的组织结构:

前端测试:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>登陆</title>
</head>

<body>

<form action="http://localhost:8888/login" method="post">
用户名:<input type="text" name="uname" />
密码:<input type="password" name="pwd"/>
<input type="submit" value="登陆"/>
</form>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/ToBe_Coder/article/details/82080690