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. python3读取excel

    说明 2007版以前的Excel(xls结尾的),需要使用xlrd读,xlwt写. 2007版以后的Excel(xlsx结尾的),需要使用openpyxl来读写. pypi的地址: https://p ...

  2. [React]核心概念

    本文是对React文档:核心概念部分的笔记,内容大致与文档相同. 文档链接 React哲学部分写的很好,务必要看 JSX JSX是JS的语法扩展,配合react使用,为JS和HTML的混写 JSX支持 ...

  3. 【tensorflow2.0】处理结构化数据-titanic生存预测

    1.准备数据 import numpy as np import pandas as pd import matplotlib.pyplot as plt import tensorflow as t ...

  4. Java数据类型与mysql对应表

  5. 1~n的之间的k个数组成和为n的方案数(动态规划)

    绯色的子弹 Description 众所周知,夏季奥林匹克运动会时隔56年第二次在东京举办,紧接着出来的<名侦探柯南 M24绯色的子弹>竟也是有奥运会的背景,最重要的是重归主线!!!(赤井 ...

  6. 使用Azure Rest API获得Access Token介绍

    背景 本文主要介绍如何获取如何获取Azure Rest API的访问token,所采用的是v2.0版本的Microsoft标识平台,关于1.0和2.0的区别可以参考 https://docs.azur ...

  7. 《综合》MMM集群

    <综合>MMM集群 部署集群基础环境 MySQL-MMM架构部署 MySQL-MMM架构使用 1 部署集群基础环境 1.1 问题 本案例要求为MySQL集群准备基础环境,完成以下任务操作: ...

  8. man手册、zip备份

                                                                                                        ...

  9. 【linux】阿里云防火墙相关

    1. 需现在阿里云安全组策略中开启相应端口,80.3306等. 2. 想用外网访问3306需开启权限,进入mysql键入 GRANT ALL PRIVILEGES ON *.* TO 'myuser' ...

  10. SQLAlchemy查询

    SQLAlchemy查询 结果查询: from databases.wechat import User from config import session def search(): result ...