zoukankan      html  css  js  c++  java
  • 不使用tomcat,仅适用javaSE手写服务器--模拟登陆

    1、搭建框架

    我们只是简单模拟,框架简单分三个模块
    

    a,服务器端server包
    

    b,servlet,根据不同的请求url,利用反射生产对应的servlet
    

    c,IO工具包,用来关闭IO流
    

        d,编写web.xml
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app>
    	<servlet>
    		<servlet-name>login</servlet-name>
    		<servlet-class>com.xzlf.servlet.LoginServlet</servlet-class>
    	</servlet>
    	<servlet>
    		<servlet-name>register</servlet-name>
    		<servlet-class>com.xzlf.servlet.RegisterServlet</servlet-class>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>login</servlet-name>
    		<url-pattern>/login</url-pattern>	
    		<url-pattern>/log</url-pattern>	
    	</servlet-mapping>
    	<servlet-mapping>
    		<servlet-name>register</servlet-name>
    		<url-pattern>/register</url-pattern>	
    		<url-pattern>/reg</url-pattern>	
    		<url-pattern>/r</url-pattern>	
    	</servlet-mapping>
    </web-app>
    
    e,写一个简单的html用于测试
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>登录</title>
    </head>
    <body>
    	<form action="http://localhost:8888/log" method="get">
    		<p>
    			用户名:<input type="text" name="uname" id="uname" />
    		</p>
    		<p>
    			密码:<input type="password" name="pwd" id="pwd" />
    		</p>
    		<p>
    			<input type="submit" value="登录" />
    		</p>
    	</form>
    </body>
    </html>
    
        f, IO工具包比比较简单,先写了:
    
    package com.xzlf.util;
    
    import java.io.Closeable;
    import java.io.IOException;
    
    /**
     * 关闭流
     * @author xzlf
     *
     */
    public class IOUtil {
    	public static void closeAll(Closeable...closeables) {
    		for (Closeable close : closeables) {
    			if(close != null) {
    				try {
    					close.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    			
    		}
    	}
    }
    
    

    2、编写xml文件以及对xml解析以及数据存储程序

    a,编写存放xml文件中servlet-name 和 servlet-class 的javabean 对象Entity
    
    package com.xzlf.server;
    
    /**
     * 映射servlet-name 和 servlet-class
     * @author xzlf
     *
     */
    public class Entity {
    	// servlet-name
    	private String name;
    	
    	// servlet -class
    	private String clazz;
    	
    	public Entity() {
    		// TODO Auto-generated constructor stub
    	}
    
    	public Entity(String name, String clazz) {
    		super();
    		this.name = name;
    		this.clazz = clazz;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public String getClazz() {
    		return clazz;
    	}
    
    	public void setClazz(String clazz) {
    		this.clazz = clazz;
    	}
    	
    }
    
    
    b,编写存放xml文件中servlet-name 和 url-pattern 的javabean 对象Mapping
    
    package com.xzlf.server;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 映射 servlet-name  和 url-pattern
     * @author xzlf
     *
     */
    public class Mapping {
    
    	// servlet-name
    	private String name;
    	
    	// url-pattern
    	private List<String> urlList;
    	
    	public Mapping() {
    		this.urlList = new ArrayList<String>();
    	}
    
    	public Mapping(String name, List<String> urlList) {
    		this();
    		this.name = name;
    		this.urlList = urlList;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public List<String> getUrlList() {
    		return urlList;
    	}
    
    	public void setUrlList(List<String> urlList) {
    		this.urlList = urlList;
    	}
    	
    }
    
    
    c,编写解析xml文件(使用Dom4j)的程序
    
    package com.xzlf.server;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    import org.dom4j.Document;
    import org.dom4j.DocumentException;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    /**
     * 解析xml
     * @author xzlf
     *
     */
    public class WebDom4j {
    	// 存储Entity
    	private List<Entity> entityList;
    	
    	// 存储Mapping
    	private List<Mapping> mappingList;
    	
    	public WebDom4j() {
    		this.entityList = new ArrayList<Entity>();
    		this.mappingList = new ArrayList<Mapping>();
    	}
    
    	public WebDom4j(List<Entity> entityList, List<Mapping> mappingList) {
    		this();
    		this.entityList = entityList;
    		this.mappingList = mappingList;
    	}
    
    	public List<Entity> getEntityList() {
    		return entityList;
    	}
    
    	public void setEntityList(List<Entity> entityList) {
    		this.entityList = entityList;
    	}
    
    	public List<Mapping> getMappingList() {
    		return mappingList;
    	}
    
    	public void setMappingList(List<Mapping> mappingList) {
    		this.mappingList = mappingList;
    	}
    	
    	public Document getDocument() {
    		Document doc = null;
    		try {
    			// 1、穿件SAXReader 对象
    			SAXReader reader = new SAXReader();
    			// 2、调用 read() 方法
    			doc = reader.read(new File("src/WEB_INFO/webxml.xml"));
    		} catch (DocumentException e) {
    			e.printStackTrace();
    		}
    		return doc;
    	}
    	
    	
    	public void parse(Document doc) {
    		// 1、获取根元素
    		Element rootElement = doc.getRootElement();
    		// 2、获取servlet 子元素
    		for(Iterator<Element> elementIterator = rootElement.elementIterator("servlet");
    				elementIterator.hasNext();) {
    			Element ele = elementIterator.next();
    			Entity entity = new Entity();
    			for (Iterator<Element> eleIterator = ele.elementIterator(); eleIterator.hasNext();) {
    				Element e = eleIterator.next();
    				if("servlet-name".equals(e.getName())) {
    					entity.setName(e.getText());
    				}else if("servlet-class".equals(e.getName())) {
    					entity.setClazz(e.getText());
    				}
    			}
    			this.entityList.add(entity);
    		}
    		// 3、获取servlet-mapping 子元素
    		for(Iterator<Element> elementIterator = rootElement.elementIterator("servlet-mapping");
    				elementIterator.hasNext();) {
    			Element ele = elementIterator.next();
    			Mapping mapping = new Mapping();
    			for (Iterator<Element> eleIterator = ele.elementIterator(); eleIterator.hasNext();) {
    				Element e = eleIterator.next();
    				if("servlet-name".equals(e.getName())) {
    					mapping.setName(e.getText());
    				}else if("url-pattern".equals(e.getName())) {
    					mapping.getUrlList().add(e.getText());
    				}
    			}
    			this.mappingList.add(mapping);
    		}
    	}
    	
    	/* 测试
    	 * public static void main(String[] args) {
    		WebDom4j web = new WebDom4j();
    		web.parse(web.getDocument());
    		List<Entity> entityList2 = web.getEntityList();
    		System.out.println(entityList2.size());
    		for (Entity entity : entityList2) {
    			System.out.println(entity.getName() + "--" + entity.getClazz());
    		}
    		System.out.println("============================");
    		List<Mapping> mappingList2 = web.getMappingList();
    		System.out.println(mappingList2.size());
    		for (Mapping mapping : mappingList2) {
    			for (String url : mapping.getUrlList()) {
    				System.out.println(mapping.getName() + "-->" + url);
    			}
    			System.out.println("------------------------");
    		}
    	}*/
    }
    
    
    d,封装serlvet 和mapping 
    
    package com.xzlf.server;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Servlet 上下文 ,就是一个容器
     * 映射 Mapping 和 Entity 
     * url-pattern --> servlet-class
     * @author xzlf
     *
     */
    public class ServletContext {
    	// key:sevlet-name value:servlet-class
    	private Map<String, String> servlet;
    	
    	// key:url-pattern value:servlet-name
    	private Map<String, String> mapping;
    	
    	public ServletContext() {
    		this.servlet = new HashMap<String, String>();
    		this.mapping = new HashMap<String, String>();
    	}
    
    	public ServletContext(Map<String, String> servlet, Map<String, String> mapping) {
    		this.servlet = servlet;
    		this.mapping = mapping;
    	}
    
    	public Map<String, String> getServlet() {
    		return servlet;
    	}
    
    	public void setServlet(Map<String, String> servlet) {
    		this.servlet = servlet;
    	}
    
    	public Map<String, String> getMapping() {
    		return mapping;
    	}
    
    	public void setMapping(Map<String, String> mapping) {
    		this.mapping = mapping;
    	}
    	
    	
    }
    
    
    e,处理Entity 和 Maping 找出url 和 servlet-class 的映射
    
    package com.xzlf.server;
    
    import java.util.List;
    import java.util.Map;
    
    import com.xzlf.servlet.Servlet;
    
    /**
     * Web应用程序
     * @author xzlf
     *
     */
    public class WebApp {
    	private static ServletContext context;
    	static {
    		context = new ServletContext();
    		// 获取对应的map关系
    		Map<String, String> servlet = context.getServlet();
    		Map<String, String> mapping = context.getMapping();
    		// 创建xml解析
    		WebDom4j web = new WebDom4j();
    		web.parse(web.getDocument());
    		// 获取解析xml 之后的List集合
    		List<Entity> entityList = web.getEntityList();
    		List<Mapping> mappingList = web.getMappingList();
    		
    		// 将List集合中的数据存储到Map中
    		for(Entity entity : entityList) {
    			servlet.put(entity.getName(), entity.getClazz());
    		}
    		
    		for (Mapping mapp : mappingList) {
    			for (String url : mapp.getUrlList()) {
    				mapping.put(url, mapp.getName());
    			}
    		}
    		
    	}
    	
    	/**
    	 * 根据不同的url创建不同的servlet对象
    	 * @param url
    	 * @return
    	 */
    	public static Servlet getServlet(String url) {
    		if(url == null || url.trim().equals("")) {
    			return null;
    		}
    		
    		try {
    			String servletName = context.getMapping().get(url);
    			String servletClazz = context.getServlet().get(servletName);
    //			System.out.println(servletName + "--" + servletClazz);
    			Class<?> clazz = Class.forName(servletClazz);
    			Object servlet = clazz.newInstance();
    			return (Servlet) servlet;
    		} catch (ClassNotFoundException e) {
    			e.printStackTrace();
    		} catch (InstantiationException e) {
    			e.printStackTrace();
    		} catch (IllegalAccessException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    	/*测试
    	public static void main(String[] args) {
    		System.out.println(getServlet("/log"));
    		System.out.println(getServlet("/reg"));
    	}
    	*/
    }
    
    

    3、封装请求数据request:包括请求的url,请求参数

    package com.xzlf.server;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * 封装请求
     * @author xzlf
     *
     */
    public class Request {
    	private InputStream is;
    	private String requestInfo;
    	private String method;
    	private String url;
    	private Map<String, List<String>> parameterValues;
    	private static final String BLANK = " ";
    	private static final String CRLF = "
    ";
    	
    	public Request() {
    		this.parameterValues = new HashMap<String, List<String>>();
    	}
    
    	public Request(InputStream is) {
    		this();
    		this.is = is;
    		BufferedReader read = null;
    		char[] buf = new char[20480];
    		int len;
    		try {
    			read = new BufferedReader(new InputStreamReader(is, "utf8"));
    			if ((len = read.read(buf)) != -1) {
    				requestInfo = new String(buf, 0, len);
    			}
    		} catch (IOException e) {
    			requestInfo = "";
    			return;
    		}
    		this.parseRequestInfo();
    	}
    
    
    	private void parseRequestInfo() {
    		if(this.requestInfo.equals("")) {
    			return;
    		}
    		int index = this.requestInfo.indexOf('/');
    		this.method = this.requestInfo.substring(0,index - 1).toLowerCase();
    		int end = this.requestInfo.indexOf("HTTP/1.1") - 1;
    		String urlStr = this.requestInfo.substring(index,end);
    		int paramIndex;// 请求参数拆分位置
    		String parameterStr = "";
    		if ("get".equals(method)) {
    			if (urlStr.contains("?")) {
    				paramIndex = urlStr.indexOf('?');
    				this.url = urlStr.substring(0, paramIndex);
    				parameterStr = urlStr.substring(paramIndex + 1);
    			}else {
    				parameterStr = "";
    			} 
    		}else {
    			this.url = urlStr;
    			paramIndex = this.requestInfo.lastIndexOf(CRLF);
    			parameterStr = this.requestInfo.substring(paramIndex).trim();
    		}
    		if(parameterStr != null && !"".equals(parameterStr)) {
    			String[] paramArr = parameterStr.split("&");
    			for (String string : paramArr) {
    				String[]  paramKV = string.split("=");
    				paramKV = Arrays.copyOf(paramKV, 2);
    				convertMap(paramKV);
    			}
    		}
    //		System.out.println(parameterStr);
    		
    	}
    
    	private void convertMap(String[] paramKV) {
    		String k = paramKV[0];
    		String v = null;
    		try {
    			v = paramKV[1] == null ? null : new URLDecoder().decode(paramKV[1], "utf8");
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    		if(!this.parameterValues.containsKey(k)) {
    			parameterValues.put(k, new ArrayList<String>());
    		}
    		this.parameterValues.get(k).add(v);
    	}
    
    	// 根据表单提交的内容获取多个值
    	public String[] getParameterValues(String name) {
    		List<String> list = this.parameterValues.get(name);
    		return list == null ? null : list.toArray(new String[0]);
    	}
    	
    	// 根据表单提交的内容获取一个值
    	public String getParameter(String name) {
    		String[] values = this.getParameterValues(name);
    		return values == null ? null : values[0];
    	}
    	
    	public String getMethod() {
    		return method;
    	}
    
    
    	public String getUrl() {
    		return url;
    	}
    
    	public Map<String, List<String>> getParameterValues() {
    		return parameterValues;
    	}
    
    }
    
    

    4、封装响应数据reponse:包括响应头和响应正文

    package com.xzlf.server;
    
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.UnsupportedEncodingException;
    
    import com.xzlf.util.IOUtil;
    
    /**
     * 封装响应
     * @author xzlf
     *
     */
    public class Response {
    	private StringBuffer headInfo;
    	private  StringBuffer content;
    	private int length;
    	
    	private BufferedWriter bw;
    	
    	private static final String BLANK = " ";
    	private static final String CRLF = "
    ";
    	public Response() {
    		headInfo = new StringBuffer();
    		content = new StringBuffer();
    	}
    	
    	public Response(OutputStream os) {
    		this();
    		try {
    			bw = new BufferedWriter(new OutputStreamWriter(os, "utf-8"));
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	public Response print(String info) {
    		content.append(info);
    		try {
    			length += info.getBytes("utf-8").length;
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    		return this;
    	}
    	
    	public Response println(String info) {
    		content.append(info);
    		content.append(CRLF);
    		try {
    			length += (info + CRLF).getBytes("utf-8").length;
    		} catch (UnsupportedEncodingException e) {
    			e.printStackTrace();
    		}
    		return this;
    	}
    	
    	public void creatHeadInfo(int code) {
    		headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
    		switch(code) {
    		case 200:
    			headInfo.append("OK");
    			break;
    		case 404:
    			headInfo.append("NOT FOUND");
    			break;
    		default:
    			headInfo.append("SERVER ERROR");
    		}
    		headInfo.append(CRLF);
    		headInfo.append("Content-Type: text/html;charset=utf-8").append(CRLF);
    		headInfo.append("Content-Length:").append(length).append(CRLF);
    		headInfo.append(CRLF);
    	}
    	
    	public void pushToClient(int code) {
    		if(headInfo == null) {
    			code = 500;
    		}
    		
    		this.creatHeadInfo(code);
    		try {
    			bw.write(headInfo.toString());
    			bw.write(content.toString());
    			bw.flush();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    		close();
    	}
    	
    	public void close() {
    		IOUtil.closeAll(bw);
    	}
    }
    
    

    5、编写servelt 处理请求:

    package com.xzlf.servlet;
    
    import com.xzlf.server.Request;
    import com.xzlf.server.Response;
    
    /**
     * 所有servlet 父类
     * @author xzlf
     *
     */
    public abstract class Servlet {
    	public void service(Request request, Response response) throws Exception {
    		this.doGet(request, response);
    		this.doPost(request, response);
    	}
    
    	public abstract void doPost(Request request, Response response) throws Exception;
    
    	public abstract void doGet(Request request, Response response) throws Exception;
    }
    
    
    package com.xzlf.servlet;
    
    import com.xzlf.server.Request;
    import com.xzlf.server.Response;
    
    public class LoginServlet extends Servlet {
    
    	@Override
    	public void doPost(Request request, Response response) throws Exception {
    		
    	}
    
    	@Override
    	public void doGet(Request request, Response response) throws Exception {
    		String uname = request.getParameter("uname");
    		String pwd = request.getParameter("pwd");
    //		System.out.println(uname+"--" + pwd);
    		if(login(uname, pwd)) {
    			response.print(uname + ":登录成功");
    		}else {
    			response.print(uname + " 登录失败,账号或密码错误");
    		}
    		
    	}
    	
    	private boolean login(String uname, String pwd) {
    		if("张三".equals(uname) && "123".equals(pwd)) {
    			return true;
    		}
    		return false;
    	}
    }
    
    
    package com.xzlf.servlet;
    
    import com.xzlf.server.Request;
    import com.xzlf.server.Response;
    
    public class RegisterServlet extends Servlet {
    
    	@Override
    	public void doPost(Request request, Response response) throws Exception {
    		// TODO Auto-generated method stub
    		
    	}
    
    	@Override
    	public void doGet(Request request, Response response) throws Exception {
    		// TODO Auto-generated method stub
    		
    	}
    
    }
    
    

    6、加入DIspatcher分发器,开启多线程

    package com.xzlf.server;
    
    import java.io.IOException;
    import java.net.Socket;
    
    import com.xzlf.servlet.Servlet;
    import com.xzlf.util.IOUtil;
    
    /**
     * 请求响应分发器
     * @author xzlf
     *
     */
    public class Dispatcher implements Runnable{
    	private Socket client;
    	private Request req;
    	private Response rep;
    	int code = 200;
    	public Dispatcher(Socket client) {
    		this.client = client;
    		try {
    			req = new Request(this.client.getInputStream());
    			rep = new Response(this.client.getOutputStream());
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    	
    	@Override
    	public void run() {
    		String url = req.getUrl();
    		System.out.println(url);
    		// 根据不同的url 创建不同的servlet对象
    		Servlet servlet = WebApp.getServlet(url);
    		if(servlet == null) {
    			code = 404;
    		}else {
    			try {
    				servlet.service(req, rep);
    			} catch (Exception e) {
    				code = 500;
    			}
    		}
    		
    		rep.pushToClient(code);
    		IOUtil.closeAll(client);
    	}
    }
    
    

    7、编写服务器端

    package com.xzlf.server;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    import com.xzlf.util.IOUtil;
    
    /**
     * 启动服务
     * @author xzlf
     *
     */
    public class Server {
    	private ServerSocket server;
    	private boolean isRuning;
    	private void start(int port) {
    		isRuning = true;
    		try {
    			server = new ServerSocket(port);
    			recive();
    		} catch (IOException e) {
    			isRuning = false;
    		}
    	}
    	
    	private void recive() {
    		try {
    			
    			while (isRuning) {
    				Socket client = server.accept();
    				Dispatcher dispatcher = new Dispatcher(client);
    				new Thread(dispatcher).start();
    			}
    			
    		} catch (IOException e) {
    			isRuning = false;
    		}
    	}
    
    	private void stop() {
    		isRuning = false;
    		IOUtil.closeAll(server);
    	}
    	
    	public static void main(String[] args) {
    		Server s = new Server();
    		s.start(8888);
    	}
    	
    }
    
    

    8、进行页面测试

    9、简单写个多线程并发进行压测

    package com.xzlf.csdnUtil;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.URL;
    
    /**
     * 对手写服务器进行压测
     * @author xzlf
     *
     */
    public class TestMyServer {
    	public static void main(String[] args) {
    		String url = "http://localhost:8888/log?";
    		for (int i = 0; i < 100; i++) {
    			new Thread(new RunThread(url, "张三" + i, "123")).start();
    			new Thread(new RunThread(url, "张三", "123")).start();
    			try {
    				Thread.sleep(200);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    	}
    
    	public static void longin(String url, String uname, String pwd) {
    
    		BufferedReader br = null;
    		try {
    			String loginUrl = url + "uname=" + uname + "&pwd=" + pwd;
    			URL login = new URL(loginUrl);
    			br = new BufferedReader(new InputStreamReader(login.openStream(), "utf-8"));
    			char[] buf = new char[1024];
    			int len = br.read(buf);
    			System.out.println(new String(buf, 0, len));
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	// 为了直接调用请求方法 用下静态内部类
    	static class RunThread implements Runnable {
    		String url;
    		String uname;
    		String pwd;
    
    		public RunThread(String url, String uname, String pwd) {
    			super();
    			this.url = url;
    			this.uname = uname;
    			this.pwd = pwd;
    		}
    
    		@Override
    		public void run() {
    			TestMyServer.longin(url, uname, pwd);
    		}
    
    	}
    }
    
    

    用的电脑还算比较新 没啥压力。

    重视基础,才能走的更远。
  • 相关阅读:
    iOS-国家代码选择功能github开源分享
    Nehe OpenGL lesson 8
    POJ 3083:Children of the Candy Corn(DFS+BFS)
    LeetCode 14
    一起talk C栗子吧(第二十二回:C语言实例--队列一)
    高仿手机QQ音乐之——Android带进度条的开关
    11.1 半联结
    oracle调优 浅析有效的游标管理
    经典算法——Jump Game(II)
    从Vue文件到Html文件
  • 原文地址:https://www.cnblogs.com/xzlf/p/12729220.html
Copyright © 2011-2022 走看看