这个稍微比上个版本做得完善了一点,用了JavaBean来封装用户信息,添加了一个管理踢用户的功能。
上一个的用户访问量是通过监听request来统计的,在这个实例中,我们也可以通过过滤器来实现统计网站访问量。
直接看源码吧,感觉没多少要讲的,我习惯把解释写在代码中。
部分源码
index.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>在线人信息管理与统计</title> </head> <body> <h2>在线人信息管理与统计</h2> <c:if test="${empty sessionScope.user}" var="boo"> <h3>会员登录:</h3> <form action='<c:url value='/LoginServlet'></c:url>' method="post"> 姓名:<input type='text' name="name"><br /> <input type="submit" value="注册"> </form> </c:if> <c:if test="${!boo}"> 亲爱的${user.name} <c:if test="${user.admin}" var="bo"> -管理员 </c:if> <c:if test="${!bo}"> -会员 </c:if> ,欢迎来到...<br /> </c:if> <br /> <a href="<c:url value='/servlet/ShowServlet'/>">显示所有在线用户</a> <br /> <a href="<c:url value='/servlet/LogOutServlet'/>">安全退出</a> <br/>网站访问量:${count} </body> </html>
MyServletContextListener
这个就是实现把访问量持久化的监听器实现类:
package cn.hncu.listeners; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.InputStreamReader; import java.io.PrintWriter; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class MyServletContextListener implements ServletContextListener{ @Override public void contextInitialized(ServletContextEvent sce) { //从服务器硬盘把之前存储的点击量数据读取出来 ServletContext sct = sce.getServletContext(); String path = sct.getRealPath("/count.txt"); try { BufferedReader br = new BufferedReader(new FileReader(path)); String line = br.readLine(); Integer count = Integer.valueOf(line); sct.setAttribute("count", count); } catch (Exception e) { //如果出异常了,我们认为文件还不存在,服务器第一次启动 e.printStackTrace(); sct.setAttribute("count",new Integer(0)); } } //关闭服务器时 @Override public void contextDestroyed(ServletContextEvent sce) { //把当前servletContext容器中存储的点击量数据 永久化到 服务器硬盘 ServletContext sct = sce.getServletContext(); String path = sct.getRealPath("/count.txt"); try { PrintWriter pw = new PrintWriter(path); pw.write(""+sct.getAttribute("count")); pw.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
CharsetFilter
实现统计访问量和全站编码的过滤器
package cn.hncu.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class CharsetFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); response.setCharacterEncoding("utf-8"); //获取该用户的ip,存储到它的session对象中 HttpServletRequest req = (HttpServletRequest) request; if(req.getSession().getAttribute("ip")==null){ req.getSession().setAttribute("ip", req.getRemoteAddr()); //这里的req和request是同一个对象!!! //所以传过去的参数还可以是request } //new一个线程统计访问量 new MyThread(request.getServletContext()).start(); //放行 chain.doFilter(request, response); } @Override public void destroy() { } } class MyThread extends Thread{ private ServletContext servletContext =null; private static Object boj = new Object(); public MyThread(ServletContext servletContext) { this.servletContext = servletContext; } @Override public void run() { synchronized (boj) { servletContext.setAttribute("count",(Integer)servletContext.getAttribute("count")+1); } } }
LoginFilter
用户访问其他页面时进行的权限过滤:
如果你没有登陆,就不给你权限去访问除主页外的其他页面。
package cn.hncu.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; if(req.getSession().getAttribute("user")==null){ HttpServletResponse resp = (HttpServletResponse) response; resp.sendRedirect(req.getContextPath()+"/index.jsp"); }else{//放行 chain.doFilter(request, response); } } @Override public void destroy() { } }
MySessionListener
有用户来访问时,我们就通过监听器去监听session的创建与销毁,在这里,我们认为一个session就是一个用户!
package cn.hncu.listeners; import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class MySessionListener implements HttpSessionListener{ @Override public void sessionCreated(HttpSessionEvent se) { Map<String, HttpSession> onLines = (Map<String, HttpSession>) se.getSession().getServletContext().getAttribute("onLines"); if(onLines==null){//第一个来访问的 onLines = Collections.synchronizedMap(new HashMap<String, HttpSession>() );//使用同步技术的Map se.getSession().getServletContext().setAttribute("onLines", onLines); } onLines.put(se.getSession().getId(), se.getSession()); } @Override public void sessionDestroyed(HttpSessionEvent se) { Map<String, HttpSession> onLines = (Map<String, HttpSession>) se.getSession().getServletContext().getAttribute("onLines"); //这里也要防范好!多线程,多个管理同时踢一个人的时候,如果不防范就会出问题 if(onLines.containsKey( se.getSession().getId() )){ onLines.remove( se.getSession().getId() ); } } }
LoginServlet
用于判断用户登录与设置管理员的servlet。
package cn.hncu.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Random; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.hncu.domain.User; public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); if(name!=null && name.trim().length()>0){ User user = new User(); user.setName(name); //用user作为参数到后台登录,这里我们简化了,直接假设登录成功 if(true){ Random r = new Random(); int a = r.nextInt(2); if(a%2==0){ user.setAdmin(true); }else{ user.setAdmin(false); } } request.getSession().setAttribute("user", user); } response.sendRedirect(request.getContextPath()+"/index.jsp"); } }