学习内容》:
//========学习内容=========
请求与响应(2)
请求与响应(3)
《代码内容》:
主要思路——> 通过反射配置文件 获取到请求的控制层类,并执行控制层
//===================================================================================//
服务器代码—->做了一个ServerHandler线程来模拟多浏览器同时访问服务器
Server.Class
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public void startServer(){
System.out.println("服务器启动中...");
try {
//服务器开放连接端口
ServerSocket serverSocket = new ServerSocket(9999);
while (true){
Socket socket = serverSocket.accept();
System.out.println("接收到一个新的请求");
//可能有多个用户同时访问服务器,那么每个用户的socket请求过来都不一样
//这里需要用到多线程并发的效果,设计一个线程来处理每个用户发过来的请求
ServerHandler handler = new ServerHandler(socket);
handler.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ServerHandler.Class——>线程类,处理每个请求
package server;
import controller.IndexController;
import java.io.*;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.HashMap;
import java.util.Properties;
public class ServerHandler extends Thread{
private Socket socket = null;
public ServerHandler(Socket socket){
this.socket = socket;
}
//重写线程的run方法 也就是我们的Handler需要做的事情
public void run(){
/**
* 分析:我们需要启动服务器后,通过socket获取流读取请求过来的资源名
* 那么--->我们就设计一个方法 来读这个请求资源名
* **/
this.ReadRequestContentAndParams(socket);
}
//设计一个方法 来读取浏览器发送过来的请求
private void ReadRequestContentAndParams(Socket socket) {
try {
//因为 浏览器 发送过来的是一行的信息--->资源名 用高级流来读取一行
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取到的资源名和参数
String contentAndParams = reader.readLine();
System.out.println(contentAndParams);
//现在我拿到了资源名和参数,我需要把他们做一个解析。
this.parseContentAndParams(contentAndParams);
} catch (IOException e) {
e.printStackTrace();
}
}
//设计一个方法 用来解析 资源名 和 参数
private void parseContentAndParams(String contentAndParams) {
//index?uname=武伟&upassword=123123
String content = null;
HashMap paramsMap = null;
if (contentAndParams.contains("?")){
content = contentAndParams.substring(0, contentAndParams.indexOf("?"));
String[] params = contentAndParams.substring(content.length() + 1).split("&");
for (String keyAndValue : params){
String[] KV = keyAndValue.split("=");
paramsMap = new HashMap<String,String>();
paramsMap.put(KV[0],KV[1]);
}
}else{
content = contentAndParams;
}
//解析完后 把解析好的资源名 和 参数 包装成一个request对象
HttpServletRequest request = new HttpServletRequest(content,paramsMap);
HttpServletResponse response = new HttpServletResponse();
//解析好了之后 我们可以通过拿到的 资源名 去找 Controller
this.findController(request,response);
}
//通过资源名拿到配置文件中对应的控制层的类全名,进行反射类全名,执行控制层方法
private void findController(HttpServletRequest request,HttpServletResponse response) {
Properties properties = new Properties();
try {
//加载配置文件
properties.load(new FileReader("src/web.properties"));
//通过配置文件的key找到对应的控制层的名字
String realControllerName = properties.getProperty(request.getContent());
//我拿到 类全名之后 进行反射然后执行对应的方法
Class clazz = Class.forName(realControllerName);
Object obj = clazz.newInstance();
Method controllerMethod = clazz.getMethod("test", HttpServletRequest.class, HttpServletResponse.class);
controllerMethod.invoke(obj,request,response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
HttpServletRequest——->实体类对象, 用来包装 请求 资源名 和 参数
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 getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public HashMap<String, String> getParamsMap() {
return paramsMap;
}
public void setParamsMap(HashMap<String, String> paramsMap) {
this.paramsMap = paramsMap;
}
@Override
public String toString() {
return "HttpServletRequest{" +
"content='" + content + '\'' +
", paramsMap=" + paramsMap +
'}';
}
}
学习总结:
学懂的:
明白了最重要的地方
(1)HttpServletRequest和HttpServletResponse对象是在接收到请求之后,将资源名解析,包装成Request对象
而接收到请求后该如何响应回去,这里用Response对象来做参数最终Controller层执行后将Response已经填满响应信息
那么久直接可以响应回去啦
(2)在请求响应(2)这节课中 在优化上—-将配置文件中的信息做了缓存机制
将对象做了缓存机制 —->如果对象不存在,就new一个放入缓存中,下次用的时候先判断有没有 并且static修饰
这样这个对象是—->单例设计模式——>生命周期延迟加载方式
有问题**的地方:
今天的请求响应(2)没有封装,明天起来再写**