监听器和邮箱服务
第1章 监听器介绍
监听器:监听事件源,根据事件源上发生事件,做出相应的处理。
1.2 监听机制相关概念
事件源:发生事件的源头,监听器需要监听的对象。
事件:事件源上发生的动作,监听器监听的内容。
监听器:负责监听事件源的对象。
第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截图):
@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....");
}
}
2.2.2 配置监听器对象
注意:当服务器加载项目的时候,会读取web.xml文件中listener标签,那么服务器会自动创建监听器对象,并且自动调用其方法
自动调用其方法,也是通过反射调用(因为他的方法名称和参数是固定的)
监听器的小结:
1)创建一个类,实现监听器接口
2)在监听器对象的方法中,书写相关的代码
3)在web.xml中配置当前监听器。省略
2.3 ServletContext创建销毁监听
ServletContextListener定义(API截图):
代码演示:
@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对象初始化截图:
监听servletcontext对象销毁截图:
2.4 ServletContextListener案例:定时任务
需求:项目启动时,获取服务器时间(new Date()),每一秒钟更新一次,打印在控制台
思路:
1)监控项目的启动(使用ServletContextListener来监听ServletContext对象的初始化)
1)获取服务器时间:new Date();
2)每一秒更新一次:定时器Timer
4)给定时器设置定时任务
Timer:定时器 任务调度的对象
timeTask:定时器的任务(类)
delay:从什么时候开始执行,立即执行设置为:0
period :间隔多少时间重复执行,毫秒值,1秒=1000毫秒
TimerTask:定时器的任务(类)
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截图):
代码演示:
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....");
}
}
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对象中的属性的变化情况
它们中的的监听 添加 、删除 、 修改的方法名称全部一致:
代码演示:
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...");
}
}
结果:
第4章 Session中的bean(JavaBean)监听
当我们给Session中保存一个Java对象的时候,或者把Java对象从Session中移除的时候会触发专门用来监听Session中对象变化的监听器中的方法。拥有这个方法的对象——HttpSessionBindingListener接口
属性监听和bean监听的区别:
属性监听:是对三个容器中的任何属性(包括对象和不是对象的数据,基本类型数据)的变化,进行监听
Bean监听:它只监听javabean对象往session中保存和session中移出的过程。
由于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");
%>
效果:
Bean监听需求:
在线人数,根据session创建和销毁,来做人数的增减。
在线会员统计:
1)User类实现bean监听接口
2)每次监听到loginUser对象被绑定到session中的时候,会员人数加一
3)每次监听到loginUser对象被解绑的时候,会员人数减一
总结:
1 熟悉监听器相关的概念(事件源 事件 监听器)
2 掌握监听器的创建步骤
3 完成笔记中两个案例(定时任务 在线人数)
服务器的启动时间动态获取如何做?
第5章 电子邮件学习
5.1 一、电子邮件运行机制?
平时生活中写信:
用户1——————》邮局——————————》邮局——————》用户2
5.1.1 错误的常识:
5.1.2 正确的原理:
今天的邮件服务器逻辑:
6.使用外网服务器(QQ)发送邮件
获取QQ邮箱服务器地址:
修改服务器地址:
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,找到红框内容,查看代码:
在集合多添加了一行用户认证:
代码添加:认证
报错:认证需要用户名和密码:
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 服务)
验证:密保
(3)获取授权码
3、在第三方客户端怎么设置?
在第三方客户端的密码框里面输入16位授权码进行验证。(涂改处写入授权码)
代码:
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("xxxxx@qq.com", "xxxx@qq.com", "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, "xxxxxx@qq.com", "授权码");
} 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("xxxxxxx@qq.com", "xxxxx@qq.com", "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
<body>
当前在线游客人数:${onlineNum.size()}<br/>
当前在线登录人数:${userNum.size() }<br/>
当前在线总数:${onlineNum.size()+userNum.size() }<br/>
<a href="${pageContext.request.contextPath }/BeanLoginServlet">用户登录</a>
<a href="${pageContext.request.contextPath }/LogOutServlet">退出登录</a><br/>
</body>
listerner
@WebListener
public class ListenerTest01 implements ServletContextListener, HttpSessionListener,HttpSessionAttributeListener{
private Set<HttpSession> onlineNum;
private Set<HttpSession> 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<HttpSession>) 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<HttpSession>) 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);
}
}
游客访问页面情况
游客登录后页面情况