day08

监听器和邮箱服务

第1章 监听器介绍

监听器:监听事件源,根据事件源上发生事件,做出相应的处理。

1.2 监听机制相关概念

事件源:发生事件的源头,监听器需要监听的对象。
事件:事件源上发生的动作,监听器监听的内容。
监听器:负责监听事件源的对象。

day08_第1张图片
图片1.png

第2章 web监听器介绍

2.1 javaweb监听器介绍

JavaWEB中的监听器主要监听JavaWEB中的request、session、ServletContext对象的各种变化。
主要监听的任务:

监听request、ServletContext 、session对象的创建和销毁 (练习)
ServletRequestListener
ServletContextListener
HttpSessionListener

监听request、session、ServletContext 对象存放的数据变化情况(练习)
ServletContextAttributeListener
HttpSessionAttributeListener
ServletRequestAttributeListener

监听session中保存的JavaBean的状态
HttpSessionBindingListener

2.2 javaweb监听器创建步骤(示例:ServletRequestListener)

2.2.1 需要定义一个类实现对应的监听器接口

ServletRequestListener定义(API截图):


day08_第2张图片
ServletRequestListener.png
day08_第3张图片
RequestListener.png
@WebListener
public class MyServletRequestListener implements ServletRequestListener{
    @Override
    //监听request对象销毁的方法
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("MyServletRequestListener.....requestDestroyed....");    
    }
    @Override
    //监听request对象初始化的方法
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("MyServletRequestListener.....requestInitialized....");
    }
}
day08_第4张图片
结果.png

2.2.2 配置监听器对象

注意:当服务器加载项目的时候,会读取web.xml文件中listener标签,那么服务器会自动创建监听器对象,并且自动调用其方法
自动调用其方法,也是通过反射调用(因为他的方法名称和参数是固定的)
监听器的小结:
1)创建一个类,实现监听器接口
2)在监听器对象的方法中,书写相关的代码
3)在web.xml中配置当前监听器。省略

2.3 ServletContext创建销毁监听

ServletContextListener定义(API截图):

day08_第5张图片
ServletContextListener.png
day08_第6张图片
ContextListener.png

代码演示:

@WebListener
public class MyServletContextListener implements ServletContextListener{
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("MyServletContextListener.....contextInitialized....");  
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("MyServletContextListener.....contextDestroyed....");
    }
}

监听servletcontext对象初始化截图:

day08_第7张图片
初始化.png

监听servletcontext对象销毁截图:

day08_第8张图片
销毁.png

2.4 ServletContextListener案例:定时任务

需求:项目启动时,获取服务器时间(new Date()),每一秒钟更新一次,打印在控制台

思路:
1)监控项目的启动(使用ServletContextListener来监听ServletContext对象的初始化)
1)获取服务器时间:new Date();
2)每一秒更新一次:定时器Timer
4)给定时器设置定时任务

Timer:定时器 任务调度的对象

day08_第9张图片
timer.png
day08_第10张图片
图片2.png
图片3.png
day08_第11张图片
参数.png

timeTask:定时器的任务(类)
delay:从什么时候开始执行,立即执行设置为:0
period :间隔多少时间重复执行,毫秒值,1秒=1000毫秒
TimerTask:定时器的任务(类)

day08_第12张图片
timerTask.png
图片4.png

Run方法中应该写我们的定时任务:每一秒钟更新一次时间,打印在控制台上

代码实现:

Timer timer= new Timer();
timer.schedule(new TimerTask(){
    @Override
public void run() {
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //打印时间
        System.out.println(sdf.format(new Date()));
            }
        }, 0, 3000);

2.5 HttpSessionListener对象监听session的创建与销毁监听

HttpSessionListener定义(API截图):

day08_第13张图片
HttpSessionListener.png
day08_第14张图片
SessionListener.png

代码演示:

public class MyHttpSessionListener implements HttpSessionListener{
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("MyHttpSessionListener....sessionCreated....");
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("MyHttpSessionListener....sessionDestroyed....");
    }
}
day08_第15张图片
ss.png

2.6 案例——统计在线人数

需求:统计当前访问网站的人数有多少人?

问题:什么时候我们可以知道用户访问了网站?
只要用户访问了我们的网站,session一定会创建。只要用户离开,点退出(注销),session就销毁。

思路:
只要判断session创建,在线人数就加一
只要判断session销毁,在线人数就减一

在线人数的数据,要存在哪里?
答:ServletContext对象中,所有应用程序范围都可以获取,所有访问当前网站的用户,都应该可以看到在线人数

总思路:
1 现在项目启动的时候,初始化在线人数0,保存在ServletContext
2 监听到session创建数据加一
3 监听到session销毁数据减一
4 在页面展示数据

代码实现:

@WebListener
public class MyHttpSessionListener implements HttpSessionListener {

    /**
     * Default constructor. 
     */
    public MyHttpSessionListener() {
        // TODO Auto-generated constructor stub
    }


    public void sessionCreated(HttpSessionEvent se)  { 
        System.out.println("MyHttpSessionListener-------sessionCreated");
        // 在监听器中只要判断session创建,在线人数就加一
        ServletContext context = se.getSession().getServletContext();
        //获取里面的在线人数
        Integer onlineNum=(Integer)context.getAttribute("onlineNum");
        onlineNum++;
        context.setAttribute("onlineNum", onlineNum);
         se.getSession().setMaxInactiveInterval(60);
    }

    public void sessionDestroyed(HttpSessionEvent se)  { 
        System.out.println("MyHttpSessionListener-------sessionDestroyed");
        // 在监听器中只要判断session销毁,在线人数就减去一
        ServletContext context = se.getSession().getServletContext();
        //获取里面的在线人数
        Integer onlineNum=(Integer)context.getAttribute("onlineNum");
        onlineNum--;
        context.setAttribute("onlineNum", onlineNum);
    }   
}
@WebListener
public class MyServletContextListener implements ServletContextListener {

    public MyServletContextListener() {     
    }
    public void contextDestroyed(ServletContextEvent arg0)   { 
    }

    public void contextInitialized(ServletContextEvent sce)  { 
        System.out.println("MyServletContextListener---------contextInitialized");
        ServletContext context= sce.getServletContext();
        context.setAttribute("onlineNum", 0);
    }   
}

index.jsp

  当前在线人数:${onlineNum }

第3章 属性变化的监听

主要是监听使用setAttribute、removeAttribute方法。

ServletContextAttributeListener 专门用于监听ServletContext对象中的属性的变化情况
HttpSessionAttributeListener 专门用于监听session对象中的属性的变化情况
ServletRequestAttributeListener 专门用于监听request对象中的属性的变化情况
它们中的的监听 添加 、删除 、 修改的方法名称全部一致:

day08_第16张图片
图片1.png

代码演示:
Jsp:

<%
    session.setAttribute("name", "毛爷爷");
    session.setAttribute("name", "邓爷爷");
        session.removeAttribute("name");
%>

监听器:

public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener    {

    @Override
public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("MyHttpSessionAttributeListener....attributeAdded...");
    }

    @Override
public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("MyHttpSessionAttributeListener....attributeRemoved...");
    }

    @Override
public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("MyHttpSessionAttributeListener....attributeReplaced...");
    }

}

结果:

day08_第17张图片
图片2.png

第4章 Session中的bean(JavaBean)监听

当我们给Session中保存一个Java对象的时候,或者把Java对象从Session中移除的时候会触发专门用来监听Session中对象变化的监听器中的方法。拥有这个方法的对象——HttpSessionBindingListener接口

属性监听和bean监听的区别:

属性监听:是对三个容器中的任何属性(包括对象和不是对象的数据,基本类型数据)的变化,进行监听
Bean监听:它只监听javabean对象往session中保存和session中移出的过程。

day08_第18张图片
图片2.png
day08_第19张图片
图片3.png

由于HttpSessionBindingListener是用来监听某个JavaBean对象的绑定(存入session容器)和解绑(从session容器中移除)的,所以这个监听器的实现类必须是被操作的JavaBean(HttpSessionBindingListener不需要再web.xml中配置)

javaBean:

public class User implements HttpSessionBindingListener{

    private int age;
    private String name;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println("User....valueBound...");
        
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println("User....valueUnbound...");
        
    }
}

JSP:

 <%
    session.setAttribute("user", new User());
     session.removeAttribute("user");
     %>

效果:

day08_第20张图片
图片4.png

Bean监听需求:
在线人数,根据session创建和销毁,来做人数的增减。
在线会员统计:
1)User类实现bean监听接口
2)每次监听到loginUser对象被绑定到session中的时候,会员人数加一
3)每次监听到loginUser对象被解绑的时候,会员人数减一

总结:
1 熟悉监听器相关的概念(事件源 事件 监听器)
2 掌握监听器的创建步骤
3 完成笔记中两个案例(定时任务 在线人数)

服务器的启动时间动态获取如何做?

第5章 电子邮件学习

5.1 一、电子邮件运行机制?

平时生活中写信:

用户1——————》邮局——————————》邮局——————》用户2

5.1.1 错误的常识:

day08_第21张图片
图片5.png

5.1.2 正确的原理:

day08_第22张图片
图片6.png

今天的邮件服务器逻辑:

day08_第23张图片
图片8.png

6.使用外网服务器(QQ)发送邮件

获取QQ邮箱服务器地址:

day08_第24张图片
图片9.png
day08_第25张图片
图片10.png
day08_第26张图片
图片11.png

修改服务器地址:
props.put("mail.smtp.host", "smtp.qq.com");

错误:需要认证信息

com.sun.mail.smtp.SMTPSendFailedException: 503 Error: need EHLO and AUTH first !
  nested exception is:
    com.sun.mail.smtp.SMTPSenderFailedException: 503 Error: need EHLO and AUTH first !

添加认证:
在javamail-samples,找到红框内容,查看代码:

day08_第27张图片
图片12.png

在集合多添加了一行用户认证:


day08_第28张图片
图片15.png

代码添加:认证

day08_第29张图片
图片16.png

报错:认证需要用户名和密码:

javax.mail.AuthenticationFailedException: failed to connect, no password specified?

填上用户名和密码,继续报错:设置ssl端口587

javax.mail.AuthenticationFailedException: 530 Error: A secure connection is requiered(such as ssl). More information at http://service.mail.qq.com/cgi-bin/help?id=28

添加端口,继续报错:需要授权码(使用第三方客户端登录QQ邮箱),根据网址提示操作

javax.mail.AuthenticationFailedException: 535 Error: ÇëʹÓÃÊÚȨÂëµÇ¼¡£ÏêÇéÇë¿´: http://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256

什么是授权码,它又是如何设置?

1、什么是授权码?

授权码是QQ邮箱推出的,用于登录第三方客户端的专用密码。
适用于登录以下服务:POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务。
温馨提醒:为了你的帐户安全,更改QQ密码以及独立密码会触发授权码过期,需要重新获取新的授权码登录。

2、怎么获取授权码?
先进入设置-》帐户页面找到入口,按照以下流程操作。
(1)点击“开启”(pop3/smtp 服务)

day08_第30张图片
图片17.png

验证:密保

(3)获取授权码


day08_第31张图片
图片18.png

3、在第三方客户端怎么设置?

在第三方客户端的密码框里面输入16位授权码进行验证。(涂改处写入授权码)

图片19.png

代码:

import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class MsgMailTest {
    public static void main(String[] args) {
        sendMail("[email protected]", "[email protected]", "javaMailTest", "嘿嘿,编程发邮件");
    }

    public static void sendMail(String from, String to, String subject, String msgText) {
        
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.qq.com");
        props.put("mail.debug", true);
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "587");

        Session session = Session.getInstance(props, null);
        session.setDebug(false);

        try {
            MimeMessage msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress(from));
            InternetAddress[] address = { new InternetAddress(to) };
            msg.setRecipients(Message.RecipientType.TO, address);
            msg.setSubject(subject);
            msg.setSentDate(new Date());
            msg.setText(msgText);
            // xxx邮箱用户名,yyy,邮箱授权密码
            Transport.send(msg, "[email protected]", "授权码");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

延时发送邮件

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class DelaySendMail {
        public  static void delaysendMail(){
            Timer timer=new Timer();
            timer.schedule(new TimerTask(){
    @Override
    public void run() {
    System.out.println("准备发送邮件.......");
    MsgMailTest.sendMail("[email protected]", "[email protected]", "Test", "嘿嘿");
    System.out.println("发送邮件完成....");
    }
      },  new Date(new Date().getTime() + 1000*60));
        }
}

需要jar包:
javax.mail.jar

练习

统计当前在线人数,并区分游客和登陆用户
训练考核知识点

Session工作机制
登陆功能原理
监听器描述

操作步骤描述

1.登陆功能以及退出功能已经开发好.直接使用即可.

2.创建监听器并实现ServletContextListener, HttpSessionListener, HttpSessionAttributeListener

3.创建两个集合放置session.其中一个集合放置未登陆的session.另一个集合放置登陆后的session.

4.在servletContext创建时对集合进行初始化.并放入application域(方便在页面取出)

5.每当有session创建时,说明有新的用户访问网站,将session放入游客集合

6.每当有session添加登陆成功标识时,说明有游客登陆了.将session从游客集合中移除,添加到登陆用户集合

7.每当有session移除时说明有登录用户或游客离开了.将session从用户或游客集合中移除

8.在index.jsp中取出游客以及登陆用户集合的数量显示

练习
JSP


    当前在线游客人数:${onlineNum.size()}
当前在线登录人数:${userNum.size() }
当前在线总数:${onlineNum.size()+userNum.size() }
用户登录 退出登录

listerner

@WebListener
public class ListenerTest01 implements ServletContextListener, HttpSessionListener,HttpSessionAttributeListener{
    private Set onlineNum;
    private Set userNum;
    ServletContext context;
    public ListenerTest01() {
        // TODO Auto-generated constructor stub
    }
    

    @SuppressWarnings("unchecked")
    public void sessionCreated(HttpSessionEvent se)  { 
        System.out.println("MyListener-------sessionCreated");
//       在监听器中只要判断session创建,在线人数就加一
        //获取里面的在线人数
        onlineNum=(Set) context.getAttribute("onlineNum");
        onlineNum.add(se.getSession());
        context.setAttribute("onlineNum", onlineNum);
    }

    /**
     * @see ServletRequestListener#requestDestroyed(ServletRequestEvent)
     */
    public void requestDestroyed(ServletRequestEvent arg0)  { 
        System.out.println("MyListener-------requestDestroyed");
    }

    /**
     * @see ServletRequestListener#requestInitialized(ServletRequestEvent)
     */
    public void requestInitialized(ServletRequestEvent arg0)  { 
        System.out.println("MyListener-------requestInitialized");
    }

    /**
     * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
     */
    @SuppressWarnings("unchecked")
    public void sessionDestroyed(HttpSessionEvent se)  { 
        System.out.println("MyListener-------sessionDestroyed");
        //获取里面的在线人数减一
        onlineNum=(Set) context.getAttribute("onlineNum");
        onlineNum.remove(se.getSession());
        context.setAttribute("onlineNum", onlineNum);
    }

    /**
     * @see ServletContextListener#contextDestroyed(ServletContextEvent)
     */
    public void contextDestroyed(ServletContextEvent arg0)  { 
         // TODO Auto-generated method stub
    }

    /**
     * @see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    public void contextInitialized(ServletContextEvent sce)  { 
        System.out.println("MyListener---------contextInitialized");
        //初始化数据
        onlineNum =new HashSet<>();
        userNum =new HashSet<>();
        context= sce.getServletContext();
        context.setAttribute("onlineNum", onlineNum);
        context.setAttribute("userNum", userNum);
    }


    @Override
    public void attributeAdded(HttpSessionBindingEvent arg0) {
        //登录操作
        //游客减一
        onlineNum.remove(arg0.getSession());
        //用户加一
        userNum.add(arg0.getSession());
        context.setAttribute("onlineNum", onlineNum);
        context.setAttribute("userNum", userNum);
    }


    @Override
    public void attributeRemoved(HttpSessionBindingEvent arg0) {
        //登出操作
        //游客加一
        onlineNum.add(arg0.getSession());
        //用户减一
        userNum.remove(arg0.getSession());
        context.setAttribute("onlineNum", onlineNum);
        context.setAttribute("userNum", userNum);
        
    }


    @Override 
    public void attributeReplaced(HttpSessionBindingEvent arg0) {
        // TODO Auto-generated method stub
        
    }   
}

BeanLoginServlet

@WebServlet("/BeanLoginServlet")
public class BeanLoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public BeanLoginServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        //模拟用户登录
        HttpSession session=request.getSession();
        //用户登录成功
        User loginUser=new User();
        session.setAttribute("user", loginUser);
        request.getRequestDispatcher("jsp1/index.jsp").forward(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

LogOutServlet

@WebServlet("/LogOutServlet")
public class LogOutServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public LogOutServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        //模拟用户登录
        HttpSession session=request.getSession();
        //用户登录成功
        session.removeAttribute("user");
        request.getRequestDispatcher("jsp1/index.jsp").forward(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

游客访问页面情况

day08_第32张图片
图片20.png

游客登录后页面情况

day08_第33张图片
图片21.png

你可能感兴趣的:(day08)