预备知识

编写服务器用到的知识点

1) Socket 编程
2) HTML
3) HTTP 协议
4) 反射
5) XML 解析
6) 服务器编写

Socket编程

https://www.cnblogs.com/bfcs/p/10790130.html

HTML知识

HTML:HyperText Markup Language 超文本标记语言用于描述网页文档的一种标记语言

表单(form):与用户之间进行交互

  method:请求方式 get/post

     get 数据量小,安全性低,默认方式

     post 数据量大,安全性高
  action:请求的服务器路径

  id :(用户的的浏览器在文档里区分唯一性)前端区分唯一性,js 中

  name:名称,后端(服务器)区分唯一性,获取值,只要提交数据给后台(服务器)必须存在 name

 <html>
<head>
<title>登陆界面</title>
</head>
<body>
<form action="" method="post" >
<p>用户名:<input type="text" name="username" id="name"/></p>
<p>密码:<input type="password" name="password" id="pwd"/></p>
<input type="submit" value="提交"/>
</form>
</body>
</html>

HTTP协议

协议

1) 应用层:HTTP、FTP、TELNET、SNMP、DNS
2) 传输层:TCP、UDP
3) 网络层:IP

HTTP 协议简介

HTTP:超文本传输协议,是网络应用层的协议,建立在 TCP/IP 协议基础上,HTTP 使用可靠的 TCP 连接,默认端口为 80。

用户打开 Web 浏览器(常见的 HTTP 客户端),输入 URL地址,就能接收到远程 HTTP 服务器端发送过来的网页,即HTTP 遵循请求(Request)/应答(Response)模型。

Web 浏览器向 Web 服务器发送请求,Web 服务器处理请求并返回适当的应答,所有 HTTP 连接都被构造成一套请求与应答。

HTTP 协议严格规定了 HTTP 请求和 HTTP 响应的数据格式

HTTP 请求格式

1) 请求方式、URI(统一资源定位符)、HTTP 协议/版本

2) 请求头 Request Header

  请求头包含许多有关客户端环境和请求正文的有用信息。例如,请求头可以声明浏览器所用的语言,请求正文的长度等。

3) 请求正文 Requet Content (只有在 post 方式才有)请求头和请求正文之间必须有符号行(回车符或行结束符),与请求头分开。这个行非常重要,它表示请求头已结束,接

下来的是请求正文。 通常 post 方式的数据存放于此,请求正文中可以包含客户提交的查询字符串等信息。在实际应用中,HTTP 请求正文可以包含更多的内容

HTTP响应格式

1) HTTP 协议版本、状态代码、描述

2) 响应头(Response Head)

3) 响应正文(Respose Content)

Tomcat

是 SUN 公司推出的小型 Servlet/JSP 调试工具)的基础上发展起来的一个优秀的 Servlet 容器,Tomcat本身完全用 Java 语言编写

Tomcat 使用

1) 配置 Tomcat

  a) JAVA_HOME Java JDK 的根目录

  b) CATALINA_HOME Tomcat 根目录

2) 启动和关闭 Tomcat

  启动 Tomcat 服务器:startup.bat  本地主机8080端口

  关闭 Tomcat 服务器:shutdown.bat

3) 部署项目到服务器

  在 webapps 目录下新建目录存放.html 页面     访问页面

Tomcat 的运行原理

客户浏览器发出要求,访问特定的 Servlet 的请求。

1) Tomcat 服务器接收到客户请求并解析。

2) Tomcat 服 务 器 创 建 一 个 ServletRequest 对 象 , 在ServletRequest 对象中包含了客户请求信息及其他关于客户的信息,如请求头,请求正文,以及客户机的 IP 地址等。

3) Tomcat 服务器创建一个 ServletResponse 对象

4) Tomcat 服务器调用客户所请求的 Servlet 的 service 服务方法,并且把 ServletRequst 对象和 ServletResponse 对象做为参数传给该服务方法。

5) Servlet 从 ServletRequest 对象中可获取客户的请求信息。

6) Servlet 利用 ServletResponse 对象来生成响应结果。

7) Tomcat 服务器把 Servlet 生成的响应结果发送给客户。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

手写服务器项目

1.搭建项目框架

2.编写XML文档

 <?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<serlvet-class>com.bjsxt.servlet.LoginServlet</serlvet-class>
</servlet>
<servlet-mapping>
<serlvet-name>login</serlvet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/log</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>register</servlet-name>
<serlvet-class>com.bjsxt.servlet.RegisterServlet</serlvet-class>
</servlet>
<servlet-mapping>
<serlvet-name>register</serlvet-name>
<url-pattern>/reg</url-pattern>
<url-pattern>/register</url-pattern>
<url-pattern>/regis</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>favicon</servlet-name>
<serlvet-class>com.bjsxt.servlet.FaviconServlet</serlvet-class>
</servlet>
<servlet-mapping>
<serlvet-name>favicon</serlvet-name>
<url-pattern>/favicon.ico</url-pattern> </servlet-mapping>
</web-app>

3.编写 IOCloseUtil 类

 import java.io.Closeable;
import java.io.IOException; public class IOCloseUtil { //用于关闭所有流
public static void closeAll(Closeable...close) { //可变参数
for (Closeable closeable : close) {
if(closeable != null) {
try {
closeable.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
}

4.DOM4J 解析 XML 配置文件

  1)Entity 实体类的编写

 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;
import org.omg.CORBA.PUBLIC_MEMBER; public class WebDom4j { //用于解析XML
private List<Entitty> entityList;//用于存储N多Entity,而每一个Entity都是servlet-name与servlet-class
private List<Mapping> mappingList;//用于存储N多Mapping,而每一个Mapping都是一个servlet-name与多个url-pattern //公有取值赋值方法
public List<Entitty> getEntityList() {
return entityList;
}
public void setEntityList(List<Entitty> entityList) {
this.entityList = entityList;
}
public List<Mapping> getMappingList() {
return mappingList;
}
public void setMappingList(List<Mapping> mappingList) {
this.mappingList = mappingList;
} //构造方法
public WebDom4j() {
entityList = new ArrayList<Entitty>();
mappingList = new ArrayList<Mapping>();
}
//获取Document对象的方法
public Document getDocument() { //Document英语翻译:文件;文档
//alt+shift+z包围异常快捷键
try {
//(1)创建SAXReader对象
SAXReader reader = new SAXReader();
//(2)调用read()方法
return reader.read(new File("src/WEB_INFO/web.xml"));
} catch (DocumentException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return null;
}
//把获取到的Document对象解析
public void parse(Document doc) {
//(1)获取根元素
Element root = doc.getRootElement(); //web-app
//(2)解析servlet
for(Iterator<Element> ite = root.elementIterator("servlet"); ite.hasNext();) {
Element subElement = ite.next();//得到每一个servlet
//创建一个实体类
Entitty ent = new Entitty();//用于存储servlet-name与servlet-class
for(Iterator<Element> subite = subElement.elementIterator(); subite.hasNext();) {
Element ele = subite.next(); //可能是servlet-name,也可能是servlet-class
if("servlet-name".equals(ele.getName())) {
ent.setName(ele.getText()); //给实体类中的name赋值
}else if ("servlet-class".equals(ele.getName())) {
ent.setClazz(ele.getText());
}
}
//经过上面的循环后Entity有值了,把Entity添加到集合中
entityList.add(ent);
}
//解析servlet-mapping
for(Iterator<Element> ite = root.elementIterator("servlet-mapping"); ite.hasNext();) {
Element subEle = ite.next();//得到每一个servlet-mapping
//创建一个mapping类对象
Mapping map = new Mapping();
//解析servlet-mapping下的子元素
for(Iterator<Element> subite = subEle.elementIterator(); subite.hasNext();) {
Element ele = subite.next();//可能是servlet-name,也可能是url-pattern
if("servlet-name".equals(ele.getName())) {
map.setName(ele.getText());
}else if("url-pattern".equals(ele.getName())){
//获取集合对象,调用集合对象的添加方法,添加元素
map.getUrlPattern().add(ele.getText());
}
}
//mapping添加到集合中
mappingList.add(map);
}
}
}

  2)Mapping 实体类的编写

 /**
* <servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
<url-pattern>/log</url-pattern>
</servlet-mapping>
* @author CHB
*
*/ import java.util.ArrayList;
import java.util.List; public class Mapping { //映射关系 多个路径访问共享资源 servlet-name和url-pattern对应的实体类 多个资源与小名之间的关系
private String name;//servlet-name
private List<String> urlPattern;//url-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() {
urlPattern = new ArrayList<String>();
}
public Mapping(String name, List<String> urlPattern) {
super();
this.name = name;
this.urlPattern = urlPattern;
}
}

  3)解析 XML 文件,WebDom4j类的编写

  导入Dom4j的jar包:在项目下新建文件夹lib,把jar包复制进去,导入后右键jar包选择构建路径再选择添加至构建路径

 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;
import org.omg.CORBA.PUBLIC_MEMBER; public class WebDom4j { //用于解析XML
private List<Entitty> entityList;//用于存储N多Entity,而每一个Entity都是servlet-name与servlet-class
private List<Mapping> mappingList;//用于存储N多Mapping,而每一个Mapping都是一个servlet-name与多个url-pattern //公有取值赋值方法
public List<Entitty> getEntityList() {
return entityList;
}
public void setEntityList(List<Entitty> entityList) {
this.entityList = entityList;
}
public List<Mapping> getMappingList() {
return mappingList;
}
public void setMappingList(List<Mapping> mappingList) {
this.mappingList = mappingList;
} //构造方法
public WebDom4j() {
entityList = new ArrayList<Entitty>();
mappingList = new ArrayList<Mapping>();
}
//获取Document对象的方法
private Document getDocument() { //Document英语翻译:文件;文档
//alt+shift+z包围异常快捷键
try {
//(1)创建SAXReader对象
SAXReader reader = new SAXReader();
//(2)调用read()方法
return reader.read(new File("src/WEB_INFO/web.xml"));
} catch (DocumentException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return null;
}
//把获取到的Document对象解析
public void parse(Document doc) {
//(1)获取根元素
Element root = doc.getRootElement(); //web-app
//(2)解析servlet
for(Iterator<Element> ite = root.elementIterator("servlet"); ite.hasNext();) {
Element subElement = ite.next();//得到每一个servlet
//创建一个实体类
Entitty ent = new Entitty();//用于存储servlet-name与servlet-class
for(Iterator<Element> subite = subElement.elementIterator(); subite.hasNext();) {
Element ele = subite.next(); //可能是servlet-name,也可能是servlet-class
if("servlet-name".equals(ele.getName())) {
ent.setName(ele.getText()); //给实体类中的name赋值
}else if ("servlet-class".equals(ele.getName())) {
ent.setClazz(ele.getText());
}
}
//经过上面的循环后Entity有值了,把Entity添加到集合中
entityList.add(ent);
}
//解析servlet-mapping
for(Iterator<Element> ite = root.elementIterator("servlet-mapping"); ite.hasNext();) {
Element subEle = ite.next();//得到每一个servlet-mapping
//创建一个mapping类对象
Mapping map = new Mapping();
//解析servlet-mapping下的子元素
for(Iterator<Element> subite = subEle.elementIterator(); subite.hasNext();) {
Element ele = subite.next();//可能是servlet-name,也可能是url-pattern
if("servlet-name".equals(ele.getName())) {
map.setName(ele.getText());
}else if("url-pattern".equals(ele.getName())){
//获取集合对象,调用集合对象的添加方法,添加元素
map.getUrlPattern().add(ele.getText());
}
}
//mapping添加到集合中
mappingList.add(map);
}
}
}

 5.反射创建servlet对象

  1)编写 ServletContext 类:Servlet 上下文,就是一个容器,用于存储映射关系

 import java.util.HashMap;
import java.util.Map; public class ServletContext { //上下文 Entity与Mapping的映射关系 实体与映射关系类
private Map<String, String> servlet;//key是servlet-name,值是servlet-class
private Map<String, String> mapping;//hashmap键不能重复,值却可以,key是url-pattern, 值是servlet-name //公有的取值赋值方法
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() {
servlet = new HashMap<String, String>();
mapping = new HashMap<String, String>();
}
}

  2)编写 WebApp 类

  a) 初始化程序运行的数据

  b) 根据不同的 url 创建所请求的 Servlet 对象

 import java.util.List;
import java.util.Map; import javax.print.attribute.standard.Severity; import cn.chb.servlet.Servlet; /* a) 初始化程序运行的数据
  b) 根据不同的 url 创建所请求的 Servlet 对象
* */ public class WebApp { //app应用程序
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并把数据放到了entityList和mappingList当中
//获取解析XML之后的List集合
List<Entitty> entityList = web.getEntityList();
List<Mapping> mappingList = web.getMappingList(); //将List集合中的数据存储到Map集合
for(Entitty entity:entityList) {
servlet.put(entity.getName(), entity.getClazz());
}
for(Mapping map:mappingList) {
//遍历url-pattern集合
List<String> urlPattern = map.getUrlPattern();
for(String s:urlPattern) {
mapping.put(s, map.getName());
}
}
}
/**
* 根据url创建不同的servlet对象
* @param url
* @return
*
*/
public static Servlet getServlet(String url){
if(url == null||url.trim().equals("")) {
return null;
}
try {
//如果url正确
String servletName = context.getMapping().get(url);//根据key(url)获取值(servlet-name)
//根据servlet-name得到对应的servlet-class
String servletClass = context.getServlet().get(servletName);//等到的是一个完整的包名+类名字符串
//使用反射创建servlet对象
Class<?> clazz = Class.forName(servletClass);
//调用无参构造方法创建servlet对象
Servlet servlet = (Servlet)clazz.newInstance();
return servlet;
} catch (ClassNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (InstantiationException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return null;
}
}

6.封装 Request_method_url

  1) 编写 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; import com.bjsxt.servlet.Servlet;
import com.bjsxt.util.IOCloseUtil; public class Server {//服务器,用于启动和停止服务
private ServerSocket server;
private boolean isShutDown=false;//默认没有出错
public static void main(String[] args) {
Server server=new Server();//创建服务器对象
server.start();
}
public void start(){
this.start(8888);
}
public void start(int port){
try {
server=new ServerSocket(port);
this.receive(); //调用接收请求信息的方法
} catch (IOException e) {
isShutDown=true;
}
}
private void receive() {
try {
while(!isShutDown){
//(1)监听
Socket client=server.accept();
//创建线程类的对象
Dispatcher dis=new Dispatcher(client);
//创建线程的代理类,并启动线程
new Thread(dis).start();
} } catch (IOException e) {
this.stop();//关闭服务器
} }
public void stop(){
isShutDown=true;
IOCloseUtil.closeAll(server);
}
}

  2)编写 HTML

 <html>
<head>
<title>登陆</title>
</head>
<body>
<form action="http://127.0.1:8888/log" method="get" >
<p>用户名:<input type="text" name="username" id="username"/></p>
<p>密码:<input type="password" name="pwd" id="password"/></p>
<p>
爱好:<input type="checkbox" name="hobby" value="ball"/>足球
<input type="checkbox" name="hobby" value="read"/>读书
<input type="checkbox" name="hobby" value="pain"/>画画
</p>
<p><input type="submit" value="登陆"/></p>
<input type="submit" value="提交"/>
</form>
</body>
</html>

  3) 封装 Request_method_url

 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; public class Request { /*请求类*/
private InputStream is;//输入流
private String requestInfo;//请求字符串:请求方式,路径,参数,协议/协议版本,请求正文
private String method;//请求方式
private String url;//请求的url //输入框中的name为key,值为输入的内容
/*
* key:username value:chb
* key:pwd value:123456
*/
private Map<String, List<String>> parametermapValues;//参数
private static final String CRLF="\r\n";//换行
private static final String BLANK=" ";//空格
//构造方法,初始化属性
public Request() {
parametermapValues = new HashMap<String, List<String>>();
method = "";
requestInfo = "";
url = "";
}
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 (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
//调用本类中分解请求信息的方法
this.parseRequestInfo();
}
//分解请求信息的方法 方式、路径、参数
private void parseRequestInfo() {
String paraString ="";//用于存储请求参数
//获取请求参数的第一行
String firstLine=requestInfo.substring(0, requestInfo.indexOf(CRLF)).trim();//从0开始到第一个换行
//分解出请求方式
int index = firstLine.indexOf("/");//找出斜线的位置GET /(这里) HTTP/1.1
this.method = firstLine.substring(0, index).trim();//trim()去掉空格
//分解url,可能包含参数,也可能不包含参数
String urlString = firstLine.substring(index, firstLine.indexOf("HTTP/")).trim();
//判断请求方式是GET还是POST
if("get".equalsIgnoreCase(this.method)) {//GET包含请求参数
if(urlString.contains("?")) {//包含有问号,说明有参数
String [] urlArray = urlString.split("\\?");//以?号分割获取参数
this.url = urlArray[0];
paraString = urlArray[1];
}else {
this.url = urlString;
}
}else {//POST不包含请求参数,参数在请求正文
this.url = urlString;
//最后一个换行到结尾是请求正文
paraString = requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
}
if(paraString.equals("")) {//如果没有参数
return;
}
}
//username=chbt&pwd=123&hobby=ball&hobby=paint
/**
* username=chb
* pwd=123
* hobby=ball
* hobby=paint
*
* username=
* @param prarString
*/
private void parseParam(String prarString){
String [] token=prarString.split("&");
for(int i=0;i<token.length;i++){
String keyValues=token[i];
String []keyValue=keyValues.split("="); //username chb pwd 123
if (keyValue.length==1) { //username=
keyValue=Arrays.copyOf(keyValue, 2);
keyValue[1]=null;
}
//将 表单元素的name与name对应的值存储到Map集合
String key=keyValue[0].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){
//根据key获取value
List<String> values=parametermapValues.get(name);
if (values==null) {
return null;
}else{
return values.toArray(new String [0] );
} }
private String getParamter(String name){
//调用本类中根据name获取多个值的方法
String [] values=this.getParamterValues(name);
if (values==null) {
return null;
}else{
return values[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;
}
}

7.封装 Response

1) 构造响应头

2) 推送到客户端

 import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException; import com.bjsxt.util.IOCloseUtil; public class Response {//响应
private StringBuilder headInfo;//响应头
private StringBuilder content;//响应内容
private int length;//响应内容的长度
//流
private BufferedWriter bw; //两个常量,换行和空格
private static final String CRLF="\r\n";//换行
private static final String BLANK=" ";//空格 //构造方法
public Response() {
headInfo=new StringBuilder();
content=new StringBuilder(); }
//带参构造方法
public Response(OutputStream os){
this();//调用本类的无参构造方法
try {
bw=new BufferedWriter(new OutputStreamWriter(os, "utf-8"));
} catch (UnsupportedEncodingException e) {
headInfo=null;
} }
//构造正文部分
public Response print(String info){
content.append(info);
try {
length+=info.getBytes("utf-8").length;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this;
}
public Response println(String info){
content.append(info).append(CRLF);
try {
length+=(info+CRLF).getBytes("utf-8").length;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return this;
} //构造响应头 private void createHeadInfo(int code){
headInfo.append("HTTP/1.1").append(BLANK).append(code).append(BLANK);
switch (code) {
case 200:
headInfo.append("OK");
break;
case 500:
headInfo.append("SERVER ERROR");
break;
default:
headInfo.append("NOT FOUND");
break;
}
headInfo.append(CRLF);
headInfo.append("Content-Type:text/html;charset=utf-8").append(CRLF);
headInfo.append("Content-Length:"+length).append(CRLF);
headInfo.append(CRLF);
}
/**
* 推送到客户机的浏览器
* @param code
*/
public void pushToClient(int code){
if (headInfo==null) {
code=500;
}
try {
//调用本类中的构造响应头
this.createHeadInfo(code);
bw.write(headInfo.toString());
bw.write(content.toString());
bw.flush();
this.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void close(){
IOCloseUtil.closeAll(bw);
}
}

3)编写相应的 Servlet 构造响应内容

 import com.bjsxt.server.Request;
import com.bjsxt.server.Response; public abstract class Servlet { //是所有的请求的Servlet的父类
public void service(Request req,Response rep) throws Exception{
this.doGet( req, rep);
this.doPost( req, rep);
}
public abstract void doGet(Request req,Response rep) throws Exception;
public abstract void doPost(Request req,Response rep) throws Exception;
}
 import com.bjsxt.server.Request;
import com.bjsxt.server.Response; public class LoginServlet extends Servlet { @Override
public void doGet(Request req, Response rep) throws Exception {
//获取请求参数
String name=req.getParameter("username");
String pwd=req.getParameter("pwd"); if(this.login(name, pwd)){
//调用响应中的构建内容的方
rep.println(name+"登录成功");
}else{
rep.println(name+"登录失败,对不起,账号或密码不正确");
} }
private boolean login(String name,String pwd){
if ("bjsxt".equals(name)&&"123".equals(pwd)) {
return true;
}
return false;
} @Override
public void doPost(Request req, Response rep) throws Exception {
// TODO Auto-generated method stub }
}
 import com.bjsxt.server.Request;
import com.bjsxt.server.Response; public class FaviconServlet extends Servlet { @Override
public void doGet(Request req, Response rep) throws Exception {
// TODO Auto-generated method stub } @Override
public void doPost(Request req, Response rep) throws Exception {
// TODO Auto-generated method stub } }

8.封装分发器实现多线程

 import java.io.IOException;
import java.net.Socket; import com.bjsxt.servlet.Servlet;
import com.bjsxt.util.IOCloseUtil; /**
* 一个请求与响应就是一个Dispatcher
* @author Administrator
*
*/
public class Dispatcher implements Runnable {
private Request req;
private Response rep;
private Socket client;
private 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) {
code=500;
return ;
}
}
@Override
public void run() {
//根据不同的url创建指定的Servlet对象
//System.out.println(req.getUrl());
Servlet servlet=WebApp.getServlet(req.getUrl());
if (servlet==null) {
this.code=404;
}else{
//调用相应的Servlet中的service方法
try {
servlet.service(req,rep);
} catch (Exception e) {
this.code=500;
}
}
//将响应结果推送到客户机的浏览器
rep.pushToClient(code);
IOCloseUtil.closeAll(client);
} }

手写Tomcat服务器的更多相关文章

  1. JavaSE 手写 Web 服务器(一)

    原文地址:JavaSE 手写 Web 服务器(一) 博客地址:http://www.extlight.com 一.背景 某日,在 Java 技术群中看到网友讨论 tomcat 容器相关内容,然后想到自 ...

  2. 手写Tomcat

    学习JavaWeb之后,只知道如何部署项目到Tomcat中,而并不了解其内部如何运行,底层原理为何,因此写下此篇博客初步探究一下.学习之前需要知识铺垫已列出:Tomcat目录结构.HTTP协议.IO. ...

  3. JavaSE 手写 Web 服务器(二)

    原文地址:JavaSE 手写 Web 服务器(二) 博客地址:http://www.extlight.com 一.背景 在上一篇文章 <JavaSE 手写 Web 服务器(一)> 中介绍了 ...

  4. 黑马vue---40、结合Node手写JSONP服务器剖析JSONP原理

    黑马vue---40.结合Node手写JSONP服务器剖析JSONP原理 一.总结 一句话总结: 服务端可以返回js代码给script标签,那么标签会执行它,并且可带json字符串作为参数,这样就成功 ...

  5. 【项目】手写FTP服务器-C++实现FTP服务器

    X_FTP_server 手写FTP服务器-C++实现FTP服务器 项目Gitee链接:https://gitee.com/hsby/ftp_Server 简介 一个基于libevent的高并发FTP ...

  6. 手写Javaweb服务器

    简单web服务器 回忆socket 创建客服端(在httpClient_1包下) public class Client {    public static void main(String[] a ...

  7. 手写tomcat——编写一个提供servlet能力的 http服务器

    点击查看代码 package com.grady.diytomcat; import com.grady.diytomcat.handler.RequestHandler; import org.do ...

  8. 手写tomcat——编写一个echo http服务器

    核心代码如下: public class DiyTomcat1 { public void run() throws IOException { ServerSocket serverSocket = ...

  9. 利用html 5 websocket做个山寨版web聊天室(手写C#服务器)

    在之前的博客中提到过看到html5 的websocket后很感兴趣,终于可以摆脱长轮询(websocket之前的实现方式可以看看Developer Works上的一篇文章,有简单提到,同时也说了web ...

随机推荐

  1. 练手WPF(四)——贪吃蛇小游戏的简易实现(上)

    一. 游戏界面首先,按照惯例,编辑MainWindow.xaml,先将游戏界面制作好.非常简单:(1)主游戏区依然使用我们熟悉的Canvas控件,大小为640X480像素,设定每小格子为20px,所以 ...

  2. AES加解密异常java.security.InvalidKeyException: Illegal key size

    AES加解密异常 Java后台AES解密,抛出异常如下:java.security.InvalidKeyException: Illegal key size Illegal key size or ...

  3. linux 环境下部署 Asp.Net Core 项目 访问 oralce 数据库

    1.ASP.NET Core 是一个跨平台的高性能开源框架,可以部署到Linux上,那项目部署在Linux上有哪些好处呢? 1.linux硬件需求小,大部分版本免费,成本低. 2.linux的用户管理 ...

  4. 【设计模式】Composite

    目录 前言 安卓View的实现 View Beyond setContentView setContentView做了什么事情? 如何将xml文件变成对象的? 小结 View的绘制流程 三个流程 三个 ...

  5. java9模块不可见问题

    问题描述 jdk.internal.reflect包不可见 问题原因 java9模块化之后,java.base只把jdk.internal.reflect暴露给了少数几个内部包而没有向当前模块暴露. ...

  6. 在ie下转换时间戳出错

    在将特定格式转换为时间戳的时候,我们通常的做法事new Date(str).getTime(), 这个方法在谷歌上是可行的,但是在ie上需要注意一点,就是这个str如果是“2019-11-15”的格式 ...

  7. bootstrap基础样式学习(一)

    1.按钮btn .btn 按钮基础的样式 .btn-default 白底黑子的按钮 .btn-danger/warning/success/info/primary .btn-lg/sm/xs 按钮大 ...

  8. python基础-内置装饰器classmethod和staticmethod

    面向对象编程之classmethod和staticmethod classmethod 和 staticmethod都是python内置的装饰器 classmethod 的作用:给在类内部定义的方法装 ...

  9. redis高并发总结

    Redis是单线程的,省去了很多上下文切换线程的时间:(官方答案:因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽.既然单线程容易实现, ...

  10. linux的initcall机制

    linux的initcall机制(针对编译进内核的驱动) initcall机制的由来 我们都知道,linux对驱动程序提供静态编译进内核和动态加载两种方式,当我们试图将一个驱动程序编译进内核时,开发者 ...