HttpServletRequest เพื่อทำ URL ให้สมบูรณ์


248

ฉันมีHttpServletRequestวัตถุ

ฉันจะได้รับ URL ที่ถูกต้องและครบถ้วนซึ่งทำให้สายนี้มาถึง servlet ของฉันได้อย่างไร

หรืออย่างน้อยที่สุดแม่นยำเท่าที่จะเป็นไปได้เพราะอาจมีบางสิ่งที่สามารถสร้างใหม่ได้ (ลำดับของพารามิเตอร์อาจ)


ดูเพิ่มเติมได้ที่: stackoverflow.com/questions/4931323/…
Christophe Roussy

ทำไมเราถึงไม่ใช้ฟังก์ชั่น util สำหรับมัน
vanduc1102

คำตอบ:


393

The HttpServletRequestมีวิธีการดังต่อไปนี้:

  • getRequestURL() - ส่งคืนส่วนของ URL แบบเต็มก่อนที่จะมีอักขระตัวคั่นสตริงแบบสอบถาม ?
  • getQueryString() - ส่งคืนส่วนของ URL แบบเต็มหลังจากอักขระตัวแยกสตริงการสืบค้น ?

ดังนั้นหากต้องการรับ URL แบบเต็มให้ทำดังนี้

public static String getFullURL(HttpServletRequest request) {
    StringBuilder requestURL = new StringBuilder(request.getRequestURL().toString());
    String queryString = request.getQueryString();

    if (queryString == null) {
        return requestURL.toString();
    } else {
        return requestURL.append('?').append(queryString).toString();
    }
}

3
คุณคัดลอกคำอธิบายจาก getRequestURI (ไม่ถูกต้อง) แต่ใช้ getRequestURL ในรหัส (ขวา)
Vinko Vrsalovic

21
คุณต้องตรวจสอบตามเงื่อนไขว่าสตริงแบบสอบถามว่างเปล่าหรือไม่
Adam Gent

8
คุณกำลังกลายพันธุ์ StringBuffer สำรอง URL ที่ร้องขอ หากการดำเนินการตามคำขอไม่ได้สร้างสำเนาการป้องกันซึ่งเป็นวิธีที่ดีมากในการแนะนำพฤติกรรมที่แปลกและข้อบกพร่องในส่วนอื่น ๆ ของรหัสที่คาดว่าจะอยู่ในรูปแบบดั้งเดิม
Ken Blair

5
ใช้ StringBuilder แทน StringBuffer
Gladwin Burboz

17
@KenBlair: StringBuffer จะถูกส่งกลับตามวัตถุประสงค์เพื่อให้คุณสามารถเพิ่มที่เก็บเพิ่มเติมได้อย่างง่ายดาย เนื่องจากสิ่งนี้ถูกระบุไว้บน javadoc มันจะไร้สาระอย่างมากในการใช้งานเพื่อคาดหวังว่า StringBuffer ที่ส่งคืนจะไม่ถูกแก้ไขโดยผู้เรียก - ดังนั้นนี่จึงเป็นเรื่องที่ดี
stolsvik

145

ฉันใช้วิธีนี้:

public static String getURL(HttpServletRequest req) {

    String scheme = req.getScheme();             // http
    String serverName = req.getServerName();     // hostname.com
    int serverPort = req.getServerPort();        // 80
    String contextPath = req.getContextPath();   // /mywebapp
    String servletPath = req.getServletPath();   // /servlet/MyServlet
    String pathInfo = req.getPathInfo();         // /a/b;c=123
    String queryString = req.getQueryString();          // d=789

    // Reconstruct original requesting URL
    StringBuilder url = new StringBuilder();
    url.append(scheme).append("://").append(serverName);

    if (serverPort != 80 && serverPort != 443) {
        url.append(":").append(serverPort);
    }

    url.append(contextPath).append(servletPath);

    if (pathInfo != null) {
        url.append(pathInfo);
    }
    if (queryString != null) {
        url.append("?").append(queryString);
    }
    return url.toString();
}

8
นี่คือคำตอบที่เป็นประโยชน์สำหรับการอ้างอิงอย่างรวดเร็วไปยังบิตทั้งหมดของข้อมูลที่มีอยู่ใน HttpServletRequest อย่างไรก็ตามฉันคิดว่าคุณต้องการตรวจสอบโครงร่างในการตัดสินใจว่าจะเพิ่มส่วนพอร์ตเข้ากับผลลัพธ์หรือไม่ ตัวอย่างเช่น "https" จะเป็น 443
Peter Cardona

2
การเพิ่มประสิทธิภาพขนาดเล็กจะใช้ StringBuilder แทน StringBuffer เพียงคำใบ้
คริส

11
เพียงความคิดเห็น: ความปลอดภัยของเธรดไม่ได้เป็นปัญหาในตัวอย่างที่เฉพาะเจาะจงนี้เนื่องจากurlมีการประกาศอินสแตนซ์และใช้เฉพาะในเมธอดเท่านั้นดังนั้นจึงไม่สามารถเข้าถึงได้จากเธรดอื่นนอกเหนือจากที่เรียกว่าเมธอด
Diogo Kollross

1
ความปลอดภัยของเธรดไม่ได้เป็นปัญหาที่นี่เนื่องจากคุณกำลังสร้างอินสแตนซ์ของคุณStringBufferสำหรับการโทรแต่ละครั้งและไม่แชร์กับเธรดอื่น StringBuilderนี้ควรจะมีการเปลี่ยนแปลงที่จะเป็น
เกรย์

1
เหตุผลใดที่จะไม่ใช้getRequestURI?
Christophe Roussy

27
// http://hostname.com/mywebapp/servlet/MyServlet/a/b;c=123?d=789

public static String getUrl(HttpServletRequest req) {
    String reqUrl = req.getRequestURL().toString();
    String queryString = req.getQueryString();   // d=789
    if (queryString != null) {
        reqUrl += "?"+queryString;
    }
    return reqUrl;
}

5
StringBufferคุณไม่สนใจประโยชน์จาก
BalusC

ใช่. ฉันยอมรับมัน แต่มันก็มีเพียงสองสิ่งเท่านั้นที่ฉันเดา
Teja Kantamneni

9
มันเป็นอีกหนึ่งวัตถุ (StringBuilder) และไม่กลายพันธุ์ StringBuffer พื้นฐานที่ถูกส่งกลับ ฉันจะชอบสิ่งนี้มากกว่าคำตอบ "ยอมรับ" JVM จะปรับความแตกต่างให้ดีที่สุดโดยไม่คำนึงถึงและสิ่งนี้ไม่มีความเสี่ยงในการแนะนำบั๊ก
Ken Blair

(request.getRequestURL (). toString () + ((request.getQueryString ()! = null)? ("?" + request.getQueryString ()): "")
อเล็กซ์


6

HttpUtil ถูกคัดค้านนี่เป็นวิธีการที่ถูกต้อง

StringBuffer url = req.getRequestURL();
String queryString = req.getQueryString();
if (queryString != null) {
    url.append('?');
    url.append(queryString);
}
String requestURL = url.toString();

5

การรวมผลลัพธ์getRequestURL()และgetQueryString()ควรจะได้ผลลัพธ์ที่ต้องการ


วิธีจัดการกับ params โพสต์ที่เกี่ยวข้อง?
แฟลช

2
@flash พูดอย่างเคร่งครัดพารามิเตอร์ POST ไม่ได้เป็นส่วนหนึ่งของ URL ซึ่งเป็นเนื้อหาของคำขอ
Geert

1

คุณสามารถใช้ตัวกรอง

@Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
            HttpServletRequest test1=    (HttpServletRequest) arg0;

         test1.getRequestURL()); it gives  http://localhost:8081/applicationName/menu/index.action
         test1.getRequestURI()); it gives applicationName/menu/index.action
         String pathname = test1.getServletPath()); it gives //menu/index.action


        if(pathname.equals("//menu/index.action")){ 
            arg2.doFilter(arg0, arg1); // call to urs servlet or frameowrk managed controller method


            // in resposne 
           HttpServletResponse httpResp = (HttpServletResponse) arg1;
           RequestDispatcher rd = arg0.getRequestDispatcher("another.jsp");     
           rd.forward(arg0, arg1);





    }

อย่าลืมใส่ <dispatcher>FORWARD</dispatcher>การแมปตัวกรองใน web.xml


สำหรับบันทึก ... test1.getRequestURI ()); มันให้ /applicationName/menu/index.action (เช่นมันมีเครื่องหมายทับชั้นนำ)
Stevko

1

ใช้วิธีการต่อไปนี้บนวัตถุ HttpServletRequest

java.lang.String getRequestURI () - กลับมาเป็นส่วนหนึ่งของ URL ของคำขอนี้จากชื่อโปรโตคอลถึงสตริงแบบสอบถามในบรรทัดแรกของการร้องขอ HTTP

java.lang.StringBuffer getRequestURL () -Reconstructs URL ที่ไคลเอ็นต์ใช้เพื่อทำการร้องขอ

java.lang.String getQueryString () - ส่ง คืนสตริงเคียวรีที่มีอยู่ใน URL คำขอหลังพา ธ


0

ค่อนข้างช้าไปงานปาร์ตี้ แต่ฉันรวมสิ่งนี้ไว้ในห้องสมุด MarkUtils-WebของฉันในWebUtils - Checkstyle- Approvedและ JUnit- certified :

import javax.servlet.http.HttpServletRequest;

public class GetRequestUrl{
    /**
     * <p>A faster replacement for {@link HttpServletRequest#getRequestURL()}
     *  (returns a {@link String} instead of a {@link StringBuffer} - and internally uses a {@link StringBuilder})
     *  that also includes the {@linkplain HttpServletRequest#getQueryString() query string}.</p>
     * <p><a href="https://gist.github.com/ziesemer/700376d8da8c60585438"
     *  >https://gist.github.com/ziesemer/700376d8da8c60585438</a></p>
     * @author Mark A. Ziesemer
     *  <a href="http://www.ziesemer.com.">&lt;www.ziesemer.com&gt;</a>
     */
    public String getRequestUrl(final HttpServletRequest req){
        final String scheme = req.getScheme();
        final int port = req.getServerPort();
        final StringBuilder url = new StringBuilder(256);
        url.append(scheme);
        url.append("://");
        url.append(req.getServerName());
        if(!(("http".equals(scheme) && (port == 0 || port == 80))
                || ("https".equals(scheme) && port == 443))){
            url.append(':');
            url.append(port);
        }
        url.append(req.getRequestURI());
        final String qs = req.getQueryString();
        if(qs != null){
            url.append('?');
            url.append(qs);
        }
        final String result = url.toString();
        return result;
    }
}

อาจเป็นคำตอบที่เร็วและมีประสิทธิภาพที่สุดที่นี่จนถึงหลัง Mat Banik - แต่ถึงแม้เขาจะไม่ได้คำนึงถึงการกำหนดค่าพอร์ตที่ไม่เป็นมาตรฐานด้วย HTTP / HTTPS

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


0

คุณสามารถเขียนง่าย ๆ หนึ่งซับกับ ternary และถ้าคุณใช้ประโยชน์จากรูปแบบการสร้างของ StringBuffer จาก.getRequestURL():

private String getUrlWithQueryParms(final HttpServletRequest request) { 
    return request.getQueryString() == null ? request.getRequestURL().toString() :
        request.getRequestURL().append("?").append(request.getQueryString()).toString();
}

แต่นั่นเป็นเพียงวากยสัมพันธ์น้ำตาล

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