学习内容》:

    //========学习内容=========
    请求与响应(2)
    请求与响应(3)

    《代码内容》:

    主要思路——> 通过反射配置文件 获取到请求的控制层类,并执行控制层

    //===================================================================================//

    服务器代码—->做了一个ServerHandler线程来模拟多浏览器同时访问服务器

    Server.Class

    1. package server;
    2. import java.io.IOException;
    3. import java.net.ServerSocket;
    4. import java.net.Socket;
    5. public class Server {
    6. public void startServer(){
    7. System.out.println("服务器启动中...");
    8. try {
    9. //服务器开放连接端口
    10. ServerSocket serverSocket = new ServerSocket(9999);
    11. while (true){
    12. Socket socket = serverSocket.accept();
    13. System.out.println("接收到一个新的请求");
    14. //可能有多个用户同时访问服务器,那么每个用户的socket请求过来都不一样
    15. //这里需要用到多线程并发的效果,设计一个线程来处理每个用户发过来的请求
    16. ServerHandler handler = new ServerHandler(socket);
    17. handler.start();
    18. }
    19. } catch (IOException e) {
    20. e.printStackTrace();
    21. }
    22. }
    23. }

    ServerHandler.Class——>线程类,处理每个请求

    1. package server;
    2. import controller.IndexController;
    3. import java.io.*;
    4. import java.lang.reflect.Method;
    5. import java.net.Socket;
    6. import java.util.HashMap;
    7. import java.util.Properties;
    8. public class ServerHandler extends Thread{
    9. private Socket socket = null;
    10. public ServerHandler(Socket socket){
    11. this.socket = socket;
    12. }
    13. //重写线程的run方法 也就是我们的Handler需要做的事情
    14. public void run(){
    15. /**
    16. * 分析:我们需要启动服务器后,通过socket获取流读取请求过来的资源名
    17. * 那么--->我们就设计一个方法 来读这个请求资源名
    18. * **/
    19. this.ReadRequestContentAndParams(socket);
    20. }
    21. //设计一个方法 来读取浏览器发送过来的请求
    22. private void ReadRequestContentAndParams(Socket socket) {
    23. try {
    24. //因为 浏览器 发送过来的是一行的信息--->资源名 用高级流来读取一行
    25. BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    26. //读取到的资源名和参数
    27. String contentAndParams = reader.readLine();
    28. System.out.println(contentAndParams);
    29. //现在我拿到了资源名和参数,我需要把他们做一个解析。
    30. this.parseContentAndParams(contentAndParams);
    31. } catch (IOException e) {
    32. e.printStackTrace();
    33. }
    34. }
    35. //设计一个方法 用来解析 资源名 和 参数
    36. private void parseContentAndParams(String contentAndParams) {
    37. //index?uname=武伟&upassword=123123
    38. String content = null;
    39. HashMap paramsMap = null;
    40. if (contentAndParams.contains("?")){
    41. content = contentAndParams.substring(0, contentAndParams.indexOf("?"));
    42. String[] params = contentAndParams.substring(content.length() + 1).split("&");
    43. for (String keyAndValue : params){
    44. String[] KV = keyAndValue.split("=");
    45. paramsMap = new HashMap<String,String>();
    46. paramsMap.put(KV[0],KV[1]);
    47. }
    48. }else{
    49. content = contentAndParams;
    50. }
    51. //解析完后 把解析好的资源名 和 参数 包装成一个request对象
    52. HttpServletRequest request = new HttpServletRequest(content,paramsMap);
    53. HttpServletResponse response = new HttpServletResponse();
    54. //解析好了之后 我们可以通过拿到的 资源名 去找 Controller
    55. this.findController(request,response);
    56. }
    57. //通过资源名拿到配置文件中对应的控制层的类全名,进行反射类全名,执行控制层方法
    58. private void findController(HttpServletRequest request,HttpServletResponse response) {
    59. Properties properties = new Properties();
    60. try {
    61. //加载配置文件
    62. properties.load(new FileReader("src/web.properties"));
    63. //通过配置文件的key找到对应的控制层的名字
    64. String realControllerName = properties.getProperty(request.getContent());
    65. //我拿到 类全名之后 进行反射然后执行对应的方法
    66. Class clazz = Class.forName(realControllerName);
    67. Object obj = clazz.newInstance();
    68. Method controllerMethod = clazz.getMethod("test", HttpServletRequest.class, HttpServletResponse.class);
    69. controllerMethod.invoke(obj,request,response);
    70. } catch (Exception e) {
    71. e.printStackTrace();
    72. }
    73. }
    74. }

    HttpServletRequest——->实体类对象, 用来包装 请求 资源名 和 参数

    1. package server;
    2. import java.util.HashMap;
    3. public class HttpServletRequest {
    4. /**
    5. * 这个类实体 用来存储 浏览器 请求过来的资源名和参数
    6. * **/
    7. private String content;
    8. private HashMap<String,String> paramsMap;
    9. public HttpServletRequest() {}
    10. public HttpServletRequest(String content, HashMap<String, String> paramsMap) {
    11. this.content = content;
    12. this.paramsMap = paramsMap;
    13. }
    14. public String getContent() {
    15. return content;
    16. }
    17. public void setContent(String content) {
    18. this.content = content;
    19. }
    20. public HashMap<String, String> getParamsMap() {
    21. return paramsMap;
    22. }
    23. public void setParamsMap(HashMap<String, String> paramsMap) {
    24. this.paramsMap = paramsMap;
    25. }
    26. @Override
    27. public String toString() {
    28. return "HttpServletRequest{" +
    29. "content='" + content + '\'' +
    30. ", paramsMap=" + paramsMap +
    31. '}';
    32. }
    33. }

    学习总结:
    学懂的:
    明白了最重要的地方

    (1)HttpServletRequest和HttpServletResponse对象是在接收到请求之后,将资源名解析,包装成Request对象
    而接收到请求后该如何响应回去,这里用Response对象来做参数最终Controller层执行后将Response已经填满响应信息
    那么久直接可以响应回去啦

    (2)在请求响应(2)这节课中 在优化上—-将配置文件中的信息做了缓存机制
    将对象做了缓存机制 —->如果对象不存在,就new一个放入缓存中,下次用的时候先判断有没有 并且static修饰
    这样这个对象是—->单例设计模式——>生命周期延迟加载方式

    有问题**的地方:
    今天的请求响应(2)没有封装,明天起来再写**