HttpServletRequest - Nhận tham số chuỗi truy vấn, không có dữ liệu biểu mẫu


76

Trong HttpServletRequest , getParameterMaptrả về một Bản đồ của tất cả các tham số chuỗi truy vấn và tham số dữ liệu đăng.

Có cách nào để có được Bản đồ các tham số chuỗi truy vấn CHỈ? Tôi đang cố gắng tránh sử dụng getQueryString và phân tích cú pháp các giá trị.


15
Bạn có thể có cả hai ... bạn có thể có các tham số chuỗi truy vấn trên một yêu cầu POST. Và trong trường hợp đó, tất cả chúng đều được trả về bởi "getParameterMap"
JasonStoltz

Ồ được thôi. Tại sao một người cần cả hai, chỉ tò mò?
Jacob

2
Bởi vì trên trang kết quả, tôi muốn một chuỗi truy vấn xuất hiện trong url / có trong chuỗi truy vấn. Chúng tôi có một hệ thống theo dõi tìm kiếm các thông số cụ thể trong chuỗi truy vấn.
JasonStoltz

req.getParameterMap (). chứaKey ("tên người dùng");
Parag Jadhav

Câu trả lời:


22

Trái ngược với những gì cularis đã nói, có thể có cả hai trong bản đồ tham số.

Cách tốt nhất tôi thấy là ủy quyền cho Bản đồ tham số và đối với mỗi lần truy xuất tham số, hãy kiểm tra xem queryString có chứa "&? <parameterName> =" hay không.

Lưu ý rằng tham sốName cần được mã hóa URL trước khi có thể thực hiện kiểm tra này, như Qerub đã chỉ ra.

Điều đó giúp bạn tiết kiệm phân tích cú pháp và vẫn chỉ cung cấp cho bạn các tham số URL.


2
Lưu ý rằng parameterNameURL cần được mã hóa trước khi có thể thực hiện kiểm tra này.
qerub

12
Chuỗi truy vấn không bao giờ chứa ?. Đó là ký tự phân cách giữa URI và chuỗi truy vấn.
BalusC

Xin chào @DoubleMalt, tôi cũng có yêu cầu tương tự nhưng không thể nhận được giải pháp bạn đã cung cấp. Bạn có thể cung cấp mã ví dụ?
Vishal Zanzrukia

@VishalZanzrukia: Mã của bạn không hoạt động là gì?
DoubleMalt

1
Tôi thích ý tưởng này, nhưng không phải lúc nào cũng có ký tự "=" trong chuỗi truy vấn. Nếu giá trị tham số trống thì chỉ có <parameterName> trong chuỗi truy vấn. Cá nhân tôi nghĩ rằng chia tách theo "&" và "=" sẽ là một giải pháp tốt hơn.
Bren

95

Bạn có thể sử dụng request.getQueryString(), nếu chuỗi truy vấn giống như

username=james&password=pwd

Để có tên, bạn có thể làm điều này

request.getParameter("username"); 

Đây là để sử dụng các trang Máy chủ Java.
Jorgesys

2
thứ hai sẽ làm hỏng luồng yêu cầu, tôi giả sử câu hỏi là làm thế nào để lấy tên người dùng và giữ luồng đầu vào để xử lý sau
Pavel Niedoba

23

Servlet API thiếu tính năng này vì nó được tạo ra trong thời điểm mà nhiều người tin rằng chuỗi truy vấn và nội dung thông báo chỉ là hai cách khác nhau để gửi tham số, không nhận ra rằng mục đích của các tham số về cơ bản là khác nhau.

Tham số chuỗi truy vấn? Foo = bar là một phần của URL vì chúng tham gia vào việc xác định tài nguyên (có thể là một tập hợp nhiều tài nguyên), chẳng hạn như "tất cả những người ở độ tuổi 42":

GET / người? Tuổi = 42

Các tham số nội dung thông báo trong POST hoặc PUT ở đó để thể hiện sự sửa đổi đối với (các) tài nguyên đích. Fx đặt giá trị cho thuộc tính "hair":

PUT / người? Tuổi = 42

tóc = màu xám

Vì vậy, chắc chắn RESTful là sử dụng cả tham số truy vấn và tham số nội dung cùng một lúc, tách biệt để bạn có thể sử dụng chúng cho các mục đích khác nhau. Tính năng chắc chắn bị thiếu trong Java servlet API.


12

Như các câu trả lời khác nói rằng không có cách nào nhận được các tham số chuỗi truy vấn bằng api servlet.

Vì vậy, tôi nghĩ cách tốt nhất để lấy các tham số truy vấn là tự phân tích cú pháp chuỗi truy vấn. (Việc lặp lại các tham số và kiểm tra xem chuỗi truy vấn có chứa tham số phức tạp hơn không)

Tôi đã viết mã dưới đây để lấy tham số chuỗi truy vấn. Sử dụng apache StringUtils và ArrayUtils cũng hỗ trợ các giá trị tham số truy vấn được phân tách bằng CSV.

Ví dụ: username=james&username=smith&password=pwd1,pwd2sẽ trở lại

password : [pwd1, pwd2] (chiều dài = 2)

username : [james, smith] (chiều dài = 2)

public static Map<String, String[]> getQueryParameters(HttpServletRequest request) throws UnsupportedEncodingException {
    Map<String, String[]> queryParameters = new HashMap<>();
    String queryString = request.getQueryString();
    if (StringUtils.isNotEmpty(queryString)) {
        queryString = URLDecoder.decode(queryString, StandardCharsets.UTF_8.toString());
        String[] parameters = queryString.split("&");
        for (String parameter : parameters) {
            String[] keyValuePair = parameter.split("=");
            String[] values = queryParameters.get(keyValuePair[0]);
            //length is one if no value is available.
            values = keyValuePair.length == 1 ? ArrayUtils.add(values, "") :
                    ArrayUtils.addAll(values, keyValuePair[1].split(",")); //handles CSV separated query param values.
            queryParameters.put(keyValuePair[0], values);
        }
    }
    return queryParameters;
}

Tôi xem xét việc này tốt hơn nhiều mà trả lời được chấp nhận, không biết tại sao để tránh phân tích chuỗi truy vấn vì tạo ủy quyền không phải là giải pháp tốt hơn
Pavel Niedoba

1
Tôi chỉ đang tự hỏi, nếu bất kỳ tham số truy vấn nào chứa &ký tự trong giá trị của nó, liệu nó có cung cấp cho bạn kết quả chính xác không
amdg

1
@amdg - ký tự đó sẽ được mã hóa URL, vì vậy mã đó tốt. Nếu nó không được mã hóa, chuỗi sẽ không thể phân tích được.
marathon

Cân nhắc sử dụng cả URLDecoder.decode(keyValuePair[0])(hoặc [1]): docs.oracle.com/javase/6/docs/api/java/net/URLDecoder.html
Sao Diêm Vương

1
tham số truy vấn với các giá trị được phân tách bằng csv không được xem xét ở đây. ví dụ: username=james&username=smith&password=pwd1,pwd2sẽ có một bản đồ với 2 giá trị cho tên người dùng (chính xác) nhưng chỉ có 1 giá trị cho mật khẩu (không chính xác)
Niv

4

Java 8

return Collections.list(httpServletRequest.getParameterNames())
                  .stream()
                  .collect(Collectors.toMap(parameterName -> parameterName, httpServletRequest::getParameterValues));

2

Tôi e rằng không có cách nào để lấy các tham số chuỗi truy vấn được phân tích cú pháp riêng biệt với các tham số bài đăng. BTW thực tế là không có API như vậy có thể có nghĩa là bạn nên kiểm tra thiết kế của mình. Tại sao bạn sử dụng chuỗi truy vấn khi gửi POST? Nếu bạn thực sự muốn gửi nhiều dữ liệu hơn vào URL, hãy sử dụng quy ước giống REST, ví dụ: thay vì gửi

http://mycompany.com/myapp/myservlet?first=11&second=22

Nói:

http://mycompany.com/myapp/myservlet/11/22


Tôi đang sử dụng tham số chuỗi truy vấn trong POST vì tôi muốn duy trì bất kỳ và tất cả các chuỗi truy vấn được chuyển đến dạng ban đầu thông qua POST. Điều này chủ yếu dành cho mục đích theo dõi ... tôi không chắc rằng quy ước giống REST sẽ hoạt động trong trường hợp này, bởi vì tôi khá chắc chắn rằng thư viện theo dõi tìm kiếm các tham số cụ thể trong chuỗi truy vấn.
JasonStoltz

Bất kỳ lý do cụ thể nào mà bạn muốn khuyên bạn nên sử dụng quy ước giống REST cho tham số chuỗi truy vấn? Không chắc tôi hiểu lợi thế là gì?
JasonStoltz

8
"BTW thực tế là không có API như vậy có nghĩa là có lẽ bạn nên kiểm tra thiết kế của mình." Trong trường hợp này nó có nghĩa là Oracle nên kiểm tra thiết kế của họ :)
Stijn de Witt
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.