查找从给定客户端IP创建的活动会话数

Som*_*omu 10 java session servlets ip-address

有没有办法确定从给定客户端IP地址创建的活动会话数?

Bal*_*usC 13

标准的Servlet API不提供相应的功能.你可以做的最好的事情是维护一个Map<HttpSession, String>你自己(在哪里String是IP地址),并检查每一个ServletRequest是否HttpSession#isNew()和它Map一起添加ServletRequest#getRemoteAddr().然后,您可以使用Collections#frequency()on 获取活动会话的IP地址数量Map#values().你只需要确保您删除HttpSessionMap过程中HttpSessionListener#sessionDestroyed().

这一切都可以在一个单独的Listener实现ServletContextListener,HttpSessionListenerServletRequestListener.

这是一个启动示例:

public class SessionCounter implements ServletContextListener, HttpSessionListener, ServletRequestListener {

    private static final String ATTRIBUTE_NAME = "com.example.SessionCounter";
    private Map<HttpSession, String> sessions = new ConcurrentHashMap<HttpSession, String>();

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

}
Run Code Online (Sandbox Code Playgroud)

web.xml如下方式定义:

<listener>
    <listener-class>com.example.SessionCounter</listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)

您可以在任何servlet中使用它,如下所示:

SessionCounter counter = SessionCounter.getInstance(getServletContext());
int count = counter.getCount("127.0.0.1");
Run Code Online (Sandbox Code Playgroud)

  • 这是一篇尚未更新的旧帖子 - 但为了避免未来读者出现问题,值得指出的是,这个例子虽然在大多数方面都不错,但并不是线程安全的.HashMap不是一个线程安全的数据结构,这个例子没有做任何事情来同步对HashMap的访问,这意味着在现实世界中这样做会导致并发问题.只是一个警告; 任何实现都应该使用不同的数据结构,否则应该同步对sessions-variable的访问. (2认同)