servlet接口
使用servlet编程需要实现或者继承实现了javax.servlet.Servlet接口的类,其中定义了5个签名方法:
1 public void init(ServletConfig config) throws ServletException2 public void service(ServletRequest req,ServletResponse res) throws ServletException,java.io.IOException3 public void destroy()4 public ServletConfig getServletConfig()5 public java.lang.String getServletInfo()
init(),service(),destroy对应着servlet的生命周期,init只在加载该servlet时执行且只此一次,容器根据用户请求调用对应servlet的service执行方法,当实例销毁移除前容器调用destroy处理后续操作。
模拟容器主要工作流程:
- 等待http请求
- 根据请求创建对应Request与Response对象
- 如果请求的是静态资源,则调用StaticResourceProcessor发送对应资源
- 如果请求是servlet,则加载该类并执行其service方法
简单servlet容器
主要类信息如下:
- HttpServer 与web服务器类似,不同的是加入了servlet请求判断,并调用ServletProcessor处理对应servlet
- Request 与上一篇web服务器类似,但是实现了ServletRequest接口
- Response 与上一篇web服务器类似,但是实现了ServletResponse接口
- StaticResourceProcessor 用于处理请求静态资源时调用
- ServletProcessor 用于当请求是servlet时调用
- Constant 定义一些常量
- MyLogger 自己定义在控制台打印日志信息,可以忽略
- PrimitiveServlet 实现servlet接口,自定义servlet程序用于请求调用
说明:部分接口只是实现了需要用到的方法,并没有完全实现所有方法,使用默认即可,代码里面没有贴出来
(一)HttpServer
1 public class HttpServer { 2 MyLogger logger = new MyLogger<>(HttpServer.class); 3 private static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; 4 private boolean shutdown = false; 5 6 public void await() { 7 ServerSocket serverSocket = null; 8 int port = 8080; 9 try {10 serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));11 logger.log("server started......." + "at " + serverSocket.toString());12 } catch (IOException e) {13 // TODO Auto-generated catch block14 e.printStackTrace();15 System.exit(1);16 }17 while (!shutdown){18 Socket socket = null;19 InputStream inputStream = null;20 OutputStream outputStream = null;21 try {22 socket = serverSocket.accept();23 logger.log("accepted new request...");24 inputStream = socket.getInputStream();25 outputStream = socket.getOutputStream();26 Request request = new Request(inputStream);27 request.Parse();28 Response response = new Response(outputStream);29 response.setRequest(request);30 logger.log("inition done,begin process.......");31 if(request.getUri() == null){32 logger.log("request uri is null...close socket");33 socket.close();34 continue;35 }36 else if(request.getUri().startsWith("/servlet/")){37 logger.log("execute servlet...");38 ServletProcessor servletProcessor = new ServletProcessor();39 servletProcessor.process(request, response);40 }41 else {42 logger.log("send staticResource...");43 StaticResourceProcessor staticResourceProcessor = new StaticResourceProcessor();44 staticResourceProcessor.process(request, response);45 }46 socket.close();47 shutdown = request.getUri().equals(SHUTDOWN_COMMAND);48 } catch (IOException e) {49 // TODO Auto-generated catch block50 e.printStackTrace();51 }52 }53 }54 }
(二)Request
1 public class Request implements ServletRequest{ 2 3 MyLogger logger = new MyLogger(ServletRequest.class); 4 private String uri; 5 private InputStream in; 6 7 public Request(InputStream in){ 8 this.in = in; 9 }10 11 public String parseUri(String request){12 int index1,index2;13 index1 = request.indexOf(" ");14 if (index1 != -1){15 index2 = request.indexOf(" ", index1+ 1);16 if (index1 < index2)17 return request.substring(index1 + 1, index2);18 }19 return null;20 }21 22 public void Parse(){23 StringBuffer request = new StringBuffer(2048);24 byte[] bs = new byte[2048];25 int i;26 try {27 i = in.read(bs);28 } catch (IOException e) {29 e.printStackTrace();30 i = -1;31 }32 33 for(int j=0; j
(三)Response
1 public class Response implements ServletResponse{ 2 3 MyLogger logger = new MyLogger(Response.class); 4 private static final int BUFFER_SIZE = 1024; 5 private Request request; 6 private OutputStream out; 7 private PrintWriter writer; 8 9 public Response(OutputStream out) {10 this.out = out;11 }12 13 public void setRequest(Request request) {14 this.request = request;15 }16 //假设请求的是图片资源17 public void sendStaticResource() throws IOException{18 byte[] buffer = new byte[BUFFER_SIZE];19 FileInputStream fis = null;20 File file = new File(Constant.WEB_ROOT, request.getUri());21 try {22 logger.log("Begin read file + " + file.toString());23 fis = new FileInputStream(file);24 String headerMsg = "HTTP/1.1 200 OK\r\n" + 25 "Content-Type: image/jpg\r\n" + 26 "Content-Length: " + file.length() + "\r\n" +27 "\r\n" ;28 logger.log("headerMsg->\r\n" + headerMsg);29 out.write(headerMsg.getBytes());30 int ch = fis.read(buffer, 0, BUFFER_SIZE);31 while (ch != -1){32 out.write(buffer, 0, BUFFER_SIZE);33 ch = fis.read(buffer, 0, BUFFER_SIZE);34 }35 } catch (FileNotFoundException e) {36 String html = "file not found
";37 logger.log("FileNotFoundException");38 String errorMsg = "HTTP/1.1 404 file not found\r\n" + 39 "Content-Type: text/html\r\n" + 40 "Content-Length: " + html.getBytes().length + "\r\n" +41 "\r\n" +42 html;43 out.write(errorMsg.getBytes());44 logger.log("errorMsg->" + errorMsg);45 }46 finally {47 if(fis != null){48 fis.close();49 }50 }51 }52 }
(四)StaticResourceProcessor
1 public class StaticResourceProcessor {2 public void process(Request request,Response response) {3 try {4 response.sendStaticResource();5 } catch (IOException e) {6 e.printStackTrace();7 }8 }9 }
(五)ServletProcessor
1 public class ServletProcessor { 2 public void process(Request request,Response response){ 3 String uri = request.getUri(); 4 String servletName = uri.substring(uri.lastIndexOf("/") + 1); 5 URLClassLoader loader = null; 6 7 URL[] urls = new URL[1]; 8 URLStreamHandler urlStreamHandler = null; 9 File classPath = new File(Constant.WEB_ROOT);10 try {11 String repository = (new URL("file",null,classPath.getCanonicalPath() + 12 File.separator)).toString();13 urls[0] = new URL(null,repository,urlStreamHandler);14 loader = new URLClassLoader(urls);15 } catch (IOException e) {16 // TODO Auto-generated catch block17 e.printStackTrace();18 }19 Class myClass = null;20 try {21 myClass = loader.loadClass(servletName);22 } catch (ClassNotFoundException e) {23 e.printStackTrace();24 }25 26 Servlet servlet = null;27 try {28 servlet = (Servlet) myClass.newInstance();29 servlet.service((ServletRequest)request, (ServletResponse) response);30 31 } catch (InstantiationException | IllegalAccessException e) {32 // TODO Auto-generated catch block33 e.printStackTrace();34 } catch (ServletException e) {35 // TODO Auto-generated catch block36 e.printStackTrace();37 } catch (IOException e) {38 // TODO Auto-generated catch block39 e.printStackTrace();40 }41 42 }43 }
(六)MyLogger
1 public class MyLogger{ 2 private String classStr = ""; 3 4 public void log(T msg){ 5 System.out.println(classStr + "(" + 6 (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date()) + ")" + ": " + msg); 7 } 8 public MyLogger(Class classz){ 9 classStr = classz.getName();10 }11 }
(七)PrimitiveServlet
1 public class PrimitiveServlet implements Servlet{ 2 MyLogger Logger = new MyLogger<>(PrimitiveServlet.class); 3 @Override 4 public void destroy() { 5 // TODO Auto-generated method stub 6 7 } 8 9 @Override10 public ServletConfig getServletConfig() {11 // TODO Auto-generated method stub12 return null;13 }14 15 @Override16 public String getServletInfo() {17 // TODO Auto-generated method stub18 return null;19 }20 21 @Override22 public void init(ServletConfig arg0) throws ServletException {23 // TODO Auto-generated method stub24 25 }26 27 @Override28 public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {29 Logger.log("service execute.....");30 PrintWriter writer = response.getWriter();31 writer.println("Hey,welcome on board!");32 writer.println("lets rock!");33 }34 35 }
(八)Constant
public class Constant { public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "bin";}