java 入门从零基础到手写服务器
package com.bjsxt.server;
/**<servlet>
<servlet-name>login</servlet-name>
<servlet-class>/com.bjsxt.servlet.LoginServlet.java</servlet-class>
</servlet>
* servlet-name和一个servlet-name所对应的一个实体类
* @author guohaifeng
*描述的是别名和Servlet之间的关系
*/
public class Entity {
private String name;//servlet-name
private String clazz;//servlet-class
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;
}
public Entity(String name, String clazz) {
super();
this.name = name;
this.clazz = clazz;
}
public Entity() {
super();
}
}
package com.bjsxt.server;
/**
* <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>
* @author guohaifeng
*映射关系,多个路径访问共享资源
*/
import java.util.ArrayList;
import java.util.List;
public class Mapping {
private String name; //servlet-name
private List<String>urlPattern;//servlet-pattern
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;
}
public Mapping(String name, List<String> urlPattern) {
super();
this.name = name;
this.urlPattern = urlPattern;
}
public Mapping() {
urlPattern=new ArrayList<String>();
}
}
package com.bjsxt.server;
/**
* 请求
* @author guohaifeng
*
*/
import java.io.IOException;
import java.io.InputStream;
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;
import org.omg.CosNaming.NamingContextExtPackage.URLStringHelper;
public class Request {
//输入流
private InputStream is;
//请求的字符串,请求方式,请求路径,参数,协议,请求正文,
private String requestInfo;
//请求的方式
private String method; //请求的路径
//请求的url
private String url;
//输入框的name为键,值为Value
private Map<String,List<String>>parametermapValues;//参数
private Map<String, List<String>> paramtermapValuesMap;
private static final String CRLF="rn"; //换行
private static final String BLANK="" ;//空格
//构造方法,开始初始化属性
public Request() {
parametermapValues=new HashMap<String, List<String>>();
method="";
url="";
requestInfo="";
}
public Request(InputStream is) {
this(); //调用本类无参的构造方法来为本类初始化
this.is=is;
try {
byte[]buf=new byte[20480];
int len=this.is.read(buf);
requestInfo=new String(buf, 0,len);
} catch (IOException e) {
return;
}
this.PaseRequestInfo();
}
//分解请求信息的方法
private void PaseRequestInfo() {
String paraString = null;
//获取请求参数的第一行
//从0开始,到第一个换行的位置
String firstLine=requestInfo.substring(0,requestInfo.indexOf(CRLF)).trim();
//分解出请求方式
int index=firstLine.indexOf("/");
this.method=firstLine.substring(0,index).trim();
//分解url 可能包含参数,也可能不包含参数post
String uString=firstLine.substring(index,firstLine.indexOf("HTTP")).trim();
//判断请求方式是GET还是POST
//包含请求参数
if("get".equalsIgnoreCase(this.method)) {
if(uString.contains("?")) {
String[]urlArray=uString.split("?");
this.url=urlArray[0];
paraString=urlArray[1];
}else {
this.url=uString;
}
}else {//post不包含请求参数
this.url=uString;
paraString=requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
}
if (paraString.equals("")) {
return;
}
//请求参数
System.out.println(paraString);
//调用本类中分析分解请求参数的方法
this.parseParm(paraString);
}
//用于测试
public void show() {
System.out.println(this.url);
System.out.println(this.method);
}
private void parseParm(String prarString) {
String[] token=prarString.split("&");
for(int i=0;i<token.length;i++) {
String keValues=token[i];
//username bjsxt pwd 123
String []keyValue=keValues.split("=");
if(keyValue.length==1) {
keyValue=Arrays.copyOf(keyValue, 2);
keyValue[1]=null;
}
//将 表单元素的name与name对应的值存储到Map集合中
String key=keyValue[0].trim();
///String value=keyValue[1]==null?null:keyValue[1].trim();
String value=keyValue[1]==null?null:decode(keyValue[1].trim(), "UTF-8");
if(!parametermapValues.containsKey(key)) {
parametermapValues.put(key,new ArrayList<String>());
}
List<String>values=parametermapValues.get(key);
values.add(value);
}
}
//根据表单元素的name获取多个值
private String[] getParamterValues(String name) {
List<String>values=parametermapValues.get(name);
if(values==null) {
return null;
}else {
return values.toArray(new String[0]);
}
}
//根据表单元素的name获取单个值
private String getParamter(String name) {
//调用本类中根据name获取多个值的方法
String[]value=this.getParamterValues(name);
if(value==null) {
return null;
}else {
return value[0];
}
}
//处理中文 因为浏览器对中文进行编码,进行解密
private String decode(String value,String code) {
try {
return URLDecoder.decode(value, code);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void main(String []args) {
Request req=new Request();
//调用分解参数的方法
req.parseParm("username=%E5%A4%A7%E6%B2%99%E5%9C%B0%E5%A4%9A%E6%89%80&password=%E5%A4%A7%E8%90%A8%E8%BE%BE&hobby=JAVA&hobby=Python&hobby=%E5%A4%A7%E6%95%B0%E6%8D%AE");
System.out.println(req.parametermapValues);
//调用获取多个值的方法
String []str=req.getParamterValues("hobby");
for(String string:str) {
System.out.println(string);
}
//调用获取单个值的方法
System.out.println(req.getParamter("username"));
}
}
package com.bjsxt.server;
/**
* 响应
* @author guohaifeng
*
*/
import java.io.BufferedWriter;
import java.io.OutputStream;
public class Respose {
private StringBuilder headInfo; //响应头
private StringBuilder content; //响应内容
private int length; //响应内容长度
private static final String CRLF=""; //换行
private static final String BLANK=""; //空格
//流
private BufferedWriter bw;
public Respose(StringBuilder headInfo, StringBuilder content, int length, BufferedWriter bw) {
super();
this.headInfo = headInfo;
this.content = content;
this.length = length;
this.bw = bw;
}
//无参构造方法
public Respose() {
headInfo=new StringBuilder();
content=new StringBuilder();
}
//带参构造
public Respose(OutputStream os) {
this(); //调用本类的无参构造方法
}
}
package com.bjsxt.server;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 用于启动和停止服务
* @author guohaifeng
*
*/
public class Server {
private ServerSocket server;
public void start() {
this.start(8888); //创建服务器对象
}
public void start(int port) {
try {
server=new ServerSocket(port);
this.receive(); //调用接收请求信息的方法
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//调用接收请求信息的方法
private void receive() {
try {
//监听数据的方法
Socket client=server.accept();
//获取用户的请求
// InputStream is=client.getInputStream();
// byte[]buf=new byte[20480];
// int len=is.read(buf);
// System.out.println(new String(buf, 0,len));
//封装请求信息
Request request=new Request(client.getInputStream());
//request.show();
/**
* 作出响应
*/
StringBuilder sb=new StringBuilder();
sb.append("HTTP/1.1").append(" ").append(200).append(" ").append("OK").append("rn");
sb.append("Content-Type:text/html;charset=utf-8").append("rn");
//内容
String str="<html><head><title>响应结果</title></head><body>成功</body></html>";
sb.append("Content-Length:"+str.getBytes("utf-8").length).append("rn");
sb.append("rn");
sb.append(str);
//通过输出流发送
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"utf-8"));
bw.write(sb.toString());
bw.flush();
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void stop() {
}
public static void main(String[] args) {
Server server=new Server();
server.start();
}
}
package com.bjsxt.server;
import java.util.HashMap;
import java.util.Map;
/**
* Entity与Mapping的映射关系
* @author guohaifeng
*servlet上下文 就是一个容器
*/
public class ServletContext {
//key是servlet-name(entity中的name),值是servlet-class(entity中的clazz)
private Map<String,String>servlet;
//key是url-patten(Mapping中的List集合中的每一个元素),值是servlet-name(Mapping中的name)
private Map<String, String>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;
}
public ServletContext(Map<String, String> servlet, Map<String, String> mapping) {
super();
this.servlet = servlet;
this.mapping = mapping;
}
public ServletContext() {
servlet=new HashMap<String, String>();
mapping=new HashMap<String, String>();
}
}
package com.bjsxt.server;
import java.util.List;
import java.util.Map;
import com.bjsxt.servlet.Servlet;
/**
* App的意思是应用程序
* @author guohaifeng
*
*/
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 webDom4j=new WebDom4j();
//开始解析XML
webDom4j.parse(webDom4j.getDocument());
//获取解析XML之后的List集合
List<Entity>entitlist=webDom4j.getEntityList();
List<Mapping>mList=webDom4j.getMappingList();
//将list中的数据存储到Map集合
for (Entity entity : entitlist) {
servlet.put(entity.getName(),entity.getClazz());
}
//System.out.println(servlet);
for (Mapping map : mList) {
//遍历url-pattern的集合
List<String>urlpattern=map.getUrlPattern();
for(String s:urlpattern) {
mapping.put(s, map.getName());
}
}
System.out.println(mapping);
}
/**
* 根据url创建不同的Servlet对象
* @param url
* @return
* @throws
*/
public static Servlet getServlet(String url) {
if (url==null||url.trim().equals("")) {
return null;
}
try {
//如果url正确
//根据url的key获取servlet-name的值 /login,/reg=register
String servletName= context.getMapping().get(url);
//根据servletName得到对应的servlet-class
//得到是一个完整的包名加类名的字符串
String servletClass = context.getServlet().get(servletName);
//使用反射创建Servlet对象
Class<?>clazzClass=Class.forName(servletClass);
//调用无参构造方法创建Servlet对象
Servlet servlet = (Servlet)clazzClass.newInstance();
return servlet;
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
System.out.println(getServlet("/log"));
}
}
package com.bjsxt.server;
/**
* 解析XML的类
* @author guohaifeng
*
*/
import java.io.File;
import java.lang.Character.Subset;
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;
import org.omg.CORBA.PRIVATE_MEMBER;
public class WebDom4j {
//用于存储N多Entity,而每一个Entity都是Servlet-name与servlet-class
private List<Entity>entityList;
//用于存储N多Mapping,而每一个Mapping都是一个Servlet-name与N多个url-pattern
private List<Mapping>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 WebDom4j(List<Entity> entityList, List<Mapping> mappingList) {
super();
this.entityList = entityList;
this.mappingList = mappingList;
}
public WebDom4j() {
entityList=new ArrayList<Entity>();
mappingList=new ArrayList<Mapping>();
}
/**
* 获取Document对象
* @return
*/
public Document getDocument() {
//创建SAXReader对象
try {
SAXReader reader=new SAXReader();
// 调用read方法
return reader.read(new File("src/WEB_INFO/web.xml"));
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public void parse(Document doc) {
//获取根元素
Element root=doc.getRootElement();
//获取servlet子元素
for(Iterator<Element> ite=root.elementIterator("servlet");ite.hasNext();) {
Element subElement=ite.next();
//创建一个实体类
//用于存储servlet-name与servlet-class
Entity entity=new Entity();
for (Iterator<Element> subite=subElement.elementIterator();subite.hasNext();) {
//可能是servlet-name也可能是servlet-class
Element ele=subite.next();
if("servlet-name".equals(ele.getName())) {
entity.setName(ele.getText());
}else if ("servlet-class".equals(ele.getName())) {
entity.setClazz(ele.getText());
}
}
entityList.add(entity);
}
// //测试
// for(Entity e:entityList) {
// System.out.println(e.getName()+"t"+e.getClazz());
// }
//解析servletMapping
for (Iterator<Element>ite=root.elementIterator("servlet-mapping");ite.hasNext();) {
//得到每一个Servlet-mapping
Element subele=ite.next();
Mapping mapping=new Mapping();
//解析servlet-mapping下的子元素
for (Iterator<Element>subite=subele.elementIterator();subite.hasNext();) {
Element ele = subite.next();
if("servlet-name".equals(ele.getName())) {
mapping.setName(ele.getText());
}else if ("url-pattern".equals(ele.getName())) {
//获取集合对象,调用集合对象的添加方法,添加元素
mapping.getUrlPattern().add(ele.getText());
}
}
mappingList.add(mapping);
}
// for (Mapping m : mappingList) {
// System.out.println(m.getName());
// for(String str:m.getUrlPattern()) {
// System.out.print(str);
// }
// }
}
// public static void main(String[] args) {
// WebDom4j webDom4j=new WebDom4j();
// webDom4j.parse(webDom4j.getDocument());
// }
}
package com.bjsxt.servlet;
public class LoginServlet extends Servlet {
}
package com.bjsxt.servlet;
/**
* 是所有的请求的Servlet的父类
* @author guohaifeng
*
*/
public class Servlet {
}
package com.bjsxt.util;
import java.io.Closeable;
import java.io.IOException;
/**
* 封装关闭IO流的类
* @author guohaifeng
*
*/
public class IOCloseUtil {
public static void CloseAll(Closeable... able) {
for(Closeable c:able) {
if(c!=null) {
try {
c.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.bjsxt.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/log</url-pattern>
</servlet-mapping>
</web-app>