上一篇说了一些必要的知识,下面就开始写我们的项目
1. ServerMain.java
存放main函数,调用各种方法
package cob.briup.webServer.v2_1.main;
import java.net.ServerSocket;
import java.net.Socket;
import cob.briup.webServer.v2_1.util.ServerInfo;
public class ServerMain {
public static void main(String[] args) {
ServerSocket server = null;
Socket socket = null;
try {
// 初始化变量
//从文件中读入端口号
server = new ServerSocket(Integer.parseInt(ServerInfo.getInfos("port")));
System.out.println("服务器启动,等待浏览器连接");
//while死循环,使服务器一直运行
while (true) {
socket = server.accept();
System.out.println("浏览器连接成功");
//多线程处理多个浏览器发来的请求
ServerHandler handler = new ServerHandler(socket);
//启动多线程
handler.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.ServerHandler.java
多线程处理多个浏览器发来的请求
package cob.briup.webServer.v2_1.main;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import cob.briup.webServer.v2_1.requst.Request;
import cob.briup.webServer.v2_1.response.Response;
import cob.briup.webServer.v2_1.util.BeanFactory;
import cob.briup.webServer.v2_1.util.ServerInfo;
import cob.briup.webServer.v2_1.webclass.WebClass;
public class ServerHandler extends Thread {
private Socket socket;
//处理浏览器发出的http请求,按行读入
private BufferedReader in = null;
private PrintStream out = null;
String errorPage = ServerInfo.getInfos("errorPage");
public ServerHandler(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintStream(socket.getOutputStream());
// 构建request对象,分析请求
Request request = new Request(in);
String res = request.getResource();
Response response = new Response(out);
/*
* if(程序){ 调用程序 }else if(文件){ 构建Response,调用
* doResponse(request.getResouse()) 返回数据 }
*/
if (res.contains(".bean")) {
System.out.println("调用程序");
// 1 先拿到资源名 .之前的内容
String key = res.substring(1, res.indexOf("."));
System.out.println("资源名:" + key);
WebClass wc = BeanFactory.getBean(key);
if (wc != null) {
wc.doService(request, response);
} else {
response.doResponse(errorPage);
}
} else {
System.out.println("查看文件");
response.doResponse(res);
}
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. Request.java
处理request请求的函数
package cob.briup.webServer.v2_1.requst;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Map;
public class Request {
/**
* 1.整合请求过程要用到的属性
*/
// http请求按行读入
private BufferedReader in = null;
// GET 还是 POST
private String method = null;
// 请求的资源名
private String resource = null;
// 接收页面数据
private Map<String, String> params = new HashMap<>();
/**
* 2.分析请求行,得到请求方式和请求资源 赋值给属性
*/
public Request(BufferedReader in) {
try {
// 分析资源
String requestLine = in.readLine();
// "".equals(requestLine)
// 如果请求行不是空字符串也不是null再进行处理
if (!"".equals(requestLine) && requestLine != null) {
System.out.println("请求行:" + requestLine);
String[] infos = requestLine.split(" ");
this.method = infos[0];
// infos[1]在get方式传参的时候
// 如果真的有参数,资源名?key=value&key2=value2
String value = infos[1];
if (getMethod().toUpperCase().equals("GET")) {
if (value.contains("?")) {
String kv = value.substring(value.indexOf("?") + 1);
parseParam(kv);
resource = value.substring(0, value.indexOf("?"));
} else {
resource = value;
}
} else if (getMethod().toUpperCase().equals("POST")) {
resource = value;
String line = null;
int requestBodyLen = 0;
// 读请求头,找有木有Content-length
while ((line = in.readLine()) != null) {
if (line.contains("Content-Length")) {
requestBodyLen = Integer.parseInt(line.substring(line.indexOf(":") + 1).trim());
}
if (line.equals("")) {
break;
}
}
// 按照字符读取请求体,再拼接成字符串
if (requestBodyLen > 0) {
// 拼接字符串使用StringBuffer
StringBuffer buff = new StringBuffer();
for (int i = 0; i < requestBodyLen; i++) {
buff.append((char) in.read());
}
parseParam(buff.toString());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 解析页面传来的参数放入map中
public void parseParam(String kv) {
// 先使用&拆分出一对key-value
String[] strkv = kv.split("&");
for (int i = 0; i < strkv.length; i++) {
// 再使用=拆分出一对key-value中的key和value
params.put(strkv[i].split("=")[0], strkv[i].split("=")[1]);
}
}
/**
* 3.提供get方法获取请求资源
*/
public String getResource() {
System.out.println("文件名:" + resource);
return resource;
}
public String getMethod() {
return method;
}
// 提供从私有map中获取参数value的方法
public String getParameter(String key) {
return params.get(key);
}
}
4.response.java
做出响应的函数
package cob.briup.webServer.v2_1.response;
import java.io.File;
import java.io.FileInputStream;
import java.io.PrintStream;
import cob.briup.webServer.v2_1.util.ServerInfo;
public class Response {
/**
* 1.整合响应过程要用到的属性
*/
// 数据仓库位置
private String storage = ServerInfo.getInfos("storage");
String indexPage = ServerInfo.getInfos("indexPage");
String errorPage = ServerInfo.getInfos("errorPage");
// 返还的文件
private File file = null;
private FileInputStream fis = null;
private PrintStream out = null;
/**
* 2.初始化属性
*/
public Response(PrintStream out) {
this.out = out;
}
/**
* 3.处理响应逻辑,将要返还给客户端的资源
*/
public void doResponse(String resource) {
try {
if (resource.equals("/")) {
resource = indexPage;
}
// 响应行
String responseLine = "HTTP/1.1 200 OK";
File file = new File(storage + "/" + resource);
if (!file.exists()) {
file = new File(storage + errorPage);
responseLine = "HTTP/1.1 404 NotFound";
}
// 文件存在,统一处理
// 通过fis读进程序,再通过socket响应给客户端
fis = new FileInputStream(file);
byte[] temp = new byte[1024];
out.println(responseLine);
// 空行
out.println();
// while循环负责写文件,相当于写响应体
while (fis.read(temp) != -1) {
out.write(temp);
out.flush();
}
// 文件输出完毕关闭输出流
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
5.BeanFactory.java
package cob.briup.webServer.v2_1.util;
//1.读取配置文件,将配置文件所描述的类,进行实例化
//2.提供生产方法,传入字符串拿出对应的对象
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import cob.briup.webServer.v2_1.webclass.WebClass;
public class BeanFactory {
static Properties beans = new Properties();
static Map<String, WebClass> objects = new HashMap<String, WebClass>();
static {
try {
// 从当前所在类的目录下找beans.properties文件
beans.load(BeanFactory.class.getResourceAsStream("beans.properties"));
Set<Object> keys = beans.keySet();
Iterator<Object> it = keys.iterator();
while (it.hasNext()) {
String key = (String) it.next();
String className = beans.getProperty(key);
Object o = Class.forName(className).newInstance();
objects.put(key, (WebClass) o);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static WebClass getBean(String beanName) {
return objects.get(beanName);
}
}
6. ServerInfo.java
package cob.briup.webServer.v2_1.util;
import java.io.IOException;
import java.util.Properties;
public class ServerInfo {
static Properties infos = new Properties();
static {
try {
infos.load(ServerInfo.class.getResourceAsStream("infos.properties"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getInfos(String key) {
return infos.getProperty(key);
}
}
7. WebClass.java
package cob.briup.webServer.v2_1.webclass;
import cob.briup.webServer.v2_1.requst.Request;
import cob.briup.webServer.v2_1.response.Response;
//能被客户端访问的服务端的类必须包含某个特定方法
//定义接口,接口中包含doService()方法
public interface WebClass {
public void doService(Request request, Response response);
}
8.LoginWebClass
用于控制登录的类
package cob.briup.webServer.v2_1.webclass;
import cob.briup.webServer.v2_1.webclass.WebClass;
import java.io.IOException;
import java.util.Properties;
import cob.briup.webServer.v2_1.requst.Request;
import cob.briup.webServer.v2_1.response.Response;
import cob.briup.webServer.v2_1.util.ServerInfo;
public class LoginWebClass implements WebClass {
static Properties users = new Properties();
static {
try {
users.load(LoginWebClass.class.getResourceAsStream("userInfo.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void doService(Request request, Response response) {
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("页面用户名:" + username + "\t" + "页面密码:" + password);
String psd = users.getProperty(username);
System.out.println("文件用户名:" + username + "\t" + "文件密码:" + psd);
if (psd == null || username == null) {
System.out.println("用户不存在");
response.doResponse(ServerInfo.getInfos("loginFailP"));
} else if (psd != null) {
if (psd.equals(password)) {
System.out.println("用户存在且密码正确");
response.doResponse(ServerInfo.getInfos("loginSucceedP"));
} else if (psd != password) {
System.out.println("用户名存在但是密码不正确");
response.doResponse(ServerInfo.getInfos("loginFailP"));
}
}
}
}
9.RegisterWebClass
用于控制注册的类
package cob.briup.webServer.v2_1.webclass;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;
import cob.briup.webServer.v2_1.requst.Request;
import cob.briup.webServer.v2_1.response.Response;
import cob.briup.webServer.v2_1.util.ServerInfo;
public class RegisterWebClass implements WebClass {
static Properties users = new Properties();
PrintWriter writeUserInfo = null;
boolean userExists = false;
static {
try {
users.load(LoginWebClass.class.getResourceAsStream("userInfo.properties"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void doService(Request request, Response response) {
String username = request.getParameter("username");
String password = request.getParameter("password");
String path = "F:\\杰普培训\\code\\JD1710_MyWebServer\\src\\cob\\briup\\webServer\\v2_1\\webclass\\userInfo.properties";
File userInfo = new File(path);
Set<Object> keySet = users.keySet();
for (Object o : keySet) {
if (o.equals(username)) {
userExists = true;
}
}
try {
if (!userExists) {
writeUserInfo = new PrintWriter(new FileWriter(userInfo, true));
writeUserInfo.println(username + "=" + password);
writeUserInfo.flush();
writeUserInfo.close();
response.doResponse(ServerInfo.getInfos("loginP"));
} else {
System.out.println("要注册的用户已经存在");
response.doResponse(ServerInfo.getInfos("regisFailP"));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(userInfo.exists());
}
}
10.运行结果
10.1 服务器开启
10.2浏览器访问默认资源
10.3浏览器访问服务器没有的资源
10.4
注册功能
注册失败
10.5
登录功能
登录成功
登录失败