手写服务器最终版本;
<?xml version="1.0" encoding="UTF-8"?> <web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.bjsxt.servlet.LoginWeb</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/g</url-pattern>
<url-pattern>/y</url-pattern>
</servlet-mapping>
</web-app> public class CloseUtil {
/**
* 关闭IO流
*/
/*
public static void closeIO(Closeable... io){
for(Closeable temp:io){
try {
if (null != temp) {
temp.close();
}
} catch (Exception e) {
}
}
}*/
/**
* 使用泛型方法实现关闭IO流
* @param io
*/
public static <T extends Closeable> void closeIO(T... io){
for(Closeable temp:io){
try {
if (null != temp) {
temp.close();
}
} catch (Exception e) {
}
}
}
public static void closeSocket(ServerSocket socket){
try {
if (null != socket) {
socket.close();
}
} catch (Exception e) {
}
}
public static void closeSocket(Socket socket){
try {
if (null != socket) {
socket.close();
}
} catch (Exception e) {
}
}
public static void closeSocket(DatagramSocket socket){
try {
if (null != socket) {
socket.close();
}
} catch (Exception e) {
}
}
} /**
* 抽象为一个父类
* @author Administrator
*
*/
public abstract class Servlet {
public void service(Request req,Response rep) throws Exception{
this.doGet(req,rep);
this.doPost(req,rep);
} protected abstract void doGet(Request req,Response rep) throws Exception;
protected abstract void doPost(Request req,Response rep) throws Exception;
} public class LoginWeb extends Servlet { @Override
public void doGet(Request req, Response rep) throws Exception {
rep.println("success.....");
} @Override
public void doPost(Request req, Response rep) throws Exception {
// TODO Auto-generated method stub } } /**
* 创建服务器,并启动
*
* 1、请求
* 2、响应
* @author Administrator
*
*/
public class Server {
private ServerSocket server;
public static final String CRLF="\r\n";
public static final String BLANK=" "; private boolean isShutDown= false;
/**
* @param args
*/
public static void main(String[] args) { Server server = new Server();
server.start(); }
/**
* 启动方法
*/
public void start(){
start(); }
/**
* 指定端口的启动方法
*/
public void start(int port){
try {
server = new ServerSocket(port);
this.receive();
} catch (IOException e) {
//e.printStackTrace();
stop();
} }
/**
* 接收客户端
*/
private void receive(){
try {
while(!isShutDown){
new Thread(new Dispatcher(server.accept())).start();
}
} catch (IOException e) {
//e.printStackTrace();
stop();
} } /**
* 停止服务器
*/
public void stop(){
isShutDown=true;
CloseUtil.closeSocket(server);
} } public class ServletContext {
//为每一个servlet取个别名
// login -->com.bjsxt.server.demo03.LoginServlet
private Map<String,String> servlet ;
//url -->login
// /log -->login
// /login -->login
private Map<String,String> mapping; ServletContext(){
servlet =new HashMap<String,String>();
mapping =new HashMap<String,String>();
} 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;
}
} public class WebApp {
private static ServletContext contxt;
static{
try {
//获取解析工厂
SAXParserFactory factory = SAXParserFactory.newInstance();
//获取解析器
SAXParser sax = factory.newSAXParser();
//指定xml+处理器
WebHandler web = new WebHandler();
sax.parse(Thread.currentThread().getContextClassLoader()
.getResourceAsStream("WEB_INFO/web.xml"), web); //将list 转成Map
contxt =new ServletContext();
Map<String,String> servlet =contxt.getServlet(); //servlet-name servlet-class
for(Entity entity:web.getEntityList()){
servlet.put(entity.getName(), entity.getClz()); } //url-pattern servlet-name
Map<String,String> mapping =contxt.getMapping();
for(Mapping mapp:web.getMappingList()){
List<String> urls =mapp.getUrlPattern();
for(String url:urls ){
mapping.put(url, mapp.getName());
}
} } catch (Exception e) { } } public static Servlet getServlet(String url) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
if((null==url)||(url=url.trim()).equals("")){
return null;
}
//根据字符串(完整路径)创建对象 //return contxt.getServlet().get(contxt.getMapping().get(url));
String name=contxt.getServlet().get(contxt.getMapping().get(url));
return (Servlet)Class.forName(name).newInstance();//确保空构造存在
}
} public class WebHandler extends DefaultHandler{
private List<Entity> entityList;
private List<Mapping> mappingList;
private Entity entity;
private Mapping mapping;
private String beginTag ;
private boolean isMap; @Override
public void startDocument() throws SAXException {
//文档解析开始
entityList =new ArrayList<Entity>() ;
mappingList =new ArrayList<Mapping>() ; }
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
//开始元素
if(null!=qName){
beginTag=qName; if(qName.equals("servlet")){
isMap=false;
entity=new Entity();
}else if(qName.equals("servlet-mapping")){
isMap=true;
mapping=new Mapping();
} } } @Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//处理内容
if(null!=beginTag){
String str =new String(ch,start,length);
if(isMap ){ if(beginTag.equals("servlet-name")){
mapping.setName(str);
}else if(beginTag.equals("url-pattern")){
mapping.getUrlPattern().add(str);
}
}else{
if(beginTag.equals("servlet-name")){
entity.setName(str);
}else if(beginTag.equals("servlet-class")){
entity.setClz(str);
}
}
}
} @Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//结束元素
if(null!=qName){ if(qName.equals("servlet")){
entityList.add(entity);
}else if(qName.equals("servlet-mapping")){
mappingList.add(mapping);
} }
beginTag=null;
} @Override
public void endDocument() throws SAXException {
//文档解析结束
} /*public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//获取解析工厂
SAXParserFactory factory =SAXParserFactory.newInstance();
//获取解析器
SAXParser sax =factory.newSAXParser();
//指定xml+处理器
WebHandler web = new WebHandler();
sax.parse(Thread.currentThread().getContextClassLoader()
.getResourceAsStream("com/bjsxt/server/demo4/web.xml")
,web); System.out.println(web.getEntityList());
}*/
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;
} } /**
* 封装响应信息
* @author Administrator
*
*/
public class Response {
//两个常量
public static final String CRLF="\r\n";
public static final String BLANK=" ";
//流
private BufferedWriter bw ; //正文
private StringBuilder content; //存储头信息
private StringBuilder headInfo;
//存储正文长度
private int len =;
public Response(){
headInfo =new StringBuilder();
content =new StringBuilder();
len =;
}
public Response(Socket client){
this();
try {
bw= new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
} catch (IOException e) {
headInfo=null;
}
}
public Response(OutputStream os){
this();
bw= new BufferedWriter(new OutputStreamWriter(os));
}
/**
* 构建正文
*/
public Response print(String info){
content.append(info);
len+=info.getBytes().length;
return this;
} /**
* 构建正文+回车
*/
public Response println(String info){
content.append(info).append(CRLF);
len+=(info+CRLF).getBytes().length;
return this;
} /**
* 构建响应头
*/
private void createHeadInfo(int code){
//1) HTTP协议版本、状态代码、描述
headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
switch(code){
case :
headInfo.append("OK");
break;
case :
headInfo.append("NOT FOUND");
break;
case :
headInfo.append("SEVER ERROR");
break;
}
headInfo.append(CRLF);
//2) 响应头(Response Head)
headInfo.append("Server:bjsxt Server/0.0.1").append(CRLF);
headInfo.append("Date:").append(new Date()).append(CRLF);
headInfo.append("Content-type:text/html;charset=GBK").append(CRLF);
//正文长度 :字节长度
headInfo.append("Content-Length:").append(len).append(CRLF);
headInfo.append(CRLF); //分隔符
}
//推送到客户端
void pushToClient(int code) throws IOException{
if(null==headInfo){
code =;
}
createHeadInfo(code);
//头信息+分割符
bw.append(headInfo.toString());
//正文
bw.append(content.toString());
bw.flush();
}
public void close(){
CloseUtil.closeIO(bw);
} } /**
* 封装request
* @author Administrator
*
*/
public class Request {
//请求方式
private String method;
//请求资源
private String url;
//请求参数
private Map<String,List<String>> parameterMapValues; //内部
public static final String CRLF="\r\n";
private InputStream is;
private String requestInfo; public Request(){
method ="";
url ="";
parameterMapValues=new HashMap<String,List<String>>();
requestInfo="";
}
public Request(InputStream is){
this();
this.is=is;
try {
byte[] data = new byte[];
int len = is.read(data);
requestInfo = new String(data, , len);
} catch (Exception e) {
return ;
}
//分析请求信息
parseRequestInfo();
}
/**
* 分析请求信息
*/
private void parseRequestInfo(){
if(null==requestInfo ||(requestInfo=requestInfo.trim()).equals("")){
return ;
}
/**
* =====================================
* 从信息的首行分解出 :请求方式 请求路径 请求参数(get可能存在)
* 如:GET /index.html?name=123&pwd=5456 HTTP/1.1
*
* 如果为post方式,请求参数可能在 最后正文中
*
* 思路:
* 1)请求方式 :找出第一个/ 截取即可
* 2)请求资源:找出第一个/ HTTP/
* =====================================
*/
String paramString =""; //接收请求参数 //1、获取请求方式
String firstLine =requestInfo.substring(,requestInfo.indexOf(CRLF));
int idx =requestInfo.indexOf("/"); // /的位置
this.method=firstLine.substring(, idx).trim();
String urlStr =firstLine.substring(idx,firstLine.indexOf("HTTP/")).trim();
if(this.method.equalsIgnoreCase("post")){
this.url=urlStr;
paramString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim(); }else if(this.method.equalsIgnoreCase("get")){
if(urlStr.contains("?")){ //是否存在参数
String[] urlArray=urlStr.split("\\?");
this.url=urlArray[];
paramString=urlArray[];//接收请求参数
}else{
this.url=urlStr;
}
} //不存在请求参数
if(paramString.equals("")){
return ;
}
//2、将请求参数封装到Map中
parseParams(paramString);
}
private void parseParams(String paramString){
//分割 将字符串转成数组
StringTokenizer token=new StringTokenizer(paramString,"&");
while(token.hasMoreTokens()){
String keyValue =token.nextToken();
String[] keyValues=keyValue.split("=");
if(keyValues.length==){
keyValues =Arrays.copyOf(keyValues, );
keyValues[] =null;
} String key = keyValues[].trim();
String value = null==keyValues[]?null:decode(keyValues[].trim(),"gbk");
//转换成Map 分拣
if(!parameterMapValues.containsKey(key)){
parameterMapValues.put(key,new ArrayList<String>());
} List<String> values =parameterMapValues.get(key);
values.add(value);
} }
/**
* 解决中文
* @param value
* @param code
* @return
*/
private String decode(String value,String code){
try {
return java.net.URLDecoder.decode(value, code);
} catch (UnsupportedEncodingException e) {
//e.printStackTrace();
}
return null;
}
/**
* 根据页面的name 获取对应的多个值
* @param args
*/
public String[] getParameterValues(String name){
List<String> values=null;
if((values=parameterMapValues.get(name))==null){
return null;
}else{
return values.toArray(new String[]);
}
}
/**
* 根据页面的name 获取对应的单个值
* @param args
*/
public String getParameter(String name){
String[] values =getParameterValues(name);
if(null==values){
return null;
}
return values[];
}
public String getUrl() {
return url;
} public void close(){
CloseUtil.closeIO(is);
}
} /*
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/log</url-pattern>
</servlet-mapping> */
public class Mapping {
private String name;
private List<String> urlPattern; public Mapping(){
urlPattern =new ArrayList<String>();
} public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getUrlPattern() {
return urlPattern;
}
public void setUrlPattern(List<String> urlPattern) {
this.urlPattern = urlPattern;
} } /*
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.bjsxt.server.demo4.LoginServlet</servlet-class>
</servlet>
*/
public class Entity {
private String name;
private String clz;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClz() {
return clz;
}
public void setClz(String clz) {
this.clz = clz;
} } /**
* 一个请求与响应 就一个此对象
* @author Administrator
*
*/
public class Dispatcher implements Runnable{
private Socket client;
private Request req;
private Response rep;
private int code=;
Dispatcher(Socket client){
this.client=client;
try {
req =new Request(client.getInputStream());
rep =new Response(client.getOutputStream());
} catch (IOException e) {
//e.printStackTrace();
code =;
return ;
}
} @Override
public void run() {
try {
Servlet serv =WebApp.getServlet(req.getUrl());
if(null==serv){
this.code=; //找不到处理
}else{
serv.service(req, rep);
}
rep.pushToClient(code); //推送到客户端
}catch (Exception e) {
e.printStackTrace();
this.code=;
}
try {
rep.pushToClient();
} catch (IOException e) {
e.printStackTrace();
}
req.close();
rep.close();
CloseUtil.closeSocket(client);
} }

java24 手写服务器最终版本的更多相关文章

  1. -手写Spring注解版本&事务传播行为

    视频参考C:\Users\Administrator\Desktop\蚂蚁3期\[www.zxit8.com] 0018-(每特教育&每特学院&蚂蚁课堂)-3期-源码分析-手写Spri ...

  2. 77、tensorflow手写识别基础版本

    ''' Created on 2017年4月20日 @author: weizhen ''' #手写识别 from tensorflow.examples.tutorials.mnist import ...

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

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

  4. 不使用tomcat,仅适用javaSE手写服务器--模拟登陆

    1.搭建框架 我们只是简单模拟,框架简单分三个模块 a,服务器端server包 b,servlet,根据不同的请求url,利用反射生产对应的servlet c,IO工具包,用来关闭IO流 d,编写we ...

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

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

  6. MyTomcat(手写服务器)

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

  7. [webpack]手写一个mvp版本的webpack

    let fs = require('fs'); let path = require('path'); let babylon = require('babylon'); // Babylon 把源码 ...

  8. 手写简易WEB服务器

    今天我们来写一个类似于Tomcat的简易服务器.可供大家深入理解一下tomcat的工作原理,本文仅供新手参考,请各位大神指正!首先我们要准备的知识是: Socket编程 HTML HTTP协议 服务器 ...

  9. 手写Tomcat服务器

    预备知识 编写服务器用到的知识点 1) Socket 编程2) HTML3) HTTP 协议4) 反射5) XML 解析6) 服务器编写 Socket编程 https://www.cnblogs.co ...

随机推荐

  1. 对QT的产品,以及QT的一些综合评论 good

    QT你不能说他不流行吧, WPS, Wirshark, KDE, dropbox, skype, virtualbox都和qt有关吧, 你想写个跨平台的C++程序, QT是个不错的选择, 普通PC应用 ...

  2. java.sizeOf

    Introduction With java.SizeOf you can measure the real memory size of your Java objects. Download it ...

  3. Rails 撤销操作

    即使再小心,在开发 Rails 应用程序过程中仍然可能犯错.幸运的是,Rails 提供了一些工具能够帮助你进行复原. 举例来说,一个常见的情况是,你想更改控制器的名字,这时你就要撤销生成的代码.生成控 ...

  4. ActionBar官方教程(11)自定义ActionBar的样式(含重要的样式属性表及练习示例)

    Styling the Action Bar If you want to implement a visual design that represents your app's brand, th ...

  5. Linux -- Ubuntu搭建java开发环境

    Steps 1 Check to see if your Ubuntu Linux operating system architecture is 32-bit or 64-bit, open up ...

  6. C# MVC模式下商品抽奖

    很久没有写博客,于是就把最近项目需求的一个抽奖功能给整理了下,语言表达能力不好,写的不好请勿吐槽,一笑而过就好.好了下面开始说说这个抽奖功能.因为涉及到公司的项目所以一些敏感的地方均已中文代替. 首先 ...

  7. 用JavaScript(js)对时间格式化

    Date.prototype.format =function(format)     {         var o = {         "M+" : (this.getMo ...

  8. import project后,出现Unable to get system library for the project

    import project 后,出现Unable to get system library for the project. 这是因为在import 一个项目的时候,没有指定android sdk ...

  9. ZOJ3732 Graph Reconstruction Havel-Hakimi定理

    分析: 给定一个非负整数序列{dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化. 进一步,若图为简单图,则称此序列可简单图化 (来自百度百科) 可简单图化的判定可以用Have ...

  10. [Tommas] UNION 和 UNION ALL 的区别

    UNION指令的目的是将两个 SQL 语句的结果合并起来.从这个角度来看,UNION跟 JOIN 有些许类似,因为这两个指令都可以由多个表格中撷取资料.UNION的一个限制是两个 SQL 语句所产生的 ...