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);
} }
}

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

不使用tomcat,仅适用javaSE手写服务器--模拟登陆的更多相关文章

  1. JavaSE 手写 Web 服务器(二)

    原文地址:JavaSE 手写 Web 服务器(二) 博客地址:http://www.extlight.com 一.背景 在上一篇文章 <JavaSE 手写 Web 服务器(一)> 中介绍了 ...

  2. JavaSE 手写 Web 服务器(一)

    原文地址:JavaSE 手写 Web 服务器(一) 博客地址:http://www.extlight.com 一.背景 某日,在 Java 技术群中看到网友讨论 tomcat 容器相关内容,然后想到自 ...

  3. java24 手写服务器最终版本

    手写服务器最终版本; <?xml version="1.0" encoding="UTF-8"?> <web-app> <serv ...

  4. 通过手写服务器的方式,立体学习Http

    前言 Http我们都已经耳熟能详了,而关于Http学习的文章网上有很多,各个知识点的讲解也可说是深入浅出.然而,学习过后,我们对Http还是一知半解.问题出在了哪? Http是一个客户机与服务器之间的 ...

  5. 3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖

    本次博客的目标 1. 手写spring循环依赖的整个过程 2. spring怎么解决循环依赖 3. 为什么要二级缓存和三级缓存 4. spring有没有解决构造函数的循环依赖 5. spring有没有 ...

  6. 前端面试手写代码——模拟实现new运算符

    目录 1 new 运算符简介 2 new 究竟干了什么事 3 模拟实现 new 运算符 4 补充 预备知识: 了解原型和原型链 了解this绑定 1 new 运算符简介 MDN文档:new 运算符创建 ...

  7. MyTomcat(手写服务器)

    Tomcat 是非常流行的 Web Server,它还是一个满足 Servlet 规范的容器.那么想一想,Tomcat 和我们的 Web 应用是什么关系? 从感性上来说,我们一般需要把 Web 应用打 ...

  8. 手写一个模拟的ReentrantLock

    package cn.daheww.demo.juc.reentrylock; import sun.misc.Unsafe; import java.lang.reflect.Field; impo ...

  9. Java修炼——手写服务器项目

    项目工程总览: 1.Dispatcher类(一个请求与响应就是一个Dispatcher) package com.bjsxt.server; import java.io.IOException; i ...

随机推荐

  1. VS2015 Visual Assist X 破解版安装教程

    前言 此方法适合VS2010~VS2015版本. 安装包下载方法:公众号[视觉IMAX]后台回复「VA助手」,即可得到安装包下载链接. 工作以来,一直在使用VS2015,之前一直根据的网上飘云阁的破解 ...

  2. 【原创】linux spinlock/rwlock/seqlock原理剖析(基于ARM64)

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  3. 武林高手?敏捷开发,唯velocity取胜

    去年学习软件工程教材,初识敏捷开发.目前所在的团队,也是使用敏捷开发方式.今天读了这篇文章,对于这段时间的效率有所警醒.其次,个人认同文章中的用户故事,结对编程思想. 文章援引:http://gitb ...

  4. STL(六)——map、multimap

    STL--map.multimap 文章目录 STL--map.multimap 关联容器与map的介绍 map与set的异同 map与multimap的异同 map类对象的构造 map添加元素 ma ...

  5. sql.Rows 转换为 []map[string]interface{} 类型

    // *sql.Rows 转换为 []map[string]interface{}类型 func rows2maps(rows *sql.Rows) (res []map[string]interfa ...

  6. java 根据图片文字动态生成图片

    今天在做热敏打印机打印二维码,并有文字描述,想到的简单的方法就是根据热敏打印机的纸张宽度和高度,生成对应的图片,如下: package com.orisdom.utils; import lombok ...

  7. 1035 Password (20分)(水)

    To prepare for PAT, the judge sometimes has to generate random passwords for the users. The problem ...

  8. JAVABEAN的SCOPE属性(转载)

    对于JSP 程序而言,使用JavaBeans  组件不仅可以封装许多信息,而且还可以将一些 数据处理的逻辑隐藏到JavaBeans  的内部,除此之外,我们还可以设定JavaBeans  的Scope ...

  9. Scratch 怎么打开SB文件怎么打开

    扩展名是.sb( )的文件均可以用匹配版本的scratch或比匹配版本高的scratch打开,列表如下:类型 可打开.sb ···1.4(1.3).sb2 ···2.0.sb3··· 3.0或3.0b ...

  10. 怎样让scratch里的人物两腿走动

    需要人物角色至少有两个“造型”,表现走路时的两个动作.以默认的“小猫”觉色为例,它有两个“造型”,可以用来表现奔跑的动作. 但是要想让小猫跑起来,需要脚本来实现,简单跑动脚本如下 scratch学习视 ...