溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Servlet到Spring的請求分發(fā)機制是什么

發(fā)布時間:2021-12-27 16:36:20 來源:億速云 閱讀:119 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“Servlet到Spring的請求分發(fā)機制是什么”,在日常操作中,相信很多人在Servlet到Spring的請求分發(fā)機制是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Servlet到Spring的請求分發(fā)機制是什么”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

在講請求分發(fā)之前先梳理一下一個Web請求的交互邏輯:

  1. 首先用戶在客戶端發(fā)送一個請求到服務(wù)器。

  2. 這個請求首先會經(jīng)過操作系統(tǒng)的 TCP/IP 協(xié)議棧解析后發(fā)送至某一個端口

  3. 在該端口運行著一個 Web 應(yīng)用服務(wù)器(假設(shè)是 Tomcat)

  4. 接著 Tomcat 會把請求根據(jù)請求路徑傳送給對應(yīng)的 Servlet 處理
    (要注意的是,Web 服務(wù)器本身是不處理請求的,比如說 Tomcat,它只負(fù)責(zé)分發(fā)請求)

1.Servlet時期的請求分發(fā)

在還沒有 spring 框架的時候,只能單純用 Servlet 處理請求。

具體做法是:把 Servlet 及其映射路徑配置在一個叫 web.xml 的配置文件中,當(dāng)服務(wù)器啟動時,Tomcat 會自動讀取這個文件,然后根據(jù)文件中的配置,把請求分配到對應(yīng)的 Servlet。

這個時候請求分發(fā)的工作是在 Tomcat 中完成的,通常一個業(yè)務(wù)對應(yīng)一個 Servlet。比如說關(guān)于用戶的增刪改查,對應(yīng)的 Servlet 很有可能是這樣子的:

  1. AddUserServlet

  2. DeleteUserServlet

  3. UpdateUserServlet
    ...

對應(yīng)的結(jié)構(gòu)圖如下:

Servlet到Spring的請求分發(fā)機制是什么  

這和我們?nèi)缃耖_發(fā)中的架構(gòu)很不一樣,因為現(xiàn)在通常是一個類里面包含了對同個業(yè)務(wù)所有處理邏輯。比如說對用戶的增刪改查都放在同一個類里,用不同的方法區(qū)分。

但在以前,一個 Servlet 里面通常只有一個 service 是有用的,其他和生命周期相關(guān)的方法基本只是給一個空殼的重寫,所以一個 service 方法就對應(yīng)一個業(yè)務(wù)處理邏輯。這種分類方法不僅給 web 服務(wù)器帶來很大負(fù)擔(dān)的,而且會導(dǎo)致 web.xml 文件十分龐大。(User 的增刪改查邏輯對應(yīng)4個 Servlet,要是能把和 User 相關(guān)的處理邏輯分發(fā)給一個大的 UserServlet 就好了)

后來有人找到了把和 User 相關(guān)的處理邏輯分發(fā)給一個大的 UserServlet 的方法。具體方法就是使用 Java 中的反射。詳細(xì)代碼如下:

/**
* 該Servlet不需要進行配置,因為該Servlet從來不需要被直接訪問,使用來被繼承的
* 可以定義為abstract class
*/
public abstract class BaseServlet extends HttpServlet{

@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//解決post表單中文亂碼問題
request.setCharacterEncoding("utf-8");

//獲取method屬性的值(方法名)
String methodName = request.getParameter("method");
if(methodName == null || methodName.trim().isEmpty()) {
throw new RuntimeException("您沒有傳遞method參數(shù)!無法確定您想要調(diào)用的方法!");
}

//使用反射調(diào)用方法
try {
//獲取當(dāng)前Servlet的Class信息
Class clazz = this.getClass();//實際訪問的Servlet,不是BaseServlet,是BaseServlet的子類比如UserServlet
//使用反射創(chuàng)建對象
//Object obj = clazz.newInstance();
//獲取方法
Method method = clazz.getMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
//使用反射執(zhí)行方法
method.invoke(this, request,response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
 

這樣一來,分發(fā)請求的結(jié)構(gòu)就變成了這樣:

Servlet到Spring的請求分發(fā)機制是什么  

也就是說同類業(yè)務(wù)的請求分配給同一個 Serlvet,當(dāng)具體到細(xì)分的業(yè)務(wù)邏輯時,使用不同的方法進行區(qū)分;在運行的時候使用反射調(diào)用具體的方法。

這么做能明顯減輕服務(wù)器分發(fā)請求的壓力,也讓 web.xml 文件變得更加簡潔。而且同類型的業(yè)務(wù)邏輯能夠編寫在同一個類中,方便管理維護。但是有沒有可能做得更好呢?

 

2.Spring框架的請求分發(fā)

先用一幅圖來描述 Spring 框架的請求分發(fā),圖片通俗易懂:

Servlet到Spring的請求分發(fā)機制是什么  

從圖中可以看到 web 服務(wù)器此時已經(jīng)不用考慮分發(fā)請求的問題了,它只需要把請求發(fā)送給 DispatcherServlet 即可。請求分發(fā)的任務(wù)將落到 DispatcherServlet 身上。

而 DispatchServlet 也不再是把請求分發(fā)給其他 Servlet,而是根據(jù)請求路徑分發(fā)給對應(yīng)的 Controller,然后再分發(fā)到 Controller 中對應(yīng)的處理方法。

下面給出一個迷你簡寫版的 DispatchServlet 代碼:

public class DispatcherServlet implements Servlet {

   @Override
   public void init(ServletConfig servletConfig) throws ServletException {}

   @Override
   public ServletConfig getServletConfig() {
       return null;
   }

   @Override
   public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
       for(MappingHandler mappingHandler : HandlerManager.mappingHandlerList){
           try{
               if (mappingHandler.handle(servletRequest, servletResponse)){
                   return;
               }
           } catch (IllegalAccessException e) {
               e.printStackTrace();
           } catch (InstantiationException e) {
               e.printStackTrace();
           } catch (InvocationTargetException e) {
               e.printStackTrace();
           }
       }
   }

   @Override
   public String getServletInfo() {
       return null;
   }

   @Override
   public void destroy() {}
}
 

從上面的代碼可以看到 DispatcherServlet 處理請求的邏輯也很簡單,就是根據(jù)請求路徑找到對應(yīng)可以處理的處理器。

至于 MappingHandler 是怎么初始化的,這就涉及到 Spring 框架中控制反轉(zhuǎn)和依賴注入的知識了。簡單來說就是,在開發(fā)的過程中,我們不再把請求路徑配置在 web.xml 里面,而是通過注解的方式配置在每一個個處理方法的上方。當(dāng) spring 框架啟動后,會根據(jù)注解把每個處理方法初始化為一個個 MappingHandler(里面包括請求路徑和處理邏輯),供 DispatcherServlet 調(diào)配使用。

這樣的請求分發(fā)方式無疑比 Serlvet 時期的請求分發(fā)更加靈活,強大。它把請求分發(fā)的工作從 web 服務(wù)器上移植到框架中,可擴展性更強。而且配合 spring 框架的控制反轉(zhuǎn)機制,把處理邏輯類的初始化及生命周期控制交給框架管理,更加安全高效。

到此,關(guān)于“Servlet到Spring的請求分發(fā)機制是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI