2012-04-17 11 views
9

Non sono sicuro di come pronunciare il titolo qui, e per questo non sono nemmeno sicuro di come cercare la risposta.Esiste un contesto di richiesta in Java?

Ho un motore servlet java che gestisce le richieste. Supponiamo di avere una richiesta 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(); 
} 

Ora in doSomething, voglio essere in grado di accedere a quale utente ha effettuato la richiesta. In questo momento sto facendo con la creazione di un oggetto Java e passandolo a dovunque ho bisogno:

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

Facendo questo, ho accesso all'istanza di MyUserObj, e può essere ulteriormente passato lungo, se necessario.

Questo sembra sciatto. In asp.net MVC3 (attualmente sto imparando, è iniziato dopo che ho iniziato a imparare java, ma ho trovato che fosse davvero conveniente quindi mi ha fatto ripensare a come lo stavo facendo in java) Posso, ad esempio, archiviare gli articoli per l'attuale thread come questo: HttpContext.Current.Items.Add("myId", "123"). HttpContext è quindi disponibile in altre funzioni senza che debba passare un oggetto.

C'è un modo in Java per impostare alcune variabili per richiesta (o anche impostare il MyUserObject per accedere in seguito) senza passare l'oggetto attraverso come parametro?

Se si tratta di una domanda comune già risolta, sentitevi liberi di indicarmi la direzione giusta perché non ero sicuro di come esprimerla.

+0

Mi sono preso la libertà di modificare il titolo. Si prega di verificare se è una buona – Bozho

+0

Mi piacerebbe semplicemente passarlo esplicitamente, lo stato implicito e le dipendenze sono dannose per la manutenibilità. Quadro come Spring dovrebbe aiutare a rimuovere parte della caldaia e il disordine facendo questo esplicitamente. – millimoose

+0

Se hai capito la mia domanda, mi fido che la modifica del titolo sia migliore del mio titolo originale :) – Two13

risposta

19

Non c'è nell'API servlet, ma è possibile crearlo facilmente. (Alcuni framework come spring-mvc, struts forniscono tale funzionalità)

Basta usare uno public static ThreadLocal per memorizzare e recuperare l'oggetto. È anche possibile memorizzare lo HttpServletRequest stesso nel threadlocal e utilizzare i suoi metodi setAttribute()/ oppure è possibile memorizzare un threadlocal Map, per essere agnostico dell'API del servlet. Una nota importante è che è necessario pulire il threadlocal dopo la richiesta (con un filtro, ad esempio).

Si noti inoltre che passare l'oggetto come parametro è considerato una pratica migliore, poiché di solito lo si passa dal livello Web a un livello di servizio, che non dovrebbe dipendere dall'oggetto relativo al Web, ad esempio HttpContext.

Se si decide che è bene per memorizzarli in un thread-local, invece di passare in giro:

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

E un filtro necessario:

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

su 'ServletRequest.setAttribute'? –

+2

devi passare la richiesta allora. Presumo che non sia quello che l'OP vuole. L'ho aggiunto come opzione, che richiederebbe comunque il threadlocal anche se – Bozho

+0

Ah, buon punto, nessun analogo a 'HttpContext.Current'. –

4

È possibile collegare un oggetto alla richiesta corrente con setAttribute. Questa API viene utilizzata principalmente per il routing interno, ma è sicura anche per i propri scopi, purché si utilizzi uno spazio dei nomi appropriato per i nomi degli attributi.

+0

non è necessario passare l'oggetto ServletRequest come parametro? – Two13

+0

Lo faresti. Tuttavia, se stai passando la richiesta per iniziare, puoi evitare di aggirare altri oggetti correlati alla richiesta. – ataylor

Problemi correlati