java自建服务器(二)

封装分发器_实现多线程

思路:

一个服务器,可能有多个客户端向其提交访问请求,所以这个服务器需要一直处于待机状态,每一个客户端请求和服务器响应都可能是不同的,所以我们创建一个类:Dispatcher类

开始修改

Server类的receive方法里,使用
Request req=new Request(client.getInputStream());获取请求
使用Response rep=new Response(client.getOutputStream());去获取响应,我们在Dispatcher类内将请求和响应的获取和发送进行封装

所以,我们也会对原有的Server类的receive方法做出一些改动

原来的start()方法和receive()方法

        //启动服务的方法 -- port是指端口
    public void start(int port){
      try {
          //启动服务
          server = new ServerSocket(port);
          //检测是否有客户机发送请求
          this.receive();//调用接收信息的方法

      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    
    //接收服务
    private void receive() {
        try {
            //监听
            Socket client = server.accept();
            //获取用户的请求   封装请求信息
            Request req=new Request(client.getInputStream());
            req.show();

            /**做出响应*/

            //调用封装后的响应方法
            Response rep=new Response(client.getOutputStream());
            //调用webApp类的servlet对象
            Servlet servlet=WebApp.getServlet(req.getUrl());
            int code=200;
            if (servlet==null) {
                code=404;
            }
        //调用Servlet中的服务的方法
            try {
                servlet.service(req, rep);
            } catch (Exception e) {
                e.printStackTrace();
            }
            rep.pushToClient(code);
            IOCloseUtil.closeAll(client);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

封装一个分发器,去创建一个多线程类:

package bjsxt.server;

import bjsxt.servlet.Servlet;
import bjsxt.util.IOCloseUtil;

import java.io.IOException;
import java.net.Socket;

/**
 * 一个请求和一个响应就是一个Dispatcher
 * 为其添加多线程的操作能力,添加Runnable接口
 *
 * 在Server类内,使用 Request req=new Request(client.getInputStream());获取请求
 * 使用Response rep=new Response(client.getOutputStream());获取响应
 */
public class Dispatcher implements Runnable{
    private Request req;
    private Response rep;
    private Socket client;
    private int code = 200;//状态码
    //构造方法初始化属性
    public Dispatcher(Socket client){
        //将局部变量的值赋给成员变量
        this.client = client;
        try {
            req = new Request(this.client.getInputStream());
            rep = new Response(this.client.getOutputStream());
        } catch (IOException e) {
           code=500;
           return;
        }
    }
    @Override
    public void run() {
        System.out.println("输出url:"+req.getUrl());
        //根据不同的url创建指定的Servlet对象
        Servlet servlet = WebApp.getServlet(req.getUrl());
        if (servlet==null){
            this.code=404;
        }else{
            //调用相应的Servlet中的service方法
            try {
                servlet.service(req,rep);
            } catch (Exception e) {
               this.code=500;
            }
        }
        //将响应结果推送到客户机的浏览器
        rep.pushToClient(code);
        IOCloseUtil.closeAll(client);
    }
}

在Server内创建一个boolean类型的变量

  private boolean isShutDown = false;//默认没有出错

修改start方法和receive方法:
对start方法启动服务时出现异常时如何处理进行修改
在receive方法内:
创建多线程对象

完善关闭服务器的方法stop()

    //启动服务的方法 -- port是指端口
    public void start(int port){
      try {
          //启动服务
          server = new ServerSocket(port);
          //检测是否有客户机发送请求
          this.receive();//调用接收信息的方法

      } catch (IOException e) {
          isShutDown=true;  //出现错误时,isShutDown为true
      }
    }
    //接收服务
    private void receive() {
        try {
            while (!isShutDown){//使用循环时刻监听是否有客户级的浏览器发送请求,在没有出现错误的情况下循环
                //监听
                Socket client = server.accept();
                //创建线程类的对象
                Dispatcher dis = new Dispatcher(client);
                //创建代理类并启动线程
                new Thread(dis).start();
            }

        } catch (IOException e) {
            //在使用请求与相应时出现错误
            this.stop();//将服务器关闭
        }
    }
    
      //关闭服务器的方法 -- 这里的IOCloseUtil方法来自bjsxt.util包下
    public void stop(){
        isShutDown=true;
        IOCloseUtil.closeAll(server);
    }

Server类最后修改结果:

package bjsxt.server;
 
import bjsxt.util.IOCloseUtil; 
import java.io.IOException; 
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务器,用于启动和停止服务
 */
public class Server {
    private ServerSocket server;
    private boolean isShutDown = false;//默认没有出错

    public static void main(String[] args) {
        Server server = new Server();
        server.start();
    }
    public void start(){
        this.start(9999);
    }
    //启动服务的方法 -- port是指端口
    public void start(int port){
      try {
          //启动服务
          server = new ServerSocket(port);
          //检测是否有客户机发送请求
          this.receive();//调用接收信息的方法

      } catch (IOException e) {
          isShutDown=true;  //出现错误时,isShutDown为true
      }
    }
    //接收服务
    private void receive() {
        try {
            while (!isShutDown){    //使用循环时刻监听是否有客户级的浏览器发送请求,在没有出现错误的情况下循环
                //监听
                Socket client = server.accept();
                //创建线程类的对象
                Dispatcher dis = new Dispatcher(client);
                //创建代理类并启动线程
                new Thread(dis).start();
            }

        } catch (IOException e) {
            //在使用请求与相应时出现错误
            this.stop();//将服务器关闭
        }
    }

      //关闭服务器的方法
    public void stop(){
        isShutDown=true;
        IOCloseUtil.closeAll(server);
    }
}

实现效果

当我们启动Server服务器类后,在浏览器第一次输入用户名和密码之后,自建服务器不会关闭,会一直运行
在这里插入图片描述

进行整合

本次整合,是将两个博文进行结合,对自建服务器的项目进行的一个整合

输出时多出一个/favicon.ico路径

关于这个路径为什么会出现,我们可以参考这个博文的解说
https://www.cnblogs.com/LoveJenny/archive/2012/05/22/2512683.html
下面,我们开始解决这个问题

原因分析

因为这个图标没有在XML内进行配置,没有对应的Servlet,所以就出现了一个空指针异常

开始解决

配置XML

<?xml version="1.0" encoding="UTF-8" ?>
<web-app>
<!-- 
	这里是以前的xml设置 
 -->
 
    <!-- 解决无法解析请求到的资源路径/favicon.ico报的空指针异常的问题 -->
    <servlet>
        <servlet-name>favicon</servlet-name>
        <servlet-class>bjsxt.servlet.faviconServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>favicon</servlet-name>
        <url-pattern>/favicon.ico</url-pattern>
    </servlet-mapping>
</web-app>

在bjsxt.servlet包下,添加一个faviconServlet类:

package bjsxt.servlet;

import bjsxt.server.Request;
import bjsxt.server.Response;

public class faviconServlet extends Servlet{
    @Override
    public void doGet(Request req, Response rep) throws Exception {

    }

    @Override
    public void doPost(Request req, Response rep) throws Exception {

    }
}

再次提交运行,异常被解决
在这里插入图片描述
至此,我们的服务器整合结束

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值