2012-04-17 10 views
9

No estoy seguro de cómo expresar el título aquí, y por eso tampoco estoy seguro de cómo buscar la respuesta.¿Hay un contexto de solicitud en Java?

Tengo un motor de servlet java que maneja las solicitudes. Digamos que tenemos una solicitud 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(); 
} 

Ahora en doSomething, quiero ser capaz de acceder el usuario que hizo la solicitud. En este momento lo estoy haciendo mediante la creación de un objeto java y pasándolo a donde quiera que necesito:

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

Al hacer esto, tienen acceso a la instancia de MyUserObj, y se puede pasar más adelante si es necesario.

Esto se siente descuidado. En asp.net MVC3 (actualmente lo estoy aprendiendo, comencé después de que comencé a aprender Java, pero encontré que esto era realmente conveniente, así que me hizo replantearme cómo lo estaba haciendo en Java). Puedo, por ejemplo, almacenar elementos para la versión actual. hilo como este: HttpContext.Current.Items.Add("myId", "123"). HttpContext está entonces disponible en otras funciones sin que tenga que pasar alrededor de un objeto.

¿Hay alguna manera en java para establecer algunas variables por solicitud (o incluso configurar el MyUserObject para acceder más tarde) sin pasar el objeto como un parámetro?

Si esta es una pregunta común ya respondida, siéntase libre de apuntarme en la dirección correcta ya que no estaba seguro de cómo pronunciarla.

+0

Me tomé la libertad de editar su título. Verifique si es bueno – Bozho

+0

Me gustaría pasarlo de forma explícita, el estado implícito y las dependencias son malas para la mantenibilidad. Los marcos como Spring deberían ayudar a eliminar parte de la repetición y el desorden al hacer esto explícitamente. – millimoose

+0

Si entendiste mi pregunta, confío en que la edición de tu título es mejor que mi título original :) – Two13

Respuesta

19

No hay una API de servlet, pero puede hacer la suya con bastante facilidad. (Algunos frameworks como spring-mvc, los puntales proporcionan tal funcionalidad)

Simplemente use un public static ThreadLocal para almacenar y recuperar el objeto. Incluso puede almacenar el HttpServletRequest en el threadlocal y usar sus métodos setAttribute()/getAttribute(), o puede almacenar un threadlocal Map, para que sea independiente de la API del servlet. Una nota importante es que debe limpiar el threadlocal después de la solicitud (con un filtro, por ejemplo).

También tenga en cuenta que pasar el objeto como parámetro se considera una práctica mejor, ya que normalmente pasa de la capa web a una capa de servicio, que no debe depender del objeto web, como HttpContext.

Si decide que está bien para almacenarlos en un local de subprocesos, en lugar de pasarlos en torno a:

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

y un filtro necesario:

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

What acerca de 'ServletRequest.setAttribute'? –

+2

tienes que pasar la solicitud a continuación. Supongo que no es lo que quiere el OP. Lo agregué como opción, que aún requeriría threadlocal a través de – Bozho

+0

Ah, buen punto, sin análogo a 'HttpContext.Current'. –

4

Puede adjuntar un objeto a la solicitud actual con setAttribute. Esta API se usa principalmente para el enrutamiento interno, pero también es seguro de usar para sus propios fines, siempre que use un espacio de nombre adecuado para los nombres de sus atributos.

+0

¿no tendría que pasar el objeto ServletRequest como parámetro? – Two13

+0

Lo harías. Sin embargo, si está revisando la solicitud para comenzar, puede evitar pasar otros objetos relacionados con la solicitud. – ataylor

Cuestiones relacionadas