doGet และ doPost ใน Servlets


105

ฉันได้พัฒนาหน้า HTML ที่ส่งข้อมูลไปยัง Servlet ใน Servlet ฉันใช้วิธีการdoGet()และdoPost():

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException  {

     String id = req.getParameter("realname");
     String password = req.getParameter("mypassword");
}

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {

    String id = req.getParameter("realname");
    String password = req.getParameter("mypassword");
}

ในโค้ดเพจ html ที่เรียก Servlet คือ:

<form action="identification" method="post" enctype="multipart/form-data">
    User Name: <input type="text" name="realname">
    Password: <input type="password" name="mypassword">
    <input type="submit" value="Identification">
</form> 

เมื่อฉันใช้method = "get"ใน Servlet ฉันได้รับค่าของ ID และรหัสผ่าน แต่เมื่อใช้method = "post", ID nullและรหัสผ่านมีการกำหนดให้ เหตุใดฉันจึงไม่ได้รับค่าในกรณีนี้

อีกสิ่งหนึ่งที่ฉันต้องการทราบคือวิธีใช้ข้อมูลที่สร้างหรือตรวจสอบโดย Servlet ตัวอย่างเช่นหาก Servlet ที่แสดงด้านบนรับรองความถูกต้องของผู้ใช้ฉันต้องการพิมพ์รหัสผู้ใช้ในหน้า HTML ของฉัน ฉันควรจะสามารถส่งสตริง 'id' เป็นการตอบกลับและใช้ข้อมูลนี้ในหน้า HTML ของฉัน เป็นไปได้ไหม?


คุณใช้วิธีการโพสต์ที่ html อย่างไร?
Igor Artamonov

นอกจากนี้คุณต้องการลูปแปลก ๆ มากกว่าชื่อพารามิเตอร์สำหรับอะไร?
Igor Artamonov

1
คุณได้ลองลบ "enctype = multipart / form-data" แล้วหรือยัง ฉันสงสัยว่านั่นคือปัญหาของคุณ
Jack Leow

นั่นแหล่ะ เหตุใดจึงไม่โพสต์งานเมื่อเป็นปัจจุบัน ขอบคุณสำหรับความช่วยเหลือของคุณ!
dedalo

คำตอบ:


197

บทนำ

คุณควรใช้doGet()เมื่อคุณต้องการที่จะตัดในHTTP GET ร้องขอ คุณควรใช้doPost()เมื่อคุณต้องการที่จะสกัดกั้นในการร้องขอ HTTP POST นั่นคือทั้งหมด อย่าโอนพอร์ตหนึ่งไปยังอีกเครื่องหนึ่งหรือในทางกลับกัน (เช่นในprocessRequest()วิธีสร้างอัตโนมัติที่โชคร้ายของ Netbeans ) สิ่งนี้ไม่สมเหตุสมผล

รับ

โดยปกติ HTTP GET คำขอidempotent กล่าวคือคุณจะได้รับผลลัพธ์เดียวกันทุกครั้งที่คุณดำเนินการตามคำขอ (ออกจากการอนุญาต / การรับรองความถูกต้องและลักษณะของหน้าเว็บที่คำนึงถึงเวลา - ผลการค้นหาข่าวล่าสุด ฯลฯ - การพิจารณาจากภายนอก) เราสามารถพูดคุยเกี่ยวกับคำขอที่คั่นหน้าได้ การคลิกลิงก์คลิกบุ๊กมาร์กป้อน URL ดิบในแถบที่อยู่ของเบราว์เซอร์ ฯลฯ ทั้งหมดจะเริ่มการร้องขอ HTTP GET หาก Servlet กำลังฟัง URL ที่เป็นปัญหาระบบdoGet()จะเรียกวิธีการนั้น โดยปกติจะใช้เพื่อประมวลผลคำขอล่วงหน้า ได้แก่ การทำธุรกิจบางอย่างก่อนที่จะนำเสนอเอาต์พุต HTML จาก JSP เช่นการรวบรวมข้อมูลเพื่อแสดงในตาราง

@WebServlet("/products")
public class ProductsServlet extends HttpServlet {

    @EJB
    private ProductService productService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Product> products = productService.list();
        request.setAttribute("products", products); // Will be available as ${products} in JSP
        request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
    }

}
<table>
    <c:forEach items="${products}" var="product">
        <tr>
            <td>${product.name}</td>
            <td><a href="product?id=${product.id}">detail</a></td>
        </tr>
    </c:forEach>
</table>

นอกจากนี้ลิงก์ดู / แก้ไขรายละเอียดดังที่แสดงในคอลัมน์สุดท้ายด้านบนมักจะไม่ปรากฏ

@WebServlet("/product")
public class ProductServlet extends HttpServlet {

    @EJB
    private ProductService productService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Product product = productService.find(request.getParameter("id"));
        request.setAttribute("product", product); // Will be available as ${product} in JSP
        request.getRequestDispatcher("/WEB-INF/product.jsp").forward(request, response);
    }

}
<dl>
    <dt>ID</dt>
    <dd>${product.id}</dd>
    <dt>Name</dt>
    <dd>${product.name}</dd>
    <dt>Description</dt>
    <dd>${product.description}</dd>
    <dt>Price</dt>
    <dd>${product.price}</dd>
    <dt>Image</dt>
    <dd><img src="productImage?id=${product.id}" /></dd>
</dl>

โพสต์

คำขอ HTTP POST ไม่ใช่สิ่งที่จำเป็น หาก enduser ส่งแบบฟอร์ม POST บน URL ล่วงหน้าซึ่งยังไม่ได้ทำการเปลี่ยนเส้นทางแสดงว่า URL นั้นไม่จำเป็นต้องบุ๊กมาร์ก ข้อมูลแบบฟอร์มที่ส่งจะไม่แสดงใน URL การคัดลอก URL ไปยังหน้าต่าง / แท็บใหม่ของเบราว์เซอร์อาจไม่จำเป็นต้องให้ผลลัพธ์เหมือนกับหลังการส่งแบบฟอร์ม จากนั้น URL ดังกล่าวจะไม่สามารถบุ๊กมาร์กได้ หาก Servlet กำลังฟัง URL ที่เป็นปัญหาระบบdoPost()จะเรียกมัน โดยปกติจะใช้เพื่อประมวลผลคำขอ ได้แก่ การรวบรวมข้อมูลจากรูปแบบ HTML ที่ส่งมาและทำธุรกิจบางอย่างด้วย (การแปลงการตรวจสอบความถูกต้องการบันทึกในฐานข้อมูล ฯลฯ ) ในที่สุดผลลัพธ์จะแสดงเป็น HTML จากหน้า JSP ที่ส่งต่อ

<form action="login" method="post">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit" value="login">
    <span class="error">${error}</span>
</form>

... ซึ่งสามารถใช้ร่วมกับ Servlet ชิ้นนี้ได้:

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @EJB
    private UserService userService;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = userService.find(username, password);

        if (user != null) {
            request.getSession().setAttribute("user", user);
            response.sendRedirect("home");
        }
        else {
            request.setAttribute("error", "Unknown user, please try again");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }

}

คุณจะเห็นว่าถ้าUserพบใน DB (เช่นชื่อผู้ใช้และรหัสผ่านถูกต้อง) Userจะถูกใส่ในขอบเขตเซสชัน (เช่น "เข้าสู่ระบบ") และ servlet จะเปลี่ยนเส้นทางไปยังหน้าหลักบางหน้า (ตัวอย่างนี้ไปที่http://example.com/contextname/home) อื่น ๆ มันจะตั้งข้อผิดพลาดและส่งต่อการร้องขอกลับไปที่หน้า JSP ${error}เดียวกันเพื่อให้ได้รับข้อความแสดงโดย

คุณสามารถ "ซ่อน" login.jspในได้หากจำเป็น/WEB-INF/login.jspเพื่อให้ผู้ใช้สามารถเข้าถึงได้โดย servlet เท่านั้น http://example.com/contextname/loginนี้ช่วยให้การทำความสะอาดของ URL สิ่งที่คุณต้องทำคือเพิ่ม a doGet()ให้กับ servlet ดังนี้:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}

(และอัปเดตบรรทัดเดียวกันdoPost()ตามนั้น)

ที่กล่าวว่าผมไม่แน่ใจว่าถ้ามันเป็นเพียงแค่การเล่นไปรอบ ๆ และการถ่ายภาพในที่มืด แต่รหัสที่คุณโพสต์ไม่ได้ดูดี (เช่นใช้compareTo()แทนequals()และเครื่องตักดิน parameternames แทนการเพียงแค่ใช้getParameter()และidและpasswordดูเหมือนว่าจะ ถูกประกาศเป็นตัวแปรอินสแตนซ์ servlet - ซึ่งไม่ใช่เธรดที่ปลอดภัย ) ดังนั้นผมจะขอแนะนำให้เรียนรู้อีกเล็กน้อยเกี่ยวกับพื้นฐาน Java SE API โดยใช้บทเรียนออราเคิล (ตรวจสอบบท "เส้นทางครอบคลุมพื้นฐาน") และวิธีการใช้ JSP / Servlets วิธีการที่เหมาะสมโดยใช้บทเรียนเหล่านั้น

ดูสิ่งนี้ด้วย:


อัปเดต : ตามการอัปเดตคำถามของคุณ (ซึ่งเป็นเรื่องสำคัญมากคุณไม่ควรลบบางส่วนของคำถามเดิมของคุณสิ่งนี้จะทำให้คำตอบไร้ค่า .. แต่เพิ่มข้อมูลในบล็อกใหม่) ปรากฎว่าคุณ multipart/form-dataประเภทการเข้ารหัสรูปแบบการตั้งค่าโดยไม่จำเป็นที่จะ สิ่งนี้จะส่งพารามิเตอร์คำขอในองค์ประกอบที่แตกต่างจาก (ค่าเริ่มต้น) application/x-www-form-urlencodedซึ่งส่งพารามิเตอร์คำขอเป็นสตริงการสืบค้น (เช่นname1=value1&name2=value2&name3=value3) คุณต้องการmultipart/form-dataเมื่อใดก็ตามที่คุณมีไฟล์<input type="file">องค์ประกอบในรูปแบบเพื่ออัปโหลดไฟล์ซึ่งอาจเป็นข้อมูลที่ไม่ใช่อักขระ (ข้อมูลไบนารี) นี่ไม่ใช่กรณีของคุณดังนั้นเพียงแค่ลบออกและจะได้ผลตามที่คาดไว้ หากคุณต้องการอัปโหลดไฟล์คุณจะต้องตั้งค่าประเภทการเข้ารหัสและแยกวิเคราะห์เนื้อหาคำขอด้วยตัวคุณเอง โดยปกติคุณจะใช้Apache Commons FileUpload ที่นั่น แต่ถ้าคุณใช้ Servlet 3.0 API ใหม่อยู่แล้วคุณก็สามารถใช้สิ่งอำนวยความสะดวกในตัวที่เริ่มต้นด้วยHttpServletRequest#getPart(). ดูคำตอบนี้สำหรับตัวอย่างที่เป็นรูปธรรม: วิธีอัปโหลดไฟล์ไปยังเซิร์ฟเวอร์โดยใช้ JSP / Servlet


2

ทั้ง GET และ POST ถูกใช้โดยเบราว์เซอร์เพื่อขอทรัพยากรเดียวจากเซิร์ฟเวอร์ ทรัพยากรแต่ละรายการต้องการคำขอ GET หรือ POST แยกกัน

  1. วิธีการ GET มักใช้กันทั่วไป (และเป็นวิธีเริ่มต้น) ที่เบราว์เซอร์ใช้เพื่อดึงข้อมูลจากเซิร์ฟเวอร์ เมื่อใช้เมธอด GET ส่วนที่ 3 ของแพ็กเก็ตคำร้องขอซึ่งเป็นส่วนของคำร้องขอจะยังคงว่างเปล่า

เมธอด GET ถูกใช้ในหนึ่งในสองวิธี: เมื่อไม่มีการระบุเมธอดนั่นคือเมื่อคุณหรือเบราว์เซอร์กำลังขอทรัพยากรง่ายๆเช่นเพจ HTML รูปภาพ ฯลฯ เมื่อส่งแบบฟอร์มและคุณเลือกวิธีการ = รับบนแท็ก HTML หากใช้เมธอด GET กับรูปแบบ HTML ข้อมูลที่รวบรวมผ่านแบบฟอร์มจะถูกส่งไปยังเซิร์ฟเวอร์โดยต่อท้าย "?" ที่ส่วนท้ายของ URL จากนั้นเพิ่มคู่ชื่อ = ค่าทั้งหมด (ชื่อของฟิลด์ฟอร์ม html และค่าที่ป้อนในฟิลด์นั้น) คั่นด้วย "&" ตัวอย่าง: GET /sultans/shop//form1.jsp?name= Sam% 20Sultan & iceCream = vanilla HTTP / 1.0 ตัวเลือกส่วนหัวส่วนหัว << บรรทัดว่าง >>>

ข้อมูลฟอร์ม name = value จะถูกเก็บไว้ในตัวแปรสภาพแวดล้อมที่เรียกว่า QUERY_STRING ตัวแปรนี้จะถูกส่งไปยังโปรแกรมประมวลผล (เช่น JSP, Java servlet, PHP เป็นต้น)

  1. เมธอด POST ถูกใช้เมื่อคุณสร้างฟอร์ม HTML และขอ method = POST เป็นส่วนหนึ่งของแท็ก วิธีการ POST อนุญาตให้ไคลเอ็นต์ส่งข้อมูลแบบฟอร์มไปยังเซิร์ฟเวอร์ในส่วนเนื้อหาคำขอของคำขอ (ตามที่กล่าวไว้ก่อนหน้านี้) ข้อมูลจะถูกเข้ารหัสและมีรูปแบบคล้ายกับวิธี GET ยกเว้นว่าข้อมูลจะถูกส่งไปยังโปรแกรมผ่านอินพุตมาตรฐาน

ตัวอย่าง: POST /sultans/shop//form1.jsp HTTP / 1.0 ส่วนหัวที่เป็นทางเลือก << บรรทัดว่าง >>> name = Sam% 20Sultan & iceCream = vanilla

เมื่อใช้วิธีการโพสต์ตัวแปรสภาพแวดล้อม QUERY_STRING จะว่างเปล่า ข้อดี / ข้อเสียของ GET เทียบกับ POST

ข้อดีของเมธอด GET: สามารถป้อนพารามิเตอร์ที่เร็วขึ้นเล็กน้อยผ่านแบบฟอร์มหรือโดยการต่อท้ายหลังจากเพจ URL สามารถบุ๊กมาร์กด้วยพารามิเตอร์ได้

ข้อเสียของวิธี GET: สามารถส่งข้อมูลที่มีมูลค่า 4K เท่านั้น (คุณไม่ควรใช้เมื่อใช้ช่อง textarea) พารามิเตอร์จะปรากฏที่ส่วนท้ายของ URL

ข้อดีของวิธีการ POST: ไม่สามารถมองเห็นพารามิเตอร์ได้ที่ท้าย URL (ใช้สำหรับข้อมูลที่ละเอียดอ่อน) สามารถส่งข้อมูลที่มีมูลค่า 4K ไปยังเซิร์ฟเวอร์ได้มากขึ้น

ข้อเสียของวิธี POST: ไม่สามารถบุ๊กมาร์กด้วยข้อมูลได้


0

เป็นไปได้ไหมว่าคุณกำลังส่งผ่านข้อมูลผ่าน get ไม่ใช่โพสต์?

<form method="get" ..>
..
</form>

0

หากคุณ<form action="identification" >ใช้รูปแบบ html ของคุณข้อมูลจะถูกส่งผ่านโดยใช้ 'Get' ตามค่าเริ่มต้นดังนั้นคุณสามารถตรวจจับสิ่งนี้ได้โดยใช้ฟังก์ชัน doGet ในรหัส servlet java ของคุณ วิธีนี้จะส่งข้อมูลภายใต้ส่วนหัว HTML และด้วยเหตุนี้จะปรากฏใน URL เมื่อส่ง ในทางกลับกันหากคุณต้องการส่งผ่านข้อมูลในเนื้อหา HTML ให้ใช้โพสต์: <form action="identification" method="post">และรับข้อมูลนี้ในฟังก์ชัน doPost นี่คือข้อมูลจะถูกส่งผ่านภายใต้เนื้อหา html ไม่ใช่ส่วนหัว html และคุณจะไม่เห็นข้อมูลใน URL หลังจากส่งแบบฟอร์ม

ตัวอย่างจาก html ของฉัน:

<body>  
<form action="StartProcessUrl" method="post">
.....
.....

ตัวอย่างจากรหัส servlet java ของฉัน:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        PrintWriter out = response.getWriter();
         String surname = request.getParameter("txtSurname");
         String firstname = request.getParameter("txtForename");
         String rqNo = request.getParameter("txtRQ6");
         String nhsNo = request.getParameter("txtNHSNo");

         String attachment1 = request.getParameter("base64textarea1");
         String attachment2 = request.getParameter("base64textarea2");

.........
.........

0

การนำHttpServlet.service()เมธอดของ servlet container ไปใช้โดยอัตโนมัติdoGet()หรือdoPost()ตามความจำเป็นดังนั้นคุณไม่จำเป็นต้องแทนที่วิธีการบริการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.