Log4j&Filter&Listener

Log4j&Filter&Listener

日志管理


  • 背景

日志记录是应用程序运行中必不可少的一部分。具有良好格式和完备信息的日志记录可以在程序出现问题时帮助开发人员迅速地定位错误的根源

  • Log4J的使用方法
    • 导入包log4j-1.2.17.jar
    • 在资源文件下面创建一个log4j.properties
    • 使用Java代码实现日志的输出
  • 日志的级别

Log4J建议只使用四个级别,优先级从高到低分别是ERRORWARNINFODEBUG

  • 示例代码
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 ]

过滤器概述


  • WEB中的过滤器

WEB组件,在Java中最小的组件就是一个类(双向)

  • 特点

开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

简单说,就是可以实现Web容器对某个资源的访问前截获进行相关的处理,

还可以在某资源向Web容器返回响应前进行截获处理

  • Web中过滤器存在的意义
    • DRY不要重复自己
    • 责任分类:各自做自己擅长的事儿

过滤器操作和应用场景

实现Web容器对某资源的访问前截获进行相关处理,还可以在某资源向Web容器返回响应前进行截获处理

  • 过滤器能够实现的功能
    • 以常规的方式调用资源(访问servletJSP页面)
    • 利用修改过的请求信息调用资源
    • 利用资源,但在发送响应到浏览器之前对其进行修改
    • 阻止该资源调用,取而代之的是跳转到其他资源,返回一个特定的状态码
  • 应用场景
    • 可以对客户提交的数据进行重新编码req.setCharacterEndocing("UTF-8");
    • 使用浏览器不缓存页面的过滤器
    • 可以过滤掉客户的非法文字
    • 验证客户是否已经登录
    • 请求分发器(类似structs2)
    • 页面伪静态化处理(.jsp结尾的变成.html结尾)

Filter开发和使用

  • Filter的开发步骤
    • 创建一个类,实现Filter接口
    • 配置Filter(告诉Tomcat来管理Filter)
<filter>
  <filter-name>HelloFilter</filter-name>
  <filter-class>com.filter.HelloFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>HelloFilter</filter-name>
  <!-- 资源名称,指定要对那些资源进行过滤 -->
  <url-pattern>/hello</url-pattern>
</filter-mapping>

Filter的细节处理

  • 可以使用注解来配置Filter

但是使用注解来配置过滤器,就无法控制哪个过滤器先执行

  • FilterChainFilterConfig
String getFilterName() // 获取<filter-name>中的内容
String getInitParameter(String name) // 获取Filter中的初始化参数,解决硬编码
Enumeration getInitParameterNames() 
ServletContext getServletContext() // 获取当前应用对象
  • FilterCHain:过滤器链

注意:

请求的拦截操作应该在放行之前来实现

响应的拦截操作应该在放行之后来实现

请求编码过滤器

  • 示例代码
// 对请求参数的编码进行设置
public class CharacterEncodeingFilter implements Filter {
  // 编码
  private String encoding;
  // 判断是否要强制使用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 {
    // 设置请求参数的编码方式
    // 通常在程序中需要给编码一个默认值,在绝大多数情况下,我们不对其进行配置
    if (request.getCharacterEncoding() == null || force && StringUtils.hasLength(encoding)) {
      request.setCharacterEncoding(encoding);
    } else {
      // 设置默认码
      request.setCharacterEncoding("UTF-8");
    }
    chain.doFilter(request, response);
  }
}

登录验证过滤器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) {
              // 说明没有登录
              resp.sendRedirect(req.getContextPath() + "/login.jsp");
              return;
          }
          chain.doFilter(req, resp);
      }
  }

  /**
   * @see Filter#init(FilterConfig)
   */
  public void init(FilterConfig fConfig) throws ServletException {
      // 获取不需要验证的资源名称
      // 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(监听器)


  • 在JavaWeb中的监听器(对作用域对象的监听)
// 作用域对象的监听
// 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);

// 当服务器启动的时候执行该方法
  • 在作用域中属性监听器(对作用域对象属性变化的监听)
// 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);
  • 注册监听器
<listener>
  <listener-class></listener-class>
</listener>
  • 示例代码
public class MySessionAttributeListener implements HttpSessionAttributeListener {
  @Override
  public void attributeAdded(HttpSessionBindingEvent se) {
    System.out.println("添加共享数据");
  }
  
  @Override
  public void attributeRemoved(HttpSessionBindingEvent se) {
    System.out.println("删除共享数据");
  }
  
  @Override
  public void attributeReplaced(HttpSessionBindingEvent se) {
    System.out.println("修改共享数据");
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 46,724评论 6 342
  • Servlet过滤器是 Servlet 程序的一种特殊用法,主要用来完成一些通用的操作,如编码的过滤、判断用户的登...
    重山杨阅读 1,207评论 0 12
  • 监听器(listener) 监听器简介 :监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个...
    奋斗的老王阅读 2,481评论 0 53
  • 本文包括:1、Filter简介2、Filter是如何实现拦截的?3、Filter开发入门4、Filter的生命周期...
    廖少少阅读 7,247评论 3 56