SpringMVC之DispatchserServlet

SpringBoot对原生Servlet的支持

0、总结

  • 过滤器首先是要配置拦截的路径,如果对应的路径被拦截了,才会走拦截方法,需要根据条件判断是否需要拦截。如果不需要拦截,会放行;如果不满足条件,将会直接返回;
  • 过滤器可以根据指定的servlet的路径来进行拦截,也就是servlet配置的是什么路径,过滤器拦截的就是什么路径;
  • 过滤器的拦截早于拦截器的拦截;
  • 自定义的servlet将不会指定拦截器中的方法,因为springmvc中只针对DispatchserServlet才配置了拦截器;

1、注解支持

关于Servlet中原生的servlet、filter和ServletContextListener的配置

SpringBoot官网文档中提到了有两种方式来来进行操作:

  • When using an embedded container, automatic registration of classes annotated with @WebServlet, @WebFilter, and @WebListener can be enabled by using @ServletComponentScan.
  • If convention-based mapping is not flexible enough, you can use the ServletRegistrationBean, FilterRegistrationBean, and ServletListenerRegistrationBean classes for complete control.

第一种方式是使用注解版来进行配置,对于servlet和fitler可以来配置对应的请求路径和拦截路径。

第二种方式可以来使用java编写来进行配置。

下面分别来进行演示下对应的案例:

1.1、servlet

@WebServlet(urlPatterns = "/hello")
public class MyServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("hello,myservlet");
    }
}

1.2、filter

/**
 *
 * 过滤器应该是在拦截对应的路径之后,针对什么条件下会来进行过滤。所以这里的过滤条件很重要
 * 这里需要注意的是:/*单个*是servlet的写法,而/**是spring全家桶的写法
 * 如果是/*,那么表示的是将会拦截一切
 */
@WebFilter(urlPatterns = {"/*"})
public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 如果这里没有过滤掉,那么将会被拦截,页面上什么都么有输出
        System.out.println("过滤掉对应的请求信息.........");
        chain.doFilter(request,response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("拦截器开始执行");
    }

    @Override
    public void destroy() {
        System.out.println("项目正在被销毁..........");
    }
}

1.3、listener

@WebListener
public class MyWebListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("项目初始化完成......");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 只有正常销毁的时候才会执行。直接点解idea是不行的
        System.out.println("项目销毁......");
    }
}

1.4、配置注解

安装官方文档说明:需要在添加上@ServletComponentScan,那么在配置类上添加一下:

@SpringBootApplication
@ServletComponentScan(basePackages={"com.guang.springbootspringmvcorigin.servlet","com.guang.springbootspringmvcorigin.filter","com.guang.springbootspringmvcorigin.listener"})
public class SpringbootSpringmvcOriginApplication {

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

}

1.5、检测自定义的servlet是否执行了拦截器

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置处理");
        String requestURI = request.getRequestURI();
        System.out.println("-----hello----");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("处理完成之后。。。。。。。。。。");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("视图渲染之后执行");
    }
}

将拦截器配置到WebMvc中来:

@Configuration(proxyBeanMethods=true)
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor());
    }
    
}

经过测试,发现自定义的servlet处理不会经过拦截器的方法。

2、配置版

SpringBoot中也提供了对应的配置信息

If convention-based mapping is not flexible enough, you can use the ServletRegistrationBean, FilterRegistrationBean, and ServletListenerRegistrationBean classes for complete control.

下面也来操作一下,只需要将上述的注解去掉,然后在配置类类中来进行添加即可。

// 这里要加上proxyBeanMethods = true为FALSE,因为下面的配置信息中有会获取得到上面的servlet的路径信息
@Configuration(proxyBeanMethods = true)
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor());
    }

    @Bean
    public ServletRegistrationBean myServlet(){
        ServletRegistrationBean<MyServlet> myServletServletRegistrationBean = new ServletRegistrationBean<>(new MyServlet(), "/my", "/my01");
        return myServletServletRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean myFilterRegistrationBean(){
        FilterRegistrationBean<MyFilter> myFilterFilterRegistrationBean = new FilterRegistrationBean<>(new MyFilter(), myServlet());
        myFilterFilterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        return myFilterFilterRegistrationBean;
    }


    @Bean
    public ServletListenerRegistrationBean myServletListenerRegistrationBean(){
        ServletListenerRegistrationBean<MyWebListener> myFilterFilterRegistrationBean = new ServletListenerRegistrationBean<MyWebListener>(new MyWebListener());
        return myFilterFilterRegistrationBean;
    }

}

注意

  • 我在测试的时候发现,如果是自定义的servlet无法来进行处理的时候,DispatchserServlet开始执行了,因为这个是缺省匹配的;
  • 在配置自定义servlet的时候,发现路径中如果没有/,那么将会导致启动失败错误,所以以后还是直接添加上的比较好;

3、DispatcherServlet的配置

在DispatcherServletAutoConfiguration中可以看到,可以自己来对DispatcherServletAutoConfiguration来进行配置。

前缀是:spring.mvc

注册的时候,采用的也是上面的配置版中的servlet的配置来进行配置的,DispatcherServletAutoConfiguration默认的路径是/,这个可以在对应的配置中是可以看到的。

posted @ 2022-05-22 22:37  写的代码很烂  阅读(62)  评论(0编辑  收藏  举报