从tomcat角度解读play源代码
2016-07-06 16:02
344 查看
先来看下生成的web.xml 的文件
这里注意到启动的类是play.server.ServletWrapper,那么下面来看下源代码
初始化
销毁
每次请求时
注意下面的
处理response
处理代码
调用Invoker
<?xml version="1.0" ?> <web-app ....> <display-name>Play! (com.shovesoft.sp2p_shyw)</display-name> <context-param> <param-name>play.id</param-name> <param-value>war</param-value> </context-param> <listener> <listener-class>play.server.ServletWrapper</listener-class> </listener> <servlet> <servlet-name>play</servlet-name> <servlet-class>play.server.ServletWrapper</servlet-class> </servlet> <servlet-mapping> <servlet-name>play</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
这里注意到启动的类是play.server.ServletWrapper,那么下面来看下源代码
初始化
public class ServletWrapper extends HttpServlet implements ServletContextListener { public void contextInitialized(ServletContextEvent e) { Play.standalonePlayServer = false;//这个以后再看 //读取application的配置 File root = new File(e.getServletContext().getRealPath("/WEB-INF/application")); //从web.xml获取到play.id 的值 war final String playId = System.getProperty("play.id", e.getServletContext().getInitParameter("play.id")); //初始化 Play.frameworkPath = root.getParentFile(); Play.usePrecompiled = true; Play.init(root, playId); //下面根据application.conf 里的application.mode是否是DEV,就打印日志 //重新载入 Router.load(e.getServletContext().getContextPath()); } }
销毁
public void contextDestroyed(ServletContextEvent e) { Play.stop(); } public void destroy() { Logger.trace("ServletWrapper>destroy"); Play.stop(); }
每次请求时
protected void service(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException { try{ if (!routerInitializedWithContext) { Router.load((httpServletRequest.getContextPath()); } Request request = null; Response response = new Response(); response.out = new ByteArrayOutputStream(); Response.current.set(response); request = parseRequest(httpServletRequest); boolean raw = Play.pluginCollection.rawInvocation(request, response); if (raw) { copyResponse(Request.current(), Response.current(), httpServletRequest, httpServletResponse); } else { **Invoker.invokeInThread(new ServletInvocation(request, response, httpServletRequest, httpServletResponse));** } //以下都是处理异常的 }catch (NotFound e) { if (Logger.isTraceEnabled()) { Logger.trace("ServletWrapper>service, NotFound: " + e); } serve404(httpServletRequest, httpServletResponse, e); return; } catch (RenderStatic e) { if (Logger.isTraceEnabled()) { Logger.trace("ServletWrapper>service, RenderStatic: " + e); } serveStatic(httpServletResponse, httpServletRequest, e); return; } catch(URISyntaxException e) { serve404(httpServletRequest, httpServletResponse, new NotFound(e.toString())); return; } catch (Throwable e) { throw new ServletException(e); } finally { Request.current.remove(); Response.current.remove(); Scope.Session.current.remove(); Scope.Params.current.remove(); Scope.Flash.current.remove(); Scope.RenderArgs.current.remove(); Scope.RouteArgs.current.remove(); CachedBoundActionMethodArgs.clear(); } } public static Request parseRequest(HttpServletRequest httpServletRequest) throws Exception { URI uri = new URI(httpServletRequest.getRequestURI()); String method = httpServletRequest.getMethod().intern(); String path = uri.getPath(); String querystring = httpServletRequest.getQueryString() == null ? "" : httpServletRequest.getQueryString(); if (Logger.isTraceEnabled()) { Logger.trace("httpServletRequest.getContextPath(): " + httpServletRequest.getContextPath()); Logger.trace("request.path: " + path + ", request.querystring: " + querystring); } String contentType = null; if (httpServletRequest.getHeader("Content-Type") != null) { contentType = httpServletRequest.getHeader("Content-Type").split(";")[0].trim().toLowerCase().intern(); } else { contentType = "text/html".intern(); } if (httpServletRequest.getHeader("X-HTTP-Method-Override") != null) { method = httpServletRequest.getHeader("X-HTTP-Method-Override").intern(); } InputStream body = httpServletRequest.getInputStream(); boolean secure = httpServletRequest.isSecure(); String url = uri.toString() + (httpServletRequest.getQueryString() == null ? "" : "?" + httpServletRequest.getQueryString()); String host = httpServletRequest.getHeader("host"); int port = 0; String domain = null; if (host.contains(":")) { port = Integer.parseInt(host.split(":")[1]); domain = host.split(":")[0]; } else { port = 80; domain = host; } String remoteAddress = httpServletRequest.getRemoteAddr(); boolean isLoopback = host.matches("^127\\.0\\.0\\.1:?[0-9]*$"); final Request request = Request.createRequest( remoteAddress, method, path, querystring, contentType, body, url, host, isLoopback, port, domain, secure, getHeaders(httpServletRequest), getCookies(httpServletRequest)); Request.current.set(request); Router.routeOnlyStatic(request); return request; }
注意下面的
处理response
public void copyResponse(Request request, Response response, HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws IOException { String encoding = Response.current().encoding; if (response.contentType != null) { servletResponse.setHeader("Content-Type", response.contentType + (response.contentType.startsWith("text/") ? "; charset="+encoding : "")); } else { servletResponse.setHeader("Content-Type", "text/plain;charset="+encoding); } servletResponse.setStatus(response.status); if (!response.headers.containsKey("cache-control")) { servletResponse.setHeader("Cache-Control", "no-cache"); } Map<String, Http.Header> headers = response.headers; for (Map.Entry<String, Http.Header> entry : headers.entrySet()) { Http.Header hd = entry.getValue(); String key = entry.getKey(); for (String value : hd.values) { servletResponse.setHeader(key, value); } } Map<String, Http.Cookie> cookies = response.cookies; for (Http.Cookie cookie : cookies.values()) { Cookie c = new Cookie(cookie.name, cookie.value); c.setSecure(cookie.secure); c.setPath(cookie.path); if (cookie.domain != null) { c.setDomain(cookie.domain); } if (cookie.maxAge != null) { c.setMaxAge(cookie.maxAge); } servletResponse.addCookie(c); } // Content response.out.flush(); if (response.direct != null && response.direct instanceof File) { File file = (File) response.direct; servletResponse.setHeader("Content-Length", String.valueOf(file.length())); if (!request.method.equals("HEAD")) { copyStream(servletResponse, VirtualFile.open(file).inputstream()); } else { copyStream(servletResponse, new ByteArrayInputStream(new byte[0])); } b4a3 } else if (response.direct != null && response.direct instanceof InputStream) { copyStream(servletResponse, (InputStream) response.direct); } else { byte[] content = response.out.toByteArray(); servletResponse.setHeader("Content-Length", String.valueOf(content.length)); if (!request.method.equals("HEAD")) { servletResponse.getOutputStream().write(content); } else { copyStream(servletResponse, new ByteArrayInputStream(new byte[0])); } } } private void copyStream(HttpServletResponse servletResponse, InputStream is) throws IOException { if (servletResponse != null && is != null) { try { OutputStream os = servletResponse.getOutputStream(); byte[] buffer = new byte[8096]; int read = 0; while ((read = is.read(buffer)) > 0) { os.write(buffer, 0, read); } os.flush(); } catch (IOException ex) { throw ex; }finally { try { is.close(); } catch (IOException e) { Logger.error("Cannot close input stream.", e); } } } }
处理代码
public class ServletInvocation extends Invoker.DirectInvocation { private Request request; private Response response; private HttpServletRequest httpServletRequest; private HttpServletResponse httpServletResponse; public ServletInvocation(Request request, Response response, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { this.httpServletRequest = httpServletRequest; this.httpServletResponse = httpServletResponse; this.request = request; this.response = response; request.args.put(ServletWrapper.SERVLET_REQ, httpServletRequest); request.args.put(ServletWrapper.SERVLET_RES, httpServletResponse); } @Override public boolean init() { try { return super.init(); } catch (NotFound e) { serve404(httpServletRequest, httpServletResponse, e); return false; } catch (RenderStatic r) { try { serveStatic(httpServletResponse, httpServletRequest, r); } catch (IOException e) { throw new UnexpectedException(e); } return false; } } @Override public void run() { try { super.run(); } catch (Exception e) { serve500(e, httpServletRequest, httpServletResponse); return; } } @Override public void execute() throws Exception { ActionInvoker.invoke(request, response); copyResponse(request, response, httpServletRequest, httpServletResponse); } @Override public InvocationContext getInvocationContext() { ActionInvoker.resolve(request, response); return new InvocationContext(Http.invocationType, request.invokedMethod.getAnnotations(), request.invokedMethod.getDeclaringClass().getAnnotations()); } }
调用Invoker
public static void invokeInThread(DirectInvocation invocation) { boolean retry = true; while (retry) { invocation.run(); if (invocation.retry == null) { retry = false; } else { try { if (invocation.retry.task != null) { invocation.retry.task.get(); } else { Thread.sleep(invocation.retry.timeout); } } catch (Exception e) { throw new UnexpectedException(e); } retry = true; } } }
相关文章推荐
- CentOS7 下安装JDK1.7 和 Tomcat7
- Tomcat
- Nginx+Tomcat+FastDFS文件下载模块讲解
- tomcat源码流程分析(一)
- Tomcat并发数优化和设置
- SolrCloud(Win--单机多服务器)
- tomcat启动不了报错: Publishing failed Could not publish to the server. java.lang.IndexOutOfBoundsException
- Tomcat 部署应用的时候出现的提示Jstl core错误 The absolute uri
- eclipse远程调试Tomcat方法
- Tomcat绿色版安装
- tomcat源码解析(三)--请求过程之数据的接收
- 本地或者服务器同时启动2个或多个tomcat
- linux下实时查看tomcat运行日志
- 关于eclipse进行web开发tomcat启动失败的一个问题
- 使用tomcat自带的连接池,报错
- 一台服务器部署多个tomcat
- tomcat 部署网站 去掉端口号和项目名称
- Tomcat工作原理
- 注册tomcat为服务
- IntelliJ上创建Tomcat + Jersey 工程