javaWeb_统计IP
目标 : 使用servlet实现访问某站的IP统计
需要解决的问题 : 1. IP地址用什么存; 2. 存储IP的数据结构何时创建; 3. 何时获取IP存入指定数据结构
设计思路 : 将IP作为键,计数值作为值, 存储在Map集合中. Map集合的创建, 由于Map集合是相对于全站的,而不是会话或者本次request,所以使用ServletContext进行存储.使用ServletContextListener监听器进行监听ServletContext的创建事件, 监听到之后创建Map. 使用/* 过滤器Filter过滤所有对于本站的请求, 得到Map, 对于Servlet3来说ServletRequest可以直接获取ServletContext,对于servlet2来说通过request.getSession().getServletContext(). 如果Map已经存在该IP,获取count值, 自增后放入map中,没有的话直接将count值设置为1.
实际代码 :
1. ServletContext事件监听器
1 package com.theangryz.listener; 2 3 import javax.servlet.Servlet; 4 import javax.servlet.ServletContext; 5 import javax.servlet.ServletContextEvent; 6 import javax.servlet.ServletContextListener; 7 import java.util.LinkedHashMap; 8 import java.util.Map; 9 10 public class IpListener implements ServletContextListener { 11 @Override 12 public void contextInitialized(ServletContextEvent servletContextEvent) { 13 ServletContext application = servletContextEvent.getServletContext(); 14 Map<String, Integer> map = new LinkedHashMap<>(); 15 application.setAttribute("map", map); 16 } 17 18 @Override 19 public void contextDestroyed(ServletContextEvent servletContextEvent) { 20 21 } 22 }
2. Filter过滤器
1 package com.theangryz.filter; 2 3 import javax.servlet.*; 4 import java.io.IOException; 5 import java.util.Map; 6 7 public class IpFilter implements Filter { 8 @Override 9 public void init(FilterConfig filterConfig) throws ServletException { 10 11 } 12 13 @Override 14 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 15 ServletContext application = servletRequest.getServletContext(); 16 Map<String, Integer> map = (Map<String, Integer>)application.getAttribute("map"); 17 String ip = servletRequest.getRemoteAddr(); 18 if (map.containsKey(ip)){ 19 int count = map.get(ip); 20 map.put(ip, ++count); 21 }else{ 22 map.put(ip, 1); 23 } 24 filterChain.doFilter(servletRequest, servletResponse); 25 } 26 27 @Override 28 public void destroy() { 29 30 } 31 }
3. web.xml WEB容器的配置文件, 用于告诉容器自己定义的Listener, Filter, Servlet
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <filter> <filter-name>EncofingFilter</filter-name> <filter-class>com.theangryz.filter.EncodingFilter</filter-class> </filter> <filter> <filter-name>IpFilter</filter-name> <filter-class>com.theangryz.filter.IpFilter</filter-class> </filter> <filter-mapping> <filter-name>EncofingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>IpFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>com.theangryz.listener.IpListener</listener-class> </listener> <servlet> <servlet-name>AServlet</servlet-name> <servlet-class>com.theangryz.servlet.AServlet</servlet-class> </servlet> <servlet> <servlet-name>BaseServlet</servlet-name> <servlet-class>com.theangryz.servlet.BaseServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>AServlet</servlet-name> <url-pattern>/AServlet</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>BaseServlet</servlet-name> <url-pattern>/*Servlet</url-pattern> </servlet-mapping> </web-app>
4. jsp显示页面
<%-- Created by IntelliJ IDEA. User: idaepad Date: 2019/11/28 Time: 14:38 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>show page</title> <table align="center" border="1" width="60%"> <tr> <td>IP</td> <td>IPCount</td> </tr> <c:forEach items="${applicationScope.map}" var="item"> <tr> <td>${item.key}</td> <td>${item.value}</td> </tr> </c:forEach> </table> </head> <body> </body> </html>
实际编写中遇到的问题 :
1. 忘记在web.xml中声明自己定义的Filter, Listener, Servlet
2. 忘记了如何导入JSTL(jsp标准标签库)
解决 : <1> : <%@ tablib prefix="c" url="http://java.sun.com/jsp/jstl/core" %>
<2> : pom.xml中引入相关依赖 :
<dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency>
3. 导入了JSPL之后, 使用${entry.key} 与 ${entry.value}(JSP EL : jsp表达式语言), 网页没有显示相关变量值. 显示的还是${entry.value}
解决 : 原因在于web.xml中的这段代码 :
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" >
在该处的Web applcation 2.3 导致jsp页面不支持JSTL, 所以要使用JSPTL需要在JSP页面进行配置 : <%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>