项目及包
![doc是生成的API,oa下为静态页面index和交互页面userSave,lib下是用来解析XML的dom4j和jaxen](https://img-blog.csdnimg.cn/20200721175918986.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTIwOTU4MA==,size_16,color_FFFFFF,t_70#pic_center)
解析server.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<server>
<service>
<connector port="8080"> </connector>
</service>
</server>
package com.bjpowernode.httpserver.core;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class ServerParser {
public static int getPort(){
int port=8080;
try {
SAXReader saxReader = new SAXReader();
Document document=saxReader.read("conf/server.xml");
Element connectorElt=(Element)document.selectSingleNode("//connector");
port = Integer.parseInt(connectorElt.attributeValue("port"));
} catch (DocumentException e) {
e.printStackTrace();
}
return port;
}
}
两个HTML页面
<html>
<head>
<title>OA办公系统首页</title>
<meta content="text/html;charset=utf-8"/>
</head>
<body>
<center><font size="35xp" color="blue">OA办公系统首页</font></center>
</body>
</html>
<html>
<head>
<title>用户信息-保存用户信息</title>
<meta content="text/html;charset=utf-8"/>
</head>
<body>
<form name="userForm" action="/oa/user/save" method="get">
用户名:
<input type="text" name="username"/>
<br><br>
性 别:
<input type="radio" name="gender" value="1"/>男
<input type="radio" name="gender" value="0"/>女
<br><br>
兴 趣:
<input type="checkbox" name="interest" value="music"/>音乐
<input type="checkbox" name="interest" value="sport"/>运动
<input type="checkbox" name="interest" value="food"/>美食
<input type="checkbox" name="interest" value="sleep"/>睡觉
<input type="checkbox" name="interest" value="travel"/>旅游
<br><br>
<input type="submit" value="保存"/>
<input type="reset" value="重置"/>
</form>
</body>
</html>
解析服务器中的Web.xml配置文件及处理业务类
<?xml version="1.0" encoding="UTF-8"?>
<web-app>
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>org.bjpowernode.oa.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>UserSaveServlet</servlet-name>
<servlet-class>org.bjpowernode.oa.servlet.UserSaveServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserSaveServlet</servlet-name>
<url-pattern>/user/save</url-pattern>
</servlet-mapping>
</web-app>
package com.bjpowernode.httpserver.core;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class WebParser {
public static Map<String,Map<String,String>> servletMaps= new HashMap<String,Map<String,String>>();
public static void parser(String[] webAppNames) throws DocumentException{
for(String webAppName:webAppNames){
Map<String,String> servletMap=parser(webAppName);
servletMaps.put(webAppName, servletMap);
}
}
private static Map<String,String> parser(String webAppName) throws DocumentException{
String webPath = webAppName + "/WEB-INF/web.xml";
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File(webPath));
List<Element> servletNodes = document.selectNodes("/web-app/servlet");
Map<String,String> servletInfoMap = new HashMap<String,String>();
for(Element servletNode:servletNodes){
Element servletNameElt = (Element) servletNode.selectSingleNode("servlet-name");
String servletName= servletNameElt.getStringValue();
Element servletClassElt = (Element) servletNode.selectSingleNode("servlet-class");
String servletClassName= servletClassElt.getStringValue();
servletInfoMap.put(servletName, servletClassName);
}
List<Element> servletMappingNodes= document.selectNodes("/web-app/servlet-mapping");
Map<String,String> servletMappingInfoMap = new HashMap<String,String>();
for(Element servletMappingNode:servletMappingNodes){
Element servletNameElt = (Element)servletMappingNode.selectSingleNode("servlet-name");
String servletName = servletNameElt.getStringValue();
Element urlPatternElt = (Element)servletMappingNode.selectSingleNode("url-pattern");
String urlPattern = urlPatternElt.getStringValue();
servletMappingInfoMap.put(servletName, urlPattern);
}
Set<String> servletNames = servletInfoMap.keySet();
Map<String,String> servletMap=new HashMap<String,String>();
for(String servletName:servletNames){
String urlPattern = servletMappingInfoMap.get(servletName);
String servletClassName = servletInfoMap.get(servletName);
servletMap.put(urlPattern, servletClassName);
}
return servletMap;
}
}
package org.bjpowernode.oa.servlet;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import com.bjpowernode.httpserver.core.RequestObject;
import com.bjpowernode.httpserver.core.ResponseObject;
public class LoginServlet implements Servlet{
public void service(ServletRequest request,ServletResponse response){
System.out.println("正在验证身份,请稍等.....");
PrintWriter out = response.getWriter();
out.print("<html>");
out.print("<head>");
out.print("<title>正在验证</title>");
out.print("<meta content='text/heml;charset=utf-8'/>");
out.print("</head>");
out.print("<body>");
out.print("<center><font size='35px' color='blue'>正在验证身份,请稍等...</font></center>");
out.print("</body>");
out.print("</html>");
}
}
package org.bjpowernode.oa.servlet;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import com.bjpowernode.httpserver.core.RequestObject;
public class UserSaveServlet implements Servlet{
@Override
public void service(ServletRequest request, ServletResponse response) {
String username = request.getParameterValue("username");
String gender = request.getParameterValue("gender");
String[] interest = request.getParameterValues("interest");
StringBuilder interests = new StringBuilder();
for(String interestValue:interest){
interests.append(interestValue).append(" ");
}
PrintWriter out = response.getWriter();
out.print("<html>");
out.print("<head>");
out.print("<title>用户信息</title>");
out.print("<meta content='text/html;charset=utf-8'/>");
out.print("</head>");
out.print("<body>");
out.print("用户名:"+username+"<br>");
out.print("性别:"+gender+"<br>");
out.print("兴趣:"+interests);
out.print("</body>");
out.print("</html>");
}
}
封装请求与响应参数
package com.bjpowernode.httpserver.core;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletRequest;
public class RequestObject implements ServletRequest{
public Map<String,String[]> parameterMap = new HashMap<String,String[]>();
public RequestObject(String requestURI){
if(requestURI.contains("?")){
String[] uriAndData = requestURI.split("[?]");
if(uriAndData.length>1){
String data=uriAndData[1];
if(data.contains("&")){
String[] nameAndValues = data.split("&");
for(String nameAndValue:nameAndValues){
String[] nameAndValueAttr = nameAndValue.split("=");
if(parameterMap.containsKey(nameAndValueAttr[0])){
String[] values = parameterMap.get(nameAndValueAttr[0]);
String[] newValues = new String[values.length + 1];
System.arraycopy(values, 0, newValues, 0, values.length);
if(nameAndValueAttr.length>1){
newValues[newValues.length-1]=nameAndValueAttr[1];
}else{
newValues[newValues.length-1]="";
}
parameterMap.put(nameAndValueAttr[0], newValues);
}else{
if(nameAndValueAttr.length>1){
parameterMap.put(nameAndValueAttr[0],new String[]{nameAndValueAttr[1]});
}else{
parameterMap.put(nameAndValueAttr[0],new String[]{""});
}
}
}
}else{
String[] nameAndValueAttr = data.split("=");
if(nameAndValueAttr.length>1){
parameterMap.put(nameAndValueAttr[0], new String[]{nameAndValueAttr[1]});
}else{
parameterMap.put(nameAndValueAttr[0], new String[]{""});
}
}
}
}
}
public String getParameterValue(String key){
String[] value = parameterMap.get(key);
return (value!=null && value.length != 0)?value[0]:null;
}
public String[] getParameterValues(String key){
return parameterMap.get(key);
}
}
package com.bjpowernode.httpserver.core;
import java.io.PrintWriter;
import javax.servlet.ServletResponse;
public class ResponseObject implements ServletResponse{
private PrintWriter out;
public void setWriter(PrintWriter out){
this.out=out;
}
public PrintWriter getWriter(){
return out;
}
}
三个接口
package javax.servlet;
public interface Servlet {
void service(ServletRequest request, ServletResponse response);
}
package javax.servlet;
public interface ServletRequest {
String getParameterValue(String key);
String[] getParameterValues(String key);
}
package javax.servlet;
import java.io.PrintWriter;
public interface ServletResponse {
void setWriter(PrintWriter out);
PrintWriter getWriter();
}
主程序入口与处理客户端请求
package com.bjpowernode.httpserver.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import com.bjpowernode.httpserver.util.Logger;
public class BootStrap {
public static void main(String[] args) {
start();
}
public static void start() {
ServerSocket serverSocket=null;
Socket clientSocket =null;
BufferedReader br=null;
try {
Logger.log("httpserver start");
long start =System.currentTimeMillis();
String[] webAppNames = {"oa"};
WebParser.parser(webAppNames);
int port=ServerParser.getPort();
Logger.log("httpserver-port: "+port);
serverSocket = new ServerSocket(port);
long end = System.currentTimeMillis();
Logger.log("httpserver started:"+(end-start)+"ms");
while(true){
clientSocket = serverSocket.accept();
new Thread(new HandlerRequest(clientSocket)).start();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
if(br!=null){
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(clientSocket!=null){
clientSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(serverSocket!=null){
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.bjpowernode.httpserver.core;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Map;
import javax.servlet.Servlet;
import org.bjpowernode.oa.servlet.LoginServlet;
import com.bjpowernode.httpserver.util.Logger;
public class HandlerRequest implements Runnable{
public Socket clientSocket;
public HandlerRequest(Socket clientSocket){
this.clientSocket=clientSocket;
}
@Override
public void run() {
BufferedReader br =null;
PrintWriter out=null;
Logger.log("httpserver thread: "+ Thread.currentThread().getName());
try {
br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out = new PrintWriter(clientSocket.getOutputStream());
String requestLine = br.readLine();
String requestURI = requestLine.split(" ")[1];
if(requestURI.endsWith(".html") || requestURI.endsWith(".htm")){
responseStaticPage(requestURI,out);
}else{
String servletPath=requestURI;
if(servletPath.contains("?")){
servletPath=servletPath.split("[?]")[0];
}
String webAppName= servletPath.split("[/]")[1];
Map<String,String> servletMap=WebParser.servletMaps.get(webAppName);
String urlPattern = servletPath.substring(1+webAppName.length());
String servletClassName = servletMap.get(urlPattern);
if(servletClassName!=null){
ResponseObject responseObject = new ResponseObject();
responseObject.setWriter(out);
RequestObject requestObject = new RequestObject(requestURI);
out.print("HTTP/1.1 200 OK\n");
out.print("Content-Type:text/html;charset=utf-8\n\n");
Servlet servlet = ServletCache.get(urlPattern);
if(servlet==null){
Class c =Class.forName(servletClassName);
Object obj = c.newInstance();
servlet= (Servlet)obj;
ServletCache.put(urlPattern, servlet);
}
servlet.service(requestObject,responseObject);
}else{
StringBuilder html = new StringBuilder();
html.append("HTTP/1.1 404 NotFound\n");
html.append("Content-Type:text/html;charset=utf-8\n\n");
html.append("<html>");
html.append("<head>");
html.append("<title>404-错误</title>");
html.append("<meta content='text/html;charset=utf-8'/>");
html.append("</head>");
html.append("<body>");
html.append("<center><font size='35px' color='red'>404-Not Found</font></center>");
html.append("</body>");
html.append("</html>");
out.print(html);
}
}
out.flush();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(out != null){
out.close();
}
try {
if(br!=null){
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(clientSocket!=null){
clientSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void responseStaticPage(String requestURI, PrintWriter out) {
String htmlPath = requestURI.substring(1);
BufferedReader br=null;
try {
br = new BufferedReader(new FileReader(htmlPath));
StringBuilder html = new StringBuilder();
html.append("HTTP/1.1 200 OK\n");
html.append("Content-Type:text/html;charset=utf-8\n\n");
String temp =null;
while((temp=br.readLine())!=null){
html.append(temp);
}
out.print(html);
} catch (FileNotFoundException e) {
StringBuilder html = new StringBuilder();
html.append("HTTP/1.1 404 NotFound\n");
html.append("Content-Type:text/html;charset=utf-8\n\n");
html.append("<html>");
html.append("<head>");
html.append("<title>404-错误</title>");
html.append("<meta content='text/html;charset=utf-8'/>");
html.append("</head>");
html.append("<body>");
html.append("<center><font size='35px' color='red'>404-Not Found</font></center>");
html.append("</body>");
html.append("</html>");
out.print(html);
} catch (IOException e) {
e.printStackTrace();
}
}
}
日志
package com.bjpowernode.httpserver.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
private DateUtil(){}
public static String getCurrentTime(){
return dateFormat.format(new Date());
}
}
package com.bjpowernode.httpserver.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Logger {
private Logger(){
}
public static void log(String msg){
System.out.println("[INFO] "+DateUtil.getCurrentTime() + " "+msg);
}
}
缓冲池
package com.bjpowernode.httpserver.core;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Servlet;
public class ServletCache {
private static Map<String,Servlet> servletMap = new HashMap<String,Servlet>();
public static void put(String urlPattern,Servlet servlet){
servletMap.put(urlPattern, servlet);
}
public static Servlet get(String urlPattern){
return servletMap.get(urlPattern);
}
}