一、監聽器
1.監聽器(Listener)
是一個專門用于對其他物件身上發生的事件或狀態改變進行監聽和相應處理的物件,當被監視的物件發生情況時,立即采取相應的行動,監聽器其實就是一個實作特定介面的普通java程式,這個程式專門用于監聽另一個java物件的方法呼叫或屬性改變,當被監聽物件發生上述事件后,監聽器某個方法立即被執行
簡而言之:所謂的監聽器就是一個能夠監聽程式內容或者狀態是否發生改變的一個Java類
有點類似現實世界中大廈里的火災警報器
補充講解:與監聽器相關的術語
事件源:指的是被監聽物件(汽車)
監聽器:指的是監聽的物件(報警器)
事件源和監聽器系結:在汽車上安裝報警器
事件:指的是事件源物件的改變(踹了汽車一腳)----主要功能獲得事件源物件,
2.監聽器的作用
導讀模塊:雖然監聽器的作用很強大,但是servlet中并沒有相關的實作類,只是有一些介面,而這也恰恰體現出了servlet的靈活性
1.那么servlet中都提供了哪些監聽器呢?
補充:1)其實servlet中的監聽器主要是針對request,session,servletContext開展的
2)監聽器要想起作用則必須要有實作類,而實作類要起作用,則必須要有動作,所謂的動作其實就是事件,所謂的事件就是與之關聯的一些類
3)servlet中一共有8個監聽器介面,6個事件
1.1 8個監聽器介面和6個事件:
1、ServletContextListener介面
[介面方法] contextInitialized()與 contextDestroyed()
[接收事件] ServletContextEvent
[觸發場景] 在Container加載Web應用程式時(例如啟動 Container之后),會呼叫contextInitialized(),而當容器移除Web應用程式時,會呼叫contextDestroyed ()方法,
2、ServletContextAttributeListener
[介面方法] attributeAdded()、 attributeReplaced()、attributeRemoved()
[接收事件] ServletContextAttributeEvent
[觸發場景] 若有物件加入為application(ServletContext)物件的屬性,則會呼叫attributeAdded(),同理在置換屬性與移除屬性時,會分別呼叫attributeReplaced()、attributeRemoved(),
3、ServletRequestListener
[介面方法] requestInitialized()與 requestDestroyed()
[接收事件] RequestEvent
[觸發場景] 在request(HttpServletRequest)物件建立或被消滅時,會分別呼叫這兩個方法,
4、ServletRequestAttributeListener
[介面方法] attributeAdded()、 attributeReplaced()、attributeRemoved()
[接收事件] HttpSessionBindingEvent
[觸發場景] 若有物件加入為request(HttpServletRequest)物件的屬性,則會呼叫attributeAdded(),同理在置換屬性與移除屬性時,會分別呼叫attributeReplaced()、 attributeRemoved(),
5、HttpSessionListener
[介面方法] sessionCreated()與sessionDestroyed ()
[接收事件] HttpSessionEvent
[觸發場景] 在session (HttpSession)物件建立或被消滅時,會分別呼叫這兩個方法,
6、HttpSessionActivationListener
[介面方法] sessionDidActivate()與 sessionWillPassivate()
[接收事件] HttpSessionEvent
[觸發場景] Activate與Passivate是用于置換物件的動作,當session物件為了資源利用或負載平衡等原因而必須暫時儲存至硬碟或其它儲存器時(透 過物件序列化),所作的動作稱之為Passivate,而硬碟或儲存器上的session物件重新加載JVM時所采的動作稱之為Activate,所以容 易理解的,sessionDidActivate()與 sessionWillPassivate()分別于Activeate后與將Passivate前呼叫,
7、HttpSessionAttributeListener
[介面方法] attributeAdded()、 attributeReplaced()、attributeRemoved()
[接收事件] HttpSessionBindingEvent
[觸發場景] 若有物件加入為session(HttpSession)物件的屬性,則會呼叫attributeAdded(),同理在置換屬性與移除屬性時,會分別呼叫attributeReplaced()、 attributeRemoved(),
8、HttpSessionBindingListener
[介面方法] valueBound()與valueUnbound()
[接收事件] HttpSessionBindingEvent
[觸發場景] 實作HttpSessionBindingListener接 口的類別,其實體如果被加入至session(HttpSession)物件的屬性中,則會呼叫 valueBound(),如果被從session(HttpSession)物件的屬性中移除,則會呼叫valueUnbound(),實作 HttpSessionBindingListener介面的類別不需在web.xml中設定,
?
小結與分類:
備:一共分為三大類
(1)監聽ServletContext、Request、Session物件的創建和銷毀,需要在web.xml中配置
ServletContextListener
ServletRequestListener
HttpSessionListener
友情提示:這三種是最常用的了…
(2)監聽ServletContext、Request、Session物件屬性的變化,需要在web.xml中配置
ServletContextAttributeListener
ServletRequestAttributeListener
HttpSessionAttributeListener
(3)監聽Session內部的物件,不需要再web.xml中配置
HttpSessionActivationListener
HttpSessionBindingListener
2.監聽器的作用:
統計在線人數,利用HttpSessionLisener
加載初始化資訊:利用ServletContextListener
統計網站訪問量
實作訪問監控
后續的Spring等框架中也要用到
3.監聽器實體
3.1使用步驟
1)創建實作類實作需要的介面
2)在web.xml中配置<listener></listener>節點進行宣告
3)實作介面中的方法
3.2統計在線人數監聽器實體:
`package com.rj.bd.manage.listeners;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import com.sun.org.apache.bcel.internal.generic.NEW;
public class SessionListener implements HttpSessionListener {
/**
* @desc 1.session創建的時候觸發
*/
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("Session 開始創建了:: ID="+se.getSession().getId());
ServletContext ctx = se.getSession( ).getServletContext( );
Integer numSessions = (Integer) ctx.getAttribute("numSessions");
if (numSessions == null) {
numSessions = new Integer(1);
}
else {
int count = numSessions.intValue( );
numSessions = new Integer(count + 1);
}
ctx.setAttribute("numSessions", numSessions);
}
/**
* @desc 2.session銷毀的時候觸發
*/
@Override
public void sessionDestroyed(HttpSessionEvent se)
{
System.out.println("Session 銷毀了:: ID="+se.getSession().getId());
ServletContext ctx=se.getSession().getServletContext();
Integer numSessions = (Integer)ctx.getAttribute("numSessions");
if(numSessions == null) {
numSessions = new Integer(0);
}
else {
int count = numSessions.intValue( );
numSessions = new Integer(count - 2);
}
ctx.setAttribute("numSessions", numSessions);
}
}`
4擴展:監聽器,過濾器,servlet的級別
【Listener】->【Filter】->【Servlet】
5.預加載實體
`package com.rj.bd.manage.listeners;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class MyLiceneListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("===============servlet服務初始化(也就是tomcat正式啟動成功)==================");
System.out.println("***************1.可以開始預加載一些資訊了****************");
ServletContext context = sce.getServletContext();
/**
* 1.可以預先加載連庫4要素
*/
Map<String, Object> map=new HashMap<String, Object>();
map.put("username", "root");
map.put("password", "root");
map.put("drivername", "com.mysql.jdbc.Driver");
map.put("url", "jdbc://..........");
context.setAttribute("map", map);
/**
* 2.也可以在這里實作注入....其實也就是Spring框架核心的注入的原理所在,,,,,(后續講)
*/
?
?
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("===============servlet服務銷毀(也就是tomcat重新部署)==================");
}
}`
6.Request請求監聽器記錄ip實體
`package com.rj.bd.manage.listeners;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
ServletRequest servletRequest = sre.getServletRequest();
System.out.println("ServletRequest destroyed. Remote IP="+servletRequest.getRemoteAddr());
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
ServletRequest servletRequest = sre.getServletRequest();
System.out.println("ServletRequest initialized. Remote IP="+servletRequest.getRemoteAddr());
}
}`
二、發送郵件
1.生成四位驗證碼實體
`public class CodeUtils {
public static void main(String[] args) {
for (int i = 0; i <10; i++) {
CodeUtils.createCode();
}
?
?
}
public static String createCode()
{
String[] beforeShuffle = new String[] { "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
List<String> list = Arrays.asList(beforeShuffle);
Collections.shuffle(list);//自動洗牌
StringBuilder sb =new StringBuilder();
for (int i = 0; i < list.size(); i++)
{
sb.append(list.get(i));
}
String afterShuffle = sb.toString();
String result = afterShuffle.substring(5, 9);
System.out .println(result) ;
return result;
}
}`
2.日期處理工具類
public class DateUtils {
/**
* 通過時間秒毫秒數判斷兩個時間的間隔
* @param date1
* @param date2
* @return
* @throws ParseException
*/
public static int differentDaysByMillisecond(String dateStr,String dateStr2) throws ParseException
{
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date fDate=format.parse(dateStr);
Date oDate=format.parse(dateStr2);
//初始化日歷工具類
Calendar aCalendar = Calendar.getInstance();
//設定開始的日期
aCalendar.setTime(fDate);
int day1 = aCalendar.get(Calendar.DAY_OF_YEAR);//DAY_OF_YEAR:一年的第多少天
//社情結束的日期
aCalendar.setTime(oDate);
int day2 = aCalendar.get(Calendar.DAY_OF_YEAR);
int days=day2-day1;
System.out.print(days);
return days;
}
public static void main(String[] args) throws ParseException {
String dateStr = "2019-11-26 ";
Date now=new Date();//獲取當前的日期
SimpleDateFormat dFormat=new SimpleDateFormat("yyyy-MM-dd");//對當前日期進行格式化處理
System.out.println("dateStr2:"+dFormat.format(now));
System.out.println("兩個日期的差距:" + differentDaysByMillisecond(dateStr,dFormat.format(now)));
}
}
3.properties組態檔處理類
1.創建一個config檔案夾,且該檔案夾與src是平級的,且權限也是與src的級別一樣(要構建權限級別),在該目錄下創建mail.properties
2.在mail.properties寫入一些資料
emailFrom=發送的郵箱
emialFromAuthorization=郵箱碼
emailRole=XX管理系統
PS:在mail,properties中要對該檔案設定編碼集為UTF-8,且不要再里面有過多的空格和換行
package com.rj.bd.prepar;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
public class PropertyUtils {
public static Map<String, Object> getyInfoOfPropert(String propertyPath) throws IOException
{
Map<String, Object> map=new HashMap<String, Object>();
Properties prop=new Properties();
InputStream inputFile=PropertyUtils.class.getClassLoader().getResourceAsStream(propertyPath);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputFile,"utf-8"));
prop.load(bufferedReader);
Iterator<String> it=prop.stringPropertyNames().iterator();
while(it.hasNext()){
String key=it.next();
System.out.println(key+":"+prop.getProperty(key));
map.put(key, prop.getProperty(key));
}
inputFile.close();
return map;
}
public static void main(String[] args) throws IOException {
PropertyUtils.getyInfoOfPropert("mail.properties");
}
}
4.補充講解
導讀模塊:1.日常作業生活中少不了和郵件打交道,比如我們會用郵件進行資訊交流,向上級匯報日常作業;再比如大家熟悉的某個WEB系統注冊階段,通常會有一個功能,點擊發送到目標郵箱的鏈接完成賬戶激活
2.開始之前先簡單介紹一下與郵件相關的一些協議
SMTP 協議
SMTP 的全稱是 Simple Mail Transfer Protocol,即簡單郵件傳輸協議,它是一組用于從源地址到目的地址傳輸郵件的規范,通過它來控制郵件的中轉方式
SMTP 協議屬于TCP/IP協議簇,它幫助每臺計算機在發送或中轉信件時找到下一個目的地,
SMTP 服務器就是遵循SMTP協議的發送郵件服務器
SMTP 認證,簡單地說就是要求必須在提供了賬戶名和密碼之后才可以登錄 SMTP 服務器,這就使得那些垃圾郵件的散播者無可乘之機
增加 SMTP 認證的目的是為了使用戶避免受到垃圾郵件的侵擾
實際上,SMTP 已經是E-mail傳輸的標準
SMTP 規范(RFC 821)規定,每一行都要以\r\n 來結尾
POP 協議
POP3(Post Office Protocol 3)即郵局協議的第3個版本,是因特網電子郵件的第一個離線協議標準
POP郵局協議負責從郵件服務器中檢索電子郵件
它要求郵件服務器完成下面幾種任務之一
從郵件服務器中檢索郵件并從服務器中洗掉這個郵件
從郵件服務器中檢索郵件但不洗掉它
不檢索郵件,只是詢問是否有新郵件到達
POP協議支持多用戶互聯網郵件擴展,后者允許用戶在電子郵件上附帶二進制檔案,如文字處理檔案和電子表格檔案等,實際上這樣就可以傳輸任何格式的檔案了,包括圖片和聲音檔案等
在用戶閱讀郵件時,POP命令所有的郵件資訊立即下載到用戶的計算機上,不在服務器上保留
IMAP 協議
互聯網資訊訪問協議(IMAP)是一種優于POP的新協議
和POP一樣,IMAP也能下載郵件、從服務器中洗掉郵件或詢問是否有新郵件,但IMAP克服了POP的一些缺點
它可以決定客戶機請求郵件服務器提交所收到郵件的方式,請求郵件服務器只下載所選中的郵件而不是全部郵件
客戶機可先閱讀郵件資訊的標題和發送者的名字再決定是否下載這個郵件
通過用戶的客戶機電子郵件程式,IMAP可讓用戶在服務器上創建并管理郵件檔案夾或郵箱、洗掉郵件、查詢某封信的一部分或全部內容,完成所有這些作業時都不需要把郵件從服務器下載到用戶的個人計算機上,
小結:不同的協議實作的功能的側重點不一樣
因為人們發的郵件不一樣,所以這些協議還是都要用的
3.我們今天要講的郵件發送并不是指從頭到尾的創造一整套的郵件發送系統,而是利用現有的郵件服務商例如網易或者騰訊作為我們廣義上的發送代理進而實作發送郵件
普通郵件發送
public class EmailUtils {
//自己的郵箱
public static String sendEmailAccount ="******@163.com";
//郵箱授權碼
public static String sendEmailPwd="***********";
//收件人郵箱
public static String receiveMailAccount="***********@qq.com";
public static void main(String[] args) throws Exception {
createMimeMessage( sendEmailAccount, receiveMailAccount);
?
?
?
?
}
/**
* 創建一封只包含文本的簡單郵件
*
* @param session 和服務器互動的會話
* @param sendMail 發件人郵箱
* @param receiveMail 收件人郵箱
* @return
* @throws Exception
*/
public static void createMimeMessage(String sendMail, String receiveMail) throws Exception {
// 1. 創建引數配置, 用于連接郵件服務器的引數配置
Properties props = new Properties();
props.setProperty("mail.transport.protocol","smtp");// 使用的協議(JavaMail規范要求)
props.setProperty("mail.smtp.host","smtp.163.com"); // 發件人的郵箱的 SMTP 服務器地址
props.setProperty("mail.smtp.auth", "true"); // 需要請求認證
// 2. 根據配置創建會話物件, 用于和郵件服務器互動
Session session = Session.getInstance(props);
session.setDebug(true); // 設定為debug模式, 可以查看詳細的發送 log
// 3. 創建一封郵件
MimeMessage message = new MimeMessage(session);
// 4. From: 發件人(昵稱有廣告嫌疑,避免被郵件服務器誤認為是濫發廣告以至回傳失敗,請修改昵稱)
message.setFrom(new InternetAddress(sendMail, "發件人的昵稱", "UTF-8"));
// 5. To: 收件人(可以增加多個收件人、抄送、密送)
// CC:抄送人,BCC:密送
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiveMail, "XX用戶", "UTF-8"));
//message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress("xxxx@qq.com", "XX用戶", "UTF-8"));
// 6. Subject: 郵件主題(標題有廣告嫌疑,避免被郵件服務器誤認為是濫發廣告以至回傳失敗,請修改標題)
message.setSubject("這是郵箱標題", "UTF-8");
// 7. Content: 郵件正文(可以使用html標簽)(內容有廣告嫌疑,避免被郵件服務器誤認為是濫發廣告以至回傳失敗,請修改發送內容)
message.setContent("正文...", "text/html;charset=utf-8");
// 8. 設定發件時間
message.setSentDate(new Date());
// 9. 保存設定
message.saveChanges();
// 10. 根據 Session 獲取郵件傳輸物件
Transport transport = session.getTransport();
// 郵箱賬號 和 密碼 連接郵件服務器, 這里認證的郵箱必須與 message 中的發件人郵箱一致, 否則報錯
// 5. 使用
//
// PS_01: 成敗的判斷關鍵在此一句, 如果連接服務器失敗, 都會在控制臺輸出相應失敗原因的 log,
// 仔細查看失敗原因, 有些郵箱服務器會回傳錯誤碼或查看錯誤型別的鏈接, 根據給出的錯誤
// 型別到對應郵件服務器的幫助網站上查看具體失敗原因,
//
// PS_02: 連接失敗的原因通常為以下幾點, 仔細檢查代碼:
// (1) 郵箱沒有開啟 SMTP 服務;
// (2) 郵箱密碼錯誤, 例如某些郵箱開啟了獨立密碼;
// (3) 郵箱服務器要求必須要使用 SSL 安全連接;
// (4) 請求過于頻繁或其他原因, 被郵件服務器拒絕服務;
// (5) 如果以上幾點都確定無誤, 到郵件服務器網站查找幫助,
//
// PS_03: 仔細看log, 認真看log, 看懂log, 錯誤原因都在log已說明,
//11.連接SMTP服務器
transport.connect(sendEmailAccount, sendEmailPwd);
// 12. 發送郵件, 發到所有的收件地址, message.getAllRecipients() 獲取到的是在創建郵件物件時添加的所有收件人, 抄送人, 密送人
transport.sendMessage(message,message.getAllRecipients());
// 13. 關閉連接
transport.close();
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/235473.html
標籤:java
上一篇:SpringBoot 微信支付V3介面圖片上傳工具類
下一篇:Spring(ioc和di)簡介
