java nio http服务器(2)封装request和response对象

宦文柏
2023-12-01

在上一篇文章中,服务器只有一个简单的收发请求的类,我们可以把它理解为连接器。这篇文章我们来实现一下简单的request和response封装。

连接器

package com.hcserver.conn;

import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

import com.hcserver.core.OutputBuffer;
import com.hcserver.core.Request;
import com.hcserver.core.Response;
import com.hcserver.process.Process;

;
public class Server {

	public void start() throws Exception {
		Selector selector = Selector.open();
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		serverSocketChannel.configureBlocking(false);
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		serverSocketChannel.socket().setReuseAddress(true);
		serverSocketChannel.socket().bind(new InetSocketAddress(8084));
		while (true) {
			int select = selector.select();
			if (select == 0) {
				continue;
			}
			Iterator<SelectionKey> selectedKeys = selector.selectedKeys() .iterator();
			while (selectedKeys.hasNext()) {
				SelectionKey key = selectedKeys.next();
				if (key.isAcceptable()) {
					ServerSocketChannel ssc = (ServerSocketChannel) key .channel();
					SocketChannel channel = ssc.accept();
					if (channel != null) {
						channel.configureBlocking(false);
						channel.register(selector, SelectionKey.OP_READ);// 客户socket通道注册读操作
					}
				} else if (key.isReadable()) {
					SocketChannel channel = (SocketChannel) key.channel();
					channel.configureBlocking(false);

					//创建reqeust对象
					Request request = new Request(channel);
					request.parseHead();

					
					Response response = new Response(channel, selector);

					// 处理
					Process process = new Process();
					process.service(request, response);

				} else if (key.isWritable()) {
					SocketChannel channel = (SocketChannel) key.channel();
					OutputBuffer outputBuffer = (OutputBuffer) key.attachment();
					channel.write(outputBuffer.getBuffer());
					channel.shutdownOutput();
					channel.close();
				}
				selectedKeys.remove();
			}
		}
	}

}


request和response封装:

        按照规范我们需要实现HttpServletRequest接口和HttpServletResponse接口,这两个接口在Servlet-api.jar这个包中,可以在tomcat的lib目录下找到,也可以从网上下载。另外我们还需要实现自己的PrintWriter和Writer这两个类处理我们Response响应的数据。

request

package com.hcserver.core;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.security.Principal;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;

public class Request implements HttpServletRequest{

	private SocketChannel channel;
	private Head head;
	private Map<String,String> params = new HashMap<>();
	private String context;
	public Request(SocketChannel channel){
		this.channel = channel;
	}
	
	public void parseHead(){
		//TODO 解析请求头
		try {
			String receive = receive(this.channel);
			BufferedReader br = new BufferedReader(new StringReader(receive));
			this.head = new Head(br);
			this.head.parseHead();
			br.close();
			
			//解析参数
			parseParams();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private void parseParams(){
		String url = this.head.getRequestURL();
		this.context = url.substring(1,url.indexOf("?"));
		String params = url.substring(url.indexOf("?")+1,url.length());
		String[] split = params.split("&");
		for(String param : split){
			String[] split2 = param.split("=");
			this.params.put(split2[0], split2[1]);
		}
	}
	
	// 接受数据
	private String receive(SocketChannel socketChannel) throws Exception {
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		byte[] bytes = null;
		int size = 0;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		while ((size = socketChannel.read(buffer)) > 0) {
			buffer.flip();
			bytes = new byte[size];
			buffer.get(bytes);
			baos.write(bytes);
			buffer.clear();
		}
		bytes = baos.toByteArray();
		return new String(bytes);
	}
	
	
	@Override
	public String getParameter(String arg0) {
		return this.params.get(arg0);
	}
	
	@Override
	public String getContextPath() {
		return this.context.substring(0,context.indexOf("/"));
	}
	
	@Override
	public String getServletPath() {
		return this.context.substring(context.indexOf("/")+1,context.length());
	}
	
	
	@Override
	public ServletContext getServletContext() {
		return null;
	}
	

	@Override
	public AsyncContext getAsyncContext() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object getAttribute(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Enumeration<String> getAttributeNames() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getCharacterEncoding() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getContentLength() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getContentType() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public DispatcherType getDispatcherType() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getLocalAddr() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getLocalName() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getLocalPort() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public Locale getLocale() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Enumeration<Locale> getLocales() {
		// TODO Auto-generated method stub
		return null;
	}

	

	@Override
	public Map<String, String[]> getParameterMap() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Enumeration<String> getParameterNames() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String[] getParameterValues(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getProtocol() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public BufferedReader getReader() throws IOException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getRealPath(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getRemoteAddr() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getRemoteHost() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getRemotePort() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public RequestDispatcher getRequestDispatcher(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getScheme() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getServerName() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getServerPort() {
		// TODO Auto-generated method stub
		return 0;
	}

	

	@Override
	public boolean isAsyncStarted() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isAsyncSupported() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isSecure() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void removeAttribute(String arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setAttribute(String arg0, Object arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setCharacterEncoding(String arg0)
			throws UnsupportedEncodingException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public AsyncContext startAsync() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean authenticate(HttpServletResponse arg0) throws IOException,
			ServletException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public String getAuthType() {
		// TODO Auto-generated method stub
		return null;
	}

	

	@Override
	public Cookie[] getCookies() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public long getDateHeader(String arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getHeader(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Enumeration<String> getHeaderNames() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Enumeration<String> getHeaders(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getIntHeader(String arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getMethod() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Part getPart(String arg0) throws IOException, IllegalStateException,
			ServletException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Collection<Part> getParts() throws IOException,
			IllegalStateException, ServletException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getPathInfo() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getPathTranslated() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getQueryString() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getRemoteUser() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getRequestURI() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public StringBuffer getRequestURL() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getRequestedSessionId() {
		// TODO Auto-generated method stub
		return null;
	}

	

	@Override
	public HttpSession getSession() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public HttpSession getSession(boolean arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Principal getUserPrincipal() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isRequestedSessionIdFromCookie() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isRequestedSessionIdFromURL() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isRequestedSessionIdFromUrl() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isRequestedSessionIdValid() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isUserInRole(String arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void login(String arg0, String arg1) throws ServletException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void logout() throws ServletException {
		// TODO Auto-generated method stub
		
	}
	
	public static void main(String[] args) {
		String content = "hello/MyServlet";
		
		System.out.println(content.substring(0,content.indexOf("/")));
		System.out.println(content.substring(content.indexOf("/")+1,content.length()));
	}
	
	
}


 

response

package com.hcserver.core;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Collection;
import java.util.Locale;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;


public class Response implements HttpServletResponse{
	
	private SocketChannel channel;
	private Selector selector;
	
	public Response(SocketChannel channel,Selector selector){
		this.channel = channel;
		this.selector = selector;
	}
	
	
	@Override
	public PrintWriter getWriter() throws IOException {
		MyPrintWriter ww = new MyPrintWriter(new OutputBuffer(channel,selector));
		return ww;
	}

	
	@Override
	public void flushBuffer() throws IOException {
		// TODO Auto-generated method stub
		
	}
	@Override
	public int getBufferSize() {
		// TODO Auto-generated method stub
		return 0;
	}
	@Override
	public String getCharacterEncoding() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String getContentType() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public Locale getLocale() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		// TODO Auto-generated method stub
		
		return null;
	}
	@Override
	public boolean isCommitted() {
		// TODO Auto-generated method stub
		return false;
	}
	@Override
	public void reset() {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void resetBuffer() {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void setBufferSize(int arg0) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void setCharacterEncoding(String arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setContentLength(int arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setContentType(String arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setLocale(Locale arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void addCookie(Cookie arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void addDateHeader(String arg0, long arg1) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void addHeader(String arg0, String arg1) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void addIntHeader(String arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public boolean containsHeader(String arg0) {
		// TODO Auto-generated method stub
		return false;
	}


	@Override
	public String encodeRedirectURL(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public String encodeRedirectUrl(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public String encodeURL(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public String encodeUrl(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public String getHeader(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public Collection<String> getHeaderNames() {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public Collection<String> getHeaders(String arg0) {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public int getStatus() {
		// TODO Auto-generated method stub
		return 0;
	}


	@Override
	public void sendError(int arg0, String arg1) throws IOException {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void sendError(int arg0) throws IOException {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void sendRedirect(String arg0) throws IOException {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setDateHeader(String arg0, long arg1) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setHeader(String arg0, String arg1) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setIntHeader(String arg0, int arg1) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setStatus(int arg0, String arg1) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setStatus(int arg0) {
		// TODO Auto-generated method stub
		
	}
	
	
	
}


 

printwriter

package com.hcserver.core;

import java.io.PrintWriter;
import java.io.Writer;

public class MyPrintWriter extends PrintWriter{

	
	public MyPrintWriter(Writer write){
		super(write);
	}

	@Override
	public void print(String s) {
		super.print(s);
	}
	
}


 

Writer

package com.hcserver.core;

import java.io.IOException;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

public class OutputBuffer extends Writer{

	ByteBuffer buffer = ByteBuffer.allocate(1024);
	private SocketChannel channel;
	private Selector selector;
	
	public OutputBuffer(SocketChannel channel,Selector selector){
		this.channel = channel;
		this.selector = selector;
	}
	
	@Override
	public void write(char[] cbuf, int off, int len) throws IOException {
		String content = new String(cbuf);
		byte[] bytes = content.getBytes();
		buffer.put(bytes);
		buffer.flip();
		this.channel.register(selector, SelectionKey.OP_WRITE, this);
	}

	@Override
	public void flush() throws IOException {
		
	}

	@Override
	public void close() throws IOException {
		
	}

	public ByteBuffer getBuffer() {
		return buffer;
	}

	public void setBuffer(ByteBuffer buffer) {
		this.buffer = buffer;
	}
	
	
	
}


 

head请求头

package com.hcserver.core;

import java.io.BufferedReader;
import java.io.IOException;
/**
 * http 头信息
 * @author chuer
 * @date 2014-7-10 下午5:07:04
 * @version V1.0
 */
public class Head {
	public static final String ACCEPT = "Accept";
	public static final String ACCEPT_LANGUAGE = "Accept-Language";
	public static final String USER_AGENT = "User-Agent";
	public static final String ACCEPT_ENCODING = "Accept-Encoding";
	public static final String HOST = "Host";
	public static final String DNT = "DNT";
	public static final String CONNECTION = "Connection";
	public static final String COOKIE = "Cookie";
	private BufferedReader br;
	
	private String method;
	private String requestURL;
	private String protocol;
	private String agent;
	private String host;
	private int port;
	private String encoding;
	private String language;
	private String  accept;
	private String dnt;
	private String connection;
	private String cookie;
	
	public Head(BufferedReader br){
		this.br = br;
	}
	
	public void parseHead(){
		
		String s = null;
		try {
			s = br.readLine();//第一行
			String[] firstLine = s.split(" ");
			if(firstLine.length == 3){
				this.method = firstLine[0].trim();
				this.requestURL = firstLine[1].trim();
				this.protocol = firstLine[2].trim();
			}
			//继续读剩下的头信息
			s = br.readLine();
			while (s !=null) {
				String[] split = s.split(":");
				
				switch(split[0].trim()){
				case ACCEPT:{
					this.accept = split[1].trim();
				}
				case ACCEPT_LANGUAGE :{
					this.language = split[1].trim();
					break;
				}
				case USER_AGENT :{
					this.agent = split[1].trim();
					break;
				}
				case ACCEPT_ENCODING :{
					this.encoding = split[1].trim();
					break;
				}
				case HOST :{
					this.host = split[1].trim();
					break;
				}
				case DNT :{
					this.dnt = split[1].trim();
					break;
				}
				case CONNECTION :{
					this.connection = split[1].trim();
					break;
				}
				case COOKIE :{
					this.cookie = split[1].trim();
					break;
				}
				}
				s = br.readLine();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public String getMethod() {
		return method;
	}
	public void setMethod(String method) {
		this.method = method;
	}
	public String getRequestURL() {
		return requestURL;
	}
	public void setRequestURL(String requestURL) {
		this.requestURL = requestURL;
	}
	public String getProtocol() {
		return protocol;
	}
	public void setProtocol(String protocol) {
		this.protocol = protocol;
	}

	public String getAgent() {
		return agent;
	}

	public void setAgent(String agent) {
		this.agent = agent;
	}

	public String getHost() {
		return host;
	}

	public void setHost(String host) {
		this.host = host;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public String getLanguage() {
		return language;
	}

	public void setLanguage(String language) {
		this.language = language;
	}

	public String getAccept() {
		return accept;
	}

	public void setAccept(String accept) {
		this.accept = accept;
	}

	public String getDnt() {
		return dnt;
	}

	public void setDnt(String dnt) {
		this.dnt = dnt;
	}

	public String getConnection() {
		return connection;
	}

	public void setConnection(String connection) {
		this.connection = connection;
	}

	public String getCookie() {
		return cookie;
	}

	public void setCookie(String cookie) {
		this.cookie = cookie;
	}

	
	
}


处理类

package com.hcserver.process;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Process {
	
	
	public void service(HttpServletRequest request,HttpServletResponse response){
		String context = request.getContextPath();
		String servletPath = request.getServletPath();
		
		String aa = request.getParameter("aa");
		String bb = request.getParameter("bb");
		
		System.out.println("project name = "+context);
		System.out.println("sevlet name = "+servletPath);
		System.out.println("param aa = "+aa);
		System.out.println("param bb = "+bb);
		
		try {
			//返回页面
			response.getWriter().print("hello world...");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
}


 

启动类

package com.hcserver;

import com.hcserver.conn.Server;

public class ServerStartUp {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		Server server = new Server();
		
		server.start();
		
	}

}


启动服务器,浏览器,输入:http://localhost:8084/hello/MySevlet?aa=1&bb=3回车后浏览器显示 hello world..

后台输出

project name = hello
sevlet name = MySevlet
param aa = 1
param bb = 3


 

 

 类似资料: