แยกวิเคราะห์คำขอ HTTP ด้วยตัวกรองบันทึก Java
javax.servlet.Filterวิธีที่สะดวกในการนำไปใช้และแยกวิเคราะห์เนื้อหาของคำขอ HTTP และบันทึกเอาต์พุตกรองแนะนำชั้นเรียน.
ตัวกรองบันทึกนี้ใช้ "java.util.logging.Logger" สำหรับเอาต์พุตบันทึก และคุณสามารถเปลี่ยนเอาต์พุตข้อมูลได้โดยการเปลี่ยนระดับการบันทึก
javax.servlet.Filter คืออะไร?
เมื่อสร้างเว็บแอปพลิเคชัน นอกเหนือจากการประมวลผลทางธุรกิจหลักแล้ว จำเป็นต้องดำเนินการประมวลผลรองทั่วไปก่อนและหลังการประมวลผลธุรกิจหลัก
ตัวอย่างเช่น การตรวจสอบสิทธิ์ไคลเอ็นต์ การตรวจสอบสิทธิ์ การบันทึก ฯลฯ
การเข้ารหัสการประมวลผลด้านข้างในแต่ละทรัพยากรกลายเป็นสาเหตุสำคัญในการขัดขวางการบำรุงรักษาซอฟต์แวร์ ส่งผลให้แอปพลิเคชันบำรุงรักษาได้ยาก
โดยทั่วไปแล้ว เมื่อใช้ javax.servlet.Filter คุณสามารถดำเนินการประมวลผลด้านนี้ได้ก่อนที่คำขอจะถูกส่งไปยังคลาสเซิร์ฟเล็ต
นอกจากนี้ เนื่องจากการตั้งค่าตัวกรองสามารถทำได้ใน web.xml คุณจึงเพิ่มหรือลบตัวกรองได้อย่างยืดหยุ่นโดยไม่ต้องเปลี่ยนซอร์สโค้ด
ลองใช้ตัวกรองบันทึก
ลองใช้ตัวกรองบันทึกเพื่อกรองคำขอ HTTP และวิเคราะห์คำขอเหล่านั้น
เวลานี้แมวตัวผู้เราจะใช้แอปพลิเคชันตัวอย่างที่มีอยู่ตั้งแต่ต้น
คุณสามารถเรียกใช้ตัวกรองนี้ได้ทันทีโดยทำการตั้งค่าต่อไปนี้
2. วางไฟล์คลาสที่คอมไพล์ไว้ใต้ "/examples/WEB-INF/classes"
3.ตั้งค่าคำจำกัดความต่อไปนี้ใน web.xml
LogFilter LogFilter การบันทึกระดับ ดี LogFilter /*
*รูปแบบ URL เมื่อใช้เฟรมเวิร์ก Struts เป็นดังนี้
*.ทำ
โปรดตรวจสอบผลลัพธ์บันทึกของการดำเนินการหน้าจอตัวอย่างเซสชัน
ข้อมูลบันทึกเอาต์พุตและระดับบันทึก
●บันทึกเนื้อหาเอาต์พุต
ข้อมูลบันทึก | ระดับบันทึก |
---|---|
ข้อมูลคุกกี้ | ดี |
ข้อมูลส่วนหัว HTTP | ดี |
HTTPข้อมูลอื่นๆ | ดี |
พารามิเตอร์คำขอ HTTP | กำหนดค่า |
ขอวัตถุขอบเขต | กำหนดค่า |
วัตถุที่มีขอบเขตเซสชัน | กำหนดค่า |
การใช้หน่วยความจำก่อนและหลังคำขอ | กำหนดค่า |
ข้อมูลการเปลี่ยนหน้าจอ | ข้อมูล |
วิธีที่ดีที่สุดคือใช้ระดับบันทึกดังต่อไปนี้
- FINE: ส่งออกบันทึกที่มีรายละเอียดมากที่สุด ตั้งค่านี้หากคุณต้องการวิเคราะห์คำขอ HTTP โดยละเอียด
- CONFIG... ส่งออกบันทึกที่มีรายละเอียดค่อนข้างมาก เป็นความคิดที่ดีที่จะรักษาระดับนี้ไว้ในช่วงระยะเวลาการพัฒนา
- INFO: ส่งออกเฉพาะข้อมูลการเปลี่ยนหน้าจอ
●วิธีการเปลี่ยนระดับบันทึก
คุณสามารถเปลี่ยนระดับเอาต์พุตของบันทึกได้โดยการตั้งค่าพารามิเตอร์การเริ่มต้น logging.Level
ตัวอย่าง:
การบันทึกระดับ ข้อมูล
รหัสแหล่งที่มา
นำเข้า javax.servlet.Filter;
นำเข้า javax.servlet.FilterChain;
นำเข้า javax.servlet.FilterConfig;
นำเข้า javax.servlet.ServletException;
นำเข้า javax.servlet.ServletRequest;
นำเข้า javax.servlet.ServletResponse;
นำเข้า javax.servlet.http.Cookie;
นำเข้า javax.servlet.http.HttpServletRequest;
นำเข้า javax.servlet.http.HttpServletResponse;
นำเข้า javax.servlet.http.HttpSession;
/**
* ใช้ javax.servlet.Filter เพื่อวิเคราะห์เนื้อหาของคำขอ HTTP และบันทึกเอาต์พุต
* คลาสตัวกรอง
*/
LogFilter คลาสสาธารณะใช้ตัวกรอง {
ตัวบันทึก Logger แบบคงที่ส่วนตัว =
Logger.getLogger(LogFilter.class.getName());
สตริงสุดท้ายคงที่ส่วนตัว LINE_SEPA =
System.getProperty("line.separator");
สตริงสุดท้ายแบบคงที่ส่วนตัว NEXT_PAGE = “LogFilter.NEXT_PAGE”;
/**
* เริ่มต้นตัวกรองบันทึกนี้
* การทำแผนที่ @param
*/
โมฆะสาธารณะ init (การแมป FilterConfig) {
สตริง str = mapping.getInitParameter("logging.Level");
System.out.println (“ตั้งค่าระดับบันทึกเป็น “+str+”.”);
ระดับระดับ = null;
พยายาม {
ระดับ = ระดับ.parse(str);
} จับ (ข้อยกเว้นจ) {
e.printStackTrace();
ระดับ = ระดับข้อมูล;
}
LogManager.getLogManager().รีเซ็ต();
ตัวจัดการตัวจัดการ = CustomConsoleHandler ใหม่ ();
handler.setFormatter (CustomFormatter ใหม่ ());
handler.setLevel (ระดับ);
logger.setLevel (ระดับ);
logger.getParent().addHandler(ตัวจัดการ);
}
/**
* นี่คือตัวกรองที่ส่งออกบันทึก
* @param ร้องขอคำขอ HTTP กำลังประมวลผล
* @param การตอบสนอง การตอบสนอง HTTP ที่ถูกสร้างขึ้น
* @param chain
*/
โมฆะสาธารณะ doFilter (ServletRequest _request, ServletResponse _response,
สายโซ่ FilterChain) พ่น IOException, ServletException {
// --------------------" กำลังประมวลผลล่วงหน้า "
คำขอ HttpServletRequest = (HttpServletRequest) _request;
การตอบสนอง HttpServletResponse = (HttpServletResponse) _response;
ถ้า (logger.isLoggable (ระดับ. CONFIG)) {
logger.config(
“============ เริ่มคำขอ!!”
+”รหัสเธรด:”
+ Thread.currentThread().hashCode()
+ ” ========================================================”);
}
// การใช้ความจำ
สตริง actionMemory = null;
ถ้า (logger.isLoggable (ระดับ. CONFIG)) {
actionMemory = getMemoryInfo(” ”
+ เวลาใหม่ (System.currentTimeMillis ()) + ” คำขอ [ก่อนหน้า]”);
}
ถ้า (logger.isLoggable (ระดับ FINE)) {
logger.fine(“ข้อมูลคุกกี้” + getCookieInfo(คำขอ));
}
ถ้า (logger.isLoggable (ระดับ FINE)) {
logger.fine("ข้อมูลส่วนหัว HTTP" + getHeadersInfo(คำขอ));
}
ถ้า (logger.isLoggable (ระดับ FINE)) {
คนตัดไม้
.fine(“ข้อมูล HTTP อื่น ๆ” + getRequestOtherInfo(คำขอ));
}
ถ้า (logger.isLoggable (ระดับ. CONFIG)) {
สตริง reqlog = getRequestParametersInfo (คำขอ);
logger.config (“พารามิเตอร์คำขอ HTTP” + reqlog);
}
ถ้า (logger.isLoggable (ระดับ. CONFIG)) {
logger.config(“วัตถุขอบเขตคำขอ”
+ getRequestAttributeInfo (คำขอ));
}
ถ้า (logger.isLoggable (ระดับ. CONFIG)) {
String sessionlog = getSessionInfo (คำขอ, จริง);
logger.config("วัตถุขอบเขตเซสชัน (ก่อนการประมวลผลคำขอ)"
+ บันทึกเซสชัน);
}
// เรียกตัวกรองถัดไป
chain.doFilter (คำขอ, ตอบกลับ);
// ———————————————————- “หลังการประมวลผล”
ถ้า (logger.isLoggable (ระดับ. CONFIG)) {
String sessionlog = getSessionInfo (คำขอ, เท็จ);
logger.config("วัตถุขอบเขตเซสชัน (หลังการประมวลผลคำขอ)"
+ บันทึกเซสชัน);
}
// การใช้ความจำ
ถ้า (logger.isLoggable (ระดับ. CONFIG)) {
actionMemory = ”การใช้หน่วยความจำก่อนและหลังคำขอ”+LINE_SEPA
+ actionMemory + LINE_SEPA
+ getMemoryInfo(” ” + เวลาใหม่ (System.currentTimeMillis())
+ ”คำขอ[หลัง]”);
logger.config(actionMemory+LINE_SEPA);
}
// ข้อมูลการเปลี่ยนหน้าจอ
ถ้า (logger.isLoggable (ระดับ.INFO)) {
สตริง nextPage = (สตริง) request.getAttribute(NEXT_PAGE);
ถ้า (หน้าถัดไป == null || หน้าถัดไปความยาว () == 0) {
หน้าถัดไป = request.getRequestURI();
}
logger.info(“NEXT_PAGE=[” + หน้าถัดไป + “], ”
+ “IP_ADDRESS=[” + request.getRemoteAddr() + “], ”
+ “SESSION_ID=[” + request.getSession().getId() + “], ”
+ “USER-AGENT=[” + request.getHeader(“user-agent”) + “]”);
}
ถ้า (logger.isLoggable (ระดับ. CONFIG)) {
logger.config(
“============ สิ้นสุดคำขอ!!”
+”รหัสเธรด:”+ Thread.currentThread().hashCode()
+ ” =========================================================”
+LINE_SEPA+LINE_SEPA);
}
}
/**
*
*/
โมฆะสาธารณะทำลาย () {
}
// ーーーーーーーーーーー วิธีการส่วนตัวด้านล่าง
getMemoryInfo สตริงคงที่ส่วนตัว (ข้อความสตริง) {
DecimalFormat dFromat = รูปแบบทศนิยมใหม่ (“#,###KB”);
ฟรียาว = Runtime.getRuntime().freeMemory() / 1024;
รวมยาว = Runtime.getRuntime().totalMemory() / 1024;
ยาวสูงสุด = Runtime.getRuntime().maxMemory() / 1024;
ใช้นาน = ทั้งหมด – ฟรี;
ข้อความสตริง = ข้อความ + ” : ” + “total=” + dFromat.format(total) + “, ”
+ “จำนวนที่ใช้แล้ว=” + dFromat.format(ใช้แล้ว) + ” (” + (ใช้แล้ว * 100 / ทั้งหมด)
+ “%) สูงสุดที่มีอยู่=” + dFromat.format(สูงสุด);
กลับข้อความ;
}
/**
* ส่งออกส่วนหัวคำขอทั้งหมดไปยังบันทึก
*/
สตริงคงที่ส่วนตัว getHeadersInfo (คำขอ HttpServletRequest) {
บัฟ StringBuffer = StringBuffer ใหม่ (LINE_SEPA);
การแจงนับ headerNames = request.getHeaderNames();
ในขณะที่ (headerNames.hasMoreElements()) {
สตริง headerName = (สตริง) headerNames.nextElement();
buff.ผนวก(” “);
buff.append(ชื่อส่วนหัว);
buff.ผนวก(“=”);
buff.append(request.getHeader(ชื่อส่วนหัว));
buff.ผนวก(LINE_SEPA);
}
กลับ buff.toString();
}
สตริงคงที่ส่วนตัว getCookieInfo (คำขอ HttpServletRequest) {
บัฟ StringBuffer = StringBuffer ใหม่ ();
คุกกี้[] คุกกี้ = request.getCookies();
ถ้า (คุกกี้ == null) {
กลับ "";
}
สำหรับ (int i = 0; i < Cookies.length; i++) {
buff.append(“\n — คุกกี้[” + i + “] —\n”);
buff.ผนวก(” “);
buff.append(คุกกี้[i].getName());
buff.ผนวก(“=”);
buff.append(คุกกี้[i].getValue());
buff.ผนวก(LINE_SEPA);
buff.ผนวก(” “);
buff.append(“getVersion()”);
buff.ผนวก(“=”);
buff.append(คุกกี้[i].getVersion());
buff.ผนวก(LINE_SEPA);
buff.ผนวก(” “);
buff.append(“getComment()”);
buff.ผนวก(“=”);
buff.append(คุกกี้[i].getComment());
buff.ผนวก(LINE_SEPA);
buff.ผนวก(” “);
buff.append(“getDomain()”);
buff.ผนวก(“=”);
buff.append(คุกกี้[i].getDomain());
buff.ผนวก(LINE_SEPA);
buff.ผนวก(” “);
buff.append(“getMaxAge()”);
buff.ผนวก(“=”);
buff.append(คุกกี้[i].getMaxAge());
buff.ผนวก(LINE_SEPA);
buff.ผนวก(” “);
buff.append(“getPath()”);
buff.ผนวก(“=”);
buff.append(คุกกี้[i].getPath());
buff.ผนวก(LINE_SEPA);
buff.ผนวก(” “);
buff.append(“getSecure()”);
buff.ผนวก(“=”);
buff.append(คุกกี้[i].getSecure());
buff.ผนวก(LINE_SEPA);
}
กลับ buff.toString();
}
สตริงคงที่ส่วนตัว getRequestParametersInfo (คำขอ HttpServletRequest) {
บัฟ StringBuffer = StringBuffer ใหม่ (LINE_SEPA);
แผนที่ แผนที่ = แปลงคำขอ (คำขอ);
TreeMap trr = TreeMap ใหม่ (แผนที่);
ตัววนซ้ำ itr = trr.keySet().ตัววนซ้ำ();
ในขณะที่ (itr.hasNext()) {
คีย์สตริง = (สตริง) itr.next();
buff.ผนวก(” “);
buff.append (คีย์);
buff.ผนวก(“=”);
ค่าวัตถุ = map.get (คีย์);
ค่าสตริง [] = ค่า (สตริง []);
ถ้า (values.length == 1) {
buff.append(ค่า[0]);
} อื่น {
// อาร์เรย์สตริงถูกแปลง
สตริง strValue = ชั้น (ค่า);
buff.ผนวก(strValue);
}
buff.ผนวก(LINE_SEPA);
}
กลับ buff.toString();
}
สตริงคงที่ส่วนตัว getRequestAttributeInfo (คำขอ HttpServletRequest) {
บัฟ StringBuffer = StringBuffer ใหม่ (LINE_SEPA);
การแจงนับ e = request.getAttributeNames();
ในขณะที่ (e.hasMoreElements()) {
ชื่อสตริง = (สตริง) e.nextElement();
buff.append(” ชื่อ=” + ชื่อ + “, คุณลักษณะClass=”
+ request.getAttribute(ชื่อ).getClass().getName()
+ “, toString() = ” + request.getAttribute(ชื่อ)
+ LINE_SEPA);
}
กลับ buff.toString();
}
สตริงคงที่ส่วนตัว getRequestOtherInfo (คำขอ HttpServletRequest) {
บัฟ StringBuffer = StringBuffer ใหม่ ();
buff.ผนวก(LINE_SEPA);
buff.append(”getCharacterEncoding()=”);
buff.append(request.getCharacterEncoding());
buff.ผนวก(LINE_SEPA);
buff.append(”getContentLength()=”);
buff.append(request.getContentLength());
buff.ผนวก(LINE_SEPA);
buff.append(”getContentType()=”);
buff.append(request.getContentType());
buff.ผนวก(LINE_SEPA);
buff.append(”getLocale()=”);
buff.append(request.getLocale());
buff.ผนวก(LINE_SEPA);
buff.append(”getProtocol()=”);
buff.append(request.getProtocol());
buff.ผนวก(LINE_SEPA);
buff.append(”getRemoteAddr()=”);
buff.append(request.getRemoteAddr());
buff.ผนวก(LINE_SEPA);
buff.append(”getRemoteHost()=”);
buff.append(request.getRemoteHost());
buff.ผนวก(LINE_SEPA);
buff.append(”getScheme()=”);
buff.append(request.getScheme());
buff.ผนวก(LINE_SEPA);
buff.append(”getServerName()=”);
buff.append(request.getServerName());
buff.ผนวก(LINE_SEPA);
buff.append(”getServerPort()=”);
buff.append(request.getServerPort());
buff.ผนวก(LINE_SEPA);
buff.append(”isSecure()=”);
buff.append(คำขอ.isSecure());
buff.ผนวก(LINE_SEPA);
buff.append(”getAuthType()=”);
buff.append(request.getAuthType());
buff.ผนวก(LINE_SEPA);
buff.append(”getContextPath()=”);
buff.append(request.getContextPath());
buff.ผนวก(LINE_SEPA);
buff.append(”getMethod()=”);
buff.append(request.getMethod());
buff.ผนวก(LINE_SEPA);
buff.append(”getPathInfo()=”);
buff.append(request.getPathInfo());
buff.ผนวก(LINE_SEPA);
buff.append(”getPathTranslated()=”);
buff.append(request.getPathTranslated());
buff.ผนวก(LINE_SEPA);
buff.append(”getQueryString()=”);
buff.append(request.getQueryString());
buff.ผนวก(LINE_SEPA);
buff.append(”getRemoteUser()=”);
buff.append(request.getRemoteUser());
buff.ผนวก(LINE_SEPA);
buff.append(”getRequestedSessionId()=”);
buff.append(request.getRequestedSessionId());
buff.ผนวก(LINE_SEPA);
buff.append(”getRequestURI()=”);
buff.append(request.getRequestURI());
buff.ผนวก(LINE_SEPA);
buff.append(”getServletPath()=”);
buff.append(request.getServletPath());
buff.ผนวก(LINE_SEPA);
buff.append(”getUserPrincipal()=”);
buff.append(request.getUserPrincipal());
buff.ผนวก(LINE_SEPA);
buff.append(”isRequestedSessionIdFromCookie()=”);
buff.append(request.isRequestedSessionIdFromCookie());
buff.ผนวก(LINE_SEPA);
buff.append(”isRequestedSessionIdFromURL()=”);
buff.append(request.isRequestedSessionIdFromURL());
buff.ผนวก(LINE_SEPA);
buff.append(”isRequestedSessionIdValid()=”);
buff.append(request.isRequestedSessionIdValid());
buff.ผนวก(LINE_SEPA);
กลับ buff.toString();
}
สตริงคงที่ส่วนตัว getSessionInfo (คำขอ HttpServletRequest, บูลีนก่อน) {
เซสชัน HttpSession = request.getSession();
บัฟ StringBuffer = StringBuffer ใหม่ ();
buff.ผนวก(LINE_SEPA);
ถ้า (ก่อน) {
buff.append(” session.isNew() = ” + session.isNew());
buff.ผนวก(LINE_SEPA);
buff.append(” session.getId() = ” + session.getId());
buff.ผนวก(LINE_SEPA);
}
การแจงนับ e = session.getAttributeNames();
ในขณะที่ (e.hasMoreElements()) {
สตริง sessionName = (สตริง) e.nextElement();
สตริง sessionClassName = session.getAttribute (sessionName)
.getClass().getName();
buff.append(” name =” + sessionName + “, value =”
+ session.getAttribute(ชื่อเซสชัน) + “, คุณลักษณะClass = ”
+ sessionClassName+LINE_SEPA);
}
กลับ buff.toString();
}
คำขอแปลง Hashtable แบบคงที่ส่วนตัว (คำขอ HttpServletRequest) {
Hashtable tempHash = ใหม่ Hashtable();
การแจงนับ e = request.getParameterNames();
ในขณะที่ (e.hasMoreElements()) {
คีย์สตริง = (สตริง) e.nextElement();
ค่าสตริง [] = request.getParameterValues (คีย์);
String[] parameterValues = สตริงใหม่ [values.length];
สำหรับ (int i = 0; i <values.length; i++) {
ค่าพารามิเตอร์ [i] = convUnicode (ค่า [i]);
}
tempHash.put (คีย์, ค่าพารามิเตอร์);
}
กลับ tempHash;
}
ชั้นสตริงคงที่ส่วนตัว (ค่าวัตถุ) {
ถ้า (ค่า == null) {
ส่งคืน "โมฆะ";
} อื่นถ้า (ค่าอินสแตนซ์ของสตริง []) {
กลับค่า convString ((สตริง []));
} อื่น {
ส่งคืนค่า.toString();
}
}
/**
* ส่งกลับเนื้อหาของอาร์เรย์สตริง [strArray] เป็นสตริงเหมือนกับที่แสดงด้านล่าง
* "[temp1,temp2,temp3]"
* @param strArray อาร์เรย์สตริงที่จะประเมิน
* @return String หลังการแปลง
*/
convString สตริงคงที่ส่วนตัว (สตริง [] strArray) {
ถ้า (strArray == null)
กลับเป็นโมฆะ;
บัฟ StringBuffer = StringBuffer ใหม่ (“[“);
สำหรับ (int i = 0; i < strArray.length; i++) {
buff.append(strArray[i] + “, “);
}
buff.delete(บัฟความยาว() – 2, ความยาวบัฟ());
buff.ผนวก(“]”);
กลับ buff.toString();
}
/**
* แปลง [str] เป็น Unicode
* @param str
* @กลับ
*/
convUnicode สตริงคงที่ส่วนตัว (String str) {
ถ้า (str == null)
กลับเป็นโมฆะ;
พยายาม {
คืนสตริงใหม่ (str.getBytes (“8859_1”), “JISAutoDetect”);
} จับ (UnsupportedEncodingException e) {
โยน RuntimeException ใหม่ (e);
}
}
// ———————————————————————–
CustomFormatter คลาสคงที่ขยายตัวจัดรูปแบบ {
รูปแบบสตริงสุดท้ายคงที่ = “yyyy/MM/dd HH:mm:ss”;
รูปแบบสตริงที่ซิงโครไนซ์สาธารณะ (บันทึก LogRecord) {
StringBuffer buf = StringBuffer ใหม่ ();
//ตั้งวันที่และเวลา
วันที่ วันที่ = วันที่ใหม่ ();
date.setTime(record.getMillis());
ตัวจัดรูปแบบ SimpleDateFormat = SimpleDateFormat ใหม่ (รูปแบบ);
buf.append(formatter.format(วันที่));
buf.ผนวก(“:”);
// กำหนดระดับ
buf.append(“[” + record.getLevel().getName() + “]”);
buf.ผนวก(“:”);
buf.ผนวก(record.getMessage());
buf.ผนวก(LINE_SEPA);
กลับ buf.toString();
}
}
CustomConsoleHandler คลาสคงที่ขยาย StreamHandler {
CustomConsoleHandler สาธารณะ () {
ซุปเปอร์();
setOutputStream (System.out);
}
/**
* ออก LogRecord
* เริ่มแรก คำขอบันทึกจะถูกส่งไปยังออบเจ็กต์ Logger
* และวัตถุนี้จะเริ่มต้น LogRecord และ
*เปลี่ยนเส้นทางที่นี่
*
* @param record คำอธิบายเหตุการณ์บันทึก บันทึกที่เป็นโมฆะจะถูกละเว้น
* และจะไม่มีการส่งการแจ้งเตือน
*/
โมฆะสาธารณะเผยแพร่ (บันทึก LogRecord) {
super.publish(บันทึก);
ล้าง();
}
/**
* แทนที่ StreamHandler.close เพื่อล้าง แต่
* สตรีมเอาท์พุตไม่ได้ปิด กล่าวอีกนัยหนึ่ง System.err ไม่ได้ถูกปิด
*/
โมฆะสาธารณะปิด () {
ล้าง();
}
}
}