您的位置:首页 > 运维架构 > Tomcat

从tomcat角度解读play源代码

2016-07-06 16:02 344 查看
先来看下生成的web.xml 的文件

<?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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: