不使用tomcat,仅适用javaSE手写服务器--模拟登陆
2021-02-12 23:21
阅读:679
YPE html>
标签:多线程并发 ram dex const error inpu 分发器 contain inf
1、搭建框架
我们只是简单模拟,框架简单分三个模块
a,服务器端server包
b,servlet,根据不同的请求url,利用反射生产对应的servlet
c,IO工具包,用来关闭IO流
d,编写web.xml
login com.xzlf.servlet.LoginServlet register com.xzlf.servlet.RegisterServlet login /login /log register /register /reg /r
e,写一个简单的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 urlList;
public Mapping() {
this.urlList = new ArrayList();
}
public Mapping(String name, List urlList) {
this();
this.name = name;
this.urlList = urlList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getUrlList() {
return urlList;
}
public void setUrlList(List 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 entityList;
// 存储Mapping
private List mappingList;
public WebDom4j() {
this.entityList = new ArrayList();
this.mappingList = new ArrayList();
}
public WebDom4j(List entityList, List mappingList) {
this();
this.entityList = entityList;
this.mappingList = mappingList;
}
public List getEntityList() {
return entityList;
}
public void setEntityList(List entityList) {
this.entityList = entityList;
}
public List getMappingList() {
return mappingList;
}
public void setMappingList(List 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 elementIterator = rootElement.elementIterator("servlet");
elementIterator.hasNext();) {
Element ele = elementIterator.next();
Entity entity = new Entity();
for (Iterator 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 elementIterator = rootElement.elementIterator("servlet-mapping");
elementIterator.hasNext();) {
Element ele = elementIterator.next();
Mapping mapping = new Mapping();
for (Iterator 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 entityList2 = web.getEntityList();
System.out.println(entityList2.size());
for (Entity entity : entityList2) {
System.out.println(entity.getName() + "--" + entity.getClazz());
}
System.out.println("============================");
List 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 servlet;
// key:url-pattern value:servlet-name
private Map mapping;
public ServletContext() {
this.servlet = new HashMap();
this.mapping = new HashMap();
}
public ServletContext(Map servlet, Map mapping) {
this.servlet = servlet;
this.mapping = mapping;
}
public Map getServlet() {
return servlet;
}
public void setServlet(Map servlet) {
this.servlet = servlet;
}
public Map getMapping() {
return mapping;
}
public void setMapping(Map 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 servlet = context.getServlet();
Map mapping = context.getMapping();
// 创建xml解析
WebDom4j web = new WebDom4j();
web.parse(web.getDocument());
// 获取解析xml 之后的List集合
List entityList = web.getEntityList();
List 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> parameterValues;
private static final String BLANK = " ";
private static final String CRLF = "\r\n";
public Request() {
this.parameterValues = new HashMap>();
}
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());
}
this.parameterValues.get(k).add(v);
}
// 根据表单提交的内容获取多个值
public String[] getParameterValues(String name) {
List 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> 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
用的电脑还算比较新 没啥压力。
不使用tomcat,仅适用javaSE手写服务器--模拟登陆
标签:多线程并发 ram dex const error inpu 分发器 contain inf
原文地址:https://www.cnblogs.com/xzlf/p/12729220.html
文章来自:搜素材网的编程语言模块,转载请注明文章出处。
文章标题:不使用tomcat,仅适用javaSE手写服务器--模拟登陆
文章链接:http://soscw.com/index.php/essay/54666.html
文章标题:不使用tomcat,仅适用javaSE手写服务器--模拟登陆
文章链接:http://soscw.com/index.php/essay/54666.html
评论
亲,登录后才可以留言!