springboot使用代码及注解两种方式注册servlet、filter、listener、intercepter

1 servlet简介

  servlet是一种用于开发动态web资源的技术

  参考博客:servlet基础知识     httpservlet详解

 

2 在springboot应用中添加servlet

  springboot的主servlet是DispacherServlet,它默认的url-pattern是“/”,如果我们还需要其他的servlet就需要开发人员自己进行定义和注册

  2.1 springboot支持代码和注解来注册servlet 

    2.1.1 代码注册

      通过ServletRegistrationBean获得控制

@Configuration
public class WebConfiguration {

    @Bean
    public ServletRegistrationBean<MyServlet> servletRegistrationBean() {
        //方法一:使用ServletRegistrationBean(HttpServlet servlet, String... urlMappings)带参构造方法
        //ServletRegistrationBean<MyServlet> servletServletRegistrationBean = new ServletRegistrationBean<>(new MyServlet(), "/myServlet");

        //方法二:使用ServletRegistrationBean()空参构造方法
        ServletRegistrationBean<MyServlet> servletServletRegistrationBean = new ServletRegistrationBean<>();

        //相当于<servlet-class>com.springboot.example.demo.servlets.MyServlet</servlet-class>
        servletServletRegistrationBean.setServlet(new MyServlet());
        //相当于<url-pattern>/myServlet</url-pattern>
        //addUrlMappings(String... urlMappings):之所以使用可变参数,是因为一个servlet可以对于多个url-pattern
        servletServletRegistrationBean.addUrlMappings("/myServlet");

        //相当于<servlet-name>myServlet</servlet-name>
        servletServletRegistrationBean.setName("myServlet");
        return servletServletRegistrationBean;
    }
}

2.1.2 注解注册

      在启动类上标注@ServletComponentScan,在自定义的servlet类上标注@WebServlet即可

@SpringBootApplication
@ServletComponentScan//加上此注解
public class ExampleApplication {

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

}
@WebServlet(urlPatterns = "/myServlet", name = "myServlet")//加上此注解
public class MyServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println(request.getRequestURL());
        ServletConfig config = getServletConfig();
        System.out.println(config.getServletName());
    }
}

注:@WebServlet(urlPatterns = "/myServlet", name = "myServlet")注解括号里面的属性可以不写,即直接简写成@WebServlet,这时:此servlet会拦截所有请求,等价于"/*",并且以该servlet的全限定名作为servlet-name,所以强烈建议指定urlPattern

3 过滤器

  过滤器和servlet一样,支持代码注册和注解注册;

  过滤器可以拿到原始请求和响应的相关信息但是拿不到控制方法的相关信息

  3.1 实现方式01

    3.1.1 编写自定义过滤器

      技巧01:必须实现 Filter 接口

      技巧02:init() 方法用于初始化,项目启动的时候就会被调用,而且只会被调用一次

      技巧03:destroy() 方法用于销毁,项目关闭的时候会被调用,而且只会被调用一次

      技巧04:doFilter() 方法用户处理过滤逻辑,只要满足过滤条件就会被执行;在doFilter方法中必须执行FilterChain对象的doFilter方法,否则前端过来的请求就不会进入到控制层

      技巧05:@WebFilter(urlPatterns = "/*") 注解的作用是指定过滤的请求路径,是一个String类型的数组

      技巧06:可以利用 @Order(Integer类型) 来设置该过滤器的顺序号

@Configuration
public class WebConfiguration {

    @Bean
    public FilterRegistrationBean<MyFilter> filterRegistrationBean() {
        //方式一:使用FilterRegistrationBean(Filter filter, ServletRegistrationBean<?>... servletRegistrationBeans)带参构造
        //FilterRegistrationBean<MyFilter> filterFilterRegistrationBean = new FilterRegistrationBean<>(new MyFilter());

        //方式二:FilterRegistrationBean()空参构造
        FilterRegistrationBean<MyFilter> filterFilterRegistrationBean = new FilterRegistrationBean<>();
        //相当于<filter-class>com.springboot.example.demo.servlets.MyFilter</filter-class>
        filterFilterRegistrationBean.setFilter(new MyFilter());
        //相当于<url-pattern>/MyFilter</url-pattern>
        filterFilterRegistrationBean.addUrlPatterns("/*");
        //相当于<filter-name>myFilter</filter-name>
        filterFilterRegistrationBean.setName("MyFilter");
        //相当于最先使用这个过滤器进行过滤
        filterFilterRegistrationBean.setOrder(1);
        return filterFilterRegistrationBean;
    }
}

3.2 实现方式02

    创建一个过滤器类,该类必须实现Filter接口;直接在该过滤器类中添加@WebFilter注解后该过滤器就会生效,无需再做其他任何操作

    技巧01:这种方式默认会对所有的请求进行拦截

    技巧02:通常只有一个过滤器时使用这种方式,而且这种方式只适用于自定义的过滤器

@SpringBootApplication
@ServletComponentScan//加上此注解
public class ExampleApplication {

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

}
@WebFilter(urlPatterns = "/*", filterName = "myFilter")//加入此注解
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init()");
        System.out.println(filterConfig.getFilterName());
    }

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

    @Override
    public void destroy() {
        System.out.println("destroy()");
    }
}

注:@WebFilter(urlPatterns = "/*", filterName = "myFilter")注解括号里面的属性可以不写,即直接简写成@WebFilter,这时:此filter会拦截所有请求,等价于"/*",并且以该filter的全限定名作为filterName,所以强烈建议指定urlPattern

3.3 实现方式03

    创建一个过滤器类,该类必须实现Filter接口;直接在该过滤器类中添加@Component注解后该过滤器就会生效,无需再做其他任何操作

注:这种方式默认会对所有的请求进行拦截,并且filterName为当前类名第一个字母小写后的字符串,如:MyFilter类的filterName为myFilter

@Component//加入此注解
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init()");
        System.out.println(">>>>>>"+filterConfig.getFilterName());
    }

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

    @Override
    public void destroy() {
        System.out.println("destroy()");
    }
}

4 监听器

  监听器同样支持代码和注解两种注册方式

  4.1 实现方式01:

@Configuration
public class WebConfiguration {

    @Bean
    public ServletListenerRegistrationBean<MyListener> servletListenerRegistrationBean() {
        //方式一:使用ServletListenerRegistrationBean(EventListener listener)带参构造方法
        //ServletListenerRegistrationBean<MyListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>(new MyListener());

        //方式二:使用ServletListenerRegistrationBean()空参参构造方法
        ServletListenerRegistrationBean<MyListener> servletListenerRegistrationBean = new ServletListenerRegistrationBean<>();
        //注册自定义MyListener
        servletListenerRegistrationBean.setListener(new MyListener());
        //执行顺序
        servletListenerRegistrationBean.setOrder(1);
        return servletListenerRegistrationBean;
    }
}

        4.1 实现方式02:

@SpringBootApplication
@ServletComponentScan//加上此注解
public class ExampleApplication {

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

}
@WebListener//加入此注解
public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized()");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed()");
    }
}

5 拦截器

  5.1 HandlerInterceptor

    spring为我们提供了HandlerInterceptor接口来实现拦截器功能

    HandlerInterceptor在调用controller之前和调用controller之后以及视图渲染完成之后都可以得到控制;我们不可以通过拦截器来修改request内容,但是我们可以通过抛出异常或者返回false来结束请求

    技巧01:拦截器可以获取到原始的请求和响应信息,也可以拿到controller层的类名信息和方法名信息;但是拿不到方法的参数信息;因为DispatcherServlet在进行请求分发时先执行拦截器,然后在将请求数据封装到controller层中控制方法的参数上去的。

5.2 创建自定义拦截器

    自定义拦截器需要实现HandlerInterceptor接口,然后根据自己的需求去重写相应的方法

public class MyInterceptor implements HandlerInterceptor {

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

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

    }

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

    }
}

5.2.1 preHandle

      调用controller之前执行,如果该方法返回false或者抛出异常就会结束请求

      技巧01:preHandle返回false或者抛出异常是就不会在继续往下执行(即:不会再进入conroller层,也不会执行postHandle和afterCompletion)

    5.2.2 postHandle

      调用controller之后视图渲染完成之前

      技巧01:如果controller层中的方法抛出了异常就会不会执行该方法了

    5.2.3 afterCompletion

      视图渲染完成之后

      技巧01:不管controller层是否抛出异常都会执行该方法,只有preHandle返回false或者preHandle方法中抛出异常才不会执行该方法

  5.3 配置自定义拦截器

    spring为我们提供了 WebMvcConfigurerAdapter 我们只需要重写addInterceptors方法就可以实现自定义拦截器的配置

    技巧01:继承了WebMvcConfigurerAdapter类后我们可以通过该重写相关方法来实现配置

    坑01:从spring5.0和springBoot2.0开始WebMvcConfigurerAdapter就失效了,解决方法在下面

@Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")
        .excludePathPatterns("/myServlet");//排除的路径
    }
}

注: webmvcconfigureradapter过时问题

  在修改一些SpringBoot的默认配置时需要继承webmvcconfigureradapter,但是从spring5.0和springboot2.0开始这个类就逐渐被废弃掉了;但是从webmvcconfigureradapter的源码可以看出这个类实现了WebMvcConfigurer接口,所以我们可以在自定义的配置类中直接实现WebMvcConfigurer接口即可

  技巧01:虽然是实现了WebMvcConfigurer接口,但是不需要重写WebMvcConfigurer中的所有方法,仅仅根据需求进行重写就可以啦

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")
        .excludePathPatterns("/myServlet");//排除的路径
    }
}

注:如果使用的是第三方引入的servlet、filter、listener,那就只能使用代码的方式进行注册,不能使用注解了,因为添加不了注解。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值