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