手写Javaweb服务器
简单web服务器
回忆socket
创建客服端(在httpClient_1包下)
public class Client {
public static void main(String[] args) {
//1.创建socket对象
Socket client=null;
DataOutputStream dos = null;
DataInputStream dis =null;
try {
client = new Socket("localhost", 8888);
//2.获取输出流请求
dos = new DataOutputStream(client.getOutputStream());
dos.writeUTF("我是客服端:服务器你好!");
//3.获取输出流响应
dis = new DataInputStream(client.getInputStream());
System.out.println(dis.readUTF());
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流
IOClose.closeAll(dis,dos,client);
}
}
创建IOClose类
public class IOClose {
//关闭全部的工具类
public static void closeAll(Closeable...c){
for (Closeable closeable : c) {
if (closeable!=null){
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建服务端(在httpserver_1包下)
package com.feng.server;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
//1.创建ServerSocket对象
ServerSocket server = null;
Socket client =null;
DataInputStream dis =null;
DataOutputStream dos =null;
try {
server = new ServerSocket(8888);
//2.监听是否有客服端发送请求
client = server.accept();
//3.获取Socket对象
//4.获取输入流 ->得到客服端的请求
dis = new DataInputStream(client.getInputStream());
System.out.println(dis.readUTF());
//5.获取输出流 ->给客服端响应结果
dos = new DataOutputStream(client.getOutputStream());
dos.writeUTF("客服端你好,我是服务器,我接受到了你的信息");
} catch (IOException e) {
e.printStackTrace();
} finally {
IOClose.closeAll(dos,dis,client,server);
}
同样创建IOClose
在CS结构server(2)
package com.feng.server;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server2 {
public static void main(String[] args) {
//1.创建ServerSocket对象
ServerSocket server = null;
Socket client =null;
BufferedReader br = null;
try {
server = new ServerSocket(8888);
//2.监听是否有客服端发送请求
client = server.accept();
//获取来自浏览器的请求信息
br = new BufferedReader(new InputStreamReader(client.getInputStream(), "utf-8"));
String str=null;
while ((str=br.readLine()).length()>0) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
IOClose.closeAll(br,client,server);
}
}
}
创建HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>javaWeb</title>
</head>
<body>
<h1>HelloWorld</h1>
<form action="http://localhost:8888/index.html" method="post">
<p>用户名:<input type="text" id="uname" name="username"></p>
<p>密码:<input type="password" id="pwd" name="password"></p>
<p><input type="submit" value="登入"/></p>
</form>
</body>
</html>
创建server3
获取来自浏览器的请求信息
//获取来自浏览器的请求信息
is = client.getInputStream();
byte[] buf = new byte[20480];
int len = is.read(buf);
System.out.println(new String(buf,0,len));
对web浏览器做出响应
添加参数
String CRLF="\r\n";
String BLANK=" ";
InputStream is = null;
/**对web浏览器做出响应*/
StringBuilder sb = new StringBuilder();
StringBuilder sbContent = new StringBuilder(); //响应的文本
sbContent.append("<html><head><title>响应结果</title></head>");
sbContent.append("<body>登入成功</body></html>");
//1拼接响应头
sb.append("HTTP/1.1").append(BLANK).append(200).append(BLANK).append("OK");
sb.append(CRLF);
sb.append("Content-Type: text/html;charset=UTF-8");
sb.append(CRLF);
sb.append("Content-Length:").append(sbContent.toString().getBytes().length).append(CRLF);
sb.append(CRLF);//带表响应头与响应正文部分之间的换行
sb.append(sbContent);
//2通过输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"UTF-8"));
bw.write(sb.toString());
bw.flush();
bw.close();
整合server3
public class Server3 {
public static void main(String[] args) {
//1.创建ServerSocket对象
ServerSocket server = null;
Socket client =null;
String CRLF="\r\n";
String BLANK=" ";
InputStream is = null;
try {
server = new ServerSocket(8888);
//2.监听是否有客服端发送请求
client = server.accept();
//获取来自浏览器的请求信息
is = client.getInputStream();
byte[] buf = new byte[20480];
int len = is.read(buf);
System.out.println(new String(buf,0,len));
/**对web浏览器做出响应*/
StringBuilder sb = new StringBuilder();
StringBuilder sbContent = new StringBuilder(); //响应的文本
sbContent.append("<html><head><title>响应结果</title></head>");
sbContent.append("<body>登入成功</body></html>");
//1拼接响应头
sb.append("HTTP/1.1").append(BLANK).append(200).append(BLANK).append("OK");
sb.append(CRLF);
sb.append("Content-Type: text/html;charset=UTF-8");
sb.append(CRLF);
sb.append("Content-Length:").append(sbContent.toString().getBytes().length).append(CRLF);
sb.append(CRLF);//带表响应头与响应正文部分之间的换行
sb.append(sbContent);
//2通过输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"UTF-8"));
bw.write(sb.toString());
bw.flush();
bw.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
//6.关闭流
IOClose.closeAll(is,client,server);
}
}
}
手写服务器 整体架构,编写XML文件
创建Request,Response,Server,WebApp(在server包下)
创建Servlet,LoginServlet(在servlet包下)
创建IOCloseUtil(在util包下)
创建web.xml(在WEB_INFO包下)
<?xml version="1.0" encoding="UTF-8"?>
<web-app >
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.feng.servlet.LoginServlet</servlet-class>
</servlet>
<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>
</web-app>
创建Entity,Mapping,ServletContext,WebDom4j,创建IOClose在util包下
配置解析XML文件
补充实体类
package com.feng.server;
public class Entity { //servlet-name或每一个servlet-name所对应得实体类
private String name;
private String clazz;
public Entity() {
}
public Entity(String name, String clazz) {
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;
}
}
补充Mapping类
package com.feng.server;
import java.util.ArrayList;
import java.util.List;
public class Mapping { //映射关系,多个路径可以访问资源
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() {
this.urlPattern = new ArrayList<String>();
}
public Mapping(String name, List<String> urlPattern) {
this.name = name;
this.urlPattern = urlPattern;
}
}
配置dom4j
package com.feng.server;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class WebDom4j { //用于解析xml
private List<Entity> entityList; //用于储存实体类,每一个实体类一个servlet-name对应一个servlet-class
private List<Mapping> mappingList;//用于储存映射类,每一个servlet-name对应一个url-pattern
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() {
entityList = new ArrayList<Entity>();
mappingList = new ArrayList<Mapping>();
}
//获取Document对象的方法
public Document getDocument(){
try {
//创建SAXReader对象
SAXReader reader = new SAXReader();
//调用read方法
return reader.read(new File("web/WEB-INF/web.xml"));
} catch (DocumentException e) {
e.printStackTrace();
}
return null;
}
//获取元素
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
//创建一个实体类
Entity ent = new Entity(); //用于储存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());
} else if ("servlet-class".equals(ele.getName())) {
ent.setClazz(ele.getText());
}
}
entityList.add(ent);//放到集合中
}
//测试
/* for (Entity entity : entityList) {
System.out.println(entity.getName() + "\t" + entity.getClazz());
}*/
//解析servlet-mapping
for (Iterator<Element> ite = root.elementIterator("servlet-mapping"); ite.hasNext();){
Element subEle = ite.next();//得到每一个servlet-mapping
//创建一个mapping对象
Mapping map = new Mapping();
//解析mapping下面每一个子元素
for (Iterator<Element> subIte = subEle.elementIterator(); subIte.hasNext();){
Element ele = subIte.next();//可能是name,也可能是url
if ("servlet-name".equals(ele.getName())) {
map.setName(ele.getText());
} else if ("url-pattern".equals(ele.getName())) {
//获取集合对象,调用集合对象的添加方法,添加元素
map.getUrlPattern().add(ele.getText());
}
}
mappingList.add(map);
}
//测试
/*for (Mapping m : mappingList) {
System.out.println(m.getName());
for (String s : m.getUrlPattern()) {
System.out.println(s);
}
}*/
}
//用于测试
public static void main(String[] args) {
WebDom4j web = new WebDom4j();
web.parse(web.getDocument());
}
}
更新编写XML
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.feng.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/log</url-pattern>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>register</servlet-name>
<servlet-class>com.feng.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>register</servlet-name>
<url-pattern>/reg</url-pattern>
<url-pattern>/regis</url-pattern>
<url-pattern>/register</url-pattern>
</servlet-mapping>
</web-app>
编写servletContext Servlet 上下文,容器用于存储映射关系
package com.feng.server;
import java.util.HashMap;
import java.util.Map;
/**
*ServletContext 上下文 就是一个容器
*/
public class ServletContext { //Entity与Mapping之间的映射关系
private Map<String, String> servlet;//key是servlet-name(实体类中的name),值servlet-class,实体类中的值
private Map<String, String> mapping;//key是url-pattern(Map中的每一个元素),值servlet-name,实体类中的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>();
}
}
编写WebAPP 初始化程序数据
package com.feng.server;
import com.feng.servlet.Servlet;
import java.util.List;
import java.util.Map;
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文件对象
WebDom4jTest web = new WebDom4jTest();
//解析xml
web.parse(web.getDocument());
//获取解析xml之后的List集合
List<Entity> entityList = web.getEntityList();
List<Mapping> mappingList = web.getMappingList();
//将List集合储存到map集合中
for (Entity entity : entityList) {
servlet.put(entity.getName(),entity.getClazz());
}
//System.out.println(servlet);
for (Mapping map : mappingList) {
//遍历url-pattern的集合
List<String> urlPattern = map.getUrlPattern();
for (String s : urlPattern) {
mapping.put(s,map.getName());
}
}
//System.out.println(mapping);
}
/*
* 根据url创建不同的Servlet对象
* */
public static Servlet getServlet(String url){
if (url ==null||url.trim().equals("")){
return null;
}
try {
//如果url正确
//根据url的key获取servlet-name的值
String servletName = context.getMapping().get(url);
//根据servlet-name找到对应得servlet-class
String servletClass = context.getServlet().get(servletName);
//得到的是一个完整的包+类名的字符串
//使用反射创建servlet对象
Class<?> clazz = Class.forName(servletClass);
Servlet servlet = (Servlet) clazz.newInstance();
return 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("/login"));
}
}
编写服务
public class Server { //服务器,用于启动或停止服务
private ServerSocket server;
public static void main(String[] args) {
Server server = new Server();//创建服务器
server.start();
}
private void start() {
this.start(8888);
}
public void start(int port){
try {
server = new ServerSocket(port);
this.receive();//调用接受请求的方式
} catch (IOException e) {
e.printStackTrace();
}
}
private void receive() {
try {
//1监听
Socket client = server.accept();
//创建线程类
Dispatcher dis = new Dispatcher(client);
//创建代理线程
new Thread(dis).start();
//获取用户的请求
/**InputStream is = client.getInputStream();
byte[] buf = new byte[20480];
int len = is.read(buf);
System.out.println(new String(buf, 0, len));*/
//封装请求信息
Request req = new Request(client.getInputStream());
req.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop(){
}
}
编写Request
package com.feng.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.PrivateKey;
import java.util.*;
public class Request { //请求
//输入流
private InputStream is;
private String requestInfo; //请求字符串,请求方式,请求路径,参数,协议,协议版本,请求正文。。
private String method;//请求的方式
private String url;//请求的路径
public String getUrl() {
return url;
}
/*
* 输入框的name为key,值为value
* */
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="";
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.parseRequestInfo();
}
//分解请求信息的方法
/**
* 请求方式
* 请求路径
* 请求的参数
* */
public void parseRequestInfo() {
String paraString="";//用于存储请求参数
//获取参数的第一行
String firstLine = requestInfo.substring(0, requestInfo.indexOf(CRLF)).trim();//从0开始到第一个换行的位置
//分解出请求方式
int index = firstLine.indexOf("/");
this.method = firstLine.substring(0, index).trim();
//分解url ,get可能包含的参数,也可能不包含的参数post
String urlString = firstLine.substring(index, firstLine.indexOf("HTTP/")).trim();
//判断请求方式是GET或POST
if ("get".equalsIgnoreCase(this.method)) { //包含请求参数
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;
}
//请求参数
System.out.println(paraString);
}
//用于测试
public void show(){
System.out.println(this.url);
System.out.println(this.method);
}
}
编写login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登入</title>
</head>
<body>
<form action="http://localhost:8888/log" method="post">
<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="paint"/>画画
</p>
<p><input type="submit" value="登入"></p>
</form>
</body>
</html>
储存参数,处理中文
/**
*username = admin
* pwd = 123
* hobby =ball
* hobby = paint
* */
public void parseParam(String prarString){
String[] token = prarString.split("&");
for (int i=0;i<token.length;i++){
String keyValues = token[i];
String[] keyValue = keyValues.split("=");//把=分割掉,得到K和V
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获取多个值
public String [] getParamterValues(String name) {
//根据key获取value
List<String> values = parameterMapValues.get(name);
if (values == null ){
return null;
} else {
return values.toArray(new String[0] );
}
}
public 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) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Request req = new Request();
//调用分解参数的方法
req.parseParam("username=中文加密&pwd=123&hobby=ball&hobby=read");
System.out.println(req.parameterMapValues);
//调用获取多个值的方法
String[] str = req.getParamterValues("hobby");
for (String string : str) {
System.out.println(string);
}
//调用单个获取值的方法
System.out.println(req.getParamter("pwd"));
}
加到Server类中,测试响应
//封装请求信息
Request req = new Request(client.getInputStream());
//req.show();
/**
* 做出响应
* */
StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1").append(" ").append(200).append(" ").append("OK").append("\r\n");
sb.append("Content-Type:text/html;charset=utf-8").append("\r\n");
//内容
String str = "<html><head><title>响应结果</title></head><body>成功</body></html>";
sb.append("Content-Length:"+str.getBytes("utf-8").length).append("\r\n");
sb.append("\r\n");
sb.append(str);
//通过输出流发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"utf-8"));
bw.write(sb.toString());
bw.flush();
bw.close();
编写Response
package com.feng.server;
import com.feng.util.IOCloseUtil;
import java.io.*;
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) {
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).append(CRLF);
try {
length+=(info+CRLF).getBytes("utf-8").length;
} catch (UnsupportedEncodingException e) {
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");
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);
}
/**
* 推送到客户机的浏览器
* */
public void pushToClient(int code){
if (headInfo==null){
code=500;
}
//调用本类中的构造响应头
this.createHeadInfo(code);
try {
bw.write(headInfo.toString());
bw.write(content.toString());
bw.flush();
this.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
IOCloseUtil.closeAll(bw);
}
}
然后再把Server里面做出响应那段代码注释掉
package com.feng.server;
import com.feng.servlet.Servlet;
import com.feng.util.IOCloseUtil;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server { //服务器,用于启动或停止服务
private ServerSocket server;
public static void main(String[] args) {
Server server = new Server();//创建服务器
server.start();
}
private void start() {
this.start(8888);
}
public void start(int port){
try {
server = new ServerSocket(port);
this.receive();//调用接受请求的方式
} catch (IOException e) {
e.printStackTrace();
}
}
private void receive() {
try {
//1监听
Socket client = server.accept();
//创建线程类
Dispatcher dis = new Dispatcher(client);
//创建代理线程
new Thread(dis).start();
//获取用户的请求
/* InputStream is = client.getInputStream();
byte[] buf = new byte[20480];
int len = is.read(buf);
System.out.println(new String(buf, 0, len));*/
//封装请求信息
Request req = new Request(client.getInputStream());
//req.show();
/**
* 做出响应
* */
/*StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1").append(" ").append(200).append(" ").append("OK").append("\r\n");
sb.append("Content-Type:text/html;charset=utf-8").append("\r\n");
//内容
String str = "<html><head><title>响应结果</title></head><body>成功</body></html>";
sb.append("Content-Length:"+str.getBytes("utf-8").length).append("\r\n");
sb.append("\r\n");
sb.append(str);
//通过输出流发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(),"utf-8"));
bw.write(sb.toString());
bw.flush();
bw.close();*/
Response rep = new Response(client.getOutputStream());
Servlet servlet = WebApp.getServlet(req.getUrl());
int code=200;
if (servlet ==null){
code=404;
}
//调用Servlet中的服务方法
try {
servlet.service(req,rep);
} catch (Exception e) {
e.printStackTrace();
}
rep.pushToClient(code);
IOCloseUtil.closeAll(client); //单线程已被删除
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop(){
}
}
封装Response
编写servlet
public abstract class Servlet { //是所有请求servlet的父类
public void service(Request req, Response rep) throws Exception {
this.deGet(req,rep);
this.doPost(req,rep);
}
public abstract void deGet(Request req, Response rep) throws Exception;
public abstract void doPost(Request req, Response rep) throws Exception;
}
编写LoginServlet
public class LoginServlet extends Servlet {
@Override
public void deGet(Request req, Response rep) throws Exception {
//获取请求参数
String name = req.getParamter("username");
String pwd = req.getParamter("pwd");
if (this.login(name,pwd)) {
//调用响应中的构建内容的方法
rep.printLn(name+"登入成功");
}else {
rep.printLn(name+"登录失败,对不起,账号和密码不准确");
}
}
private boolean login(String name,String pwd){
if ("admin".equals(name)&&"123".equals(pwd)) {
return true;
}
return false;
}
@Override
public void doPost(Request req, Response rep) throws Exception {
}
}
封装分发器,实现多线程
package com.feng.server;
import com.feng.servlet.Servlet;
import com.feng.util.IOCloseUtil;
import java.io.IOException;
import java.net.Socket;
/**
* 一个请求与响应就是一个Dispatcher
*
* @author asus
* */
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对象
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);
}
}
实现多线程
package com.feng.server;
import com.feng.servlet.Servlet;
import com.feng.util.IOCloseUtil;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class Server { //服务器,用于启动或停止服务
private ServerSocket server;
private boolean isShutDown=false; //默认没有出错
public static void main(String[] args) {
Server server = new Server();//创建服务器
server.start();
}
private 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) {
e.printStackTrace();
}
}
public void stop(){
isShutDown=true;
IOCloseUtil.closeAll(server);
}
}
可能会出现空指针异常
缺少favicon映射类,在xml里面配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.feng.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/log</url-pattern>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>register</servlet-name>
<servlet-class>com.feng.servlet.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>register</servlet-name>
<url-pattern>/reg</url-pattern>
<url-pattern>/regis</url-pattern>
<url-pattern>/register</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>favicon</servlet-name>
<servlet-class>com.feng.servlet.FaviconServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>favicon</servlet-name>
<url-pattern>/favicon.ico</url-pattern>
</servlet-mapping>
</web-app>
添加FaviconServlet
package com.feng.servlet;
import com.feng.server.Request;
import com.feng.server.Response;
public class FaviconServlet extends Servlet {
@Override
public void deGet(Request req, Response rep) throws Exception {
}
@Override
public void doPost(Request req, Response rep) throws Exception {
}
}
手写Javaweb服务器的更多相关文章
- JavaSE 手写 Web 服务器(二)
原文地址:JavaSE 手写 Web 服务器(二) 博客地址:http://www.extlight.com 一.背景 在上一篇文章 <JavaSE 手写 Web 服务器(一)> 中介绍了 ...
- JavaSE 手写 Web 服务器(一)
原文地址:JavaSE 手写 Web 服务器(一) 博客地址:http://www.extlight.com 一.背景 某日,在 Java 技术群中看到网友讨论 tomcat 容器相关内容,然后想到自 ...
- 黑马vue---40、结合Node手写JSONP服务器剖析JSONP原理
黑马vue---40.结合Node手写JSONP服务器剖析JSONP原理 一.总结 一句话总结: 服务端可以返回js代码给script标签,那么标签会执行它,并且可带json字符串作为参数,这样就成功 ...
- 【项目】手写FTP服务器-C++实现FTP服务器
X_FTP_server 手写FTP服务器-C++实现FTP服务器 项目Gitee链接:https://gitee.com/hsby/ftp_Server 简介 一个基于libevent的高并发FTP ...
- 手写Tomcat服务器
预备知识 编写服务器用到的知识点 1) Socket 编程2) HTML3) HTTP 协议4) 反射5) XML 解析6) 服务器编写 Socket编程 https://www.cnblogs.co ...
- 利用html 5 websocket做个山寨版web聊天室(手写C#服务器)
在之前的博客中提到过看到html5 的websocket后很感兴趣,终于可以摆脱长轮询(websocket之前的实现方式可以看看Developer Works上的一篇文章,有简单提到,同时也说了web ...
- MiniCat:手写Http服务器
minicat 项目介绍 已实现http基础协议.参数接受.servlet.filter.cookie.多文件上传等.支持NIO. 一款轻量化Http服务器.支持bio.nio两种模式.归属Coody ...
- 手写网站服务器~用Python手动实现一个简单的服务器,不借助任何框架在浏览器中输出任意内容
写在前面的一些P话: 在公司网站开发中,我们往往借助于Flask.Django等网站开发框架去提高网站开发效率.那么在面试后端开发工程师的时候,面试官可能就会问到网站开发的底层原理是什么? 我们不止仅 ...
- 自己手写http服务器 http响应信息的封装与测试
package cn.edu.sss.httpServer; import java.io.BufferedWriter; import java.io.IOException; import jav ...
随机推荐
- 一、Git是什么?
Git是什么? Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控 ...
- uniapp vue v-html,显示富文本,内容img图片超出解决办法
uniapp h5中,v-html,img图片中style=width:auto;会显示图片原来的尺寸,会超出屏幕,替换成width:100%,这样就不会超出屏幕 重要的地方,例如<img sr ...
- java 并发线程池的理解和使用
一.为什么要用线程池 合理利用线程池能够带来三个好处. 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立 ...
- 多NX如何共存
在安装NX时,本机已经装了NX其他版本,只能修改当前程序,无法安装,那么多NX如何共存? 如图:先安装了32位NX8.5,后安装64位NX 8.5时弹的框. 解决办法有两种: 1)将已经安装的NX目录 ...
- xss利用——BeEF#stage4(其余功能介绍)
目录 信息收集 => 社会工程 =>网络扫描 => 结合metasploit => tunneling => xss => 维持权限 功能介绍 #1 - 信息收集 ...
- 记录jmeter使用beanshell断言获取复杂的json字符串参数值
实战示例 测试场景 电商系统经常会涉及到商品的库存数量的压测,在用户下单前需要先做库存余量的判断,当余量不足时用户无法下单,保证商品的有效售卖 库存余量查询响应结果 响应结果一般是json字符串的形式 ...
- 票房和口碑称霸国庆档,用 Python 爬取猫眼评论区看看电影《我和我的家乡》到底有多牛
今年的国庆档电影市场的表现还是比较强势的,两名主力<我和我的家乡>和<姜子牙>起到了很好的带头作用. <姜子牙>首日破 2 亿,一举刷新由<哪吒之魔童降世&g ...
- python在一个画布上画多个子图
转载:https://blog.csdn.net/qq_26449287/article/details/103022636 matplotlib 是可以组合许多的小图, 放在一张大图里面显示的. 使 ...
- 【题解】[LNOI2014]LCA
题目戳我 \(\text{Solution:}\) 这题的转化思想很巧妙-- 考虑把\(dep\)给拆掉. 首先可以明确的是,每一个\(LCA\)一定在\(root\to z\)的路径上. 考虑一个\ ...
- 【题解】[SHOI2007]善意的投票 / [JLOI2010]冠军调查
Link \(\text{Solution:}\) 我们令源点和汇点分别为睡觉和不睡觉这两种互斥的决策点.把小朋友看成点,问题转化为最小割. 每一个小朋友对自己的意愿指向的汇点/源点.容量为\(1.\ ...