HttpServletRequest untuk melengkapi URL

247

Saya punya HttpServletRequestobjek.

Bagaimana cara saya mendapatkan URL lengkap dan tepat yang menyebabkan panggilan ini tiba di servlet saya?

Atau setidaknya seakurat mungkin, karena mungkin ada hal-hal yang dapat dibuat ulang (urutan parameter, mungkin).

flybywire
sumber
Lihat juga: stackoverflow.com/questions/4931323/…
Christophe Roussy
mengapa kami tidak menggunakan fungsi util untuk itu
vanduc1102

Jawaban:

392

Ini HttpServletRequestmemiliki metode berikut:

  • getRequestURL() - mengembalikan bagian dari URL lengkap sebelum karakter pemisah string kueri ?
  • getQueryString() - mengembalikan bagian dari URL lengkap setelah karakter pemisah string kueri ?

Jadi, untuk mendapatkan URL lengkap, lakukan saja:

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();
    }
}
Bozho
sumber
3
Anda menyalin deskripsi dari getRequestURI (salah) tetapi menggunakan getRequestURL dalam kode (kanan).
Vinko Vrsalovic
21
Anda perlu memeriksa secara kondisional apakah string kueri kosong.
Adam Gent
8
Anda juga memutasikan StringBuffer yang mendukung URL permintaan. Jika implementasi permintaan tidak membuat salinan defensif itu cara yang sangat baik untuk memperkenalkan perilaku aneh dan bug di bagian kode lain yang mengharapkannya dalam bentuk aslinya.
Ken Blair
5
Gunakan StringBuilder sebagai ganti StringBuffer
Gladwin Burboz
17
@ KenBlair: StringBuffer dikembalikan dengan sengaja, sehingga Anda dapat dengan mudah menambahkan lebih banyak simpanan. Karena ini ditentukan pada javadoc, akan sangat tidak masuk akal dari implementasi untuk mengharapkan bahwa StringBuffer yang dikembalikan tidak akan dimodifikasi oleh pemanggil - oleh karena itu, ini keren.
stolsvik
145

Saya menggunakan metode ini:

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();
}
Mat B.
sumber
8
Ini adalah jawaban yang bermanfaat untuk referensi cepat ke semua bit informasi yang tersedia di HttpServletRequest. Namun, saya pikir Anda ingin memeriksa skema dalam memutuskan apakah akan menambahkan bagian port ke hasilnya. "https" akan menjadi 443, misalnya.
Peter Cardona
2
optimasi kecil akan menggunakan StringBuilder bukan StringBuffer, hanya sebuah petunjuk
Chris
11
Hanya komentar: keamanan utas bukan merupakan masalah dalam contoh khusus ini karena urldideklarasikan, dipakai, dan hanya digunakan di dalam metode, sehingga tidak dapat diakses dari utas selain yang disebut metode.
Diogo Kollross
1
Seperti yang disebutkan, keamanan utas bukan masalah di sini karena Anda membuat instance dari Anda StringBufferuntuk setiap panggilan dan tidak membaginya dengan utas lainnya. Ini harus diubah menjadi StringBuilder.
Abu
1
Ada alasan untuk tidak menggunakan 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;
}
Teja Kantamneni
sumber
5
Anda mengabaikan keuntungan dari StringBuffer.
BalusC
Iya. Saya menerimanya, tetapi hanya dua benda tambahan yang saya kira.
Teja Kantamneni
9
Ini satu objek tambahan (StringBuilder) dan tidak bermutasi StringBuffer yang mendasarinya yang dikembalikan. Saya sebenarnya lebih suka ini daripada jawaban yang "diterima", JVM akan mengoptimalkan perbedaannya terlepas dan ini tidak memiliki risiko memperkenalkan bug.
Ken Blair
(request.getRequestURL (). toString () + ((request.getQueryString ()! = null)? ("?" + request.getQueryString ()): ""))
Alex
12

Dalam proyek Musim Semi yang dapat Anda gunakan

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()
Peter Szanto
sumber
3
Kenapa tidak? new ServletServerHttpRequest(request).getURI()
Matt Sidesinger
URI itu bukan URL
Sllouyssgort
6

HttpUtil menjadi usang, ini adalah metode yang benar

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

Menggabungkan hasil getRequestURL()dan getQueryString()harus memberi Anda hasil yang diinginkan.

Michael Borgwardt
sumber
bagaimana menangani params terkait posting?
Flash
2
@flash secara tegas, POST-parameter bukan bagian dari URL, mereka adalah badan dari permintaan.
Geert
1

Anda bisa menggunakan filter.

@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);





    }

jangan lupa memasukkan <dispatcher>FORWARD</dispatcher>pemetaan filter di web.xml

abishkar bhattarai
sumber
untuk catatan ... test1.getRequestURI ()); itu memberikan /applicationName/menu/index.action (yaitu mengandung slash terkemuka)
Stevko
1

Gunakan metode berikut pada objek HttpServletRequest

java.lang.String getRequestURI () -Kembalikan bagian dari URL permintaan ini dari nama protokol hingga string kueri di baris pertama permintaan HTTP.

java.lang.StringBuffer getRequestURL () -Rekonstruksi URL yang digunakan klien untuk membuat permintaan.

java.lang.String getQueryString () -Kembalikan string kueri yang terkandung dalam URL permintaan setelah path.

Kishor Prakash
sumber
0

Agak terlambat ke pesta, tapi saya memasukkan ini di perpustakaan MarkUtils-Web saya di WebUtils - Checkstyle-disetujui dan JUnit-diuji:

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;
    }
}

Mungkin jawaban tercepat dan paling tangguh di sini sejauh ini di belakang Mat Banik - tetapi bahkan jawabannya tidak memperhitungkan kemungkinan konfigurasi port non-standar dengan HTTP / HTTPS.

Lihat juga:

ziesemer
sumber
0

Anda dapat menulis satu liner sederhana dengan ternary dan jika Anda memanfaatkan pola builder dari StringBuffer dari .getRequestURL():

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

Tapi itu hanya gula sintaksis.

Johannes Stadler
sumber