javaEE之--------统计网站在线人数,安全登录等(观察者设计模式)

总体介绍下: 

监听器:监听器-就是一个实现待定接口的普通Java程序,此程序专门用于监听别一个类的方法调用。都是使用观察者设计模式。

javaEE之--------统计网站在线人数,安全登录等(观察者设计模式)_第1张图片

小弟刚接触这个,做了些简单的介绍,大神请绕道微笑,技术只是一点点,方便以后遇到问题可以看这些能解决一些问题。同时希望和大家一起分享下自己写的小小示例

servlet中事件源:

事件源:HttpSession
HttpSessionListener  - 
HttpSessionAttributeListener
HttpSessionEvent
事件源:ServletRequest
ServletRequestListenr
ServletRequestAttributeListener
ServletRequestEvent
事件源:ServletContext
ServletContextListener
ServletContextAttributeListener
ServletContextEvent

在我们这个项目中用到知识点

HttpSessionListener,监听HttpSession的创建和销毁。
sessionCreated
sessionDestroyed

Session的默认有效时间为30分。可以通过配置的方式修改它的值。
可以调用session.invalidate方法销毁当前Session.

主要作用是记录当前所有在线人数,无论是用户还是游客。
·


上面是我们做这个实例用到的知识,下面具体介绍:

 

实例需求

1、使用HttpSessionListener记录在线人数。
2、使用HttpSessionAttributeListener记录登录人数。
3、 将用户踢出系统。


一:记录在线人数我们需要用到HttpSessionListener 观察者设计模式

每一个用户访问网站都会有一个seesion的创建,所以我们从创建session的统计即可

写一个类,实现HttpSessionListener接口

sessionCreated 函数和 sessionDestroyed 我们只用到创建sessionCreated 

把创建的session全部放在一个map集合中,当前台需要获取的时候,直接从context中获取,进行其他操作。其实 sessionCreated 用到集合上锁,api自带,解决多线程问题。

public class MySessionListener implements HttpSessionListener {

	@Override
	public void sessionCreated(HttpSessionEvent se) {
		//我们把创建的session封装在一个map中
		Map<String, HttpSession> map =(Map<String, HttpSession>) se.getSession().getServletContext().getAttribute("onLines");
		if(map==null){//说明这是第一次访问是,需要自己new 一个对象
			map=Collections.synchronizedMap(new HashMap<String, HttpSession>());//采用集合上锁,采用java 自带的上锁函数
			se.getSession().getServletContext().setAttribute("onLines", map);
		}
//		System.out.println("listener添加一个了");
		map.put(se.getSession().getId(), se.getSession());//以session 的id为key,session对象为value存在map中
	}

	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
	}}


二,前台显示页面

我们采用登录前后,都在一个页面显示,采用jstl表达式进行区别就可以。

其中,我们用到当登录成功之后,我们就直接采用设置session,让其区别就可以,当我们采用安全登录也是采用这个session里面是都存在值。

  <body>
  <!-- 需求:做一个能够允许游客访问,允许登录,可以查看当前用户(包括游客),
  	信息-----name,ip,createTime,lastTime,需要一个权限是都可以踢人(使session失效)
  	就是讲session创建的时候,存一个list中去,然后相关的信息从session中回去就可以  -->
  
  <h2>这是用户登录界面</h2>
  
	<c:if test="${empty sessionScope.user}" var="boo">
		  <form action="<c:url value='/LoginServlet'/>" method="post">
			NAME:<input type="text" name="name"/><br/>
			PWD :<input type="text" name="pwd"/><br/>
			<input  type="submit" value="提交信息"/>
		  </form>
  </c:if>
  <c:if test="${!boo }">
  		欢迎您。${sessionScope.user.name}
  		<a href="<c:url value='/servlet/ShowLoginServet'/>" >显示当前访问数量</a>
  		<a href="<c:url  value='/servlet/LoginoutServlet'/>">退出</a>
  </c:if>
  <hr/>
	  <a href="<c:url  value='/jsps/show.jsp'/>">这是真实用户能访问的用户</a>
 	 <a href="<c:url  value='/open/open.jsp'/>">游客能访问的内容</a>
  
  </body>

三,登录之后处理

在是否登录,我们简单的模拟下

成功之后我们就设置一个session的值传给前台处理

<span style="font-size:18px;">	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//接收参数的编码问题已经通过 过滤器设置好
		String name=request.getParameter("name");
		String pwd =request.getParameter("pwd");
		
		//获得参数之后,开始封装数据
		User user =new User();
		user.setName(name);
		user.setPwd(pwd);
		user.setAdmin(true);
		//封装数据之后,调用service层,访问数据库,简单的模拟 当name和pwd相等就判断登录成功
		if(name!=null && !name.trim().equals("") && pwd != null && pwd.trim().length()>0 ){
			if(name.endsWith(pwd)){//模拟下,相等就是登录成功
				request.getSession().setAttribute("user", user);
			}
		}
		response.sendRedirect(request.getContextPath()+"/index.jsp");//重定向到主页
	}</span>

四,查看在线用户
<span style="font-size:14px;">  <body>
	<h2>这是用户登录拥有的资源</h2>
	<!-- 前台最后采用list<map《》>的封装信息 -->
	  <!-- 显示界面,需要知道session里面的信息,采用监听器 要监听游客,和 用户,采用httpSession-->
  	欢迎您。。${user.name }<br/>
  		<table >
  			<tr>
  				<td>姓名</td>
  				<td>IP</td>
  				<td>创建时间</td>
  				<td>最近访问时间</td>
  				<td>操作</td>
			</tr>
  		<c:forEach items="${requestScope.list }" var="map">
  		<tr>
  			<td>
  				<c:if test="${ empty map.user }" var="boo">
  					游客
  				</c:if>
  				<c:if test="${!boo }">
  					${map.user.name }
  				</c:if>
  			</td>
  			
  			<td>
  				${map.ip }
  			</td>
  			
  			<td>
  				<fmt:formatDate value="${map.createTime }" pattern="yyyy-MM-dd HH-mm-ss"/>
  			</td>
  			
  			<td>
  				<fmt:formatDate value="${map.LastAccessedTime }" pattern="yyyy-MM-dd HH-mm-ss"/>
  			
  			</td>
  			
  			<td>
  				<c:if test="${!boo && map.user.admin }">
  					<!--  <a href="<c:url value='/servlet/KitLogin'/>?id=${map.id }&&user=${user.name}">踢人</a> -->
  					
  					<a href="/onlineWeb/servlet/KitLogin?id=${map.id }&&user=${user.name}">踢人</a>
  				</c:if>
  			</td>
  			
  		</tr>
  		</c:forEach>
  			
  		</table>  </span>

查看当前用户在线人数,我们直接收集参数:

public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//在这里,我们需要将前台需要的信息在这里封装
		
		//从onLines《sessionID,session对象中》拿到整个session集合,提取其中的信息
		//然后把这个信息封装起来转给前台显示
		List<Map<String, Object>> list=new ArrayList<Map<String,Object>>();//采用list装数据
		Map<String, HttpSession> onLines=(Map<String, HttpSession>) request.getSession().getServletContext().getAttribute("onLines");
//		System.out.println(onLines);
		Iterator<Map.Entry<String, HttpSession>> it= onLines.entrySet().iterator();
		while(it.hasNext()){
			Entry<String, HttpSession> entry=it.next();
			HttpSession sess=entry.getValue();//拿到单个的session对象了
			Map<String, Object> mm =new HashMap<String, Object>();//采用map封装一行数据,然后放在list 中去,就是一个表的数据
			mm.put("id", sess.getId());//获取session的id
			mm.put("createTime",new Date(sess.getCreationTime()));//创建的时间.传过去的是date类型我们前台进行解析,显示出来
			mm.put("LastAccessedTime", new Date(sess.getLastAccessedTime()));//上次访问的时间
			mm.put("user", sess.getAttribute("user"));
			mm.put("ip", sess.getAttribute("ip"));
			//前台需要的信息补全,后台去使用
			list.add(mm);			
		}
		request.setAttribute("list", list);
		request.getRequestDispatcher("/jsps/show.jsp").forward(request, response);//呆着list对象跳转的显示页面
	}

效果图:

javaEE之--------统计网站在线人数,安全登录等(观察者设计模式)_第2张图片

五,管理员踢人

这里全部设置为管理员,可以在值对象里面修改

主要是在点击踢人时,将该对象的id传过来,踢人就是把用户的session.invalidate,设置相同的用户名,不能踢。

踢人时,我们不仅仅只是改session。还需要将map对象里面的session移除。

public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		PrintWriter pw =response.getWriter();
		String id=request.getParameter("id");
		String username=request.getParameter("user");//当前页的user
		Map<String, HttpSession> map=(Map<String, HttpSession>) request.getServletContext().getAttribute("onLines");
		HttpSession se=map.get(id);//通过id 得到session对象
		User user= (User) se.getAttribute("user"); //通过session对象可以得到user对象
		System.out.println("username传过来的www"+username);
		System.out.println("本地直接获得的www"+user.getName());
		if(!user.getName().equals(username)){//不能删除和自己同名的用户
			if(map.containsKey(id)){
				System.out.println("已经删除");
				HttpSession ss=	map.get(id);
				map.remove(id);//从context里面移除
				ss.invalidate();//让session失效
				pw.write("成功删除用户");
			}else{
				pw.write("该用户已被删除");
			}
			request.getRequestDispatcher("/jsps/show.jsp");
		}else{
			pw.write("用户不能踢自己");
		}
		pw.write("<a href='/onlineWeb/index.jsp'>返回</a>");
	}

六,主动退出

       直接将自己的session移除,和把自己的从map中移除

public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		Map<String, HttpSession> map =(Map<String, HttpSession>) request.getServletContext().getAttribute("onLines");
		String id=request.getSession().getId();
		map.remove(id);//通过id来删除,context大容器中的session对象
		request.getSession().invalidate();
		response.sendRedirect(request.getContextPath()+"/index.jsp");
	}


,安全登录

 以前我们写得示例,只要正确输入了路径和访问的项目,我们就能直接访问,没有安全性可言,但是现在我们可以利用

过滤器来实现这个功能。

我们的依据是我们登录成功之后,我们将session里面设置值,然后我们就可以根据这个来过滤了,当前我们知道,之前的全站压缩和过滤敏感词等,都是需要配置过滤器路径,所以我们在配置路径是需要注意,登录界面和处理登录界面的结果是不能被过滤的。所以一般这两个都是直接放在根目录下的。

public class SafeLoginrFilter 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;
		HttpServletResponse resp=(HttpServletResponse) response;
		if(req.getSession().getAttribute("user")==null){//这是过滤非法用户使用的,只有登录的用户才能进入用户权限
			resp.sendRedirect(req.getContextPath()+"/index.jsp");
		}else{
			chain.doFilter(req, resp);
		}
	
	}

	@Override
	public void destroy() {
	}

根据上面的这个,我们可以设置一些目录可以让游客访问,就是不用通过过滤器的页面,单独写一个文件夹都可以。

拦截路径在web.xml中配置:

<filter-mapping>
	  	<filter-name>safeLogin</filter-name>
  		<url-pattern>/servlet/*</url-pattern>
  		<url-pattern>/jsps/*</url-pattern>
  </filter-mapping>

javaEE之--------统计网站在线人数,安全登录等(观察者设计模式)_第3张图片

总结:在示例中,我们只需要知道,用HttpSessionListener,我们用它可以实现创建了多少session对象了,将他放到一个map容器中,需要的时候取出来就行了,当然,session中也存在很多有价值的,如id,访问时间,最后一次访问时间等。其余的都是以前常用的知识。

你可能感兴趣的:(过滤器,统计在线人数,自动退出,观察者设计模式,管理员踢人)