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


    整体介绍下: 

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

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

    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对象跳转的显示页面
    	}

    效果图:

    五。管理员踢人

    这里所有设置为管理员。能够在值对象里面改动

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

    踢人时,我们不只不过改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>


    总结:在演示样例中。我们仅仅须要知道。用HttpSessionListener,我们用它能够实现创建了多少session对象了,将他放到一个map容器中,须要的时候取出来即可了。当然,session中也存在非常多有价值的,如id,訪问时间。最后一次訪问时间等。

    其余的都是曾经经常使用的知识。

  • 相关阅读:
    1022 Digital Library (30 分)(map)
    1023 Have Fun with Numbers (20 分)(大整数运算)
    1019 General Palindromic Number (20 分)(回文数)
    Flink实时项目例程
    Spark Streaming+kafka+spring boot+elasticsearch实时项目(canal)
    Flink es-sink解决java.lang.NoSuchFieldError: FAIL_ON_SYMBOL_HASH_OVERFLOW
    Flink安装及WordCount实例yarn-cluster提交
    解决windows上The root scratch dir: /tmp/hive on HDFS should be writable.Current permissions are: ------
    RDD(弹性分布式数据集)介绍---Spark的核心
    Scala快速入门(零基础到入门)
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/7112775.html
Copyright © 2020-2023  润新知