java se用来写服务器_不使用tomcat,仅适用javaSE手写服务器--模拟登陆

1、搭建框架

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

cb97eaaa848fb6c65696f0bf88d2ecac.png

a,服务器端server包

44325c5cd12825b2b20e36f40988db2d.png

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

65e81924811bfc8c8bffdef73d23b9cf.png

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

f90657d5511948f12d88ec5613f07da6.png

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、进行页面测试

306273aca2de57bd6939c5313bd467ee.png

bebb6ed7f14fe8924e542e23ba9f5ca0.png

5513dc01baf3628e0d5be283fe2239eb.png

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

}

}

}

98f6513cfc39f4c197de9a22914c5697.png

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值