欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaWeb中轉(zhuǎn)發(fā)與重定向的區(qū)別小結(jié)

 更新時(shí)間:2023年10月24日 09:55:42   作者:m0nesy小孩  
轉(zhuǎn)發(fā)和重定向是JavaWeb中常用的兩種頁面跳轉(zhuǎn)方式,它們?cè)趯?shí)現(xiàn)上有一些區(qū)別,本文主要介紹了JavaWeb中轉(zhuǎn)發(fā)與重定向的區(qū)別小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下

在一個(gè)web應(yīng)用中通過兩種方式,可以完成資源的跳轉(zhuǎn):

  • 第一種方式:轉(zhuǎn)發(fā)
  • 第二種方式:重定向

1. Forward 轉(zhuǎn)發(fā)

轉(zhuǎn)發(fā) :指內(nèi)部轉(zhuǎn)發(fā)。當(dāng)一個(gè)Servlet處理請(qǐng)求的時(shí)候,它可以決定自己不繼續(xù)處理,而是轉(zhuǎn)發(fā)給另一個(gè)Servlet處理。

// 獲取請(qǐng)求轉(zhuǎn)發(fā)器對(duì)象
RequestDispatcher dispatcher = request.getRequestDispatcher("/dept/list");
// 調(diào)用請(qǐng)求轉(zhuǎn)發(fā)器對(duì)象的forward方法完成轉(zhuǎn)發(fā)
dispatcher.forward(request, response);
 
// 合并一行代碼
request.getRequestDispatcher("/dept/list").forward(request, response);
// 轉(zhuǎn)發(fā)的時(shí)候是一次請(qǐng)求,不管你轉(zhuǎn)發(fā)了多少次。都是一次請(qǐng)求。
// AServlet轉(zhuǎn)發(fā)到BServlet,再轉(zhuǎn)發(fā)到CServlet,再轉(zhuǎn)發(fā)到DServlet,不管轉(zhuǎn)發(fā)了多少次,都在同一個(gè)request當(dāng)中。
// 這是因?yàn)檎{(diào)用forward方法的時(shí)候,會(huì)將當(dāng)前的request和response對(duì)象傳遞給下一個(gè)Servlet。

注意: 因?yàn)檗D(zhuǎn)發(fā)是服務(wù)器內(nèi)部的進(jìn)行的,所以 request.getRequestDispatcher(/不要項(xiàng)目名的).forward(request, response);編寫的轉(zhuǎn)發(fā)路徑是不要加項(xiàng)目名的

舉例: 瀏覽器向 AServlet 發(fā)送請(qǐng)求,AServlet 將該請(qǐng)求 “轉(zhuǎn)發(fā)”給了 BServlet。但是前端的瀏覽器并不知道該請(qǐng)求被 BServlet 處理了,瀏覽器的地址欄上顯示的還是發(fā)送給 AServlet 請(qǐng)求的路徑信息。

package com.RainbowSea.servlet;
 
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
 
public class AServlet extends HttpServlet {
    // 地址欄上回車操作是 doGet()請(qǐng)求
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        // 轉(zhuǎn)發(fā)到 BServlet,轉(zhuǎn)發(fā)的路徑不要加項(xiàng)目名
        request.getRequestDispatcher("/b").forward(request, response);
 
    }
}
package com.RainbowSea.servlet;
 
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
import java.io.PrintWriter;
 
public class BServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        // 設(shè)置瀏覽器端顯示響應(yīng)的,格式類型,以及字符集
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
 
        writer.println("<h2> 這里是BServlet 的響應(yīng)處理 </h2>");
 
    }
}

轉(zhuǎn)發(fā)是由WEB服務(wù)器來控制的。A資源跳轉(zhuǎn)到B資源,這個(gè)跳轉(zhuǎn)動(dòng)作是Tomcat服務(wù)器內(nèi)部完成的 ,而我們前端也就是瀏覽器端是不知道我們服務(wù)器端對(duì)這個(gè)請(qǐng)求內(nèi)部轉(zhuǎn)發(fā)處理了多少次。 并且無論我們服務(wù)器內(nèi)部轉(zhuǎn)發(fā)了多少次,前端瀏覽器都僅僅只會(huì)認(rèn)為僅僅只轉(zhuǎn)發(fā)了一次,也就是僅僅發(fā)送了一次請(qǐng)求 。因?yàn)槲覀兎?wù)器端雖然進(jìn)行了轉(zhuǎn)發(fā)但是,瀏覽器的地址欄上的請(qǐng)求路徑的地址是沒有改變的(還是初始的請(qǐng)求路徑)

轉(zhuǎn)發(fā):是可以將 一個(gè)Servlet 類當(dāng)中的信息轉(zhuǎn)發(fā)到另一個(gè) Servlet 當(dāng)中去的,可以實(shí)現(xiàn) Servlet 數(shù)據(jù)的共享,需要用到 請(qǐng)求域

注意: 請(qǐng)求域的作用域(請(qǐng)求域當(dāng)中存儲(chǔ)的信息),只在一次 請(qǐng)求 范圍內(nèi)有效。而轉(zhuǎn)發(fā)機(jī)制的特點(diǎn)決定了可以實(shí)現(xiàn)請(qǐng)求域的共享:因?yàn)闊o論服務(wù)器內(nèi)部轉(zhuǎn)發(fā)了多少次,前端瀏覽器都只視為是一次請(qǐng)求。

轉(zhuǎn)發(fā)機(jī)制,將AServlett 類當(dāng)中的信息轉(zhuǎn)發(fā)到 BServlet 當(dāng)中去

package com.RainbowSea.servlet;
 
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
 
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 設(shè)置,在瀏覽器上響應(yīng)的格式類型
        Date nowTime = new Date();  // 創(chuàng)建當(dāng)前時(shí)間的 Date 對(duì)象
 
        // 將 nowTime 的數(shù)據(jù)存儲(chǔ)(綁定)到請(qǐng)求域當(dāng)中
        request.setAttribute("sysTime",nowTime);
 
        // 第一步: 獲取到轉(zhuǎn)發(fā)對(duì)象,注意:/ 開始,不家項(xiàng)目名 , / + 對(duì)應(yīng)跳轉(zhuǎn)的 Servlet 當(dāng)中的 web.xml 當(dāng)中的url映射的路徑
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/B");
 
        // 第二步: 調(diào)用轉(zhuǎn)發(fā)器的forward方法完成跳轉(zhuǎn)/轉(zhuǎn)發(fā)
        requestDispatcher.forward(request,response);
 
 
 
 
    }
}
package com.RainbowSea.servlet;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
 
public class BServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        // 設(shè)置,在瀏覽器上響應(yīng)的格式類型
        response.setContentType("text/html;charSet=utf-8");
        PrintWriter writer = response.getWriter();
 
        // 取出請(qǐng)求域當(dāng)中的數(shù)據(jù): 這里的name值與上面setAttribute(String name,Object obj) 保持一致。
        Object sysTime = request.getAttribute("sysTime");
 
        writer.println("sysTime = " + sysTime);  // 顯示到瀏覽器頁面當(dāng)中的數(shù)據(jù)
    }
}

轉(zhuǎn)發(fā)的下一個(gè)資源必須是一個(gè)Servlet嗎 ?

不一定,只要是Tomcat服務(wù)器當(dāng)中的合法資源,都是可以轉(zhuǎn)發(fā)的。例如:html....

舉例:轉(zhuǎn)發(fā)一個(gè)html文件

注意: 如果對(duì)應(yīng)的不是 Servlet ,默認(rèn)是從項(xiàng)目的中的web目錄開始的,如果是轉(zhuǎn)發(fā)web的目錄下的子目錄的話,需要指定對(duì)應(yīng)的子目錄的文件。

package com.RainbowSea.servlet;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
        // 轉(zhuǎn)發(fā)的下一個(gè)資源不一定是Servlet 資源,
        // 只要是Tomcat服務(wù)器當(dāng)中合法的資源,都是可以轉(zhuǎn)發(fā)的,例如: html...
        // 注意:轉(zhuǎn)發(fā)的時(shí)候,路徑的寫法要注意,轉(zhuǎn)發(fā)的路徑以 “/” 開始,不加項(xiàng)目名
        // 默認(rèn)是從項(xiàng)目的中的web目錄開始的,如果是轉(zhuǎn)發(fā)web的目錄下的子目錄的話,需要指定對(duì)應(yīng)的子目錄
        // 如下是含有子目錄的 / 表示 web目錄
        request.getRequestDispatcher("/test/test.html").forward(request,response);
 
    }
}

2. Redirect重定向

重定向: 是指當(dāng)瀏覽器請(qǐng)求一個(gè) URL時(shí),服務(wù)器返回一個(gè)重定向指令,告訴瀏覽器地址已經(jīng)變了,麻煩使用新的URL再重新發(fā)送新請(qǐng)求。

重定向有兩種: 一種是302響應(yīng),稱為臨時(shí)重定向,一種是301響應(yīng),稱為永久重定向。兩者的區(qū)別是,如果服務(wù)器發(fā)送301永久重定向響應(yīng),瀏覽器會(huì)緩存/hi/hello這個(gè)重定向的關(guān)聯(lián),下次請(qǐng)求/hi的時(shí)候,瀏覽器就直接發(fā)送/hello請(qǐng)求了。

說明: 所謂的重定向是將新的路徑交給瀏覽器的地址欄上,然后自動(dòng)執(zhí)行的,而前端的信息獲取是需要指明項(xiàng)目名的,所以:注意:重定向 response.sendRedirect("/項(xiàng)目名/xxx/xx");的跳轉(zhuǎn)路徑是需要寫明項(xiàng)目名的 。

// 下面這種是 302 響應(yīng),臨時(shí)重定向
// 注意:路徑上要加一個(gè)項(xiàng)目名。為什么?
// 瀏覽器發(fā)送請(qǐng)求,請(qǐng)求路徑上是需要添加項(xiàng)目名的。
// 以下這一行代碼會(huì)將請(qǐng)求路徑“/oa/dept/list”發(fā)送給瀏覽器
// 瀏覽器會(huì)自發(fā)的向服務(wù)器發(fā)送一次全新的請(qǐng)求:/oa/dept/list
response.sendRedirect("/oa/dept/list");

HttpServletResponse提供了快捷的redirect()方法實(shí)現(xiàn)302重定向。如果要實(shí)現(xiàn)301永久重定向,可以這么寫:

response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 301
response.setHeader("Location", "/hello");

舉例: 瀏覽器向 AServlet 發(fā)送請(qǐng)求,AServlet 將該請(qǐng)求 “重定向”給了 BServlet。重定向一個(gè)新的URL地址,告訴瀏覽器發(fā)送的處理請(qǐng)求的URL地址改變了,將該請(qǐng)求發(fā)送到該重定向的URL中去,也就是這里的BServlet。

package com.RainbowSea.servlet;
 
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
 
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        // 重定向的路徑 需要加項(xiàng)目名
        response.sendRedirect("/servlet12/b");
        // 可以使用 request.getContextPath() 獲取到項(xiàng)目名(也就是項(xiàng)目名的根路徑),注意該返回的路徑是帶 “/”的 /項(xiàng)目名
        // 所以不要多寫了 “/”
        // response.sendRedirect(request.getContextPath()+"/b");
 
 
 
    }
}
package com.RainbowSea.servlet;
 
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
import java.io.PrintWriter;
 
public class BServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        // 設(shè)置瀏覽器端顯示響應(yīng)的,格式類型,以及字符集
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
 
        writer.println("<h2> 這里是BServlet 的響應(yīng)處理 </h2>");
 
    }
}
 // 重定向: (重新定方向)
//response.sendRedirect("/項(xiàng)目名/");
// 重定向時(shí)的路徑當(dāng)中需要以項(xiàng)目名開始,或者說需要添加項(xiàng)目名的
// 因?yàn)樗^的重定向是將新的路徑交給瀏覽器的地址欄上,然后自動(dòng)執(zhí)行的,而前端的信息獲取是需要指明項(xiàng)目名的
// response對(duì)將這個(gè)路徑: /servlet10/B 響應(yīng)給了瀏覽器了。
// 瀏覽器又自發(fā)的向服務(wù)器發(fā)送了一個(gè)全新的請(qǐng)求: http://127.0.0.1:8080/servlet12/a
// 所以瀏覽器一共發(fā)送了 "兩次"請(qǐng)求:
// 第一次請(qǐng)求: http://127.0.0.1:8080/servlet12/a
// 第二次請(qǐng)求: http://127.0.0.1:8080/servlet12/b
// 最終瀏覽器地址欄上顯示的地址信息當(dāng)然就是最后那一次請(qǐng)求的地址,所以重定向會(huì)導(dǎo)致瀏覽器
// 地址欄上的地址發(fā)生改變。
// 但是重定向是一次新的請(qǐng)求,是無法獲取到請(qǐng)求域當(dāng)中(只在一次請(qǐng)求中有效)信息的
// 重定向操作是由:跳轉(zhuǎn)到哪個(gè)資源,是由瀏覽器的地址欄說的算的。
// 注意: request.getContextPath()返回的項(xiàng)目名的根路徑是帶有了 "/"了的
response.sendRedirect(request.getContextPath()+"/B");

重定向: 瀏覽器是知道,實(shí)際轉(zhuǎn)發(fā)了多少次請(qǐng)求的。

注意:重定向是“重定向幾次,就會(huì)發(fā)送幾次請(qǐng)求,導(dǎo)致的結(jié)果就是,重定向無法使用 請(qǐng)求域,因?yàn)檎?qǐng)求域的作用范圍是再一次請(qǐng)求當(dāng)中的,重定向無法實(shí)現(xiàn) Servlet 之間的數(shù)據(jù)共享。

舉例如下:定義了一個(gè) 名為 User 類的JavaBean,在 AServlet 當(dāng)中 new 一個(gè) User 對(duì)象,并存儲(chǔ)到AServlet請(qǐng)求域當(dāng)中,存儲(chǔ)好以后,重定向給 BServlet ,在BServlet 當(dāng)中想將存儲(chǔ)到 AServlet 請(qǐng)求域當(dāng)中的數(shù)據(jù)取出來,這是不行的,因?yàn)檎?qǐng)求域只在一次請(qǐng)求中有效,而這里重定向了一次,就會(huì)多一次請(qǐng)求也就是兩次請(qǐng)求。無法獲取到AServlet 請(qǐng)求域當(dāng)?shù)拇鎯?chǔ)的數(shù)據(jù)。

package com.RainbowSea.servlet;
 
import java.io.Serializable;
import java.util.Objects;
 
 
/**
 * 1. 一個(gè)普通的Javabean
 * 2. 什么是javabean
 * Java是咖啡,bean 是豆子
 * javabean 咖啡豆
 * 咖啡是由咖啡豆研磨而成的,寓意:是Java程序是由一個(gè)一個(gè)的javabean組成的
 * 3. 一個(gè)javaBean一般是有規(guī)范的
 *     有無參數(shù)的構(gòu)造方法
 *     屬性私有化
 *     對(duì)外提供 get/set()方法
 *     重寫toString()
 *     重寫hashCode() + equals
 *     實(shí)現(xiàn)java.io.Serializable 接口 可序列化的
 */
public class User implements Serializable {
    private String id;
    private String name;
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return Objects.equals(getId(), user.getId()) && Objects.equals(getName(), user.getName());
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(getId(), getName());
    }
 
    public User() {
 
    }
 
    public User(String id, String name) {
        this.id = id;
        this.name = name;
    }
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    @Override
    public String toString() {
        return "User{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
package com.RainbowSea.servlet;
 
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
 
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        // 創(chuàng)建 User 對(duì)象
        User user = new User("001","張三");
 
        // 將 user 對(duì)象存儲(chǔ)到 請(qǐng)求域當(dāng)中
        request.setAttribute("userObj",user);
 
        // 重定向的路徑 需要加項(xiàng)目名
        response.sendRedirect("/servlet12/b");
        // 可以使用 request.getContextPath() 獲取到項(xiàng)目名(也就是項(xiàng)目名的根路徑),注意該返回的路徑是帶 “/”的 /項(xiàng)目名
        // 所以不要多寫了 “/”
        // response.sendRedirect(request.getContextPath()+"/b");
 
 
 
    }
}
package com.RainbowSea.servlet;
 
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
import java.io.PrintWriter;
 
public class BServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        // 無法取出 AServlet 請(qǐng)求域當(dāng)中的數(shù)據(jù)
        Object userObj = request.getAttribute("userObj");
 
        // 設(shè)置瀏覽器端顯示響應(yīng)的,格式類型,以及字符集
        response.setContentType("text/html;charSet=UTF-8");
        PrintWriter writer = response.getWriter();
 
        writer.println("從AServlet 獲取的數(shù)據(jù):" + userObj);
 
    }
}

重定向:除了重定向 Servlet 資源以外,還可以重定向其他資源,比如 html...等等只要是服務(wù)器當(dāng)中合法的資源都可以。

舉例:AServlet 重定向一個(gè)名為 index.html 的資源

package com.RainbowSea.servlet;
 
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
 
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        // 重定向一個(gè)名為 index.html 的資源
        // request.getContextPath() 返回的是該webapp的項(xiàng)目的根路徑:也就是/項(xiàng)目名,注意是帶 “/”的,不要多寫了
        response.sendRedirect(request.getContextPath()+"/index.html");
        
 
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
  <h1>Hello World</h1>
  <h1>你好世界</h1>
 
</body>
</html>

3. 轉(zhuǎn)發(fā)使用不當(dāng)?shù)奈:Γ恨D(zhuǎn)發(fā)刷新問題

說明: 由于轉(zhuǎn)發(fā)的機(jī)制的特點(diǎn):無論轉(zhuǎn)發(fā)了服務(wù)器內(nèi)部 轉(zhuǎn)發(fā) 多少次,瀏覽器都視為是請(qǐng)求了一次,而且還是原來(最初的那一次請(qǐng)求,不是轉(zhuǎn)發(fā)之后到的頁面的請(qǐng)求)。這樣的特征,如果使用不當(dāng)?shù)脑?,就?huì)存在 一個(gè)刷新問題:就是你服務(wù)器內(nèi)部雖然發(fā)送了轉(zhuǎn)發(fā)性質(zhì)的跳轉(zhuǎn)到了一個(gè)新的頁面,服務(wù)器內(nèi)部轉(zhuǎn)發(fā)到一個(gè)新的頁面成功后,你在瀏覽器端重新刷新的話,還是對(duì)最初的一個(gè)URL請(qǐng)求刷新的(因?yàn)檗D(zhuǎn)發(fā)是不會(huì)改變?yōu)g覽器地址欄上的 URL 地址的)。

舉例: 我們?cè)?StudentServlet 中執(zhí)行向數(shù)據(jù)庫的一張名為 studnet 表插入一條記錄的操作。插入成功跳轉(zhuǎn)到一個(gè)名為 succeed.html的頁面,插入失敗跳轉(zhuǎn)到一個(gè)名為 error.html失敗的頁面。然后我們對(duì)跳轉(zhuǎn)到 succeed.html* 頁面后,在瀏覽器 執(zhí)行刷新 操作看看會(huì)導(dǎo)致一個(gè)什么樣的結(jié)果 ?

準(zhǔn)備工作: 創(chuàng)建一個(gè)數(shù)據(jù)表,并插入一些數(shù)據(jù)

CREATE TABLE studnet (
`no` VARCHAR(255),
 `name` VARCHAR(255)
);
 
 
INSERT INTO studnet (`no`,`name`) VALUES('1','張三'),('2','李四');

package com.RainbowSea.servlet;
 
import com.RainbowSea.DBUtil.DBUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
 
public class StudentServlet extends HttpServlet {
 
 
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        /*
        思路: 獲取到前端的提交的數(shù)據(jù)
        連接數(shù)據(jù)庫,操作數(shù)據(jù)庫
         */
        // 獲取到前端提交的數(shù)據(jù)
        request.setCharacterEncoding("UTF-8");
        String no = request.getParameter("no");
        String name = request.getParameter("name");
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        // 表示影響數(shù)據(jù)庫的行數(shù)
        int count = 0;
 
        try {
            // 1. 連接數(shù)據(jù)庫,這里的DBUtil.getConnection(); 是我寫的一個(gè)連接數(shù)據(jù)庫的工具類,大家不用太在意
            connection = DBUtil.getConnection();
 
            // 2. 獲取操作數(shù)據(jù)庫對(duì)象,預(yù)編譯sql語句,注意測(cè)試sql是否存在錯(cuò)誤
            // 注意: ? 不要加 '', ""單雙引號(hào),不然無法識(shí)別到該占位符的
            String sql = "INSERT INTO studnet (`no`,`name`) VALUES(?,?)";
            preparedStatement = connection.prepareStatement(sql);
 
            // 3. 填充占位符,真正執(zhí)行sql語句
            preparedStatement.setString(1,no);
            preparedStatement.setString(2,name);
 
            count = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 4. 釋放資源
            DBUtil.close(connection,preparedStatement,null);
        }
 
        if(count == 1) {
            // 添加成功
            // 先用 轉(zhuǎn)發(fā)機(jī)制 ,轉(zhuǎn)發(fā)服務(wù)器內(nèi)部,不要加項(xiàng)目名
            request.getRequestDispatcher("/succeed.html").forward(request,response);
        } else {
            request.getRequestDispatcher("/error.html").forward(request,response);
        }
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加成功</title>
</head>
<body>
  <h1>添加成功</h1>
 
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加失敗</title>
</head>
<body>
 
  <h1>添加失敗</h1>
 
</body>
</html>

實(shí)驗(yàn)效果如下:

但是,如果我們這時(shí)候,在瀏覽器端點(diǎn)擊刷新,這里我們,點(diǎn)擊了 3次刷新。導(dǎo)致的結(jié)果如下:

優(yōu)化: 這里我們將轉(zhuǎn)發(fā) 修改為 重定向 就沒有這樣的問題了,因?yàn)橹囟ㄏ蚴菚?huì)改變?yōu)g覽器地址欄上的 URL 地址的(為最后我們重定向(跳轉(zhuǎn))的頁面的URL地址)。

package com.RainbowSea.servlet;
 
import com.RainbowSea.DBUtil.DBUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
 
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
 
public class StudentServlet extends HttpServlet {
 
 
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
            IOException {
 
        /*
        思路: 獲取到前端的提交的數(shù)據(jù)
        連接數(shù)據(jù)庫,操作數(shù)據(jù)庫
         */
        // 獲取到前端提交的數(shù)據(jù)
        request.setCharacterEncoding("UTF-8");
        String no = request.getParameter("no");
        String name = request.getParameter("name");
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        // 表示影響數(shù)據(jù)庫的行數(shù)
        int count = 0;
 
        try {
            // 連接數(shù)據(jù)庫
            connection = DBUtil.getConnection();
 
            // 注意: ? 不要加 '', ""單雙引號(hào),不然無法識(shí)別到該占位符的
            String sql = "INSERT INTO studnet (`no`,`name`) VALUES(?,?)";
            preparedStatement = connection.prepareStatement(sql);
 
            preparedStatement.setString(1,no);
            preparedStatement.setString(2,name);
 
            count = preparedStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            // 釋放資源
            DBUtil.close(connection,preparedStatement,null);
        }
 
        if(count == 1) {
            // 添加成功
            // 先用 轉(zhuǎn)發(fā)機(jī)制 ,轉(zhuǎn)發(fā)服務(wù)器內(nèi)部,不要加項(xiàng)目名
            // request.getRequestDispatcher("/succeed.html").forward(request,response);
 
            // 優(yōu)化修改為重定向:重定向前端需要指明 項(xiàng)目名(/項(xiàng)目的根路徑)
            // request.getContextPath() 該方法可以獲取到: "/項(xiàng)目的根路徑",注意是帶有 / 的,所以不要多寫了 /
            response.sendRedirect(request.getContextPath()+"/succeed.html");
        } else {
            // request.getRequestDispatcher("/error.html").forward(request,response);
            response.sendRedirect(request.getContextPath()+"/error.html");
        }
    }
}

4. 轉(zhuǎn)發(fā) 與 重定向的區(qū)別

代碼上的區(qū)別:

轉(zhuǎn)發(fā) :轉(zhuǎn)發(fā)的路徑 不要 寫項(xiàng)目名(項(xiàng)目的根路徑)

// 獲取請(qǐng)求轉(zhuǎn)發(fā)器對(duì)象
RequestDispatcher dispatcher = request.getRequestDispatcher("/dept/list");
// 調(diào)用請(qǐng)求轉(zhuǎn)發(fā)器對(duì)象的forward方法完成轉(zhuǎn)發(fā)
dispatcher.forward(request, response);
 
// 合并一行代碼
request.getRequestDispatcher("/dept/list").forward(request, response);
// 轉(zhuǎn)發(fā)的時(shí)候是一次請(qǐng)求,不管你轉(zhuǎn)發(fā)了多少次。都是一次請(qǐng)求。
// AServlet轉(zhuǎn)發(fā)到BServlet,再轉(zhuǎn)發(fā)到CServlet,再轉(zhuǎn)發(fā)到DServlet,不管轉(zhuǎn)發(fā)了多少次,都在同一個(gè)request當(dāng)中。
// 這是因?yàn)檎{(diào)用forward方法的時(shí)候,會(huì)將當(dāng)前的request和response對(duì)象傳遞給下一個(gè)Servlet。

重定向 :重定向的路徑,需要 寫項(xiàng)目名(項(xiàng)目的根路徑)

response.sendRedirect("/servlet12/b");
// 可以使用 request.getContextPath() 獲取到項(xiàng)目名(也就是項(xiàng)目名的根路徑),注意該返回的路徑是帶 “/”的 /項(xiàng)目名,所以不要多寫了 “/”
 response.sendRedirect(request.getContextPath()+"/index.html");

形式上有什么區(qū)別 ?

轉(zhuǎn)發(fā)(一次請(qǐng)求)

在瀏覽器地址欄上發(fā)送的請(qǐng)求是:http://localhost:8080/servlet10/a ,最終請(qǐng)求結(jié)束之后,瀏覽器地址欄上的地址還是這個(gè)。沒變。

重定向(兩次請(qǐng)求)

在瀏覽器地址欄上發(fā)送的請(qǐng)求是:http://localhost:8080/servlet10/a ,最終在瀏覽器地址欄上顯示的地址是:http://localhost:8080/servlet10/b(也就是最后重定向的地址)

轉(zhuǎn)發(fā)和重定向的本質(zhì)區(qū)別 ?

轉(zhuǎn)發(fā):是由WEB服務(wù)器來控制的。A資源跳轉(zhuǎn)到B資源,這個(gè)跳轉(zhuǎn)動(dòng)作是Tomcat服務(wù)器內(nèi)部完成的。所以無論 服務(wù)器轉(zhuǎn)發(fā)了多少次,而我們前端也就是瀏覽器端是不知道我們服務(wù)器端對(duì)這個(gè)請(qǐng)求內(nèi)部轉(zhuǎn)發(fā)處理了多少次。 并且無論我們服務(wù)器內(nèi)部轉(zhuǎn)發(fā)了多少次,前端瀏覽器都僅僅只會(huì)認(rèn)為僅僅只轉(zhuǎn)發(fā)了一次,也就是僅僅發(fā)送了一次請(qǐng)求 。因?yàn)槲覀兎?wù)器端雖然進(jìn)行了轉(zhuǎn)發(fā),但是瀏覽器的地址欄上的請(qǐng)求路徑的地址是沒有改變的(還是初始的請(qǐng)求路徑)

重定向:是瀏覽器完成的。具體跳轉(zhuǎn)到哪個(gè)資源,是瀏覽器說了算。當(dāng)瀏覽器請(qǐng)求一個(gè) URL時(shí),服務(wù)器返回一個(gè)重定向指令,告訴瀏覽器要處理該請(qǐng)求的URL地址已經(jīng)變了,麻煩使用新的URL再重新發(fā)送新請(qǐng)求。所以,前端瀏覽器是知道我們重定向了多少次的,而且重定向是“重定向幾次,就會(huì)發(fā)送幾次請(qǐng)求”。

相同點(diǎn): 無論是 “轉(zhuǎn)發(fā)”還是 “重定向”都可以跳轉(zhuǎn)到另外一個(gè)資源當(dāng)中,都是不僅僅是 Servlet 資源,也可以是其他的服務(wù)器上合法的資源比如:html等等。

優(yōu)缺點(diǎn)上的區(qū)別:

轉(zhuǎn)發(fā): 可以通過請(qǐng)求域存儲(chǔ)數(shù)據(jù)的方式,實(shí)現(xiàn)多個(gè)Servlet 數(shù)據(jù)的共享。因?yàn)椋憾嗌俅无D(zhuǎn)發(fā)都是只視為一次請(qǐng)求。但是轉(zhuǎn)發(fā)存在刷新問題 。

重定向:沒有刷新問題,但是無法通過請(qǐng)求域存儲(chǔ)數(shù)據(jù)的方式,實(shí)現(xiàn)多個(gè)Servlet 數(shù)據(jù)的共享。因?yàn)椋?ldquo;重定向幾次,就會(huì)發(fā)送幾次請(qǐng)求”。而請(qǐng)求域只在一次請(qǐng)求范圍有效。

轉(zhuǎn)發(fā)與重定向 舉例圖示上的描述:

轉(zhuǎn)發(fā):

重定向:

5. “重寫向”與“轉(zhuǎn)發(fā)”的合理選擇

  • 如果在上一個(gè)Servlet當(dāng)中向request域當(dāng)中綁定了數(shù)據(jù),希望從下一個(gè)Servlet當(dāng)中把request域里面的數(shù)據(jù)取出來,使用轉(zhuǎn)發(fā)機(jī)制。
  • 剩下所有的請(qǐng)求均使用重定向。(重定向使用較多。)

重定向的目的是當(dāng)Web應(yīng)用升級(jí)后,如果請(qǐng)求路徑發(fā)生了變化,可以將原來的路徑重定向到新路徑,從而避免瀏覽器請(qǐng)求原路徑找不到資源。

6. 總結(jié):

轉(zhuǎn)發(fā) :指內(nèi)部轉(zhuǎn)發(fā)。當(dāng)一個(gè)Servlet處理請(qǐng)求的時(shí)候,它可以決定自己不繼續(xù)處理,而是轉(zhuǎn)發(fā)給另一個(gè)Servlet處理。

轉(zhuǎn)發(fā)是由WEB服務(wù)器來控制的。A資源跳轉(zhuǎn)到B資源,這個(gè)跳轉(zhuǎn)動(dòng)作是Tomcat服務(wù)器內(nèi)部完成的而我們前端也就是瀏覽器端是不知道我們服務(wù)器端對(duì)這個(gè)請(qǐng)求內(nèi)部轉(zhuǎn)發(fā)處理了多少次。 并且無論我們服務(wù)器內(nèi)部轉(zhuǎn)發(fā)了多少次,前端瀏覽器都僅僅只會(huì)認(rèn)為僅僅只轉(zhuǎn)發(fā)了一次,也就是僅僅發(fā)送了一次請(qǐng)求 。因?yàn)槲覀兎?wù)器端雖然進(jìn)行了轉(zhuǎn)發(fā)但是,瀏覽器的地址欄上的請(qǐng)求路徑的地址是沒有改變的(還是初始的請(qǐng)求路徑) 編寫的轉(zhuǎn)發(fā)路徑是不要加項(xiàng)目名的。

重定向: 是指當(dāng)瀏覽器請(qǐng)求一個(gè) URL時(shí),服務(wù)器返回一個(gè)重定向指令,告訴瀏覽器地址已經(jīng)變了,麻煩使用新的URL再重新發(fā)送新請(qǐng)求。

  • 重定向有兩種: 一種是302響應(yīng),稱為臨時(shí)重定向,一種是301響應(yīng),稱為永久重定向。兩者的區(qū)別是,如果服務(wù)器發(fā)送301永久重定向響應(yīng),瀏覽器會(huì)緩存/hi/hello這個(gè)重定向的關(guān)聯(lián),下次請(qǐng)求/hi的時(shí)候,瀏覽器就直接發(fā)送/hello請(qǐng)求了。
  • 說明: 所謂的重定向是將新的路徑交給瀏覽器的地址欄上,然后自動(dòng)執(zhí)行的,而前端的信息獲取是需要指明項(xiàng)目名的,所以:注意:重定向 response.sendRedirect("/項(xiàng)目名/xxx/xx");的跳轉(zhuǎn)路徑是需要寫明項(xiàng)目名的 。

注意:轉(zhuǎn)發(fā)機(jī)制存在的一個(gè)刷新問題。

轉(zhuǎn)發(fā) 與 重定向的區(qū)別

到此這篇關(guān)于JavaWeb中轉(zhuǎn)發(fā)與重定向的區(qū)別小結(jié)的文章就介紹到這了,更多相關(guān)JavaWeb 轉(zhuǎn)發(fā)與重定向內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Jenkins安裝以及郵件配置詳解

    Jenkins安裝以及郵件配置詳解

    這篇文章主要介紹了Jenkins安裝以及郵件配置相關(guān)問題,并通過圖文給大家做了詳細(xì)講解步驟,需要的朋友參考下吧。
    2017-12-12
  • Java并發(fā)Map面試線程安全數(shù)據(jù)結(jié)構(gòu)全面分析

    Java并發(fā)Map面試線程安全數(shù)據(jù)結(jié)構(gòu)全面分析

    本文將探討如何在Java中有效地應(yīng)對(duì)這些挑戰(zhàn),介紹一種強(qiáng)大的工具并發(fā)Map,它能夠幫助您管理多線程環(huán)境下的共享數(shù)據(jù),確保數(shù)據(jù)的一致性和高性能,深入了解Java中的并發(fā)Map實(shí)現(xiàn),包括ConcurrentHashMap和ConcurrentSkipListMap,及相關(guān)知識(shí)點(diǎn)
    2023-09-09
  • Java中wait()與sleep()兩者的不同深入解析

    Java中wait()與sleep()兩者的不同深入解析

    在Java多線程編程中,wait()和sleep()是控制線程執(zhí)行和等待的兩個(gè)關(guān)鍵方法,但它們?cè)趹?yīng)用場(chǎng)景和實(shí)現(xiàn)上有顯著差異,這篇文章主要介紹了Java中wait()與sleep()兩者的不同,需要的朋友可以參考下
    2024-11-11
  • Java中的使用及連接Redis數(shù)據(jù)庫(附源碼)

    Java中的使用及連接Redis數(shù)據(jù)庫(附源碼)

    這篇文章主要介紹了Java中的使用及連接Redis數(shù)據(jù)庫(附源碼),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Spring Cloud負(fù)載均衡及遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解

    Spring Cloud負(fù)載均衡及遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解

    這篇文章主要介紹了Spring Cloud負(fù)載均衡及遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • JavaSwing實(shí)現(xiàn)小型學(xué)生管理系統(tǒng)

    JavaSwing實(shí)現(xiàn)小型學(xué)生管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了JavaSwing實(shí)現(xiàn)小型學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 淺談Spring Boot 整合ActiveMQ的過程

    淺談Spring Boot 整合ActiveMQ的過程

    本篇文章主要介紹了淺談Spring Boot 整合ActiveMQ的過程,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • 詳解Java如何關(guān)閉線程以及線程池

    詳解Java如何關(guān)閉線程以及線程池

    java如何正確關(guān)閉線程以及線程池是一個(gè)高頻的面試題,本文將為大家詳細(xì)介紹實(shí)現(xiàn)的方法與代碼,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下
    2022-04-04
  • 淺談java對(duì)象結(jié)構(gòu) 對(duì)象頭 Markword

    淺談java對(duì)象結(jié)構(gòu) 對(duì)象頭 Markword

    這篇文章主要介紹了淺談java對(duì)象結(jié)構(gòu) 對(duì)象頭 Markword,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java源碼解析之LinkedHashMap

    Java源碼解析之LinkedHashMap

    LinkedHashMap是HashMap的子類,所以也具備HashMap的諸多特性.不同的是,LinkedHashMap還維護(hù)了一個(gè)雙向鏈表,以保證通過Iterator遍歷時(shí)順序與插入順序一致.除此之外,它還支持Access Order, ,需要的朋友可以參考下
    2021-05-05

最新評(píng)論