实现一个简易版的Tomcat(九)

前言

在页面上显示一张图片,从中了解页面中含有其他资源时,浏览器与服务端的交互过程。


实现:

1:在webapps/myweb目录下保存一张图片,名字任意。


2:在webapps/myweb目录下的index.html页面上添加图片的展示。


3:通过浏览器访问服务端该页面查看图片的显示。

通过测试发现,当一个页面上含有其他资源时,浏览器要通过多次请求将这些资源全部下载后才能完整显示页面,而由于我们的服务端目前只接收一次请求,所以导致页面不能正确被下载以便展示。

解决办法:
由于服务端已经完成了整个请求的一问一答流程,因此我们现在可以在WebServer类中循环接收客户端的连接来处理多个不同的请求。

解决后在测试过程中会时不时出现数组下标越界异常,出现的位置是HttpRequest解析请求行时,为uri属性赋值,这里之前已经注释说明
过会发生该问题。

出现下标越界异常原因:

HTTP协议中对此说明:服务端应当忽略客户端的空请求问题。所谓空请求是指浏览器进行TCP连接后并没有发送一个请求过来而是直接断开了连接,对于这样的情况,服务端中ClientHandler就不应当执行处理流程中的三步:解析请求、处理请求、响应客户端的工作了,而是在解析请求时发现是空请求时直接忽略后续所有操作。

如何实现忽略?

浏览器与服务端建立连接后,WebServer会启动线程运行ClientHandler来处理该客户端交互,而ClientHandler三步操作完成一问一答,其中第一步就是解析请求。我们在HttpRequest解析请求中的解析请求行方法parseRequestLine 一上来就读取了第一行字符串(请求行内容),如果是空请求的话,那么读取这一行字符串拿到的应当是空字符串,所以我们可以根据这个特点判定当前请求是否为空请求。

既然发现空请求现象时HttpRequest中解析请求行的方法,那么如何最终让ClientHandler忽略后续的请求和响应客户端的工作?

ClientHandler的三步操作被一个异常处理机制控制着,异常处理机制有一个特点:当try中某句代码抛出了异常时,try语句块中后续代码都不执行而是直接跳到catch,我们是否可以利用这个特点来忽略处理请求和响应客户端呢?

结论:只要想办法在遇到空请求问题时让HttpRequest的构造方法抛出一个异常给ClientHandler就可以直接跳到catch忽略后续操作了!

我们可以再HttpRequest构造方法调用parseRequestLine方法这个流程中,让parseRequestLine读取第一行字符串后先判定是否是空字符串,如果是空字符串则抛出一个异常给构造方法,然后构造方法继续将这个异常抛出,就可以抛给ClientHanlder了!

抛出什么异常来表示空请求?Java没有现成的异常说明这个情况,所以用自定义异常来定义:EmptyRequestException表示空请求异常!

注意:抛异常的过程中,由于每个方法中基本都用try-catch,因此,用throw抛异常后是否会被自己的try-catch直接拦截了? 

解决思路:在catch中专门捕获空请求,捕获后再catch中接着用throw才能将该异常抛出到方法外,其他异常则留在本方法中处理。

实现:

1:在com.webserver.http包中定义一个自定义异常:EmptyRequestException;

2:在HttpRequest的解析请求行方法读取第一行字符串后加一个分支如果是空字符串就实例化空请求异常并抛出;

3:在HttpRequest的构造方法中继续将空请求异常抛出;

4:在ClientHandler中添加一个catch捕获空请求,捕获之后不需要做任何处理,目的只为了忽略try当中的处理请求和响应客户端。

注意:2/3步如果方法中catch了最大异常Exception的话也都需要在各自的catch中捕获空请求并throw才能实际将异常抛出去。


此版本解决了由于反复处理请求而导致解析请求时数组下标越界以及随之带来的空请求问题,下个版本将对响应头进行重构。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值