Commit ba2803d2 by SunWei峰

初步完成形式主义学习

parent 2574ac2c
......@@ -208,6 +208,8 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
@Override
public boolean checkNotModified(@Nullable String etag, long lastModifiedTimestamp) {
HttpServletResponse response = getResponse();
// notModified 为 true 标志没有被修改,默认false
// 如果 notModified 已经 true || 返回状态码已经不是 200 直接返回 notModified
if (this.notModified || (response != null && HttpStatus.OK.value() != response.getStatus())) {
return this.notModified;
}
......@@ -215,7 +217,9 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
// Evaluate conditions in order of precedence.
// See https://tools.ietf.org/html/rfc7232#section-6
// 解析校验 If-Unmodified-Since 请求头。这个请求头和 If-Modified-Since 请求头相反
if (validateIfUnmodifiedSince(lastModifiedTimestamp)) {
// 设置状态码 304,并返回 notModified
if (this.notModified && response != null) {
response.setStatus(HttpStatus.PRECONDITION_FAILED.value());
}
......@@ -228,6 +232,7 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
}
// Update response
// 更新 Response。包括状态码等信息
if (response != null) {
boolean isHttpGetOrHead = SAFE_METHODS.contains(getRequest().getMethod());
if (this.notModified) {
......@@ -306,6 +311,7 @@ public class ServletWebRequest extends ServletRequestAttributes implements Nativ
return "\"" + etag + "\"";
}
// 解析校验 If-Modified-Since 请求头
private boolean validateIfModifiedSince(long lastModifiedTimestamp) {
if (lastModifiedTimestamp < 0) {
return false;
......
......@@ -998,13 +998,19 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 记录当前时间,用于记录web请求的记录时间
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
// 1234 的目的是为了保证当前线程的 LocaleContext 和 RequestAttributes 在当前请求后还能恢复,所以提取保存
// 1 提取当前线程的 LocaleContext 属性
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
// 2. 根据当前的 request 创建对应的 LocaleContext,并绑定到当前线程
LocaleContext localeContext = buildLocaleContext(request);
// 3. 提取当前线程的 RequestAttributes 属性
RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
// 4. 根据当前的request 创建对应的 RequestAttributes ,并绑定到当前线程
ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
......@@ -1013,6 +1019,7 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
initContextHolders(request, localeContext, requestAttributes);
try {
// 5. 委托给 doservice方法进行进一步处理
doService(request, response);
}
catch (ServletException | IOException ex) {
......@@ -1025,11 +1032,13 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
}
finally {
// 6. 请求结束,恢复线程原状
resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
}
logResult(request, response, failureCause, asyncManager);
// 发布请求结束的通知事件,无论成功与否
publishRequestHandledEvent(request, response, startTime, failureCause);
}
}
......
......@@ -144,6 +144,7 @@ public class HandlerExecutionChain {
for (int i = 0; i < this.interceptorList.size(); i++) {
HandlerInterceptor interceptor = this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
// 调用前置方法。如果有一个前置方法返回false,则直接调用完成方法
triggerAfterCompletion(request, response, null);
return false;
}
......
......@@ -857,7 +857,9 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
// 将 handlerMethod 转换成 ServletInvocableHandlerMethod
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
// 设置ServletInvocableHandlerMethod 的一些属性
if (this.argumentResolvers != null) {
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
......@@ -868,6 +870,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
// 创建 ModelAndView 容器,并设置一些属性
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, invocableMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
......@@ -892,11 +895,13 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
invocableMethod = invocableMethod.wrapConcurrentResult(result);
}
// 反射调用 HandlerMethod
invocableMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
// 封装成 ModelAndView
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
......
......@@ -170,10 +170,12 @@ public abstract class AbstractCachingViewResolver extends WebApplicationObjectSu
@Override
@Nullable
public View resolveViewName(String viewName, Locale locale) throws Exception {
// 如果没有缓存,则直接创建 View
if (!isCache()) {
return createView(viewName, locale);
}
else {
// 从缓存中获取视图
Object cacheKey = getCacheKey(viewName, locale);
View view = this.viewAccessCache.get(cacheKey);
if (view == null) {
......
......@@ -309,8 +309,11 @@ public abstract class AbstractView extends WebApplicationObjectSupport implement
(this.staticAttributes.isEmpty() ? "" : ", static attributes " + this.staticAttributes));
}
// 将要用到的属性放入到 mergedModel 中
Map<String, Object> mergedModel = createMergedOutputModel(model, request, response);
// 准备 Response
prepareResponse(request, response);
// 处理页面跳转。同时将 mergedModel 保存到 request 中
renderMergedOutputModel(mergedModel, getRequestToExpose(request), response);
}
......
......@@ -464,11 +464,13 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
protected View createView(String viewName, Locale locale) throws Exception {
// If this resolver is not supposed to handle the given view,
// return null to pass on to the next resolver in the chain.
// 如果当前视图解析器无法解析该视图,则返回null
if (!canHandle(viewName, locale)) {
return null;
}
// Check for special "redirect:" prefix.
// 处理前缀为 "redirect:" (重定向)的情况
if (viewName.startsWith(REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(REDIRECT_URL_PREFIX.length());
RedirectView view = new RedirectView(redirectUrl,
......@@ -481,6 +483,7 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
}
// Check for special "forward:" prefix.
// 处理前缀为 "forward:" 的情况
if (viewName.startsWith(FORWARD_URL_PREFIX)) {
String forwardUrl = viewName.substring(FORWARD_URL_PREFIX.length());
InternalResourceView view = new InternalResourceView(forwardUrl);
......@@ -488,6 +491,7 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
}
// Else fall back to superclass implementation: calling loadView.
// 调用父类的方法创建视图
return super.createView(viewName, locale);
}
......@@ -567,6 +571,7 @@ public class UrlBasedViewResolver extends AbstractCachingViewResolver implements
*/
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
AbstractUrlBasedView view = instantiateView();
// 设置视图 url 添加前缀和后缀
view.setUrl(getPrefix() + viewName + getSuffix());
view.setAttributesMap(getAttributesMap());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment