HttpServletRequest để hoàn thành URL


247

Tôi có một HttpServletRequestđối tượng.

Làm cách nào để có được URL đầy đủ và chính xác khiến cuộc gọi này đến được máy chủ của tôi?

Hoặc ít nhất là chính xác nhất có thể, vì có lẽ có những thứ có thể được tái tạo (thứ tự của các tham số, có lẽ).



tại sao chúng tôi không sử dụng chức năng cho nó
vanduc1102

Câu trả lời:


392

HttpServletRequestcác phương pháp sau:

  • getRequestURL() - trả về một phần của URL đầy đủ trước ký tự dấu tách chuỗi truy vấn ?
  • getQueryString() - trả về một phần của URL đầy đủ sau ký tự dấu tách chuỗi truy vấn ?

Vì vậy, để có được URL đầy đủ, chỉ cần làm:

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
Bạn đã sao chép mô tả từ getRequestURI (sai) nhưng sử dụng getRequestURL trong mã (phải).
Vinko Vrsalovic

21
Bạn cần kiểm tra có điều kiện nếu chuỗi truy vấn trống.
Adam Gent

8
Bạn cũng đang thay đổi StringBuffer sao lưu URL yêu cầu. Nếu việc triển khai yêu cầu không tạo ra một bản sao phòng thủ thì đó là một cách rất tốt để giới thiệu các hành vi và lỗi lạ trong các phần khác của mã mong đợi nó ở dạng ban đầu.
Ken Blair

5
Sử dụng StringBuilder thay vì StringBuffer
Gladwin Burboz

17
@KenBlair: StringBuffer được trả về mục đích, do đó bạn có thể dễ dàng thêm vào nhiều stash hơn. Vì điều này được chỉ định trên javadoc, nên việc triển khai StringBuffer sẽ không bị sửa đổi bởi người gọi sẽ vô cùng vô lý - do đó, điều này thật tuyệt.
stolsvik

145

Tôi sử dụng phương pháp này:

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
Đây là một câu trả lời hữu ích để tham khảo nhanh cho tất cả các bit thông tin có sẵn trên HttpServletRequest. Tuy nhiên, tôi nghĩ rằng bạn muốn kiểm tra lược đồ trong việc quyết định có nên thêm phần cổng vào kết quả hay không. "Https" sẽ là 443, ví dụ.
Peter Cardona

2
một tối ưu hóa nhỏ sẽ là sử dụng StringBuilder thay vì StringBuffer, chỉ là một gợi ý
Chris

11
Chỉ cần một nhận xét: an toàn của luồng không phải là một vấn đề trong ví dụ cụ thể này vì urlđược khai báo, khởi tạo và chỉ được sử dụng bên trong phương thức, vì vậy nó không thể được truy cập từ các luồng khác ngoài luồng được gọi là phương thức.
Diogo Kollross

1
Như đã đề cập, an toàn luồng không phải là vấn đề ở đây vì bạn đang tạo một phiên bản của bạn StringBuffercho mỗi cuộc gọi và không chia sẻ nó với bất kỳ luồng nào khác. Điều này nên được thay đổi để được a StringBuilder.
Xám

1
Bất kỳ lý do không sử dụng getRequestURI?
Barshe 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
Bạn đang bỏ qua lợi thế của StringBuffer.
BalusC

Đúng. Tôi chấp nhận nó, nhưng tôi đoán chỉ có hai đối tượng bổ sung.
Teja Kantamneni

9
Đó là một đối tượng bổ sung (StringBuilder) và không làm thay đổi StringBuffer bên dưới được trả về. Tôi thực sự thích điều này hơn câu trả lời "được chấp nhận", JVM sẽ tối ưu hóa sự khác biệt bất kể và điều này không có bất kỳ rủi ro nào trong việc đưa ra các lỗi.
Ken Blair

(request.getRequestURL (). toString () + ((request.getQueryString ()! = null)? ("?" + request.getQueryString ()): ""))
Alex

12

Trong một dự án mùa xuân, bạn có thể sử dụng

UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request)).build().toUriString()

3
Tại sao không? new ServletServerHttpRequest(request).getURI()
Matt Sidesinger

URI nó không phải là URL
Sllouyssgort

6

HttpUtil bị phản đối, đây là phương pháp chính xác

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


1

Bạn có thể sử dụng bộ lọc.

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





    }

đừng quên đặt <dispatcher>FORWARD</dispatcher>ánh xạ bộ lọc vào web.xml


cho bản ghi ... test1.getRequestURI ()); nó cung cấp cho /applicationName/menu/index.action (nghĩa là nó chứa dấu gạch chéo hàng đầu)
Stevko

1

Sử dụng các phương thức sau trên đối tượng HttpServletRequest

java.lang.String getRequestURI () - Trả lại một phần URL của yêu cầu này từ tên giao thức cho đến chuỗi truy vấn trong dòng đầu tiên của yêu cầu HTTP.

java.lang.StringBuffer getRequestURL () -Xác định lại URL mà khách hàng đã sử dụng để thực hiện yêu cầu.

java.lang.String getQueryString () - Trả về chuỗi truy vấn được chứa trong URL yêu cầu sau đường dẫn.


0

Hơi muộn trong bữa tiệc, nhưng tôi đã đưa nó vào thư viện MarkUtils-Web của tôi trong WebUtils - Đã được phê duyệt kiểu thử nghiệm và JUnit đã thử nghiệm:

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

Có lẽ là câu trả lời nhanh nhất và mạnh mẽ nhất ở đây cho đến nay sau Mat Banik - nhưng ngay cả câu trả lời của anh ta cũng không có cấu hình cổng không chuẩn với HTTP / HTTPS.

Xem thêm:


0

Bạn có thể viết một lớp lót đơn giản với một ternary và nếu bạn sử dụng mẫu trình tạo của StringBuffer từ .getRequestURL():

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

Nhưng đó chỉ là cú pháp đường.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.