springboot_4 spring boot 使用servlet,filter,listener和interceptor

上一篇我们学习了 spring boot 利用Controller响应数据与响应页面。 一般的Web开发使用 Controller 基本上可以完成大部分需求,但是有的时候我们还是会用到 Servlet、Filter、Listener 等等。

在spring boot中添加自己的Servlet、Filter、Listener有两种方法

  • 代码注册: 通过ServletRegistrationBean、 FilterRegistrationBean 和ServletListenerRegistrationBean 获得控制。
  • 注解注册: 在SpringBootApplication 上使用@ServletComponentScan注解后,Servlet、Filter、Listener 可以直接通过 @WebServlet、@WebFilter、@WebListener 注解自动注册,无需其他代码。

spring boot 中注册servlet

代码注册

  • 创建Servlet类:AaServlet.java。
public class AaServlet extends HttpServlet {
    @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");
        PrintWriter out = resp.getWriter();
        out.println("<h1>AaServlet</h1>");
    }
}

  • 通过ServletRegistrationBean注册。
//Project2Application.java
    @Bean
    public ServletRegistrationBean AaServletRegistration() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new AaServlet());
        registration.addUrlMappings("/a");
        return registration;
    }
  • 运行测试。

访问:http://localhost:8080/a

 
测试

注解注册

  • 创建Servlet类:BbServlet.java。
@WebServlet(urlPatterns = "/b")
public class BbServlet extends HttpServlet {
    @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");
        PrintWriter out = resp.getWriter();
        out.println("<h1>BbServlet</h1>");

    }
}
  • 添加注解@ServletComponentScan。
@ServletComponentScan
@SpringBootApplication
public class Project2Application {

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

    @Bean
    public ServletRegistrationBean AaServletRegistration() {
        ServletRegistrationBean registration = new ServletRegistrationBean(new AaServlet());
        registration.addUrlMappings("/a");
        return registration;
    }

}
  • 运行测试。

访问:http://localhost:8080/b

 
测试

filter 和 listener的注册和servlet一样。这里就不多说了。

接下来说一下拦截器。

自定义拦截器

Spring提供了HandlerInterceptor(拦截器)。它的功能跟过滤器类似,但是提供更精细的的控制能力:在request被响应之前、request被响应之后、视图渲染之前以及request全部结束之后。我们不能通过拦截器修改request内容,但是可以通过抛出异常(或者返回false)来暂停request的执行。

spring boot提供了一些拦截器,我们可以直接拿来使用,比如:

  • ConversionServiceExposingInterceptor
  • CorsInterceptor
  • LocaleChangeInterceptor
  • PathExposingHandlerInterceptor
  • ResourceUrlProviderExposingInterceptor
  • ThemeChangeInterceptor
  • UriTemplateVariablesHandlerInterceptor
  • UserRoleAuthorizationInterceptor

我们也可以自己定义拦截器,定义拦截器的步骤大致分为:

1、创建我们自己的拦截器类并实现 HandlerInterceptor 接口。
2、创建一个Java类继承WebMvcConfigurerAdapter,并重写addInterceptors 方法。
3、实例化我们自定义的拦截器,然后将对像手动添加到拦截器链中(在addInterceptors方法中添加)。

我们来亲自试一下:

  • 创建我们自己的拦截器
//MyInterceptor2
public class MyInterceptor1 implements HandlerInterceptor {

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

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

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1==========>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("MyInterceptor1==========>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
    }

}

//MyInterceptor2
public class MyInterceptor2 implements HandlerInterceptor {

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

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

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor2==========>请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("MyInterceptor2==========>在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)");
    }

}

创建一个Java类继承WebMvcConfigurerAdapter,并重写addInterceptors 方法,添加拦截器。

//MyWebAppConfigurer
@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);
    }

}

测试:运行项目,随便访问一个路径,比如http://localhost:8080/test

浏览器会报错,不用管,看控制台。

 
结果

拦截器已经起作用了。

值得注意的是:只有经过DispatcherServlet 的请求,才会走拦截器链,我们自定义的Servlet 请求是不会被拦截的,比如我们自定义的Servlet地址是不会被拦截器拦截的。

但是过滤器不同。不管是属于哪个Servlet 只要复合过滤器的过滤规则,过滤器都会拦截。


本篇文章就先介绍到这里,如果哪里讲的不明白,请及时与我联系。

参考文章:Spring Boot 拦截器



作者:cleverfan
链接:https://www.jianshu.com/p/fba5c0fd09bb
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted on 2018-01-12 13:50  0001  阅读(1576)  评论(0编辑  收藏  举报