java实现自定义服务器

自定义服务器整个项目结构
在这里插入图片描述

  1. 自定义请求类MyHttpServletRequest,处理请求
package com.myserver;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 自定义请求类,处理请求
 * @author fang
 *
 */
public class MyHttpServletRequest {

	/**
	 * 请求的动作
	 */
	private String action;

	/**
	 * 存放请求的参数
	 */
	private Map<String, String> paramMap = new HashMap<String, String>();

	public MyHttpServletRequest() {
	}

	public MyHttpServletRequest(InputStream is) throws IOException {

		// 创建一个用来接收的数据盒子
		byte[] buf = new byte[1024];
		// 接收并返回长度
		int len = is.read(buf);
		if (len == 0) {
			return;
		}
		// 取得请求数据,进行解码,防止中文乱码
		String data = new String(buf, 0, len);
		data = URLDecoder.decode(data, "utf-8");
		// 处理GET请求
		if (data.startsWith("GET")) {
			// 判断是否带参数
			if (data.contains("?")) {
				// 取得参数的字符串
				String params = data.substring(data.indexOf("?") + 1, data.indexOf("HTTP/1.1") - 1);
				// 取得带参数的请求动作
				this.action = data.substring(data.indexOf("/"), data.indexOf("?"));
				// 解析取得请求动作,将取得请求的参数存放到HashMap中
				if (params != null && !"".equals(params)) {
					parseParams(params);
				}
			} else {
				this.action = data.substring(data.indexOf("/"), data.indexOf("HTTP") - 1);
			}

		}
		// 处理PSOT请求
		if (data.startsWith("POST")) {
			int start = data.indexOf("POST") + 6;
			int end = data.indexOf("HTTP/1.1") - 1;

			// 取得请求动作
			this.action = data.substring(start, end);

			// 最后一个换行符
			int beginIndex = data.lastIndexOf("\n") + 1;
			// 取得请求参数的字符串
			String params = data.substring(beginIndex);
			// 解析参数
			if (params != null && !"".equals(params)) {
				parseParams(params);
			}
		}

	}

	/**
	 * 解析参数,将取得请求的参数存放到HashMap中
	 * 
	 * @param params 参数字符串
	 * @return 请求动作
	 */
	private void parseParams(String params) {

		// 解析参数字符串
		if (params.contains("&")) {
			// 多个参数以&为分割符
			String[] temp = params.split("&");
			if (temp != null) {
				for (int i = 0; i < temp.length; i++) {
					// key=value的形式
					String[] t = temp[i].split("=");
					// 存入集合
					paramMap.put(t[0], t[1]);
				}
			}
		} else {
			String[] p = params.split("=");
			// 存入集合
			paramMap.put(p[0], p[1]);
		}
	}

	/**
	 * 取得请求的动作
	 * 
	 * @return action
	 */
	public String getAction() {
		return action;
	}

	/**
	 * 取得属性值
	 * 
	 * @param key 键值
	 * @return 属性值
	 */
	public String getAttributeValue(String key) {
		if (paramMap.size() <= 0) {
			return null;
		}
		return paramMap.get(key);
	}

	/**
	 * 设置属性
	 * 
	 * @param key   键值
	 * @param value 属性值
	 */
	public void setAttribute(String key, String value) {
		paramMap.put(key, value);
	}

	/**
	 * 移除属性
	 * 
	 * @param key 属性对应的键值
	 */
	public void removeAttribute(String key) {
		paramMap.remove(key);
	}

}

  1. 自定义响应类MyHttpServletResponse,响应请求
package com.myserver;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;

public class MyHttpServletResponse {

	/**
	 * 输出流
	 */
	private OutputStream os;

	/**
	 * 初始化OutputStream
	 * @param os 外部传入一个输出流
	 */
	public MyHttpServletResponse(OutputStream os) {
		this.os = os;
	}

	/**
	 * 打印流
	 * @return
	 */
	public PrintWriter getPrintWriter() {
		return new PrintWriter(os);
	}

	/**
	 * 将流写入到浏览器
	 * @param is
	 * @throws IOException
	 */
	public void write(InputStream is) throws IOException {
		BufferedInputStream bis=new BufferedInputStream(is);
		byte[] buf=new byte[1024];
		int len=0;
		while((len=bis.read(buf))!=-1) {
			os.write(buf, 0, len);
		}
		os.flush();
	}

	/**
	 * 转发
	 * @param filePath 文件地址
	 * @throws IOException
	 */
	public void forward(String filePath) throws IOException {
		if (filePath.startsWith("/")) {
			filePath="webContent"+filePath;
		}else {
			filePath="webContent"+File.separator+filePath;
		}
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream(filePath));
		byte[] buf=new byte[1024];
		int len=0;
		while((len=bis.read(buf))!=-1) {
			os.write(buf, 0, len);
		}
		bis.close();
		os.flush();
	}
}

  1. 定义处理请求线程类ProcessedThread
package com.myserver;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import com.servlet.LoginServlet;

/**
 * 定义处理请求线程类
 * 
 * @author fang
 *
 */
public class ProcessedThread implements Runnable {
	
	/**
	 * 客户端套接字
	 */
	private Socket socket = null;
	
	public ProcessedThread(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		InputStream is = null;
		OutputStream os = null;
		try {
			is = socket.getInputStream();
			if (is == null) {
				throw new NullPointerException();
			}
			os = socket.getOutputStream();
			if (os == null) {
				throw new NullPointerException();
			}
			// 创建响应对象实例
			MyHttpServletResponse response = new MyHttpServletResponse(os);
			// 创建请求对象
			MyHttpServletRequest request = new MyHttpServletRequest(is);
			// 取得请求动作
			String action = request.getAction();
			String filePath = null;
			if (action == null || "".equals(action)) {
				response.forward("404.html");
				return;
			}
			boolean result = isSuffix(action);
			// 处理静态业务类
			if (result) {
				filePath = "webContent" + request.getAction();
				File file = new File(filePath);
				if (!file.exists()) {
					response.forward("404.html");
					return;
				}
				response.write(new FileInputStream(filePath));

			}
			// 处理动态业务类
			if (!result) {
				if (action.endsWith("login.do")) {
					LoginServlet loginServlet = new LoginServlet();
					loginServlet.doService(request, response);
				}
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				os.close();
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	//静态业务 允许请求的后缀
	String[] suffixs = { ".html", ".js", ".css", ".jpg", ".ico" };

	public boolean isSuffix(String action) {
		boolean isAllow = false;
		// 判断是否有
		for (String suffix : suffixs) {
			if (action.endsWith(suffix)) {
				isAllow = true;
				break;
			}
		}
		return isAllow;
	}

}

  1. 实现自定义服务器类MyServer
package com.myserver;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 实现自定义服务器
 * @author fang
 *
 */
public class MyServer {
	/**
	 * 服务端套接字
	 */
	private ServerSocket serverSocket=null;
	/**
	 * 客户端套接字
	 */
	private Socket socket=null;
	
	/**
	 * 初始化服务器
	 * @param port 端口号 默认80
	 * @throws IOException
	 */
	public MyServer(int port) throws IOException {
		//开启服务端
		serverSocket=new ServerSocket(port);
		System.out.println("服务器开启成功");
		while(true) {
			//等待客户端连接
			socket=serverSocket.accept();
			//创建处理请求的线程
			ProcessedThread processedThread=new ProcessedThread(socket);
			//使用定长线程池
			ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
			//开始执行
			fixedThreadPool.execute(processedThread);
		}
	}
	public Socket getSocket() {
		return socket;
	}
	
	public static void main(String[] args) throws IOException {
		new MyServer(80);
	}

}
  1. 测试登录类
package com.servlet;

import java.io.FileNotFoundException;
import java.io.IOException;

import com.myserver.MyHttpServletRequest;
import com.myserver.MyHttpServletResponse;

/**
 * 测试登录
 * @author fang
 *
 */
public class LoginServlet {
	
	public void doService(MyHttpServletRequest request,MyHttpServletResponse response) throws FileNotFoundException, IOException{
		//取得帐号和密码
		String userName=request.getAttributeValue("userName");
		String password=request.getAttributeValue("password");
		if ("fangzi".equals(userName) && "666".equals(password)) {
			response.forward("/main.html");
		}else {
			response.forward("/failed.html");
		}
	}

}

前端页面
首页index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>欢迎界面</title>
</head>
<body>
	<h1>欢迎使用自定义服务器</h1>
</body>
</html>

登录界面login.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
	<h1>登录界面</h1>
	<form action="login.do" method="post">
		<p>
			账号:<input name="userName" />
		</p>
		<p>
			密码:<input name="password" />
		</p>

		<p>
			<button>登录</button>
		</p>
	</form>

</body>
</html>

登录成功main.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
	登录成功
</body>
</html>

登录失败failed.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录失败</title>
</head>
<body>
	<h1>账号或密码错误</h1>
	<hr>
	<p>
		<a href="login.html">返回</a>
	</p>
</body>
</html>

图标文件favicon.ico
注意:图标这个文件一定要有,可以新建一个文件后缀名设置为.ico

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值