手写服务器系列(5) 简单服务器优化——复杂请求的支持

     上一篇 博客中我们实现了一个简单的服务器,真是极其简单。实际场景中当然不可能只是访问一下http://localhost:8080/。本篇博客,我们的目的是优化简单服务器,让它支持复杂请求。

1. 优化HttpRequest

     我们先来看看,目前的服务器对复杂get请求的支持。我们通过浏览器访问地址  http://localhost:8080/hello.do?id=123&name=456  ,控制台输出如下:

可以看到,参数还是拼接在地址后面的,我们拿到的并不是纯粹的路径,所以第一个需要优化的地址,就是截取地址和解析参数了。下面是修改后的HttpRequest:

package com.zlyx.easy.server.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

public class HttpRequest {

	/**
	 * 请求方式
	 */
	private String method;

	/**
	 * http地址
	 */
	private String httpUrl;

	/**
	 * 请求地址
	 */
	private String requetUrl;;

	/**
	 * 参数
	 */
	private Map<String, String> paramMap = new HashMap<String, String>();

	public HttpRequest(InputStream in) throws IOException {
		InputStreamReader isReader = new InputStreamReader(in);
		BufferedReader bufferedReader = new BufferedReader(isReader);
		String string = bufferedReader.readLine();
		String[] httpInfos = string.split(" ");
		this.method = httpInfos[0];
		this.httpUrl = httpInfos[1];
		int indexOf = httpInfos[1].indexOf("?");
		if (indexOf != -1) {
			this.requetUrl = httpInfos[1].substring(0, indexOf);
			ResoveParams(httpInfos[1].substring(indexOf + 1));
		} else {
			this.requetUrl = httpInfos[1];
		}
	}

	private void ResoveParams(String str) {
		String[] params = str.split("&");
		for (String p : params) {
			String[] split = p.split("=");
			if (split[0] != null) {
				paramMap.put(split[0], split[1]);
			}
		}
	}

	public String getMethod() {
		return method;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public String getHttpUrl() {
		return httpUrl;
	}

	public void setHttpUrl(String httpUrl) {
		this.httpUrl = httpUrl;
	}

	public String getRequetUrl() {
		return requetUrl;
	}

	public void setRequetUrl(String requetUrl) {
		this.requetUrl = requetUrl;
	}

	public Map<String, String> getParamMap() {
		return paramMap;
	}

	public void setParamMap(Map<String, String> paramMap) {
		this.paramMap = paramMap;
	}

	@Override
	public String toString() {
		return "HttpRequest [method=" + method + ", httpUrl=" + httpUrl + ", requetUrl=" + requetUrl + ", paramMap="
				+ paramMap + "]";
	}

}

修改HttpServlet的doGet方法,如下:

	/**
	 * 处理get请求
	 * 
	 * @throws IOException
	 */
	public void doGet() throws IOException {
		System.out.println(request);
		response.write(String.valueOf(request.hashCode()));
	}

重新发起请求,控制台输出如下:

可以看到,我们得到了期望的结果。

2. 优化HttpServlet

实际场景中,请求方式有post、get等八种。目前我们只支持doGet,很明显这是不合理的。所以接下来,我们需要优化这部分内容,支持更多请求类型:

package com.zlyx.easy.server.servlet;

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

import com.zlyx.easy.server.http.HttpRequest;
import com.zlyx.easy.server.http.HttpResponse;

public class HttpServlet {

	private String method;

	private HttpRequest request;

	private HttpResponse response;

	private HttpServlet(HttpRequest request, HttpResponse response) throws IOException {
		this.request = request;
		this.response = response;
		this.method = request.getMethod();
	}

	/**
	 * 处理请求
	 * 
	 * @param request
	 * @param response
	 * @throws IOException
	 */
	private void doGet() throws IOException {
		System.out.println(request);
		response.write(String.valueOf(request.hashCode()));
	}

	public String getMethod() {
		return method;
	}

	public void setMethod(String method) {
		this.method = method;
	}

	public HttpRequest getRequest() {
		return request;
	}

	public void setRequest(HttpRequest request) {
		this.request = request;
	}

	public HttpResponse getResponse() {
		return response;
	}

	public void setResponse(HttpResponse response) {
		this.response = response;
	}

	public static void doService(Socket socket) throws IOException {
		HttpRequest request = new HttpRequest(socket.getInputStream());
		HttpResponse response = new HttpResponse(socket.getOutputStream());
		new HttpServlet(request, response).doGet();
	}

}

修改后的代码,HttpServlet构造方法被私有化,同时,对外提供doService()方法来完成方法调用(所有的请求类型都会走Get这条线路)。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值