1 How to find HttpSession
by jsessionid?
You need to collect them all in a using a yourself.
public class HttpSessionCollector implements HttpSessionListener { private static final Mapsessions = new HashMap (); @Override public void sessionCreated(HttpSessionEvent event) { HttpSession session = event.getSession(); sessions.put(session.getId(), session); } @Override public void sessionDestroyed(HttpSessionEvent event) { sessions.remove(event.getSession().getId()); } public static HttpSession find(String sessionId) { return sessions.get(sessionId); }}
Just register it in web.xml
as follows to run it:
com.example.HttpSessionCollector
Then, anywhere you want just do HttpSessionCollector.find(sessionId)
to get the HttpSession
in question.
You need to collect them all in a using a yourself. public class HttpSessionCollector implements HttpSessionListener { private static final Map Just register it in
Then, anywhere you want just do That said, this is a huge smell. There are certainly better ways to solve the actual functional requirement than this ;) As I commented in your :
Take it serious. We're not teasing you, we're just trying to help you in the right direction to avoid that your project/webapp will break due to security holes and bad practices and/or that you will get fired. |
2 How to find number of active sessions per IP?
The standard Servlet API doesn't offer facilities for that. Best what you can do is to maintain a yourself (where the String
is the IP address) with and check on every if the and add it to the Map
along with . Then you can get the amount of IP addresses with an active session using on . You only need to ensure that you remove the HttpSession
from the Map
during .
This all can be done in a single Listener
implementing the , and .
public class SessionCounter implements ServletContextListener, HttpSessionListener, ServletRequestListener { private static final String ATTRIBUTE_NAME = "com.example.SessionCounter"; private Mapsessions = new ConcurrentHashMap (); @Override public void contextInitialized(ServletContextEvent event) { event.getServletContext().setAttribute(ATTRIBUTE_NAME, this); } @Override public void requestInitialized(ServletRequestEvent event) { HttpServletRequest request = (HttpServletRequest) event.getServletRequest(); HttpSession session = request.getSession(); if (session.isNew()) { sessions.put(session, request.getRemoteAddr()); } } @Override public void sessionDestroyed(HttpSessionEvent event) { sessions.remove(event.getSession()); } @Override public void sessionCreated(HttpSessionEvent event) { // NOOP. Useless since we can't obtain IP here. } @Override public void requestDestroyed(ServletRequestEvent event) { // NOOP. No logic needed. } @Override public void contextDestroyed(ServletContextEvent event) { // NOOP. No logic needed. Maybe some future cleanup? } public static SessionCounter getInstance(ServletContext context) { return (SessionCounter) context.getAttribute(ATTRIBUTE_NAME); } public int getCount(String remoteAddr) { return Collections.frequency(sessions.values(), remoteAddr); }}
Define it in web.xml
like follows:
com.example.SessionCounter
You can use it in any servlet like follows:
SessionCounter counter = SessionCounter.getInstance(getServletContext());int count = counter.getCount("127.0.0.1");
3 How to check Who's Online?
You need to collect all logged in users in a Set<User>
in the application scope. Just hook on login
and logout
and add and remove the User
accordingly. Basically:
public void login(User user) { // Do your business thing and then logins.add(user);}public void logout(User user) { // Do your business thing and then logins.remove(user);}
If you're storing the logged-in users in the session, then you'd like to add another hook on session destroy to issue a logout on any logged-in user. I am not sure about how Grails fits in the picture, but talking in Java Servlet API, you'd like to use for this.
public void sessionDestroyed(HttpSessionEvent event) { User user = (User) event.getSession().getAttribute("user"); if (user != null) { Setlogins = (Set ) event.getSession().getServletContext().getAttribute("logins"); logins.remove(user); }}
You can also just let the User
model implement . The implemented methods will be invoked automagically whenever the User
instance is been put in session or removed from it (which would also happen on session destroy).
public class User implements HttpSessionBindingListener { @Override public void valueBound(HttpSessionBindingEvent event) { Setlogins = (Set ) event.getSession().getServletContext().getAttribute("logins"); logins.add(this); } @Override public void valueUnbound(HttpSessionBindingEvent event) { Set logins = (Set ) event.getSession().getServletContext().getAttribute("logins"); logins.remove(this); } // @Override equals() and hashCode() as well!}
4 How to invalidate another session when a user is logged in twice?
The DB-independent approach would be to let the User
have a static Map<User, HttpSession>
variable and implement (and and ). This way your webapp will still function after an unforeseen crash which may cause that the DB values don't get updated (you can of course create a ServletContextListener
which resets the DB on webapp startup, but that's only more and more work).
Here's how the User
should look like:
public class User implements HttpSessionBindingListener { // All logins. private static Maplogins = new ConcurrentHashMap<>(); // Normal properties. private Long id; private String username; // Etc.. Of course with public getters+setters. @Override public boolean equals(Object other) { return (other instanceof User) && (id != null) ? id.equals(((User) other).id) : (other == this); } @Override public int hashCode() { return (id != null) ? (this.getClass().hashCode() + id.hashCode()) : super.hashCode(); } @Override public void valueBound(HttpSessionBindingEvent event) { HttpSession session = logins.remove(this); if (session != null) { session.invalidate(); } logins.put(this, event.getSession()); } @Override public void valueUnbound(HttpSessionBindingEvent event) { logins.remove(this); }}
When you login the User
as follows:
User user = userDAO.find(username, password);if (user != null) { sessionMap.put("user", user);} else { // Show error.}
then it will invoke the valueBound()
which will remove any previously logged in user from the logins
map and invalidate the session.
When you logout the User
as follows:
sessionMap.remove("user");
or when the session is timed out, then the valueUnbound()
will be invoked which removes the user from the logins
map.