Log4j&Filter&Listener
日志管理
- 背景
日志記錄是應(yīng)用程序運(yùn)行中必不可少的一部分蚂维。具有良好格式和完備信息的日志記錄可以在程序出現(xiàn)問(wèn)題時(shí)幫助開(kāi)發(fā)人員迅速地定位錯(cuò)誤的根源
-
Log4J
的使用方法- 導(dǎo)入包
log4j-1.2.17.jar
- 在資源文件下面創(chuàng)建一個(gè)
log4j.properties
- 使用
Java
代碼實(shí)現(xiàn)日志的輸出
- 導(dǎo)入包
- 日志的級(jí)別
Log4J
建議只使用四個(gè)級(jí)別刮萌,優(yōu)先級(jí)從高到低分別是ERROR
宙搬、WARN
斤贰、INFO
、DEBUG
- 示例代碼
private static Logger logger = Logger.getLogger(ProductServlet.class)
protected void delete(HttpServletRequest req, HttpServletResponse resp) throws Exception {
logger.debug("This is debug message.");
logger.error("This is error message.");
logger.info("This is info message.");
}
- log4j.properties(必須要確保文件被放到classes目錄下)
### \u8BBE\u7F6E###
log4j.rootLogger = debug,stdout,D,E
### \u8F93\u51FA\u4FE1\u606F\u5230\u63A7\u5236\u62AC ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### \u8F93\u51FADEBUG \u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\u5230=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.D.File = /logs/log.log
log4j.appender.D.Append = false
log4j.appender.D.Threshold = INFO
log4j.appender.D.layout = org.apache.log4j.HTMLLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### \u8F93\u51FAERROR \u7EA7\u522B\u4EE5\u4E0A\u7684\u65E5\u5FD7\u5230=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.E.File =/logs/error.log
log4j.appender.E.Append = false
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ]
過(guò)濾器概述
- WEB中的過(guò)濾器
WEB組件淆珊,在Java中最小的組件就是一個(gè)類(雙向)
- 特點(diǎn)
開(kāi)發(fā)人員可以實(shí)現(xiàn)用戶在訪問(wèn)某個(gè)目標(biāo)資源之前涮因,對(duì)訪問(wèn)的請(qǐng)求和響應(yīng)進(jìn)行攔截。
簡(jiǎn)單說(shuō)坷虑,就是可以實(shí)現(xiàn)
Web容器
對(duì)某個(gè)資源的訪問(wèn)前截獲進(jìn)行相關(guān)的處理甲馋,還可以在某資源向
Web容器
返回響應(yīng)前進(jìn)行截獲處理
-
Web
中過(guò)濾器存在的意義-
DRY
不要重復(fù)自己 - 責(zé)任分類:各自做自己擅長(zhǎng)的事兒
-
過(guò)濾器操作和應(yīng)用場(chǎng)景
實(shí)現(xiàn)
Web
容器對(duì)某資源的訪問(wèn)前截獲進(jìn)行相關(guān)處理,還可以在某資源向Web
容器返回響應(yīng)前進(jìn)行截獲處理
- 過(guò)濾器能夠?qū)崿F(xiàn)的功能
- 以常規(guī)的方式調(diào)用資源(訪問(wèn)
servlet
或JSP
頁(yè)面) - 利用修改過(guò)的請(qǐng)求信息調(diào)用資源
- 利用資源猖吴,但在發(fā)送響應(yīng)到瀏覽器之前對(duì)其進(jìn)行修改
-
阻止該資源調(diào)用
摔刁,取而代之的是跳轉(zhuǎn)到其他資源,返回一個(gè)特定的狀態(tài)碼
- 以常規(guī)的方式調(diào)用資源(訪問(wèn)
- 應(yīng)用場(chǎng)景
- 可以對(duì)客戶提交的數(shù)據(jù)進(jìn)行重新編碼
req.setCharacterEndocing("UTF-8");
- 使用瀏覽器不緩存頁(yè)面的過(guò)濾器
- 可以過(guò)濾掉客戶的非法文字
- 驗(yàn)證客戶是否已經(jīng)登錄
- 請(qǐng)求分發(fā)器(類似
structs2
) - 頁(yè)面?zhèn)戊o態(tài)化處理(.jsp結(jié)尾的變成.html結(jié)尾)
- 可以對(duì)客戶提交的數(shù)據(jù)進(jìn)行重新編碼
Filter
開(kāi)發(fā)和使用
-
Filter
的開(kāi)發(fā)步驟- 創(chuàng)建一個(gè)類海蔽,實(shí)現(xiàn)
Filter
接口 - 配置
Filter
(告訴Tomcat
來(lái)管理Filter
)
- 創(chuàng)建一個(gè)類海蔽,實(shí)現(xiàn)
<filter>
<filter-name>HelloFilter</filter-name>
<filter-class>com.filter.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HelloFilter</filter-name>
<!-- 資源名稱共屈,指定要對(duì)那些資源進(jìn)行過(guò)濾 -->
<url-pattern>/hello</url-pattern>
</filter-mapping>
Filter
的細(xì)節(jié)處理
- 可以使用注解來(lái)配置
Filter
但是使用注解來(lái)配置過(guò)濾器,就無(wú)法控制哪個(gè)過(guò)濾器先執(zhí)行
-
FilterChain
和FilterConfig
String getFilterName() // 獲取<filter-name>中的內(nèi)容
String getInitParameter(String name) // 獲取Filter中的初始化參數(shù),解決硬編碼
Enumeration getInitParameterNames()
ServletContext getServletContext() // 獲取當(dāng)前應(yīng)用對(duì)象
FilterCHain:過(guò)濾器鏈
注意:
對(duì)請(qǐng)求的攔截操作應(yīng)該在放行之前來(lái)實(shí)現(xiàn)
對(duì)響應(yīng)的攔截操作應(yīng)該在放行之后來(lái)實(shí)現(xiàn)
請(qǐng)求編碼過(guò)濾器
- 示例代碼
// 對(duì)請(qǐng)求參數(shù)的編碼進(jìn)行設(shè)置
public class CharacterEncodeingFilter implements Filter {
// 編碼
private String encoding;
// 判斷是否要強(qiáng)制使用web.xml中的編碼配置
private boolean force;
public void init(FilterConfig filterConfig) throws ServletException {
encoding = filterConfig.getInitParameter("encoding");
force = Boolean.valueOf(filterConfig.getInitParameter("force"));
}
protected void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
// 設(shè)置請(qǐng)求參數(shù)的編碼方式
// 通常在程序中需要給編碼一個(gè)默認(rèn)值党窜,在絕大多數(shù)情況下拗引,我們不對(duì)其進(jìn)行配置
if (request.getCharacterEncoding() == null || force && StringUtils.hasLength(encoding)) {
request.setCharacterEncoding(encoding);
} else {
// 設(shè)置默認(rèn)碼
request.setCharacterEncoding("UTF-8");
}
chain.doFilter(request, response);
}
}
登錄驗(yàn)證過(guò)濾器CheckLoginFilter
- 示例代碼
LoginCheckFilter
public class LoginCheckFilter implements Filter {
private String[] uris;
private String contextPath;
/**
* Default constructor.
*/
public LoginCheckFilter() {
// TODO Auto-generated constructor stub
}
/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// String uri = req.getRequestURI().substring(1);
String uri = req.getRequestURI();
if (Arrays.asList(uris).contains(uri)) {
chain.doFilter(req, resp);
} else {
Object user = req.getSession().getAttribute("USER_IN_SESSION");
if (user == null) {
// 說(shuō)明沒(méi)有登錄
resp.sendRedirect(req.getContextPath() + "/login.jsp");
return;
}
chain.doFilter(req, resp);
}
}
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// 獲取不需要驗(yàn)證的資源名稱
// login.jsp,login,randomCode
String notCheck = fConfig.getInitParameter("NOTCHECK");
contextPath = fConfig.getInitParameter("contextPath");
uris = notCheck.split(",");
for (int i = 0; i < uris.length; i++) {
uris[i] = contextPath + "/" + uris[i];
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
metadata-complete="false" version="3.0">
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com._520.pps.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>force</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>LoginCheckFilter</filter-name>
<filter-class>com._520.pps.web.filter.LoginCheckFilter</filter-class>
<init-param>
<param-name>NOTCHECK</param-name>
<param-value>login.jsp,login,randomCode</param-value>
</init-param>
<init-param>
<param-name>contextPath</param-name>
<param-value>/log4j-filter-listener</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>LoginCheckFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Listener(監(jiān)聽(tīng)器)
- 在JavaWeb中的監(jiān)聽(tīng)器(對(duì)作用域?qū)ο蟮谋O(jiān)聽(tīng))
// 作用域?qū)ο蟮谋O(jiān)聽(tīng)
// request--ServletRequestListener
void requestDestroyed(ServletRequestEvent sre);
void requestinitialized(ServletRequestEvent sre);
// session--HttpSessionListener
void sessionCreated(HttpSessionEvent se);
void sessionDestroyed(HttpSessionEvent se);
// application--ServletContextListener
void contextDestroyed(ServletContextEvent sce);
void contextInitalized(ServletContextEvent sce);
// 當(dāng)服務(wù)器啟動(dòng)的時(shí)候執(zhí)行該方法
- 在作用域中屬性監(jiān)聽(tīng)器(對(duì)作用域?qū)ο髮傩宰兓谋O(jiān)聽(tīng))
// ServletRequestAttributeListener
void attributeAdded(ServletRequestAttributeEvent srae);
void attributeRemoved(ServletRequestAttributeEvent srae);
void attributeReplaced(ServletRequestAttributeEvent srae);
// HttpSessionAttributeListener
void attributeAdded(HttpSessionBindingEvent se);
void attributeRemoved(HttpSessionBindingEvent se);
void attributeRepalced(HttpSessionBindingEvent se);
// ServletCOntextAttributeListener
void attributeAdded(ServletContextAttributeEvent scab);
void attributeRemoved(ServletContextAttributeEvent scab);
void attributeReplaced(ServletContextAttributeEvent scab);
- 注冊(cè)監(jiān)聽(tīng)器
<listener>
<listener-class></listener-class>
</listener>
- 示例代碼
public class MySessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent se) {
System.out.println("添加共享數(shù)據(jù)");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent se) {
System.out.println("刪除共享數(shù)據(jù)");
}
@Override
public void attributeReplaced(HttpSessionBindingEvent se) {
System.out.println("修改共享數(shù)據(jù)");
}
}