A ServletContext attribute is an object bound into a context
  through the ServletContext.setAttribute() method and which is
  available to ALL Servlets (thus JSP) in that context, or to other
  contexts via the getContext() method. By definition a context
  attribute exists locally in the VM where they were defined. So,
  they're unavailable on distributed applications. 
Session attributes are bound to a Session, as a mean to provide state to a set of related HTTP requests. Session attributes are
  available ONLY to those Servlets which join the session. They're also
  unavailable to different JVMs in distributed scenarios. Objects can be
  notified when they're bound/unbound to the Session implementing the
  HttpSessionBindingListener interface.
Request attributes are bound to a specific request object, and they last as far as the request is resolved or while it keeps being
  dispatched from Servlet to Servlet. They're used more as communication
  channel between Servlets via the RequestDispatcher Interface (since
  you can't add Parameters...) and by the container. Request attributes
  are very useful in web apps when you must provide setup information
  between information providers and the information presentation layer
  (a JSP) that is bound to a specific request and need not be available
  any longer, which usually happens with sessions without a rigorous
  control strategy.
IN SUMMARY, we can say that:
- Context attributes are meant for infra-structure, such as shared connection pools.
- Session attributes are meant for contextual information, such as user identification.
- Request attributes are meant for specific request info, such as query results.
Source: Servlets Interview Questions by Krishna Srinivasan @ javabeat.net