2012-04-17 28 views
9

Tôi không chắc chắn chính xác cách cụm từ tiêu đề ở đây và do đó tôi không chắc chắn về cách tìm kiếm câu trả lời.Có ngữ cảnh yêu cầu trong Java không?

Tôi có một công cụ servlet java xử lý các yêu cầu. Giả sử chúng tôi có yêu cầu doGet:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    //set up user data 

    //do whatever the user requested 
    SomeClass c = new SomeClass(); 
    c.doSomething(); 
} 

Bây giờ trong doMột cái gì đó, tôi muốn có thể truy cập người dùng đã thực hiện yêu cầu. Ngay bây giờ tôi đang làm việc đó bằng cách tạo ra một đối tượng java và đi qua nó để bất cứ nơi nào tôi cần:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    //set up user data 
    MyUserObj userObj = new MyUserObj(); 
    userObj.setId('123'); 

    //do whatever the user requested 
    SomeClass c = new SomeClass(userObj); 
    c.doSomething(); 
} 

Bằng cách này, tôi được tiếp cận với trường hợp của MyUserObj, và nó có thể được chuyển tiếp cùng nếu cần thiết.

Điều này cảm thấy cẩu thả. Trong asp.net MVC3 (Tôi hiện đang học nó, bắt đầu sau khi tôi bắt đầu học java, nhưng thấy điều này rất tiện lợi để tôi suy nghĩ lại cách tôi đang làm nó trong java), ví dụ, lưu trữ các mục cho hiện tại chủ đề như thế này: HttpContext.Current.Items.Add("myId", "123"). HttpContext là sau đó có sẵn trong các chức năng khác mà không cần tôi phải vượt qua xung quanh một đối tượng.

Có cách nào trong java để đặt một số biến cho mỗi yêu cầu (hoặc thậm chí đặt MyUserObject để được truy cập sau) mà không truyền đối tượng thông qua làm tham số?

Nếu đây là một câu hỏi thường được trả lời, vui lòng chỉ cho tôi đúng hướng vì tôi không chắc chắn cách đặt cụm từ đó.

+0

Tôi đã tự do chỉnh sửa tiêu đề của bạn. Vui lòng xác minh xem đó có phải là một trong những tốt – Bozho

+0

Tôi chỉ cần chuyển nó xung quanh một cách rõ ràng, trạng thái tiềm ẩn và các phụ thuộc không tốt để bảo trì. Các khung như Spring sẽ giúp loại bỏ một số bản mẫu và sự lộn xộn bằng cách làm điều này một cách rõ ràng. – millimoose

+0

Nếu bạn hiểu câu hỏi của tôi thì tôi tin tưởng chỉnh sửa tiêu đề của bạn tốt hơn tiêu đề gốc của tôi :) – Two13

Trả lời

19

Không có trong API servlet, nhưng bạn có thể làm cho riêng bạn khá dễ dàng. (Một số khung công tác như spring-mvc, struts cung cấp chức năng như vậy)

Chỉ cần sử dụng public static ThreadLocal để lưu trữ và truy lục đối tượng. Bạn thậm chí có thể tự lưu trữ số HttpServletRequest trong chủ đề và sử dụng các phương thức setAttribute()/getAttribute() của mình hoặc bạn có thể lưu trữ một địa chỉ Map theo chủ đề, để bất khả tri về API servlet. Một lưu ý quan trọng là bạn nên làm sạch threadlocal sau khi yêu cầu (với một bộ lọc, ví dụ). Cũng cần lưu ý rằng việc truyền đối tượng dưới dạng tham số được coi là một thực hành tốt hơn, bởi vì bạn thường chuyển nó từ lớp web sang một lớp dịch vụ, không nên phụ thuộc vào đối tượng liên quan đến web, như là HttpContext.

Nếu bạn quyết định rằng nó là tốt để lưu trữ chúng trong một thread-địa phương, chứ không phải đi qua họ xung quanh:

public class RequestContext { 
    private static ThreadLocal<Map<Object, Object>> attributes = new ThreadLocal<>(); 
    public static void initialize() { 
     attributes.set(new HashMap<Map<Object, Object>>()); 
    } 
    public static void cleanup() { 
     attributes.set(null); 
    } 
    public static <T> T getAttribute(Object key) { 
     return (T) attributes.get().get(key); 
    } 
    public static void setAttribute(Object key, Object value) { 
     attributes.get().put(key, value); 
    } 
} 

Và một bộ lọc cần thiết:

@WebFilter(urlPatterns="/") 
public class RequestContextFilter implements Filter { 
    public void doFilter(..) { 
     RequestContext.initialize(); 
     try { 
      chain.doFilter(request, response); 
     } finally { 
      RequestContext.cleanup(); 
     } 
    } 
} 
+2

về 'ServletRequest.setAttribute'? –

+2

bạn phải chuyển yêu cầu đó. Tôi cho rằng đó không phải là những gì OP muốn. Tôi thêm nó như là tùy chọn, mà vẫn sẽ yêu cầu threadlocal mặc dù – Bozho

+0

Ah, điểm tốt, không tương tự với 'HttpContext.Current'. –

4

Bạn có thể đính kèm một đối tượng theo yêu cầu hiện tại với setAttribute. API này chủ yếu được sử dụng cho định tuyến nội bộ, nhưng cũng an toàn để sử dụng cho mục đích của riêng bạn, miễn là bạn sử dụng một không gian tên thích hợp cho tên thuộc tính của mình.

+0

tôi sẽ không phải truyền đối tượng ServletRequest làm tham số không? – Two13

+0

Bạn sẽ. Tuy nhiên, nếu bạn đang đi xung quanh yêu cầu để bắt đầu, bạn có thể tránh đi qua các đối tượng liên quan đến yêu cầu khác. – ataylor

Các vấn đề liên quan