java 查找从给定客户端 IP 创建的活动会话数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3679465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find number of active sessions created from a given client IP
提问by Somu
Is there a way to determine the number of active sessions created from a given client IP address?
有没有办法确定从给定客户端 IP 地址创建的活动会话数?
回答by BalusC
The standard Servlet API doesn't offer facilities for that. Best what you can do is to maintain a Map<HttpSession, String>
yourself (where the String
is the IP address) with and check on every ServletRequest
if the HttpSession#isNew()
and add it to the Map
along with ServletRequest#getRemoteAddr()
. Then you can get the amount of IP addresses with an active session using Collections#frequency()
on Map#values()
. You only need to ensure that you remove the HttpSession
from the Map
during HttpSessionListener#sessionDestroyed()
.
标准的 Servlet API 没有为此提供工具。最好你可以做的是保持Map<HttpSession, String>
自己(这里String
是IP地址),并检查每个ServletRequest
如果HttpSession#isNew()
并将其添加到Map
沿ServletRequest#getRemoteAddr()
。然后,您可以使用Collections#frequency()
on获取活动会话的 IP 地址数量Map#values()
。您只需要确保HttpSession
从Map
during 中删除HttpSessionListener#sessionDestroyed()
。
This all can be done in a single Listener
implementing the ServletContextListener
, HttpSessionListener
and ServletRequestListener
.
这一切都可以在单个Listener
实现ServletContextListener
,HttpSessionListener
和 中完成ServletRequestListener
。
Here's a kickoff example:
这是一个启动示例:
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);
}
}
Define it in web.xml
like follows:
定义web.xml
如下:
<listener>
<listener-class>com.example.SessionCounter</listener-class>
</listener>
You can use it in any servlet like follows:
您可以在任何 servlet 中使用它,如下所示:
SessionCounter counter = SessionCounter.getInstance(getServletContext());
int count = counter.getCount("127.0.0.1");
回答by Brimstedt
I needed to get this information quickly without new deploys. It can be done by altering JSP and add the following snippet. (Only sessions with activity will get the value set):
我需要在没有新部署的情况下快速获取这些信息。可以通过更改 JSP 并添加以下代码段来完成。(只有有活动的会话才会获得值集):
<%
// Set user agent and ip in session
session.setAttribute("agent", request.getHeader("user-agent") + "@" + request.getRemoteAddr());
%>
Then create a groovy script to query jmx:
然后创建一个groovy脚本来查询jmx:
import javax.management.remote.*
import javax.management.*
import groovy.jmx.builder.*
// Setup JMX connection.
def connection = new JmxBuilder().client(port: 4934, host: '192.168.10.6')
connection.connect()
// Get the MBeanServer.
def mbeans = connection.MBeanServerConnection
def mbean = new GroovyMBean(mbeans, 'Catalina:type=Manager,host=localhost,context=/')
println "Active sessions: " + mbean['activeSessions']
def sessions = mbean.listSessionIds().tokenize(' ');
def ips = [:];
def agents = [:];
sessions.each
{
def agentString = mbean.getSessionAttribute(it, "agent");
if(agentString != null)
{
agent = agentString.tokenize('@');
}
else
{
agent = ['unknown', 'unknown'];
}
if(agents[agent[0]] == null)
{
agents[agent[0]] = [];
}
agents[agent[0]] += [it];
if(ips[agent[1]] == null)
{
ips[agent[1]] = [];
}
ips[agent[1]] += it;
};
println "Ips"
ips = ips.sort { -it.value.size }
ips.each
{
ip, list ->
println "${ip}\t${list.value.size}";
//println list;
//println "";
}
println ""
println "Agents"
agents = agents.sort { -it.value.size }
agents.each
{
agent, list ->
println "${agent}\t${agents[agent].size}";
//println list;
//println "";
}
Result
结果
Active sessions: 729
Ips
unknown 102
68.180.230.118 11
80.213.88.107 11
157.55.39.127 9
81.191.247.166 2
...
Agents
Mozilla/5.0 (compatible; MJ12bot/v1.4.5; http://www.majestic12.co.uk/bot.php?+) 117
unknown 102
Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm) 55
Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp) 29
...
回答by Ellipsis
Very nice example Balus C. We solved this problem by using an Observer Listener. Here is nice example/tutorial for the same.
非常好的例子 Balus C。我们通过使用观察者监听器解决了这个问题。这是相同的很好的示例/教程。
http://www.big-oh.net/BigOhSoftwareWeb/content/tutorials/requestObserverListener.jsp
http://www.big-oh.net/BigOhSoftwareWeb/content/tutorials/requestObserverListener.jsp
Just thought it will be helpful to other visitors. :)
只是认为这会对其他游客有所帮助。:)
Edit : *** April 2017 **
编辑:*** 2017 年 4 月 **
Looks like the http://www.big-oh.net/site that contains the source above is dead. Hereis the source from web.archive.org. Also the added the file referred webpage in github gist. Gist sourceand its html preview
看起来包含上述来源的http://www.big-oh.net/站点已经死了。这是来自 web.archive.org 的来源。还添加了 github gist 中的文件引用网页。Gist源码及其html 预览