Làm cách nào để nhận URI yêu cầu mà không có đường dẫn ngữ cảnh?


127

Phương thức request.getRequestURI () trả về URI với đường dẫn ngữ cảnh.

Ví dụ, nếu URL cơ sở của một ứng dụng là http://localhost:8080/myapp/(tức là đường dẫn ngữ cảnh là myapp ), và tôi gọi request.getRequestURI()cho http://localhost:8080/myapp/secure/users, nó sẽ trở lại /myapp/secure/users.

Có cách nào chúng ta chỉ có thể nhận được phần này /secure/users, tức là URI không có đường dẫn ngữ cảnh không?


Câu trả lời:


158

Nếu bạn đang ở trong một máy trợ giúp phía trước được ánh xạ trên mẫu tiền tố, thì bạn chỉ có thể sử dụng HttpServletRequest#getPathInfo().

String pathInfo = request.getPathInfo();
// ...

Giả sử rằng servlet trong ví dụ của bạn được ánh xạ /secure, thì điều này sẽ trả về /users, đó sẽ là thông tin quan tâm duy nhất bên trong một servlet điều khiển phía trước điển hình.

Tuy nhiên, nếu servlet được ánh xạ trên một mẫu hậu tố (tuy nhiên các ví dụ URL của bạn không chỉ ra rằng đây là trường hợp) hoặc khi bạn thực sự ở trong một bộ lọc (khi chưa thực hiện được một servlet được gọi getPathInfo()có thể trả về null), khi đó, cách tốt nhất của bạn là tự tạo chuỗi URI yêu cầu dựa trên độ dài của đường dẫn ngữ cảnh bằng Stringphương thức thông thường :

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...

Có một lý do để sử dụng này thay vì getServletPath()? Tôi đang viết một bộ lọc và tôi nhận thấy rằng getPathInfo()trả về null, nhưng getServletPath()trả về đường dẫn trừ đi bối cảnh (phù hợp để chuyển đến bộ điều phối yêu cầu).
Jason C

@JasonC: Như đã trả lời, getPathInfo()trả về null nếu servlet bộ điều khiển phía trước không được ánh xạ trên mẫu tiền tố.
BalusC

Vâng. Ý tôi là: có lý do nào bạn thích getPathInfo hơn getServletPath không? Rất nhiều câu trả lời được đánh giá cao khác ở đây cũng không sử dụng getServletPath, đó là điều khiến tôi nghi ngờ về nó và tại sao tôi lại tự hỏi. Tôi đã có một dự án servlet tôi đang làm và tôi đang cố gắng cải thiện chút kỹ năng của mình.
Jason C

1
@JasonC: đường dẫn servlet có thể thay đổi khi bạn có một khung MVC dựa trên servlet được cài đặt như JSF hoặc Spring MVC. Sau đó, nó sẽ đại diện cho đường dẫn bên trong của khung công tác MVC (ví dụ /foo.xhtmlthay vì /foo.jsf) và không phải là URI yêu cầu thực tế (cái mà như enduser sẽ thấy trong thanh địa chỉ của trình duyệt). Đường dẫn servlet ban đầu trong trường hợp như vậy tuy nhiên có thể phân giải thành thuộc tính request với khóa RequestDispatcher.FORWARD_SERVLET_PATH. Theo bất kỳ cách nào, câu hỏi yêu cầu rõ ràng về URI yêu cầu (như trong thanh địa chỉ của trình duyệt), vì vậy câu trả lời dựa trên điều đó.
BalusC

74
request.getRequestURI().substring(request.getContextPath().length())

Tuyệt vời! Điều này thật đúng với gì mà tôi đã tìm kiếm.
thợ thủ công

4
+1 Tôi nghĩ rằng đây là một câu trả lời tốt hơn getPathInfo do thực tế là getPathInfo có thể là null và các số lẻ khác. Mã Spring khác nhau có getContextPath và xóa nó khỏi URI giống như bạn đã làm thay vì getPathInfo.
Adam Gent

32

Với mùa xuân bạn có thể làm:

String path = new UrlPathHelper().getPathWithinApplication(request);

1
Tất nhiên, sẽ rất hợp lý nếu giữ một thể hiện của UrlPathHelper, ví dụ như là một biến thành viên lớp ...
James

Làm thế nào chúng ta có thể nhận được url ánh xạ yêu cầu thực tế? Vui lòng hướng dẫn tại đây: stackoverflow.com/questions/60446807/
Kẻ

14

getPathInfo () đôi khi trả về null. Trong tài liệu httpServletRequest

Phương thức này trả về null nếu không có thêm thông tin đường dẫn.

Tôi cần đường dẫn đến tệp mà không có đường dẫn ngữ cảnh trong Bộ lọc và getPathInfo () trả lại cho tôi null. Vì vậy, tôi sử dụng một phương thức khác: httpRequest.getServletPath ()

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String newPath = parsePathToFile(httpRequest.getServletPath());
    ...

}

8

Nếu bạn sử dụng request.getPathInfo () trong Bộ lọc, bạn dường như luôn nhận được null (ít nhất là với cầu tàu).

Lỗi này không hợp lệ + phản hồi ám chỉ vấn đề tôi nghĩ:

https://issues.apache.org/ormszilla/show_orms.cgi?id=28323

Tôi nghi ngờ nó có liên quan đến thực tế là các bộ lọc chạy trước khi servlet nhận được yêu cầu. Nó có thể là một lỗi container hoặc hành vi dự kiến ​​mà tôi không thể xác định được.

Mặc dù bối cảnh có sẵn, vì vậy giải pháp fforws hoạt động ngay cả trong các bộ lọc. Tôi không muốn phải làm bằng tay, nhưng việc thực hiện bị hỏng hoặc


5

Một cách để làm điều này là đặt lại đường dẫn ngữ cảnh của dịch vụ từ URI yêu cầu.

String p = request.getRequestURI();
String cp = getServletContext().getContextPath();

if (p.startsWith(cp)) {
  String.err.println(p.substring(cp.length());
}

Đọc ở đây .


-1

Có thể bạn chỉ có thể sử dụng phương pháp phân tách để loại bỏ '/ myapp' chẳng hạn:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];

3
Điều này sẽ gây ra vấn đề nếu tôi triển khai ứng dụng của mình dưới dạng root và URL cơ sở của nó trở thành localhost: 8080 . Trong trường hợp này request.getRequestURI () sẽ trả về "/ safe / user" và phương thức phân tách của bạn sẽ gây ra vấn đề ở đây. Mã không nên phụ thuộc khi triển khai.
thợ thủ cô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.