- server.properties
port=9999
- web.properties
index=controller.IndexController
login=controller.LoginController
package server;
//出现的目的是为了定义一个规则
// 方法名字必须统一 服务器找寻的时候就方便啦
// 方法参数必须统一 request response
public abstract class HttpServlet {
public abstract void service(HttpServletRequest request,HttpServletResponse response);
}
package server;
import java.util.HashMap;
public class HttpServletRequest {
//自己创建的一个类型
//目的是为了存储 浏览器发送请求时携带的所有信息
private String content;
private HashMap<String,String> paramsMap;
public HttpServletRequest() {}
public HttpServletRequest(String content, HashMap<String, String> paramsMap) {
this.content = content;
this.paramsMap = paramsMap;
}
public String getParameter(String key){
return this.paramsMap.get(key);
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public void setParamsMap(HashMap<String, String> paramsMap) {
this.paramsMap = paramsMap;
}
}
package server;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class HttpServletResponse {
//自己创建的一个对象
//存储响应信息
private StringBuilder responseContent = new StringBuilder();
//直接添加相应信息
public void write(String str){
this.responseContent.append(str);
}
//让response读取一个文件 文件中的内容是响应信息
public void sendRedirect(String path){
try {
File file = new File("src//file//"+path);
BufferedReader reader = new BufferedReader(new FileReader(file));
String value = reader.readLine();
while(value!=null){
this.responseContent.append(value);
value = reader.readLine();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public String getResponseContent(){
return this.responseContent.toString();
}
}
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public void startServer(){
try {
System.out.println("====启动服务器====");
//获取配置文件中的port号码
int port = Integer.parseInt(ServerFileReader.getValue("port"));
//自己创建一个服务
ServerSocket server = new ServerSocket(port);
while(true){
//等待某一个客户端过来连接
Socket socket = server.accept();
//启动一个线程 负责处理当前浏览器发送过来的消息
new ServerHandler(socket).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package server;
import java.io.*;
import java.net.Socket;
import java.util.HashMap;
public class ServerHandler extends Thread {
private Socket socket;
public ServerHandler(Socket socket){
this.socket = socket;
}
public void run(){
this.receiveRequest();
}
//读取消息
private void receiveRequest(){
try {
InputStream is = socket.getInputStream();//最基本的字节流
InputStreamReader isr = new InputStreamReader(is);//将字节流转化成字符流
BufferedReader reader = new BufferedReader(isr);//包装成高级流 可以读取一行
//读取消息 content?key=value&key=value
String contentAndParams = reader.readLine();
//调用一个方法解析读取过来的信息
this.parseContentAndParams(contentAndParams);
} catch (IOException e) {
e.printStackTrace();
}
}
//解析
private void parseContentAndParams(String contentAndParams){
//创建两个变量 存储请求的资源名 携带的参数
String content = null;
HashMap<String,String> paramsMap = null;
// content?key=value&key=value
//找寻问号所在的位置
int questionMarkIndex = contentAndParams.indexOf("?");
//判断是否携带了参数
if(questionMarkIndex!=-1){
//携带了参数 截取问号前面的信息-->请求资源名 问号后面的信息拆分存入map集合里
content = contentAndParams.substring(0,questionMarkIndex);
paramsMap = new HashMap<String,String>();
//处理问号后面的参数 拆分存入map集合 key=value&key=value
String params = contentAndParams.substring(questionMarkIndex+1);
String[] keyAndValues = params.split("&");
for(String keyAndValue : keyAndValues){
String[] KV = keyAndValue.split("=");
paramsMap.put(KV[0],KV[1]);
}
}else{
//没有携带参数 请求发过来的信息就是完整的资源名
content = contentAndParams;
}
//-----至此将请求发送过来的字符串解析完毕(content,paramsMap)------------------
//自己创建两个对象
// 一个是为了包含所有请求携带的信息
// 另一个是为了接受响应回来的结果 创建时是空对象 在Controller执行完毕后 将其填满
HttpServletRequest request = new HttpServletRequest(content,paramsMap);
HttpServletResponse response = new HttpServletResponse();//空的
ServletController.findController(request,response);
//上面这个方法执行完毕 真实的Controller里面的那个service方法执行完了
//response对象中应该就有响应信息啦
this.responseToBrowser(response);
}
//将最终的响应信息 写回浏览器
private void responseToBrowser(HttpServletResponse response){
try {
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println(response.getResponseContent());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package server;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Properties;
//这个类的目的是为了管理 findController方法
//1.方法与之前服务器Handler做的事情不一致 抽离出来
//2.每一次找寻Controller类的时候都需要参考一下web.properties
// 读取文件性能会比较低 增加一个缓存机制
//3.每一个Controller类都是由findController方法来找寻
// 找到了Controller类的目的是为了执行里面的方法
// 让类中的方法有一个统一的规则----便于查找和使用
//4.发现Controller类与之前的Service和Dao相似 只有方法执行 没有属性
// 让Controller类的对象变成单例模式
public class ServletController {
//添加一个缓存 用来存储web.properties配置文件中的信息(请求名字=真实Controller类名)
private static HashMap<String,String> controllerNameMap = new HashMap<>();
//添加一个集合 存储被管理的所有Controller类对象
private static HashMap<String,HttpServlet> controllerObjectMap = new HashMap<>();
//延迟加载对象的方式
//创建一个静态块 在当前类加载的时候将配置文件中的所有信息读取出来存入缓存集合中
static{
try {
Properties pro = new Properties();
pro.load(new FileReader("src//web.properties"));
Enumeration en = pro.propertyNames();
while(en.hasMoreElements()){
String content = (String)en.nextElement();
String realControllerName = pro.getProperty(content);
controllerNameMap.put(content,realControllerName);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//找人干活---控制层 (controller action servlet)
//content----index map-----{{name,zzt},{},{}}
public static void findController(HttpServletRequest request,HttpServletResponse response){
//获取request对象中的请求名字
String content = request.getContent();
try {
//先去objectMap中找寻需要的对象
HttpServlet controllerObject = controllerObjectMap.get(content);
//若对象不存在 证明之前没有使用过
if(controllerObject==null){
//参考配置文件(缓存) 真实类名
String realControllerName = controllerNameMap.get(content);
//请求对应的真实类名是否存在
if(realControllerName!=null){
//反射获取类
Class clazz = Class.forName(realControllerName);
controllerObject = (HttpServlet) clazz.newInstance();
//将新创建的对象放在上面的对象集合内
controllerObjectMap.put(content,controllerObject);
}
}
//----以上可以确保controllerObject对象肯定存在-------------
//反射找寻类中的方法
Class controllerClass = controllerObject.getClass();
Method serviceMethod = controllerClass.getMethod("service",HttpServletRequest.class,HttpServletResponse.class);
serviceMethod.invoke(controllerObject,request,response);
} catch (ClassNotFoundException e) {
response.write("请求的"+content+"Controller不存在");
} catch (NoSuchMethodException e){
response.write("405 没有可以执行的方法");
} catch (Exception e){
e.printStackTrace();
}
}
}