用java实现初步的http服务器处理GET请求和POST请求。初步完成静态资源的GET相应。
主程序入口
import java.net.*;
import java.io.*;
public class JavaWeb{
/*
java 网络基础测试
*/
public static void main(String[] args) throws Exception {
/*———————————————Socket基本应用————————————————————*/
//创建ServerSocket对象监听6560端口
Thread[] threadpool = new Thread[5];
System.out.println(threadpool.length);
ServerSocket server = null;
try{
ApplicationConfig.getConfig("lib/ApplicationConfig.json");
int port = Integer.parseInt(ApplicationConfig.port);
if (port == 0){
port = 6660;
}
server = new ServerSocket(port);
//开始监听,阻塞等待连接
System.out.println("Socket start on port " + port +"......");
String sourcepath = "$HOME$/UI/";
if (ApplicationConfig.docpath != null && !ApplicationConfig.docpath.equals("")){
sourcepath = ApplicationConfig.docpath;
}
System.out.println("资源发布路径:" + sourcepath);
while(true){
Socket socket = server.accept();
if (socket.isConnected())
{
System.out.println("客户端 " + socket.getInetAddress().getHostAddress() + "已连接。");
DealClient dealclient = new DealClient(server,socket);
Thread dealrequest = new Thread(dealclient);
dealrequest.setName(socket.getInetAddress().getHostAddress() + "Deal");
dealrequest.start();
}
}
//关闭资源
//server.close();
}
catch(Exception e){
if (server != null) {
server.close();
}
e.printStackTrace();
}
}
}
处理请求线程
import java.net.*;
import java.io.*;
import java.util.*;
public class DealClient implements Runnable{
private ServerSocket server;
private Socket client;
public DealClient(ServerSocket server, Socket client){
this.server = server;
this.client = client;
}
public DealClient(){
//默认构造方法
}
public void run(){
try{
this.dealData();
}
catch(Exception e){
e.printStackTrace();
}
}
// 处理客户端请求主方法
private void dealData() throws Exception{
try{
InputStream reader = this.client.getInputStream();
OutputStream writer = this.client.getOutputStream();
byte[] buffer = new byte[1024];
int len = buffer.length;
StringBuffer requestdata = new StringBuffer();
while((len = reader.read(buffer)) > 0){
String line = new String(buffer,0,len);
requestdata.append(line);
if (len < buffer.length) break;
}
String requestdeodedata = URLDecoder.decode(requestdata.toString(),"UTF8");
String[] requestdatalist = requestdeodedata.split("\r\n");
if (requestdatalist.length > 0){
var basehandler = new HTTPBaseHandler();
String[] requestheaderlist = requestdatalist[0].split(" ");
basehandler.requestcontent.contenttext.put("Type",requestheaderlist[0]);
basehandler.requestcontent.contenttext.put("Url",requestheaderlist[1]);
basehandler.requestcontent.contenttext.put("HttpVersion",requestheaderlist[2]);
for (int i=1; i<requestdatalist.length; i++){
if (requestdatalist[i] == "") break;
basehandler.requestcontent.contenttext.put(requestdatalist[i].split(":")[0],requestdatalist[i].split(":")[1]);
}
String qryparamstr = "";
String reqpath = "";
if (requestheaderlist[0].equals("GET")){
if (requestheaderlist[1].indexOf("?") >= 0){
if (requestheaderlist[1].split("\\?").length > 1){
qryparamstr = requestheaderlist[1].split("\\?")[1];
}
reqpath = requestheaderlist[1].split("\\?")[0].substring(1);
if (qryparamstr != "" && qryparamstr != null){
for (int k=0; k<qryparamstr.split("&").length; k++){
if (qryparamstr.split("&")[k] == "" || qryparamstr.split("&")[k] == null) continue;
basehandler.requestcontent.requestparams.put(qryparamstr.split("&")[k].split("=")[0],qryparamstr.split("&")[k].split("=")[1]);
}
}
}else{
reqpath = requestheaderlist[1].substring(1);
}
}
if (requestheaderlist[0].equals("POST")){
if (requestheaderlist[1].indexOf("?") >= 0){
if (requestheaderlist[1].split("\\?").length > 1){
qryparamstr = requestheaderlist[1].split("\\?")[1];
}
reqpath = requestheaderlist[1].split("\\?")[0].substring(1);
if (qryparamstr != "" && qryparamstr != null){
for (int k=0; k<qryparamstr.split("&").length; k++){
if (qryparamstr.split("&")[k] == "" || qryparamstr.split("&")[k] == null) continue;
basehandler.requestcontent.requestparams.put(qryparamstr.split("&")[k].split("=")[0],qryparamstr.split("&")[k].split("=")[1]);
}
}
}else{
reqpath = requestheaderlist[1].substring(1);
}
if (requestdatalist[requestdatalist.length-1] != "" && requestdatalist[requestdatalist.length-1] != null){
String[] qryparamstrlist = requestdatalist[requestdatalist.length-1].split("&");
for (int j=0; j<qryparamstrlist.length; j++){
if (qryparamstrlist[j] == "" || qryparamstrlist[j] == null) continue;
basehandler.requestcontent.requestparams.put(qryparamstrlist[j].split("=")[0],qryparamstrlist[j].split("=")[1]);
}
}
}
System.out.println(reqpath);
if (reqpath.equals("") || reqpath == null || reqpath.equals("/")){
String header = this.getHeader("text/html");
String indexhtml = this.getIndexHtml();
writer.write(header.getBytes("UTF8"));
writer.flush();
writer.write(indexhtml.getBytes("UTF8"));
writer.flush();
writer.close();
reader.close();
}else if (reqpath.indexOf(".html") > 0 || reqpath.indexOf(".htm") > 0 || reqpath.indexOf(".HTML") > 0){
this.getStaticUISource(reqpath);
reader.close();
writer.close();
}else{
String header = this.getHeader("text/html");
String errhtml = this.getErrHtml("暂未处理该请求类型的资源,尽情期待。。。");
writer.write(header.getBytes("UTF8"));
writer.flush();
writer.write(errhtml.getBytes("UTF8"));
writer.flush();
writer.close();
reader.close();
}
}else{
String header = this.getHeader("text/html");
String errhtml = this.getErrHtml("请求url异常!");
writer.write(header.getBytes("UTF8"));
writer.flush();
writer.write(errhtml.getBytes("UTF8"));
writer.flush();
writer.close();
reader.close();
}
}
catch (Exception e){
e.printStackTrace();
}
}
//生成相应头
private String getHeader(String contenttype){
if (contenttype == "" || contenttype == null){
contenttype = "text/html";
}
String retheader = "";
retheader += "HTTP/1.1 200 OK\r\n";
retheader += ("Content-Type:" + contenttype + "; charset=utf-8\r\n");
retheader += "ServerName:MrWuHttpServer\r\n";
retheader += "ServerTime:" + new Date() + "\r\n";
retheader += "\r\n";
return retheader;
}
//生成html测试页
private String getIndexHtml(){
StringBuffer rethtml = new StringBuffer();
rethtml.append("<html>\r\n");
rethtml.append("<head>\r\n");
rethtml.append("<meta charset='utf-8'/>\r\n");
rethtml.append("<title>MrWuHppt Test</title>\r\n");
rethtml.append("</head>\r\n");
rethtml.append("<body style=\"text-align: center\">\r\n");
rethtml.append("<h2>MrWu's test page.</h2>\r\n");
rethtml.append("</body>\r\n");
rethtml.append("</html>");
return rethtml.toString();
}
//生成errhtml测试页
private String getErrHtml(String errinfo){
StringBuffer rethtml = new StringBuffer();
rethtml.append("<html>\r\n");
rethtml.append("<head>\r\n");
rethtml.append("<meta charset='utf-8'/>\r\n");
rethtml.append("<title>MrWuHppt request err!</title>\r\n");
rethtml.append("</head>\r\n");
rethtml.append("<body style=\"text-align: center\">\r\n");
rethtml.append("<h2 style=\"color: red\">" + errinfo + "</h2>\r\n");
rethtml.append("</body>\r\n");
rethtml.append("</html>");
return rethtml.toString();
}
//获取静态资源
private void getStaticUISource(String path) throws IOException{
OutputStream writer = this.client.getOutputStream();
String basepath = ApplicationConfig.docpath;
if (basepath == null || basepath == ""){
basepath = "UI/";
}
String sourcepath = basepath + path;
var file = new File(sourcepath);
try{
if (!file.exists() || file.isDirectory()){
String errfile = this.getErrHtml("请求资源url异常,资源不存在!");
String header = this.getHeader("text/html");
writer.write(header.getBytes("UTF8"));
writer.flush();
writer.write(errfile.getBytes("UTF8"));
writer.flush();
writer.close();
return ;
}
var accessfile = new RandomAccessFile(file,"r");
// 定位指针
accessfile.seek(0L);
/* *** 判断文件使用的编码
int charset = (accessfile.read() << 8) + accessfile.read();
String filecharset = "GBK";
switch(charset){
case 0xefbb: filecharset="UTF8"; break;
case 0xfffe: filecharset="Uniode"; break;
case 0xfeff: filecharset="UTF-16BE"; break;
case 0x5c75: filecharset="ANSI|ASCII"; break;
default: filecharset="GBK";
}
*/
//缓存区 缓存读取的文件字节流
var outarray = new ByteArrayOutputStream();
var buffer = new byte[1024];
int readnum = 0;
//循环读取
while ((readnum = accessfile.read(buffer)) != -1){
outarray.write(buffer,0,readnum);
//String readtext = new String(buffer,0,readnum,"UTF8");
//tempstring.append(line + "\r\n");
//System.out.println("读取文件内容" + readtext + "文件指针" + file.getFilePointer());
}
String header = this.getHeader("text/html");
writer.write(header.getBytes("UTF8"));
writer.flush();
//writer.write(html.getBytes("UTF8"));
writer.write(outarray.toByteArray());
writer.flush();
accessfile.close();
writer.close();
return;
}
catch(IOException e){
e.printStackTrace();
}
}
}
配置信息信息类
import java.util.*;
import java.io.*;
import java.lang.reflect.*;
public final class ApplicationConfig {
// 服务发布资源路径
public static String docpath;
// 服务发布端口
public static String port;
//解析配置文件设置配置类属性值
public static void getConfig(String filepath) throws Exception {
try{
var file = new File(filepath);
if (!file.exists() || file.isDirectory()) return;
var reader = new BufferedReader(new FileReader(file));
String line = null;
String lineall = "";
while((line = reader.readLine()) != null){
if (line == "" || line.equals("") || line.indexOf("<!--") >=0 ) continue;
String[] linelist = line.split(":");
if (linelist.length < 2) continue;
String key = linelist[0].trim();
String value = "";
if (linelist.length == 2){
value = linelist[1].substring(1,linelist[1].length()-1);
}else{
String valuestr = "";
for (int i=1; i<linelist.length; i++){
if (i == (linelist.length-1)){
valuestr += linelist[i];
}else{
valuestr += (linelist[i] + ":");
}
}
value = valuestr.substring(1,valuestr.length()-1);
}
Field[] fields = ApplicationConfig.class.getFields();
for (var field : fields) {
if (field.getName().equals(key)){
field.set(null,value);
}
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
配置文件内容
docpath:“E:/httpd/doct/”
port:“6560”