Spring: làm cách nào để tôi đưa HttpServletRequest vào một bean theo phạm vi yêu cầu?


95

Tôi đang cố gắng thiết lập bean theo phạm vi yêu cầu vào mùa xuân.

Tôi đã thiết lập thành công nên bean được tạo một lần cho mỗi yêu cầu. Bây giờ, nó cần truy cập đối tượng HttpServletRequest.

Vì bean được tạo một lần cho mỗi yêu cầu, tôi nghĩ rằng vùng chứa có thể dễ dàng đưa đối tượng yêu cầu vào bean của tôi. Làm thế nào tôi có thể làm điều đó ?

Câu trả lời:


114

Đậu phạm vi yêu cầu có thể được tự động tải với đối tượng yêu cầu.

private @Autowired HttpServletRequest request;

2
Có cách xử lý XML cũ cho việc này không?
cherouvim

2
Không hoạt động đối với tôi (Spring mvc 3.1) - có thể có điều gì đó cần phải được thực hiện? Đi với giải pháp của Samit.
kldavis 4

2
Vấn đề là khi bạn kiểm tra trình xác thực bằng MockMvc và kiểu tiêm này, bạn sẽ gặp vấn đề. Có thể là giải pháp khác sẽ được ưu tiên trong trường hợp này
Neyko

21
Cũng có thể tự động chuyển hướng HttpServletRequest vào các bean không có phạm vi yêu cầu, bởi vì đối với HttpServletRequest Spring sẽ tạo ra một proxy HttpServletRequest biết cách lấy phiên bản thực của yêu cầu. Vì vậy, có thể an toàn khi yêu cầu tự động truyền tải ngay cả khi bộ điều khiển của bạn là phạm vi đơn.
vtor

3
Cảnh báo cho người dùng Spring <= 3.1 rằng tính năng tự động tạo sẽ không hoạt động khi chạy thử nghiệm.
Rubens Mariuzzo

138

Spring hiển thị HttpServletRequestđối tượng hiện tại (cũng như HttpSessionđối tượng hiện tại ) thông qua một đối tượng wrapper kiểu ServletRequestAttributes. Đối tượng trình bao bọc này được liên kết với ThreadLocal và được lấy bằng cách gọi staticphương thức RequestContextHolder.currentRequestAttributes().

ServletRequestAttributescung cấp phương thức getRequest()để lấy yêu cầu hiện tại, getSession()để lấy phiên hiện tại và các phương thức khác để lấy các thuộc tính được lưu trữ trong cả hai phạm vi. Đoạn mã sau, mặc dù hơi xấu, nhưng sẽ giúp bạn có được đối tượng yêu cầu hiện tại ở bất kỳ đâu trong ứng dụng:

HttpServletRequest curRequest = 
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();

Lưu ý rằng RequestContextHolder.currentRequestAttributes()phương thức trả về một giao diện và cần phải được đánh máy để ServletRequestAttributesthực thi giao diện đó.


Spring Javadoc: RequestContextHolder | ServletRequestAttributes


8
Injection là độ phân giải tốt, nhưng tôi đã phát hiện ra vấn đề với thử nghiệm MockMvc Spring validators đưa HttpServletRequest vào. Vì vậy, nếu bạn muốn cả hai bài kiểm tra thử và mã sản xuất chạy đúng cách thì đây là lựa chọn.
Neyko

@Neyko Tại sao vậy? đối với bài kiểm tra thử (Unit test?), bạn có thể tiêm HttpServletRequest giả hoặc bất cứ thứ gì bạn muốn .. phải không? Hoặc bạn có thể sử dụng MockHttpServletRequest tôi đoán?
wonhee

Nó có an toàn để được sử dụng trong một phiên bản dịch vụ có phạm vi đơn không?
Jin Kwon

2

Như được đề xuất ở đây, bạn cũng có thể đưa tham số HttpServletRequestdưới dạng phương thức, ví dụ:

public MyResponseObject myApiMethod(HttpServletRequest request, ...) {
    ...
}
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.