当前位置: 澳门新濠3559 > 编程 > 正文

澳门新濠3559:Java的过滤器能够为我们提供系统级

时间:2019-10-06 23:49来源:编程
FilterRegistrationBean方式 FilterRegistrationBean 是 springboot 提供的,此类提供setOrder方法,可以为filter设置排序值,让spring在注册webfilter之前排序后再依次注册。 改写filter 其实就输出了@webFil

FilterRegistrationBean方式

FilterRegistrationBeanspringboot提供的,此类提供setOrder方法,可以为filter设置排序值,让spring在注册web filter之前排序后再依次注册。

改写filter

其实就输出了@webFilter注解即可。其他的都没有变化。

启动类中利用@bean注册FilterRegistrationBean

@Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean registration = new FilterRegistrationBean(); //当过滤器有注入其他bean类时,可直接通过@bean的方式进行实体类过滤器,这样不可自动注入过滤器使用的其他bean类。 //当然,若无其他bean需要获取时,可直接new CustomFilter(),也可使用getBean的方式。 registration.setFilter(customFilter; //过滤器名称 registration.setName("customFilter"); //拦截路径 registration.addUrlPatterns; //设置顺序 registration.setOrder; return registration; } @Bean public Filter customFilter() { return new CustomFilter(); }

注册多个时,就注册多个FilterRegistrationBean即可

启动后,效果和第一种是一样的。

澳门新濠3559 1image

Listeeshi是servlet规范中定义的一种特殊类。用于监听servletContext、HttpSession和servletRequest等域对象的创建和销毁事件。监听域对象的属性发生修改的事件。用于在事件发生前、发生后做一些必要的处理。一般是获取在线人数等业务需求。

创建一个ServletRequest监听器(其他监听器类似创建)

@WebListener@Slf4jpublic class Customlister implements ServletRequestListener{ @Override public void requestDestroyed(ServletRequestEvent sre) { log.info; } @Override public void requestInitialized(ServletRequestEvent sre) { log.info("监听器:初始化"); }}

和创建过滤器一样,在启动类中加入@ServletComponentScan进行自动注册即可。

澳门新濠3559 2启动控制台

以上的过滤器、监听器都属于Servlet的api,我们在开发中处理利用以上的进行过滤web请求时,还可以使用Spring提供的拦截器(HandlerInterceptor)进行更加精细的控制。

编写自定义拦截器类

@Slf4jpublic class CustomHandlerInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info("preHandle:请求前调用"); //返回 false 则请求中断 return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("postHandle:请求后调用"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("afterCompletion:请求调用完成后回调方法,即在视图渲染完成后回调"); }}

通过继承WebMvcConfigurerAdapter注册拦截器

@Configurationpublic class WebMvcConfigurer extends WebMvcConfigurerAdapter{ @Override public void addInterceptors(InterceptorRegistry registry) { //注册拦截器 拦截规则 //多个拦截器时 以此添加 执行顺序按添加顺序 registry.addInterceptor(getHandlerInterceptor.addPathPatterns; } @Bean public static HandlerInterceptor getHandlerInterceptor() { return new CustomHandlerInterceptor(); }}

启动后,访问某个url,控制台输出

澳门新濠3559 3控制台澳门新濠3559 4转至互联网

在整个请求的过程,此一图胜千言,希望对此有个深刻的了解,通过不同组合实现不同的业务功能。

本章节主要介绍了常用web开发时,会用到的一些常用类,本章节对servlet未进行介绍,平时用的比较少,用法和配置其实和拦截器、监听器是类似的,再次就不阐述了。

目前互联网上很多大佬都有SpringBoot系列教程,如有雷同,请多多包涵了。本文是作者在电脑前一字一句敲的,每一步都是实践的。若文中有所错误之处,还望提出,谢谢。

  • 个人QQ:499452441
  • 微信公众号:lqdevOps

澳门新濠3559 5公众号

个人博客:

完整实例地址:chapter-7

 

过滤器实例

package com.boolib.filter;

import com.boolib.model.User;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class LoginFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if(!(request.getRequestURL().toString().endsWith("/")||request.getRequestURL().toString().endsWith("/login")||request.getRequestURL().toString().endsWith("/register")))
        {
            System.out.println("进入拦截器");
            User user =  (User)request.getSession().getAttribute("user");

            if(user==null)
            {
                System.out.println("session==null 重定向");
                response.sendRedirect("/login");
            }

            System.out.println("session有值 继续跳转");
            filterChain.doFilter(request,response);

        }
        System.out.println("不满足条件 继续跳转");
        filterChain.doFilter(request,response);
    }
}

2.用于监听用户会话对象(HttpSession)的事件监听器

在实际开发过程中,经常会碰见一些比如系统启动初始化信息、统计在线人数、在线用户数、过滤敏高词汇、访问权限控制等业务需求。这些对于业务来说一般上是无关的,业务方是无需关系的,业务只需要关系自己内部业务的事情。所以一般上实现以上的功能,都会或多或少的用到今天准备讲解的过滤器监听器拦截器来实现以上功能。

过滤器Filter,是Servlet的的一个实用技术了。可通过过滤器,对请求进行拦截,比如读取session判断用户是否登录、判断访问的请求URL是否有访问权限等。主要还是可对请求进行预处理。接下来介绍下,在springboot如何实现过滤器功能。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
//这个就是扫描相应的Servlet包;
@ServletComponentScan
public class SiteConfig {

    public static void main(String[] args) {
        SpringApplication.run(SiteConfig.class, args);
    }

}

web.xml配置

你可以在java代码中定义拦截请求,也可以在xml中定义拦截请求

 <filter>
    <filter-name>LoginAuth</filter-name>
    <filter-class>com.boolib.filter.LoginFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>LoginAuth</filter-name>
   <servlet-name>ssm</servlet-name>
  </filter-mapping>

2.拦截器(Interceptor):java里的拦截器提供的是非系统级别的拦截,也就是说,就覆盖面来说,拦截器不如过滤器强大,但是更有针对性。
Java中的拦截器是基于Java反射机制实现的,更准确的划分,应该是基于JDK实现的动态代理。它依赖于具体的接口,在运行期间动态生成字节码。
拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其
执行,同时也提供了一种可以提取Action中可重用部分代码的方式。在AOP中,拦截器用于在某个方法或者字段被访问之前,进行拦截然后再之前或
者之后加入某些操作。java的拦截器主要是用在插件上,扩展件上比如 Hibernate Spring Struts2等,有点类似面向切片的技术,在用之前先要在配置文件即xml,文件里声明一段的那个东西。

拦截器

利用WebFilter注解配置

@WebFilterServlet3.0新增的注解,原先实现过滤器,需要在web.xml中进行配置,而现在通过此注解,启动启动时会自动扫描自动注册。

编写Filter类:

//注册器名称为customFilter,拦截的url为所有@WebFilter(filterName="customFilter",urlPatterns={"/*"})@Slf4jpublic class CustomFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("filter 初始化"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub log.info("doFilter 请求处理"); //对request、response进行一些预处理 // 比如设置请求编码 // request.setCharacterEncoding; // response.setCharacterEncoding; //TODO 进行业务逻辑 //链路 直接传给下一个过滤器 chain.doFilter(request, response); } @Override public void destroy() { log.info("filter 销毁"); }}

然后在启动类加入@ServletComponentScan注解即可。

@SpringBootApplication@ServletComponentScan@Slf4jpublic class Chapter7Application { public static void main(String[] args) { SpringApplication.run(Chapter7Application.class, args); log.info("chapter7 服务启动"); }}

启动后,控制台输出:

澳门新濠3559 6image

过滤器已经生效了。但当注册多个过滤器时,无法指定执行顺序的,原本使用web。xml配置过滤器时,是可指定执行顺序的,但使用@WebFilter时,没有这个配置属性的,所以接下来介绍下通过FilterRegistrationBean进行过滤器的注册。

--小技巧--(2018-08-25修订)

  1. 通过过滤器的java类名称,进行顺序的约定,比如LogFilterAuthFilter,此时AuthFilter就会比LogFilter先执行,因为首字母AL前面。

可查看具体原因:《关于@webFilter使用@Order无效问题》

也可以通过实现ServletContextInitializer接口直接注册。
二、在SpringBootApplication上使用@ServletComponentScan注解后,Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。
通过代码注册Servlet示例代码:

HandlerInterceptor

  public interface HandlerInterceptor {

   /**
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
   */
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

   /**
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
   */
    void postHandle(
            HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
            throws Exception;

   /**
    * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
   */
    void afterCompletion(
            HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception;

}

拦截器原理

 

5:监听request的属性的增加、删除、属性值变化的ServletRequestAttributeListener

澳门新濠3559 7

image.png

调用目标资源之后,让一段代码执行。

使用注解注册Servlet示例代码

3:监听web上下文属性的增加、删除、属性值变化的ServletContextAttributeListener

澳门新濠3559 8

image.png

4.编写监听器需要实现相应的接口

根据输出可以了解拦截器链的执行顺序(具体原理介绍,大家找度娘一问便知)
最后强调一点:只有经过DispatcherServlet 的请求,才会走拦截器链,我们自定义的Servlet 请求是不会被拦截的,比如我们自定义的Servlet地址 是不会被拦截器拦截的。并且不管是属于哪个Servlet 只要符合过滤器的过滤规则,过滤器都会拦截。

Spring下的拦截器

package com.boolib.Handler;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @description 利用spring框架提供的HandlerInterceptorAdapter,实现自定义拦截器
 */
public class UserLoginInterceptorBySpring extends HandlerInterceptorAdapter {


    /**
     *  在业务处理器处理请求之前被调用
     *
     * 预处理回调方法,实现处理器的预处理(如检查登陆),第三个参数为响应的处理器,自定义Controller
     * 返回值:true表示继续流程(如调用下一个拦截器或处理器);false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
     */


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("preHandle   之后执行");
        // equalsIgnoreCase 与 equals的区别?
        if("GET".equalsIgnoreCase(request.getMethod())){
            //RequestUtil.saveRequest();
        }
        System.out.println("preHandle...");
        String requestUri = request.getRequestURI();
        String contextPath = request.getContextPath();
        String url = requestUri.substring(contextPath.length());
        //获取URL请求
        System.out.println("requestUri"   requestUri);
        System.out.println("contextPath"   contextPath);
        System.out.println("url"   url);
        String username = (String) request.getSession().getAttribute("username");

        return super.preHandle(request, response, handler);
    }


    /**
     *  在业务处理器处理请求完成之后,生成视图之前执行
     *
     * 后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle   之后执行");
        super.postHandle(request, response, handler, modelAndView);
    }


    /**
     * 在DispatcherServlet完全处理完请求之后被调用,可用于清理资源
     *
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("所有执行之后执行");

        super.afterCompletion(request, response, handler, ex);
    }
}

1.背景介绍

配置拦截器

流程

1、拦截器执行顺序是按照Spring配置文件中定义的顺序而定的。

2、会先按照顺序执行所有拦截器的preHandle方法,一直遇到return false为止,比如第二个preHandle方法是return false,则第三个以及以后所有拦截器都不会执行。若都是return true,则按顺序加载完preHandle方法。

3、然后执行主方法(自己的controller接口),若中间抛出异常,则跟return false效果一致,不会继续执行postHandle,只会倒序执行afterCompletion方法。

4、在主方法执行完业务逻辑(页面还未渲染数据)时,按倒序执行postHandle方法。若第三个拦截器的preHandle方法return false,则会执行第二个和第一个的postHandle方法和afterCompletion(postHandle都执行完才会执行这个,也就是页面渲染完数据后,执行after进行清理工作)方法。(postHandle和afterCompletion都是倒序执行)

post和after是倒序的!!!!

==========================================1================================================
==========================================2================================================
==========================================3================================================
==========================================post3================================================
==========================================post2================================================
==========================================post1================================================
==========================================after3================================================
==========================================after2================================================
==========================================after1========================================

2.知识剖析

在启动类中进行扫描

应用场景

1、日志记录,可以记录请求信息的日志,以便进行信息监控、信息统计等。
2、权限检查:如登陆检测,进入处理器检测是否登陆,如果没有直接返回到登陆页面。
3、性能监控:典型的是慢日志。

监听器

 

2:监听web上下文的初始化(服务器已准备好接收请求)与销毁的ServletContextListener

澳门新濠3559 9

image.png

BY : 魏振恒

第二个拦截器

在Servlet3.0中,监听器的配置可以直接在代码中通过注释来完成,无需在web.xml中再配置。只需要在类头上添加@WebListener 注解

常用监听器
除了上面监听session建立与销毁的listener外,还有以下几个常用的监听器。

servlet 规范中为每种事件监听器都定义了相应的接口,在编写事件监听器程序时只需实现这些接口就可以了。一些Servlet事件监听器需要在web应用程序的部署 文件描述符文件中进行注册,一个web.xml可以注册多个servlet事件监听器。web服务器按照它们在web.xml中注册顺序来加载和注册这些servlet事件监听器。servlet事件监听器的注册和调用过程都是由web容器自动完成的,当发生被监听对象被创建,修改,销毁等事件时,web容器将调用与之相关的servlet事件监听器对象的相应方法(所监听到的对象如果在创建、修改、销毁事件触发的时候就会调用这些监听器这就相当于面向事件编程的概念),用户在这些方法中编写的事件处理代码(相当于JS中的事件响应)即被执行。由于在一个web应用程序中只会为每个事件监听器类创建一个实例对象,有可能出现多个线程同时调用一个事件监听对象的情况,所以要注意多线程安全问题。

ServletContext监听器(Listener)文件

Spring HandlerInterceptor与HandlerInterceptorAdapter

拦截器适配器HandlerInterceptorAdapter
有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现,不管你需不需要,此时spring提供了一个HandlerInterceptorAdapter适配器(种适配器设计模式的实现),允许我们只实现需要的回调方法。

分享人:魏振恒

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // 多个拦截器组成一个拦截器链

        // addPathPatterns 用于添加拦截规则

        // excludePathPatterns 用户排除拦截

        registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**");

        registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**");

        super.addInterceptors(registry);

    }
}

过滤器,拦截器,监听器对比

澳门新濠3559 10

image.png

1.过滤器(Filter):所谓过滤器顾名思义是用来过滤的,Java的过滤器能够为我们提供系统级别的过滤,也就是说,能过滤所有的web请求,
这一点,是拦截器无法做到的。在Java Web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或
者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者struts
的action前统一设置字符集,或者去除掉一些非法字符(聊天室经常用到的,一些骂人的话)。filter 流程是线性的,url传来之后,检查之后,
可保持原来的流程继续向下执行,被下一个filter, servlet接收。

5、什么时候用过滤器,什么时候用监听器,什么时候用拦截器?在什么场景要使用?

MyInterceptor1.preHandle()在请求处理之前进行调用(Controller方法调用之前)
MyInterceptor2.preHandle()在请求处理之前进行调用(Controller方法调用之前)
MyInterceptor2.postHandle()请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
MyInterceptor1.postHandle()请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
MyInterceptor2.afterCompletion()在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
MyInterceptor1.afterCompletion()在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行(主要是用于进行资源清理工作)

分类:

按监听的对象划分,可以分为

ServletContext对象监听器
澳门新濠3559,HttpSession对象监听器
ServletRequest对象监听器

按监听的事件划分

对象自身的创建和销毁的监听器
对象中属性的创建和消除的监听器
session中的某个对象的状态变化的监听器

示例:用监听器统计网站在线人数

原理:每当有一个访问连接到服务器时,服务器就会创建一个session来管理会话。那么我们就可以通过统计session的数量来获得当前在线人数。

public class onLineCount implements HttpSessionListener {

    public int count=0;//记录session的数量
    public void sessionCreated(HttpSessionEvent arg0) {//监听session的创建
        count  ;
        arg0.getSession().getServletContext().setAttribute("Count", count);

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent arg0) {//监听session的撤销
        count--;
        arg0.getSession().getServletContext().setAttribute("Count", count);
    }

}

web中配置

 <listener>
     <listener-class>com.ygj.control.onLineCount</listener-class>
  </listener>

3.用于监听请求消息对象(ServletRequest)的事件监听器

 

4:监听request的创建与销毁的ServletRequestListener

澳门新濠3559 11

image.png

init(FilterConfig var1): web应用程序启动时,web服务器将创建Filter的实例对象,并调用其init方法,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作,filter对象只会创建一次,init方法也只会执行一次。

 

3.监听器(Listener):Java的监听器,也是系统级别的监听。监听器随web应用的启动而启动。Java的监听器在c/s模式里面经常用到,它会对特定的事件产生产生一个处理。监听在很多模式下用到,比如说观察者模式,就是一个使用监听器来实现的,在比如统计网站的在线人数。

又比如struts2可以用监听来启动。Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。

3.通过监听器,可以自动激发一些操作,如监听在线用户数量,当增加一个HttpSession时,给在线人数加1。

 

1:监听session属性的增加、移除以及属性值改变的HttpSessionAttributeListener

澳门新濠3559 12

image.png

视频

Web开发使用Controller基本上可以完成大部分需求,但是我们还可能会用到Servlet、Filter、Listener、Interceptor等等。
当使用Spring-Boot时,嵌入式Servlet容器通过扫描注解的方式注册Servlet、Filter和Servlet规范的所有监听器(如HttpSessionListener监听器)。

springxml配置

<!--<mvc:mapping path="/**"/>这里拦截所有的请求-->
       <!-- 拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <mvc:mapping path="/**"/>
                <bean class="com.boolib.Handler.UserLoginInterceptorBySpring" />
            </mvc:interceptor>
            <!-- 
              <mvc:interceptor>
                <mvc:mapping path="/**"/>
                <bean class="com.boolib.Handler.UserLoginInterceptorBySpring" />
            </mvc:interceptor>
            -->
        </mvc:interceptors>

提问

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * 使用注解标注过滤器

 * @WebFilter将一个实现了javax.servlet.Filter接口的类定义为过滤器

 * 属性filterName声明过滤器的名称,可选

 * 属性urlPatterns指定要过滤的URL模式,也可使用属性value来声明.(指定要过滤的URL模式是必选属性)
 */
@WebFilter(filterName = "myFilter", urlPatterns = "/*")
public class MyFilter implements Filter {


    @Override
    public void init(FilterConfig config) throws ServletException {
        System.out.println("过滤器初始化");

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        System.out.println("执行过滤操作");
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        System.out.println("过滤器销毁");
    }

}

7.参考文献

Spring boot的主Servlet为DispatcherServlet,其默认的url-pattern为"/"。也许我们在应用中还需要定义更多的Servlet,该如何使用SpringBoot来完成呢?
在spring boot中添加自己的Servlet有两种方法,代码注册Servlet和注解自动注册(Filter和Listener也是如此)。

Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * 使用@WebListener注解,实现ServletContextListener接口
 */
@WebListener
public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {

        System.out.println("ServletContex销毁");
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {

        System.out.println("ServletContex初始化");
    }

}

doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3):当有人访问web服务器时对请求进行操作。

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class MyServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doGet()<<<<<<<<<<<");
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doPost()<<<<<<<<<<<");
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello World</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>这是:MyServlet</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

过滤器中的方法

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


@WebServlet(urlPatterns="/myServlet/*", description="Servlet的说明")
public class MyServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doGet()<<<<<<<<<<<");
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(">>>>>>>>>>doPost()<<<<<<<<<<<");
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter out = resp.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello World</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>这是:MyServlet</h1>");
        out.println("</body>");
        out.println("</html>");
    }
}

2、拦截器和AOP是什么关系

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;


@WebListener
public class MyHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("Session 被创建");
    }


    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("ServletContex初始化");
    }

}

sessionCreated(HttpSessionEvent httpSessionEvent)会话创建时调用

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor1 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("MyInterceptor1.preHandle()在请求处理之前进行调用(Controller方法调用之前)");

        // 只有返回true才会继续向下执行,返回false取消当前请求
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {

        System.out.println("MyInterceptor1.postHandle()请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

        System.out.println("MyInterceptor1.afterCompletion()在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行(主要是用于进行资源清理工作)");

    }
}

拦截器类继承MethodFilterInterceptor,然后加上注解就能用了。

使用FilterRegistrationBean和ServletListenerRegistrationBean这两个类可以实现代码的方式注册Filter和Listener。

监听器类型

访问:

4、拦截器是web容器必备的吗

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class SiteConfig {

    public static void main(String[] args) {
        SpringApplication.run(SiteConfig.class, args);
    }

    @Bean
    public ServletRegistrationBean MyServlet() {
        return new ServletRegistrationBean(new MyServlet(), "/myServlet/*");

    }

}

5.编写完成后在web.xml文件中配置一下,就可以起作用了 6.可以在不修改现有系统基础上,增加web应用程序生命周期事件的跟踪

参考:

过滤器

 

Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,调用目标资源之前,让一段代码执行。

一、代码注册通过ServletRegistrationBean、FilterRegistrationBean和ServletListenerRegistrationBean获得控制。

拦截器、过滤器、监听器各有什么作用?

 

java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action

ServletContext监听器(Listener)文件(HttpSessionListener)

代码展示

然后在浏览器输入地址: http://localhost:8080/index 后,控制台的输出为:

1、过滤器和拦截器的执行顺序再说一下

过滤器属于Servlet范畴的API,与Spring 没什么关系。
Web开发中,我们除了使用 Filter 来过滤web请求外,还可以使用Spring提供的HandlerInterceptor(拦截器)。
HandlerInterceptor 的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request内容,但是可以通过抛出异常(或者返回false)来暂停request的执行。
配置拦截器也很简单,Spring 为什么提供了基础类WebMvcConfigurerAdapter ,我们只需要重写 addInterceptors 方法添加注册拦截器。
实现自定义拦截器只需要3步:
1、创建我们自己的拦截器类并实现 HandlerInterceptor 接口。
2、创建一个Java类继承WebMvcConfigurerAdapter,并重写 addInterceptors 方法。
2、实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在addInterceptors方法中添加)。
定义两个拦截器

SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单,主要有两种方式,第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口,或者是这个类继承实现了HandlerInterceptor 接口的类,比如Spring 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter;

 

监听器方法

注意不要忘记在启动类上添加@ServletComponentScan 注解。

小课堂

 

拦截器实现

在启动类中注册这个Servlet

destroy()web容器调用destroy方法销毁Filter。destroy方法在Filter的生命周期中仅执行一次。在destroy方法中,可以释放过滤器使用的资源。

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class MyInterceptor2 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        System.out.println("MyInterceptor2.preHandle()在请求处理之前进行调用(Controller方法调用之前)");

       // 只有返回true才会继续向下执行,返回false取消当前请求
        return true;

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

                           ModelAndView modelAndView) throws Exception {

        System.out.println("MyInterceptor2.postHandle()请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)

            throws Exception {

        System.out.println("MyInterceptor2.afterCompletion()在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");

    }
}

undefined_腾讯视频

过滤器(Filter)和监听器(Listener)的注册方法和 Servlet 一样,使用@WebFilter和@WebListener的方式,完成一个Filter 和一个 Listener;使用注解@ServletComponentScan扫描相应的Servlet包;
过滤器(Filter)文件

postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解释我们知道这个方法包括后面要说到的afterCompletion 方法都只能是在当前所属的Interceptor 的preHandle 方法的返回值为true 时才能被调用。postHandle 方法,顾名思义就是在当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。postHandle 方法被调用的方向跟preHandle 是相反的,也就是说先声明的Interceptor 的postHandle 方法反而会后执行,这和Struts2 里面的Interceptor 的执行过程有点类型。Struts2 里面的Interceptor 的执行过程也是链式的,只是在Struts2 里面需要手动调用ActionInvocation 的invoke 方法来触发对下一个Interceptor 或者是Action 的调用,然后每一个Interceptor 中在invoke 方法调用之前的内容都是按照声明顺序执行的,而invoke 方法之后的内容就是反向的。

不是必备的,我们任务七之前知道什么事拦截器吗?

监听器讲解

1.背景介绍

鸣谢

sessionDestroyed(HttpSessionEvent httpSessionEvent)会话结束时调用

监听你的web应用,监听许多信息的初始化,销毁,增加,修改,删除值等

1.用于监听应用程序环境对象(ServletContext)的事件监听器

先执行过滤器,然后执行拦截器。

4.解决方案

afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,该方法也是需要当前对应的Interceptor 的preHandle 方法的返回值为true 时才会执行。顾名思义,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作的。

网络

过滤器通常用在设定字符编码之类的,设置请求的默认值,监听器用来监听控制器情况。

HandlerInterceptor 接口中定义了三个方法,我们就是通过这三个方法来对用户的请求进行拦截处理的。

过滤脏话

是否调用目标资源(即是否让用户访问web资源)。

Filter也称之为过滤器,它是Servlet技术中最激动人心的技术之一,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp,Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

6.扩展思考

5.编码实战

1.Listener是Servlet的监听器

然后再之前或者之后加入某些操作。

本次代码演示是继承HandlerInterceptor.

拦截已注册用户

8.更多讨论

执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式。在AOP中,拦截器用于在某个方法或者字段被访问之前,进行拦截

3.常见问题

8.更多讨论

preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顾名思义,该方法将在请求处理之前进行调用。SpringMVC 中的Interceptor 是链式的调用的,在一个应用中或者说是在一个请求中可以同时存在多个Interceptor 。每个Interceptor 的调用会依据它的声明顺序依次执行,而且最先执行的都是Interceptor 中的preHandle 方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值Boolean 类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法,如果已经是最后一个Interceptor 的时候就会是调用当前请求的Controller 方法。

2.可以监听客户端的请求、服务端的操作等。

7.参考文献

代码实战

欢迎大家交流和讨论

本次使用HttpSession类型时间监听器

AOP也是拦截器的一种,通常用在维护数据操作层,拦截器多用于验证登陆状态之类的。

Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。

感谢大家观看

代码展示

3、怎么通过spring注解实现拦截器

第二种方式是实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。

HttpSessionListener:用于监听Session对象的创建和销毁,监听器类需要实现javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者两个都实现。

在线人数监听器

web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。

过滤器原理

编辑:编程 本文来源:澳门新濠3559:Java的过滤器能够为我们提供系统级

关键词: 澳门新濠3559