前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第13次文章:网络编程——httpserver服务器的搭建(中)

第13次文章:网络编程——httpserver服务器的搭建(中)

作者头像
鹏-程-万-里
发布2019-09-27 12:15:11
3460
发布2019-09-27 12:15:11
举报

这周的代码出了点问题,目前还没有调试完全,就先不把所有代码都粘贴上来了。下周默默的去调代码了!

对于上周的一个总结:

在上周我们搭建的服务器,仅仅具有一个传输一个界面的功能。在实际应用中,对于同一份资源的访问,往往可以通过多条路径进行访问,而且可以处理多个不同的请求。这些需求,就导致了我们在搭建服务器的时候,需要逐步去完善服务器的功能。

一、对于多请求的处理——多态

我们模拟一个具有注册和登录功能的网页,首先我们定义一个抽象类Servlet,为后面的具体功能实现提供一个规范的编写方法,然后再创建具体的注册和登录类,实现网页多请求处理,也就是多态。

第一步:创建抽象类Servlet

代码语言:javascript
复制
package com.peng.server.demo03;
/**
 * 抽象为一个父类
 */
public abstract class Servlet {
  public void service(Response rep,Request req) throws Exception{
    this.doGet(rep,req);
    this.doPost(rep,req);
  } 
  public abstract void doGet(Response rep,Request req) throws Exception;
  public abstract void doPost(Response rep,Request req) throws Exception;
}

第二步:创建登录类

代码语言:javascript
复制
package com.peng.server.demo03;
/**
 * 登录界面
 */
public class LoginServlet extends Servlet {
  @Override
  public void doGet(Response rep, Request req) throws Exception {
    String name = req.getParameter("uname");
    String pwd = req.getParameter("pwd");
    if(login(name,pwd)) {
      rep.println("登陆成功");
    }else {
      rep.println("登录失败");
    }
  }  
  public boolean login(String name,String pwd) {
    return name.equals("peng") && pwd.equals("123456");    
  }
  @Override
  public void doPost(Response rep, Request req) throws Exception {
    // TODO Auto-generated method stub
  }
}

第三步:创建注册类

代码语言:javascript
复制
package com.peng.server.demo03;
public class RegisterServlet extends Servlet{
  @Override
  public void doGet(Response rep, Request req) throws Exception {
    // TODO Auto-generated method stub   
  }
  @Override
  public void doPost(Response rep, Request req) throws Exception {
    rep.println("<html><head><title>返回注册</title>");
    rep.println("</head><body>");
    rep.println("你的用户名为:"+req.getParameter("uname"));
    rep.println("</body></html>"); 
  }
}

二、多条路径访问同一份资源

在实际情况下,对于同一份资源或者说文件的访问,往往具有多条路径可以指向目的地,所以我们需要解决多条路径访问同一份资源的问题。我们可以设想一下相关的解决方案,为了满足多条路径访问同一份资源,简单的思路就是多对一的解决方案。所以我们可以使用容器来解决这个问题,在容器的选择上,我们使用键值对map来存储目标资源和相关的所有路径,只要在键值对存在着相关路径,那么我们就可以在键值对map上进行搜索,然后将键值对中对应的键取出来,与其相对应的值进行比对。具体实现如下:

第一步:建立一个上下文,由于我们所有的网页信息均在Servlet中进行实现,所以,我们首先使用一个map为每个多态类别起一个别名,在后面的存储的时候,方便直接存储字符串,而不是存储整个类。然后再使用一个map,用来存储不同路径与Servlet类别的映射关系。根据每一条不同的路径,直接进行映射到同一份资源处。

代码语言:javascript
复制
package com.peng.server.demo03;

import java.util.HashMap;
import java.util.Map;

/**
 * 上下文
 */
public class ServletContext {
  /**
   * 使用两个map的主要作用在于:可以对于同一份资源LoginServlet,首先为其取一个别名,
   * 然后可以使用多个路径访(/log --->login ||   /login --->login)问同一份资源LoginServlet
   */
  //为每一个servlet取一个别名
  //login ---> com.peng.server.LoginServlet
  private Map<String,String> servlet;
  // mapping作为一个映射,对于多个访问路径,指向同一份资源
  //  url --->login
  //    /log --->login
  //    /login --->login
  private Map<String,String> mapping;
  public ServletContext() {
    servlet = new HashMap<String,String>();
    mapping = new HashMap<String,String>();
  }

  //set和get方法
  public Map<String, String> getServlet() {
    return servlet;
  }
  public void setServlet(Map<String, String> servlet) {
    this.servlet = servlet;
  }
  public Map<String, String> getMapping() {
    return mapping;
  }
  public void setMapping(Map<String, String> mapping) {
    this.mapping = mapping;
  }
}

第二步:将关于登录和注册的路径存储在相关的map中,比如对于路径 : /login ,将访问: /login;对于路径 : /log ,将访问: /login;对于路径: /reg ,将访问: /register。

代码语言:javascript
复制
package com.peng.server.demo03;
import java.util.Map;
public class WebApp {
  private static ServletContext context;
  static {
    context = new ServletContext();  
    Map<String,String> mapping = context.getMapping();   
    /**
     * 传送路径:
     * 对于路径 : /login  ,将访问: /login
     * 对于路径 : /log  ,将访问: /login
     * 对于路径: /reg  ,将访问: /register
     */
    mapping.put("/login", "/login");
    mapping.put("/log", "/login");
    mapping.put("/reg", "/register");   
    Map<String,String> servlet = context.getServlet();
    servlet.put("login","com.peng.server.LoginServlet");
    servlet.put("register","com.peng.server.RegisterServlet");
  } 
  //使用了反射的动态属性
  public static Servlet getServlet(String url) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    if(null == url || (url=url.trim()).equals("")) {
      return null;
    }
    //根据字符串(完整路径)创建对象
    String name = context.getServlet().get(context.getMapping().get(url));
    return (Servlet)Class.forName(name).newInstance();//在动态使用的时候创建这个对象 确保空构造存在
  }
}

三、分发器的封装

由于整个网页的请求服务属于多线程处理,所以我们需要建立一个分发器,来进行对各个用户的请求与应答进行相关的处理。

代码语言:javascript
复制
package com.peng.server.demo03;

import java.io.IOException;
import java.net.Socket;
import com.peng.server.util.CloseUtil;

public class Dispatcher implements Runnable{
  
  private Socket client; 
  private Response rep;
  private Request req;
  private int code =200;
  
  public Dispatcher(Socket client) {
    this.client = client;
    try {
      req = new Request(client.getInputStream());
      rep = new Response(client.getOutputStream());
    } catch (IOException e) {
      code = 500;//报错后,将代码状态推送1个500出去,表示代码有问题
      return ;
    }
  }  
  
  @Override
  public void run() {
    try {
      Servlet serv = WebApp.getServlet(req.getUrl());//动态的通过访问地址获取访问相关资源
      if(null == serv) {
        this.code = 404; //找不到处理
      }else {
        serv.service(rep, req);
      }
      rep.pushToClient(code);
    } catch (Exception e) {
      //若此处报错,则继续尝试推送一个500出去
      this.code = 500;
    }    
    try {
      rep.pushToClient(500);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    CloseUtil.closeAll(client);
  }
}

四、关于反射的一点概念:

在我们将多条路径和目的地资源写入到map中时,我们使用了一点反射的概念。下面简单介绍一些关于反射的东西。

1、动态语言:在运行期间随意的改变对象的类型 +结构 例如:ruby js

java不是动态语言,但具有动态属性(反射)

2、反射 镜子

1)在编译器创建对象 new 完整类名 反射---->通过对象 找出类名

2)在运行期动态的创建对象 分析对象(属性、方法)

3)jvm在创建对象时自动生成与之对应Class对象,同一个类的多个对象在jvm只有一个与之对应的class对象

3、获取Class类别的几种常用方法

1)、可以看成类的元数据。每一个对象在创建的时候,jvm会自动生成一个与之对应的class。同类型的对象对应一个class

2)、获取class对象的三种方式

a、Object中的getClass方法 : 对象.getClass()

b、类.class形式 : 如student.class.

c、最常用,Class类的静态方法 :Class.forName("完整类名")


本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java小白成长之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档