entry : urlMap.entrySet()) {
+ String url = entry.getKey();
+ Object handler = entry.getValue();
+ // 如果url没有斜线,就在前面加上斜线
+ if (!url.startsWith("/")) {
+ url = "/" + url;
+ }
+ // Remove whitespace from handler bean name.
+ if (handler instanceof String) {
+ handler = ((String) handler).trim();
+ }
+ // 这里调用的是父类的方法
+ registerHandler(url, handler);
+ }
+ }
+ }
+}
+```
+这个SimpleUrlHandlerMapping注册过程的完成,很大一部分需要它的基类来配合,这个基类就是AbstractUrlHandlerMapping。在AbstractUrlHandlerMapping的处理过程中,如果使用Bean的名称作为映射,那么直接从容器中获取这个HTTP映射对应的Bean,然后还要对不同的URL配置进行解析处理,比如在HTTP请求中配置成“/”和通配符“/*” 的URL,以及正常的URL请求,完成这个解析处理过程以后,会
+把URL和handler作为键值对放到一个handlerMap中去。
+```java
+public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered {
+ /**
+ * 为给定的URL路径注册指定的handler处理程序
+ */
+ protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
+ Assert.notNull(urlPaths, "URL path array must not be null");
+ for (String urlPath : urlPaths) {
+ registerHandler(urlPath, beanName);
+ }
+ }
+
+ /**
+ * 为给定的URL路径注册指定的handler处理程序
+ */
+ protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
+ Assert.notNull(urlPath, "URL path must not be null");
+ Assert.notNull(handler, "Handler object must not be null");
+ Object resolvedHandler = handler;
+
+ // 如果使用bean名称进行映射,就直接从IoC容器中获取该bean名称对应的handler
+ if (!this.lazyInitHandlers && handler instanceof String) {
+ String handlerName = (String) handler;
+ if (getApplicationContext().isSingleton(handlerName)) {
+ resolvedHandler = getApplicationContext().getBean(handlerName);
+ }
+ }
+
+ Object mappedHandler = this.handlerMap.get(urlPath);
+ if (mappedHandler != null) {
+ if (mappedHandler != resolvedHandler) {
+ throw new IllegalStateException(
+ "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
+ "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
+ }
+ }
+ else {
+ // 处理URL是"/"的映射,把这个"/"映射的controller设置到rootHandler中
+ if (urlPath.equals("/")) {
+ if (logger.isInfoEnabled()) {
+ logger.info("Root mapping to " + getHandlerDescription(handler));
+ }
+ setRootHandler(resolvedHandler);
+ }
+ // 处理URL是"/"的映射,把这个"/"映射的controller设置到defaultHandler中
+ else if (urlPath.equals("/*")) {
+ if (logger.isInfoEnabled()) {
+ logger.info("Default mapping to " + getHandlerDescription(handler));
+ }
+ setDefaultHandler(resolvedHandler);
+ }
+ // 处理正常的URL映射,此handlerMap的key和value分别代表URL和映射的Controller
+ else {
+ this.handlerMap.put(urlPath, resolvedHandler);
+ if (logger.isInfoEnabled()) {
+ logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
+ }
+ }
+ }
+ }
+
+ /**
+ * 为此handler映射设置根handler,即要为根路径("/")注册的handler
+ * Default is {@code null}, indicating no root handler.
+ */
+ public void setRootHandler(Object rootHandler) {
+ this.rootHandler = rootHandler;
+ }
+
+ public Object getRootHandler() {
+ return this.rootHandler;
+ }
+
+ /**
+ * 设置此handler映射的默认handler。如果未找到特定映射,则将返回此handler
+ */
+ public void setDefaultHandler(Object defaultHandler) {
+ this.defaultHandler = defaultHandler;
+ }
+
+ public Object getDefaultHandler() {
+ return this.defaultHandler;
+ }
+}
+```
+这里的handlerMap是一个HashMap,其中保存了URL请求和Controller的映射关系,这个handlerMap是在AbstractUrlHandlerMapping中定义的( Map handlerMap = new LinkedHashMap() ),这个配置好URL请求和handler映射数据的handlerMap,为Spring MVC响应HTTP请求准备好了基本的映射数据,根据这个handlerMap以及设置于其中的映射数据,可以方便地由
+URL请求得到它所对应的handler。有了这些准备工作,Spring MVC就可以等待HTTP请求的到来了。
+
+### 4.2 使用HandlerMapping完成请求的映射处理
+继续通过SimpleUrlHandlerMapping的实现来分析HandlerMapping的接口方法getHandler(),该方法会根据初始化时得到的映射关系来生成DispatcherServlet需要的HandlerExecutionChain,也就是说,这个getHandler()方法是实际使用HandlerMapping完成请求的映射处理的地方。在前面的HandlerExecutionChain的执行过程中,首先在AbstractHandlerMapping中启动getHandler的调用。
+```java
+public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered {
+ /**
+ * 查找给定请求的handler,如果找不到特定的handler,则返回到defaultHandler
+ */
+ public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
+ // 模板方法模式
+ Object handler = getHandlerInternal(request);
+ // 如果找不到特定的handler,则取defaultHandler
+ if (handler == null) {
+ handler = getDefaultHandler();
+ }
+ // defaultHandler也没有则返回null
+ if (handler == null) {
+ return null;
+ }
+ // 如果该handler是String类型的,说明它是一个beanname
+ // 根据该beanname从IoC容器中获取真正的handler对象
+ if (handler instanceof String) {
+ String handlerName = (String) handler;
+ handler = getApplicationContext().getBean(handlerName);
+ }
+ // 这里把handler添加到到HandlerExecutionChain中
+ return getHandlerExecutionChain(handler, request);
+ }
+}
+```
+取得handler的具体过程在getHandlerInternal()方法中实现,这个方法接受HTTP请求作为参数,它的实现在AbstractHandlerMapping的子类AbstractUrlHandlerMapping中,这个实现过程包括从HTTP请求中得到URL,并根据URL到urlMapping中获得handler。
+```java
+public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
+ /**
+ * 查找给定请求的URL路径 对应的handler
+ */
+ @Override
+ protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
+ // 从request中获取请求的URL路径
+ String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
+ // 将得到的URL路径与handler进行匹配,得到对应的handler,如果没有对应的handler
+ // 则返回null,这样默认的handler会被使用
+ Object handler = lookupHandler(lookupPath, request);
+ if (handler == null) {
+ // We need to care for the default handler directly, since we need to
+ // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
+ Object rawHandler = null;
+ if ("/".equals(lookupPath)) {
+ rawHandler = getRootHandler();
+ }
+ // 使用默认的handler
+ if (rawHandler == null) {
+ rawHandler = getDefaultHandler();
+ }
+ if (rawHandler != null) {
+ // Bean name or resolved handler?
+ if (rawHandler instanceof String) {
+ String handlerName = (String) rawHandler;
+ rawHandler = getApplicationContext().getBean(handlerName);
+ }
+ validateHandler(rawHandler, request);
+ handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
+ }
+ }
+ if (handler != null && logger.isDebugEnabled()) {
+ logger.debug("Mapping [" + lookupPath + "] to " + handler);
+ }
+ else if (handler == null && logger.isTraceEnabled()) {
+ logger.trace("No handler mapping found for [" + lookupPath + "]");
+ }
+ return handler;
+ }
+
+ /**
+ * 查找给定URL路径的handler实例
+ */
+ protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
+ // 直接匹配
+ Object handler = this.handlerMap.get(urlPath);
+ if (handler != null) {
+ // Bean name or resolved handler?
+ if (handler instanceof String) {
+ String handlerName = (String) handler;
+ handler = getApplicationContext().getBean(handlerName);
+ }
+ validateHandler(handler, request);
+ return buildPathExposingHandler(handler, urlPath, urlPath, null);
+ }
+ // 正则匹配
+ List matchingPatterns = new ArrayList();
+ for (String registeredPattern : this.handlerMap.keySet()) {
+ if (getPathMatcher().match(registeredPattern, urlPath)) {
+ matchingPatterns.add(registeredPattern);
+ }
+ }
+ String bestPatternMatch = null;
+ Comparator patternComparator = getPathMatcher().getPatternComparator(urlPath);
+ if (!matchingPatterns.isEmpty()) {
+ Collections.sort(matchingPatterns, patternComparator);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
+ }
+ bestPatternMatch = matchingPatterns.get(0);
+ }
+ if (bestPatternMatch != null) {
+ handler = this.handlerMap.get(bestPatternMatch);
+ // Bean name or resolved handler?
+ if (handler instanceof String) {
+ String handlerName = (String) handler;
+ handler = getApplicationContext().getBean(handlerName);
+ }
+ validateHandler(handler, request);
+ String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
+
+ // There might be multiple 'best patterns', let's make sure we have the correct URI template variables
+ // for all of them
+ Map uriTemplateVariables = new LinkedHashMap();
+ for (String matchingPattern : matchingPatterns) {
+ if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
+ Map vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
+ Map decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
+ uriTemplateVariables.putAll(decodedVars);
+ }
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
+ }
+ return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
+ }
+ // No handler found...
+ return null;
+ }
+}
+```
+经过这一系列对HTTP请求进行解析和匹配handler的过程,得到了与请求对应的handler处理器。在返回的handler中,已经完成了在HandlerExecutionChain中进行封装的工作,为handler对HTTP请求的响应做好了准备。
+
+### 4.3 DispatcherServlet对HTTP请求的分发处理
+
+
+
+
diff --git a/docs/Netty/占位文件.stkj b/docs/Spring/SpringMVC/温习一下servlet.md
similarity index 100%
rename from docs/Netty/占位文件.stkj
rename to docs/Spring/SpringMVC/温习一下servlet.md
diff --git a/docs/学习心得/编码规范/异常日志.md b/docs/学习心得/编码规范/异常日志.md
new file mode 100644
index 0000000..e69de29
diff --git a/docs/学习心得/编码规范/数据库规范.md b/docs/学习心得/编码规范/数据库规范.md
new file mode 100644
index 0000000..e69de29
diff --git a/docs/学习心得/编码规范/编程规约.md b/docs/学习心得/编码规范/编程规约.md
new file mode 100644
index 0000000..e69de29
diff --git a/images/springMVC/DispatcherServlet的处理过程.png b/images/springMVC/DispatcherServlet的处理过程.png
new file mode 100644
index 0000000..40c227d
Binary files /dev/null and b/images/springMVC/DispatcherServlet的处理过程.png differ
diff --git a/images/springMVC/DispatcherServlet的继承关系.png b/images/springMVC/DispatcherServlet的继承关系.png
new file mode 100644
index 0000000..7b99c8b
Binary files /dev/null and b/images/springMVC/DispatcherServlet的继承关系.png differ
diff --git a/images/springMVC/HandlerMapping组件.png b/images/springMVC/HandlerMapping组件.png
new file mode 100644
index 0000000..48038ca
Binary files /dev/null and b/images/springMVC/HandlerMapping组件.png differ
diff --git a/images/springMVC/SimpleUrlHandlerMapping的继承关系.png b/images/springMVC/SimpleUrlHandlerMapping的继承关系.png
new file mode 100644
index 0000000..8c5ce0a
Binary files /dev/null and b/images/springMVC/SimpleUrlHandlerMapping的继承关系.png differ
diff --git a/images/springMVC/WebApplicationContext接口的类继承关系.png b/images/springMVC/WebApplicationContext接口的类继承关系.png
new file mode 100644
index 0000000..ad12de6
Binary files /dev/null and b/images/springMVC/WebApplicationContext接口的类继承关系.png differ
diff --git a/images/springMVC/Web容器启动spring应用程序过程图.png b/images/springMVC/Web容器启动spring应用程序过程图.png
new file mode 100644
index 0000000..4777ddf
Binary files /dev/null and b/images/springMVC/Web容器启动spring应用程序过程图.png differ