溫馨提示×

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

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

java重定向和轉(zhuǎn)發(fā)的區(qū)別是什么

發(fā)布時(shí)間:2022-01-14 10:43:28 來源:億速云 閱讀:177 作者:iii 欄目:大數(shù)據(jù)

這篇“java重定向和轉(zhuǎn)發(fā)的區(qū)別是什么”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“java重定向和轉(zhuǎn)發(fā)的區(qū)別是什么”文章吧。

  1. 定義

首先來看兩者的javadoc。

sendRedirect()

/**
* Sends a temporary redirect response to the client using the
specified redirect location URL.
This method can accept relative URLs; the servlet container must convert the relative URL to an absolute URL before sending the response to the client. If the location is relative without a leading '/' the container interprets it as relative to the current request URI.
If the location is relative with a leading '/' the container interprets it as relative to the servlet container root.
*/
public void sendRedirect(String location) throws IOException;

重定向是向客戶端發(fā)送一個(gè)指定URL的臨時(shí)重定向的響應(yīng)。

forward()

/**
* Forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) on the server. This method allows one servlet to do preliminary processing of a request and another resource to generate the response.
The request and response parameters must be either the same objects as were passed to the calling servlet's service method .
*/
public void forward(ServletRequest request, ServletResponse response);

轉(zhuǎn)發(fā),則是將一個(gè)請(qǐng)求轉(zhuǎn)到服務(wù)器的另一個(gè)資源。在處理完初步請(qǐng)求另外的資源之后生成響應(yīng)。

定義基本說明了轉(zhuǎn)發(fā)操作為何可以保持request內(nèi)的parameter,attribute這些值都可以保留,而重定向操作卻會(huì)丟棄的原因:

  • 轉(zhuǎn)發(fā)是在服務(wù)端完成的,并沒有經(jīng)過客戶端

  • 轉(zhuǎn)發(fā)整個(gè)操作完成后才生成響應(yīng)

  • 重定向是服務(wù)端向客戶端發(fā)送指定的URL

  • 重定向是在客戶端完成的

我們?cè)賮砜碩omcat內(nèi)部,對(duì)于兩者是怎樣一種實(shí)現(xiàn)方式。

2. 容器實(shí)現(xiàn)

我們?cè)趕ervlet內(nèi)部一般對(duì)于這兩者的使用形式也相當(dāng)直觀,例如對(duì)于hello.jsp的請(qǐng)求:

sendRedirct方法


response.sendRedirect("/hello.jsp");

此時(shí),內(nèi)部的處理方式如下:
public void sendRedirect(String location, int status) throws IOException {
 // Generate a temporary redirect to the specified location
   try {
       String absolute = toAbsolute(location);
       setStatus(status); //這里,重定向是返回302狀態(tài)碼以及Location和對(duì)應(yīng)的url
       setHeader("Location", absolute);
   } catch (IllegalArgumentException e) {
       setStatus(SC_NOT_FOUND);
   }}



即根據(jù)Location,瀏覽器最終再發(fā)起新的請(qǐng)求,最終展現(xiàn)在瀏覽器中的即為新請(qǐng)求的URL,也就是大家常說的重定向會(huì)顯示最終的URL。


有上這些并不能造成重定向操作將之前request中已經(jīng)綁定的一系列parameter和attribute丟掉。最根本的原因是一個(gè)請(qǐng)求完整處理完成之后,整個(gè)請(qǐng)求會(huì)有一個(gè)release的過程,即CoyoteAdapter的service方法執(zhí)行完的finally塊中執(zhí)行release這一過程,基本如下:
finally {
    if (!comet && !async || error.get()) {
       request.recycle();  //注意這兩行代碼
     response.recycle();

   }
}

具體request的recycle部分代碼如下:
/**
* Release all object references, and initialize instance variables, in preparation for reuse of this object.
*/
public void recycle() {
   attributes.clear();
   requestedSessionId = null;
   requestedSessionURL = false;
   parameterMap.clear();
   pathParameters.clear();
}
我們看到用于存儲(chǔ)setAttribute方法設(shè)置的和setParameter方法設(shè)置的數(shù)據(jù)在這里都clear掉了。這也是重定向不能夠保留數(shù)據(jù)的真正原因。


forward方法


forward方法一般使用如下:
request.getRequestDispatcher("/hello.jsp").forward(request, response);

forward方法內(nèi)部最終會(huì)調(diào)用dispatcher的doForward方法

void doForward(ServletRequest request, ServletResponse response){
   // Set up to handle the specified request and response
   State state = new State(request, response, false);
   wrapResponse(state);
       ApplicationHttpRequest wrequest =
           (ApplicationHttpRequest) wrapRequest(state);
        String contextPath = context.getPath();
       HttpServletRequest hrequest = state.hrequest;
       if (hrequest.getAttribute(
               RequestDispatcher.FORWARD_REQUEST_URI) == null) {
           wrequest.setAttribute(RequestDispatcher.FORWARD_PATH_INFO,hrequest.getPathInfo());
           wrequest.setAttribute(RequestDispatcher.FORWARD_QUERY_STRING, hrequest.getQueryString());}
       wrequest.setContextPath(contextPath);
       wrequest.setRequestURI(requestURI);
       wrequest.setServletPath(servletPath);
       wrequest.setPathInfo(pathInfo);
       if (queryString != null) {
           wrequest.setQueryString(queryString);
           wrequest.setQueryParams(queryString);
       }

       processRequest(request,response,state); //進(jìn)行第二個(gè)資源的請(qǐng)求
   }
}

第二個(gè)資源的請(qǐng)求處理與一般的請(qǐng)求處理類似,只是在第一個(gè)請(qǐng)求之上,并沒有返回響應(yīng)時(shí)繼續(xù)發(fā)起第二個(gè)請(qǐng)求,此時(shí)第一個(gè)請(qǐng)求的各類參數(shù)會(huì)繼續(xù)向后傳遞,最終數(shù)據(jù)全部處理完成之后,整個(gè)響應(yīng)發(fā)送回客戶端。此時(shí)上面的release流程也依然會(huì)走,但并沒有什么影響,畢竟第二個(gè)資源已經(jīng)請(qǐng)求處理完成。

而由于瀏覽器發(fā)請(qǐng)求的時(shí)候是一個(gè)固定的URL,整個(gè)重定向是服務(wù)端內(nèi)部進(jìn)行的,瀏覽器并沒有感知到,因此也不會(huì)顯示出來。

以上就是關(guān)于“java重定向和轉(zhuǎn)發(fā)的區(qū)別是什么”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

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

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

AI