spring mvc的處理流程

一、在web.xml中配置DispatcherServlet(實現了Servlet接口)的相關信息,其中包括:

      1、初始化參數init-param的name、value(contextConfigLocation: 配置文件的路徑)

      2、Servlet處理的請求映射url (servlet-mapping)

 

二、在DispatcherServlet的初始化方法init()中做如下處理(Tomcat是Servlet容器,啓動Tomcat會加載Servlet並初始化)

      1、加載配置文件

//獲取配置文件路徑(servletConfig爲init()的入參)
String contextConfigLocation = servletConfig.getInitParameter("contextConfigLocation");

//獲取文件輸入流(this是DispatcherServlet對象)
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);

//使用Properties讀取輸入流
Properties contextConfig = new Properties();
contextConfig.load(inputStream);

//獲取配置信息,此處舉例爲:掃描包的路徑
contextConfig.getProperty("scan-package");

      2、將掃描包路徑下的所有類名存入List<String>中

URL resourcePath = this.getClass().getClassLoader().getResource("scan-path");

File scanPath = new File(resourcePath.getFile());

//遞歸獲取文件名並過濾.class文件以外的文件,保存類名(全限定名)
List<String> classNameList = new ArrayList<>();
classNameList.add(className);

      3、將加有@Controller/@Service等註解的類的對象放入ioc容器中(利用java反射機制,生成對象)

Map<String, Object> iocMap = new HashMap<>();
Class<?> clazz = Class.forName(className);
if (clazz.isAnnotationPresent(Controller.class)) {
    Object instance = clazz.newInstance();
    iocMap.put(beanName, instance);
}
//如果有實現接口的(如Service),需要把接口名及對應的實例引用放入ioc容器中(clazz.getInterfaces())

      4、將加有@Autowired註解的屬性成員賦值(通過java反射機制,完成注入)

//獲取字段(instance爲ioc容器中的對象)
Field[] fields = instance.getClass().getDeclaredFields();

//獲取註解類型名稱
String beanName = field.getType().getName();

//將字段設置爲可訪問的
field.setAccessible(true);

//設置字段的值,完成注入
field.set(instance, iocMap.get(beanName));

    5、將Controller中加有@RequestMapping註解的方法緩存起來(通過java反射機制,獲得方法)

//緩存容器
Map<String, Method> urlMethodMapping = new HashMap<>();

//instance爲ioc容器中的對象
Class<?> clazz = instance.getClass();

//獲取類RequestMapping路徑
if(clazz.isAnnotationPresent(Controller.class) && clazz.isAnnotationPresent(RequestMapping.class)) {
    RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class);
    String baseUrl = RequestMapping.value();
}

//獲取方法RequestMapping路徑
if (method.isAnnotationPresent(RequestMapping.class)) {
    String methodUrl = method.getAnnotation(RequestMapping.class).value();
}

//緩存方法
urlMethodMapping.put(url, method);

 

三、在Servlet的doGet()和doPost()中,將請求的url與緩存的urlMethodMapping比對,並調用請求的方法。(反射機制)

//HttpServletRequest、HttpServletResponse是doPost/doGet的入參
String url = reqest.getRequestURI();

//獲取緩存的方法
Method method = this.urlMethodMapping.get(url);

//取得方法對應的類型,並從ioc容器中獲取對象,再調用方法
String beanName = method.getDeclaringClass().getSimpleName();
method.invoke(iocMap.get(beanName), reqest, response);

 

在此感謝下面這篇博客和這本書,我纔對springmvc的流程有了大概的瞭解。

博客:https://blog.csdn.net/qq_40147863/article/details/96505433

書籍:《Spring 5核心原理與30個類手寫實戰》

發佈了86 篇原創文章 · 獲贊 144 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章