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 = "\r\n"; 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 = "\r\n";
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);
} }
}

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

最新文章

  1. 安装zabbix-3.0.3+nginx-1.10.1+php-5.6.22
  2. winform下如何实现右下角弹窗效果
  3. ubuntu 安装JAVA jdk的两种方法:
  4. poj1416 Shredding Company
  5. [Android Pro] root用户删除文件提示:Operation not permitted
  6. Spring技术揭幕----DispatcherServlet
  7. python学习应用笔记(一)
  8. innodb_strict_mode=1
  9. 2 JavaScript应用开发实践指南
  10. data guard switchover切换异常
  11. NAS4Free 安装配置(一)开箱图
  12. php使用openssl加密数据
  13. 学习vi和vim编辑器(5):越过基础的藩篱
  14. 【20190228】JavaScript-获取子元素
  15. Spring+Hibernate实现动态SessionFactory切换(改进版)
  16. week1 - Python基础1 介绍、基本语法、流程控制
  17. 软件工程wc项目,基于py
  18. 将pandas的Dataframe对象读写Excel文件
  19. Github上关于iOS的各种开源项目集合2(强烈建议大家收藏,查看,总有一款你需要)
  20. selenium学习一

热门文章

  1. 磅日波浪分析4H 20190927
  2. 使用内部枚举类作为外部类的参数的Mybatis的参数该如何判断
  3. CodeForces 277A 红娘问题(并查子集)
  4. 自定义yum仓库
  5. window部署ftp服务器
  6. IP和端口查询
  7. System.out.println()的真实含义
  8. Java并发之显式锁和隐式锁的区别
  9. matplotlib formatters
  10. Python入门学习指导(VS Code配置向)