servlet——三兄弟的另外两个:过滤器/监听器

过滤器

我们写多了servlet会发现,很多代码和功能是重复的,比如:解决中文乱码问题、权限验证、日志的记录等,他们的特点是:代码相同或相似、分散在不同位置、不利于维护。

过滤器就是他们的解决办法。

过滤器是请求到达目标之前的处理程序,也是响应离开服务器之前的处理程序。

我们可以定义多个过滤器来组成一个过滤器链,每个过滤器完成一个任务,请求和响应如图所示,依次经过过滤器,第一个过滤器最先被经过,离开时最后被经过。

这种设计使用了一个设计模式:责任链模式。

一个图秒懂

如图,功能类似的代码只有一份,便于维护。

我们如何使用过滤器呢?

1)开发过滤器类

2)指定过滤器过滤范围(有些请求不需要经过某些过滤器)

一共也就两个方法,非常简单,我们写一个解决中文乱码的过滤器吧:

public class EncodingFilter implements Filter{
       private String encoding;
       /**
        * 初始化操作,只执行一次
        */
       @Override
       public void init(FilterConfig config) throws ServletException {
               //先读取配置文件,获取编码类型
               encoding = config.getInitParameter("encoding");
               if(encoding == null){
                       encoding = "utf-8";
               }
               
       }
       /**
        * 相当于Servlet的service(),过滤范围的每次请求响应都经过
        */
       @Override
       public void doFilter(ServletRequest request,
                       ServletResponse response, FilterChain chain)
                       throws IOException, ServletException {
               //请求到达目标资源之前的预处理操作
               request.setCharacterEncoding(encoding);
               
               //调用下一个过滤器或者目标资源
               chain.doFilter(request, response);
               
               //响应离开服务器端之前的后处理操作(无)
               
       }
       /**
        * 销毁操作,只执行一次
        */
       @Override
       public void destroy() {
               // TODO Auto-generated method stub
               
       }

}

相关配置也和servlet类似(通过kv找到utf-8):

       <filter>
               <filter-name>EncodingFilter</filter-name>
               <filter-class>com.bjsxt.filter.EncodingFilter</filter-class>
               <init-param>
                       <param-name>encoding</param-name>
                       <param-value>utf-8</param-value>
               </init-param>
       </filter>

       <filter-mapping>
               <filter-name>EncodingFilter</filter-name>
               <url-pattern>/servlet/*</url-pattern>
       </filter-mapping>

我们再理解一下过滤器的执行过程:

代码中:

               //请求到达目标资源之前的预处理操作
            
               //调用下一个过滤器或者目标资源

               //响应离开服务器端之前的后处理操作(无)

一共有这么三个操作,而过滤器的执行过程就是如此的

化的很丑但是就是这个意思。

再写一下怎么搞过滤范围,也超简单直接上代码了:
 

public class AuthFilter implements Filter{

       @Override
       public void init(FilterConfig filterconfig) throws ServletException {
               // TODO Auto-generated method stub
               
       }
       /**
        * 过滤路径是  /servlet/*  *.jsp
        * 某些jsp应该排除在外   
        * 某些servlet应该排除在外
        */
       @Override
       public void doFilter(ServletRequest request,
                       ServletResponse response, FilterChain chain)
                       throws IOException, ServletException {
               HttpServletRequest httprequest = (HttpServletRequest)request;             
               String uri = httprequest.getRequestURI();
               
               int n1 =  uri.indexOf("login.jsp");//   >=0 存在
               int n2 =  uri.indexOf("register.jsp");
               int n3 = uri.indexOf("index.jsp");
               int n4 = -1;
               int n5 = -1;
               
               
               if(n1>=0 || n2>=0 ||n3>=0 ||n4>=0 ||n5>=0 ){ //假设是需要排除在外的资源
                       //放行
                       chain.doFilter(request, response);
               }else{//do something}
       }

       @Override
       public void destroy() {
               // TODO Auto-generated method stub
               
       }
}

监听器

监听器是一个实现特定接口的普通Java程序,这个程序专门用于监听另一个Java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行

超简单代码例子:

package listener;

import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
/**
* 记录每个请求的时间,客户端IP,URL地址到日志文件中
* @author Administrator
*
*/
public class LogListener implements ServletRequestListener,ServletRequestAttributeListener{
       /**
        * 请求结束了
        */
       @Override
       public void requestDestroyed(ServletRequestEvent servletrequestevent) {
               // TODO Auto-generated method stub
               
       }
       /**
        * 请求开始了
        * 其实对于图片、视频、音频、js、css也会有一个新的请求,所以也会被监听
        */
       @Override
       public void requestInitialized(ServletRequestEvent sre) {
               //获取要记录的每个请求的时间,客户端IP,URL地址
               Date now = new Date();
               HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
               
               String addr = request.getRemoteAddr();
               String url = request.getRequestURL().toString(); //http://127.0.0.1:8081/myservlet/servlet/UserServlet
               String qs = request.getQueryString();  //method=login
               //记录到日志文件中
               PrintWriter pw = null;
               try {
                       pw = new PrintWriter(new FileWriter("d:/requestlog.log", true));  //
                       
                       if(qs!= null){
                               pw.println("time="+now.toLocaleString()+",addr="+addr+",url="+url+"?"+qs);
                       }else{
                               pw.println("time="+now.toLocaleString()+",addr="+addr+",url="+url);
                       }                        
               } catch (FileNotFoundException e) {
                       e.printStackTrace();
               } catch (IOException e) {
                       e.printStackTrace();
               }finally{
                       pw.close();
               }
               
       }
       /**
        * request.setAttribute("error","用户名不能为空");
        *
        */
       @Override
       public void attributeAdded(
                       ServletRequestAttributeEvent servletrequestattributeevent) {
               // TODO Auto-generated method stub
               
       }
       /**
        *
        * request.removeAttribute("error");
        */
       @Override
       public void attributeRemoved(
                       ServletRequestAttributeEvent servletrequestattributeevent) {
               // TODO Auto-generated method stub
               
       }
       /**
        * request.setAttribute("error","用户名和密码错误");
        */
       @Override
       public void attributeReplaced(
                       ServletRequestAttributeEvent servletrequestattributeevent) {
               // TODO Auto-generated method stub
               
       }

}




       <listener>
               <listener-class>listener.LogListener</listener-class>
       </listener>

 

  • 186
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兔老大RabbitMQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值