cution 对象,并根 据方法签名将 URL 中的 String 转换为合适的方法参数类型,准备好全部参数 ,代码见清单 9。
清单 9. 构造 Exectuion
class Execution {
public final HttpServletRequest request;
public final HttpServletResponse response;
private final Action action;
private final Object[] args;
...
public Object execute() throws Exception {
try {
return action.method.invoke(action.instance, args);
}
catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t!=null && t instanceof Exception)
throw (Exception) t;
throw e;
}
}
}
调用 execute() 方法就可以执行目标方法,并返回一个结果。请注意,当通 过反射调用方法失败时,我们通过查找 InvocationTargetException 的根异常 并将其抛出,这样,客户端就能捕获正确的原始异常。
为了最大限度地增加灵活性,我们并不强制要求 URL 的处理方法返回某一种 类型。我们设计支持以下返回值:
String:当返回一个 String 时,自动将其作为 HTML 写入 HttpServletResponse;
void:当返回 void 时,不做任何操作;
Renderer:当返回 Renderer 对象时,将调用 Renderer 对象的 render 方 法渲染 HTML 页面。
最后需要考虑的是,由于我们将 DispatcherServlet 映射为“/”,即默认 的 Servlet,则所有的未匹配成功的 URL 都将由 DispatcherServlet 处理,包 括所有静态文件,因此,当未匹配到任何 Controller 的 @Mapping 方法后, DispatcherServlet 将试图按 URL 查找对应的静态文件,我们用 StaticFileHandler 封装,主要代码见清单 10。
清单 10. 处理静态文件
class StaticFileHandler {
...
public void handle(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String url = request.getRequestURI();
String path = request.getServletPath();
url = url.substring(path.length());
if (url.toUpperCase().startsWith("/WEB-INF/")) {
response.sendError (HttpServletResponse.SC_NOT_FOUND);
return;
}
int n = url.indexOf(''?'');
if (n!=(-1))
url = url.substring(0, n);
n = url.indexOf(''#'');
if (n!=(-1))
url = url.substring(0, n);
File f = new File(servletContext.getRealPath(url));
if (! f.isFile()) {
response.sendError (HttpServletResponse.SC_NOT_FOUND);
return;
}
long ifModifiedSince = request.getDateHeader("If- Modified-Since");
long lastModified = f.lastModified();
if (ifModifiedSince!=(-1) && ifModifiedSince>=lastModified) {
response.setStatus (HttpServletResponse.SC_NOT_MODIFIED);
return;
}
response.setDateHeader("Last-Modified", lastModified);
response.setContentLength((int)f.length());
response.setContentType(getMimeType(f));
sendFile(f, response.getOutputStream());
|