实现一个简单的Servlet就是根据传过来的uri做解析,通过指定某个目录url,用URLClassLoader查找这个目录下的所有jar文件,并生产对应的字节码,最后通过Class类的
newInstance()方法实现这个类。
对Httpserver之前的代码进行修改public class HttpServer { public static final String WEB_ROOT = System.getProperty("user.dir")+File.separator + "webroot"; private static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; private boolean shutdown = false; public static void main(String[] args) { HttpServer server = new HttpServer(); server.awiat(); } public void awiat(){ try { ServerSocket serverSocket = new ServerSocket(8080,1,InetAddress.getByName("127.0.0.1")); while(!shutdown){ Socket socket = serverSocket.accept(); InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); Request request = new Request(inputStream); request.parse(); Response response = new Response(outputStream); response.setRequest(request); if(request.getUri()==null){ continue; } if(request.getUri().startsWith("/servlet/")){ ServletProcessor servletProcessor = new ServletProcessor(); servletProcessor.process(request,response); }else { response.sendStaticResource(); } socket.close(); shutdown = request.getUri().equals(SHUTDOWN_COMMAND); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
红色区域为变更部分,即根据传进来的uri中是否含有"/servlet/"来判断是返回静态文件还是servlet请求;
让Request类进行修改,让其实现SverletRequest接口。
让Response类实现ServletRespons接口并添加成员变量PrintWriter printWriter,并实现getWriter方法;
public PrintWriter getWriter() throws IOException { //println的任何调用都会刷新输出,但print方法调用不会 printWriter = new PrintWriter(outputStream,true); return printWriter; }
添加核心类ServletProcessor,用来处理请求用哪个类进行处理的:
public class ServletProcessor { public void process(Request request,Response response){ String uri = request.getUri(); String servletName = uri.substring(uri.lastIndexOf("/")+1); URLClassLoader loader = null; try{ URL[] urls = new URL[1]; URLStreamHandler streamHandler = null; System.out.println(System.getProperty("user.dir")+File.separator); File classPath = new File(System.getProperty("user.dir")+File.separator ); String repository = (new URL("file",null,classPath.getCanonicalPath()+ File.separatorChar)).toString(); urls[0] =new URL(null,repository,streamHandler); loader = new URLClassLoader(urls); }catch (Exception e){ e.printStackTrace(); } Class myclass = null; try { myclass = loader.loadClass("com.simple.webserver."+servletName); }catch (Exception e){ e.printStackTrace(); } Servlet servlet = null; try{ servlet =(Servlet) myclass.newInstance(); servlet.service((ServletRequest) request,(ServletResponse) response); }catch (Exception e){ e.printStackTrace(); } } }
最后写一个简单的业务类:
public class Primitiveservlet implements Servlet { @Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { PrintWriter printWriter = servletResponse.getWriter(); //之试用于IE浏览器,其他浏览器无法输出,需要拼装完整的Response返回体才可以 printWriter.println("Hello webserver"); printWriter.print("1111"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } }
这样用http://localhost:8080/servlet/Primitiveservlet就可以看到浏览器(IE,其他浏览器需要拼装完整的Response返回体)的输出了;
github:https://github.com/Mrfirewind/simpelwebserver