1.1 執行流程圖
複製代碼
1.2 執行過程
複製代碼
讀取配置文件前端
SpringMVC本質上是一個Servlet,爲了讀取web.xml配置,這裏用到了ServletConfig 這個類,它表明當前Servlet在web.xml中的配置信息,經過 [^ config.getInitParameter("contextConfigLocation");//讀取啓動參數],讀取application.properties。java
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>application.properties</param-value>
</init-param>
複製代碼
初始化階段git
@Override
public void init(ServletConfig config) throws ServletException {
//1.加載配置文件
doLoadConfig(config.getInitParameter("contextConfigLocation"));
//2.初始化相關聯的類,掃描用戶設定包下的全部類
doScanner(properties.getProperty("scanPackage"));
//3.拿到掃描到的類,經過反射實例化,並放入IOC容器中,(k-v,beanName-bean),beanName默認首字母小寫
doInstance();
//4.初始化HandlerMapping(將url和method對應上)
iniHandlerMapping();
}
複製代碼
運行階段github
private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
if(handlerMapping.isEmpty()){
return;
}
String url = req.getRequestURI();
String contextPath = req.getContextPath();
url = url.replace(contextPath,"").replaceAll("/+","/");
if(!this.handlerMapping.containsKey(url)){
resp.getWriter().write("404 No Found");
return;
}
Method method = this.handlerMapping.get(url);
//獲取方法的參數列表
Class<?>[] parameterTypes = method.getParameterTypes();
//獲取請求的參數
Map<String, String[]> parameterMap = req.getParameterMap();
//保存參數值
Object [] paramValues = new Object[parameterTypes.length];
//方法的參數列表
for (int i = 0; i < parameterTypes.length; i++) {
//根據參數名稱,作某些處理
String requestParam = parameterTypes[i].getSimpleName();
if("HttpServletRequest".equals(requestParam)){
//參數類型已明確,強轉類型是
paramValues[i] = req;
continue;
}
if("HttpServletResponse".equals(requestParam)){
paramValues[i] = resp;
continue;
}
if("String".equals(requestParam)){
for (Entry<String, String[]> param : parameterMap.entrySet()) {
String valuse = Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "").replaceAll(",\\s", ",");
paramValues[i] = valuse;
}
}
}
//利用反射機制調用
try {
method.invoke(this.controllerMap.get(url),paramValues);//第一個參數爲method所對應的實例,在IOC容器中
}catch (Exception e){
e.printStackTrace();
}
複製代碼
Maven的依賴範圍provided後端
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<!-- <scope>xxx</scope>依賴範圍 * compile,缺省值,適用於全部階段,會隨着項目一塊兒發佈。 * provided,相似compile,指望JDK、容器或使用者會提供這個依賴。如servlet.jar。 * runtime,只在運行時使用,如JDBC驅動,適用運行和測試階段。 * test,只在測試時使用,用於編譯和運行測試代碼。不會隨項目發佈。 * system,相似provided,須要顯式提供包含依賴的jar,Maven不會在Repository中查找它。 -->
<scope>provided</scope>
</dependency>
</dependencies>
複製代碼
Java元註解api
/** * java中元註解有四個: @Retention @Target @Document @Inherited; *   @Retention:註解的保留位置 *     @Retention(RetentionPolicy.SOURCE) //註解僅存在於源碼中,在class字節碼文件中不包含 *     @Retention(RetentionPolicy.CLASS) // 默認的保留策略,註解會在class字節碼文件中存在,但運行時沒法得到, *     @Retention(RetentionPolicy.RUNTIME) // 註解會在class字節碼文件中存在,在運行時能夠經過反射獲取到 * *   @Target:註解的做用目標 *     @Target(ElementType.TYPE) //接口、類、枚舉、註解 *     @Target(ElementType.FIELD) //字段、枚舉的常量 *     @Target(ElementType.METHOD) //方法 *     @Target(ElementType.PARAMETER) //方法參數 *     @Target(ElementType.CONSTRUCTOR) //構造函數 *     @Target(ElementType.LOCAL_VARIABLE)//局部變量 *     @Target(ElementType.ANNOTATION_TYPE)//註解 *     @Target(ElementType.PACKAGE) ///包 * * @Document:說明該註解將被包含在javadoc中 * *   @Inherited:說明子類能夠繼承父類中的該註解 */
複製代碼