182.手写服务器之请求参数解析处理

目标:将获取的参数封装成map结构

给request增加存储参数的map数据成员,将请求参数存储到容器中,并增加参数值支持中文的函数

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*
 * 封装请求协议:获取method uri以及请求参数
 * 封装请求参数为map
 */
public class request {
	//协议信息
	private String requestInfo;
	//请求方式
	private String method;
	//请求url
	private String url;
	//请求参数
	private String queryString;
	//存储参数map结构
	private Map<String, List<String>> parameterMap;
	
	private final String CRLF = "\r\n";
	public request(InputStream is) {
		parameterMap = new HashMap<String, List<String>>();
		byte[] datas = new byte[1024*1024];
		int len;
		try {
			len = is.read(datas); //*
			requestInfo = new String(datas, 0, len);
			//分解字符串
			parseRequestInfo();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public request(Socket client) throws IOException {
		this(client.getInputStream()); //构造器相互调用,this在首行异常只能throw
	}
	private void parseRequestInfo() {
		System.out.println(requestInfo);
		//获取请求方式:从开头到空格/
		method = requestInfo.substring(0, requestInfo.indexOf('/')).toLowerCase().trim(); //trim去除前后空格
		System.out.println(method);
		//获取url:第一个/到HTTP/
		url = requestInfo.substring(requestInfo.indexOf('/')+1, requestInfo.indexOf("HTTP/"));
		int queryIndex = url.indexOf('?');
		if(queryIndex > 0) { //存在请求参数
			String[] arr = url.split("\\?");
			url = arr[0];
			queryString = arr[1];
		}
		
		//get的话参数已获取完,post的参数可能在请求体中
		if(null == queryString)
			queryString = "";
		if(method.equals("post")) {
			String qString = this.requestInfo.substring(requestInfo.lastIndexOf(CRLF)).trim();
			queryString += "&" + qString;
		}
		
		//封装参数
		convertMap();
	}
	//处理中文
	private String decode(String value, String enc) {
		try {
			return java.net.URLDecoder.decode(value, enc);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}
	private void convertMap() {
		//参数之间是&分隔的
		String[] keySValues = queryString.split("&");
		for(String queryStr : keySValues) {
			String[] kv = queryStr.split("="); //可能存在没有值的情况
			kv = Arrays.copyOf(kv, 2); //保证kv有两个元素
			String valueString = kv[1] == null ? null : decode(kv[1], "utf-8");
			if(!parameterMap.containsKey(kv[0])){
				parameterMap.put(kv[0], new ArrayList<String>());
			}
			parameterMap.get(kv[0]).add(valueString);
		}
	}
	public String[] getparameterMap(String key) {
		List<String> values = parameterMap.get(key);
		if(null == values || values.size()<1)
			return null;
		return values.toArray(new String[0]);
	}
	public String getMethod() {
		return method;
	}
	public String getUrl() {
		return url;
	}
	public String getQueryString() {
		return queryString;
	}
}
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/*
 * 封装请求信息
 */
public class server03 {
	private ServerSocket serverSocket;
	public static void main(String[] args) {
		server03 s1 = new server03();
		s1.start();
	}
	//启动服务
	public void start() {
		try {
			serverSocket = new ServerSocket(8888);
			receive();
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("启动服务失败");
		}
	}
	//接受连接处理
	public void receive() {
		try {
			Socket clientSocket = serverSocket.accept();
			System.out.println("一个客户端建立了连接");
			//获取请求协议(没有请求资源的情况下可以返回一个主页html)
			request re = new request(clientSocket);
			String[] values = re.getparameterMap("uname");
			for(String str : values)
				System.out.println(str);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	//停止服务
	public void stop() {
			
	}
}

在request中增加的map结构的键是key,值是list结构的值 1,解决了键值一对多的情况

在这里插入图片描述

在这里插入图片描述


  1. 存储一个键的多个值 ↩︎

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页