Spring Boot @ServletComponentScan 扫描 @WebServlet、@WebFilter(过滤器)、@WebListener(过滤器),SpringBoot排除数据源配置,配置决定行为


1、Servlet 三大组件 Servlet、Filter、Listener 在传统项目中需要在 web.xml 中进行相应的配置。Servlet 3.0 开始在 javax.servlet.annotation 包下提供 3 个对应的 @WebServlet、@WebFilter、@WebListener 注解来简化操作。

2、@WebServlet、@WebFilter、@WebListener 写在对应的 Servlet、Filter、Listener 类上作为标识,从而不需要在 web.xml 中进行配置了。

3、Spring Boot 应用中这三个注解默认是不被扫描的,需要在项目启动类上添加 @ServletComponentScan 注解, 表示对 Servlet 组件扫描。

4、注解的方式相比《Spring Boot 注册 Servlet 三大组件 Servlet、Filter、Listener》更加方便。

@WebServlet

 
  1. import javax.servlet.ServletException;
  2. import javax.servlet.annotation.WebServlet;
  3. import javax.servlet.http.HttpServlet;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import java.io.IOException;
  7.  
  8. /**
  9. * 标准的 Servlet ,实现 javax.servlet.http.HttpServlet. 重写其 doGet 、doPost 方法
  10. * name :表示 servlet 名称,可以不写,默认为空
  11. * urlPatterns: 表示请求的路径,如 http://ip:port/context-path/userServlet
  12. */
  13. @WebServlet(name = "UserServlet", urlPatterns = {"/userServlet"})
  14. public class UserServlet extends HttpServlet {
  15. @Override
  16. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  17. this.doPost(req, resp);
  18. }
  19.  
  20. @Override
  21. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  22. StringBuffer requestURL = req.getRequestURL();
  23. System.out.println("com.wmx.servlet.UserServlet -- " + requestURL);
  24. resp.sendRedirect("/index.html");//浏览器重定向到服务器下的 index.html 页面
  25. }
  26. }
 

@WebFilter 过滤器

  • 过滤器是在 web 应用启动的时候初始化一次, 在 web 应用停止的时候销毁

  • 可以对请求的 URL 进行过滤, 对敏感词过滤

  • 挡在拦截器的外层

  • 实现的是 javax.servlet.Filter 接口 ,是 Servlet 规范的一部分

  • 在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在 servlet 处理完以后

  • 依赖 Web 容器

  • 会多次执行

 
  1. import javax.servlet.*;
  2. import javax.servlet.annotation.WebFilter;
  3. import javax.servlet.http.HttpServletRequest;
  4. import java.io.IOException;
  5.  
  6. /**
  7. * 标准 Servlet 过滤器,实现 javax.servlet.Filter 接口,并重现它的 3 个方法
  8. * filterName:表示过滤器名称,可以不写
  9. * value:配置请求过滤的规则,如 "/*" 表示过滤所有请求,包括静态资源,如 "/user/*" 表示 /user 开头的所有请求
  10. */
  11. @WebFilter(filterName = "SystemFilter", value = {"/*"})
  12. public class SystemFilter implements Filter {
  13.  
  14. @Override
  15. public void init(FilterConfig filterConfig) throws ServletException {
  16. System.out.println("com.wmx.servlet.SystemFilter -- 系统启动...");
  17. }
  18.  
  19. @Override
  20. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  21. //转为 HttpServletRequest 输出请求路径
  22. HttpServletRequest request = (HttpServletRequest) servletRequest;
  23. System.out.println("com.wmx.servlet.SystemFilter -- 过滤器放行前...." + request.getRequestURL());
  24. filterChain.doFilter(servletRequest, servletResponse);
  25. System.out.println("com.wmx.servlet.SystemFilter -- 过滤器返回后...." + request.getRequestURL());
  26. }
  27.  
  28. @Override
  29. public void destroy() {
  30. System.out.println("com.wmx.servlet.SystemFilter -- 系统关闭...");
  31. }
  32. }
 

@WebListener 监听器

  • 实现 javax.servlet.ServletRequestListener, javax.servlet.http.HttpSessionListener, javax.servlet.ServletContextListener 等等接口

  • 主要用来监听对象的创建与销毁的发生, 比如 session 的创建销毁, request 的创建销毁, ServletContext 创建销毁

 
  1. import javax.servlet.ServletContextEvent;
  2. import javax.servlet.ServletContextListener;
  3. import javax.servlet.annotation.WebListener;
  4.  
  5. /**
  6. * 标准 Servlet 监听器,实现 javax.servlet.ServletContextListener 接口,并重写方法
  7. * ServletContextListener 属于 Servlet 应用启动关闭监听器,监听容器初始化与销毁。常用的监听器还有:
  8. * ServletRequestListener:HttpServletRequest 对象的创建和销毁监听器
  9. * HttpSessionListener:HttpSession 数据对象创建和销毁监听器
  10. * HttpSessionAttributeListener 监听HttpSession中属性变化
  11. * ServletRequestAttributeListener 监听ServletRequest中属性变化
  12. */
  13. @WebListener
  14. public class SystemListener implements ServletContextListener {
  15. @Override
  16. public void contextInitialized(ServletContextEvent sce) {
  17. System.out.println("com.wmx.servlet.SystemListener -- 服务器启动.");
  18. }
  19.  
  20. @Override
  21. public void contextDestroyed(ServletContextEvent sce) {
  22. System.out.println("com.wmx.servlet.SystemListener -- 服务器关闭.");
  23. }
  24. }
 

@ServletComponentScan

Spring Boot 应用中这三个注解默认是不被扫描的,需要在项目启动类上添加 @ServletComponentScan 注解, 表示对 Servlet 组件扫描。

 
  1. import org.springframework.boot.SpringApplication;
  2. import org.springframework.boot.autoconfigure.SpringBootApplication;
  3. import org.springframework.boot.web.servlet.ServletComponentScan;
  4.  
  5. @SpringBootApplication
  6. @ServletComponentScan //对 servlet 注解进行扫描
  7. public class RedisStuWebApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(RedisStuWebApplication.class, args);
  10. }
  11. }
 

本文演示源码:wmx-redis: redis 练习 - Gitee.com

Spring Boot @ServletComponentScan 扫描 @WebServlet、@WebFilter(过滤器)、@WebListener(过滤器)-CSDN博客

项目场景:

最近接到一个需求,大概意思呢就是数据库连接不够用了,部分服务(分服务)就不需要配置数据源了,需要跟db打交道的地方全部改成rpc去调用具备db能力的服务(总服务)


问题描述:

其实需要改的地方并不多,分服务实际上也就只有几个接口会被调用到,主要是插入操作,写一个rpc接口即可。至于排除数据源,毕竟一直都是配了数据源的,突然不配了还有点不知所措。这里就有点小坑,后面会提到。


解决方案:

1.业务逻辑

调用数据库的部分,全部改成一个接口,具体走的实现逻辑,可以通过配置文件来决定。

public interface UploadRecordDbOrRpcService {
	
    Integer insert(Object object);

    Integer updateById(Object object);

    Integer deleteById(Serializable id);

}

对应的实现类呢,会有两个一个是db的实现类,一个是rpc实现类

db实现类

public class UploadRecordDbServiceImpl implements UploadRecordDbOrRpcService {

	public Integer insert(Object object){
		
	}

    public Integer updateById(Object object){
    
    }

    public Integer deleteById(Serializable id){
    
    }
}

rpc实现类

public class UploadRecordRPCServiceImpl implements UploadRecordDbOrRpcService {

	public Integer insert(Object object){
		
	}

    public Integer updateById(Object object){
    
    }

    public Integer deleteById(Serializable id){
    
    }
}

实现类定义完成后,我们还需要一个配置文件来决定最后走的是哪一个逻辑(实现类)(注意以上的两个实现类不要注入到容器中,需要我们自己配置)
配置类:

@Configuration
@Slf4j
public class UploadBeanConfig {


    @Value("${isDB:false}")
    private boolean isDB;


    @Bean
    public UploadRecordDbOrRpcService uploadRecordDbOrRpcService(){
        if (isDB) {
            log.info("use db");
            return new UploadRecordDbServiceImpl();
        } else {
            log.info("use rpc");
            return new UploadRecordRpcServiceImpl();
        }
    }
}

我们只需要配置一下yml文件

isDB: true #表示当前服务具备db能力  false表示当前不具备db,走rpc接口

2.排除数据源

思路:
1.去除springboot相应的自动配置类 DataSourceAutoConfiguration
2.动态配置mapperScan注解

1.springboot的一大特性就是自动配置,默认情况下web工程都是需要配置数据源的。如果想要排除数据源,可以通过以下几种方式

  • @EnableAutoConfiguration/SpringBootApplication注解有一个属性exclude它可以帮助我们排除指定的自动配置类
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
public class xxxConfig {}
  • 通过配置文件进行排除
spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

2.对于mapperScan注解我们可以专门写一个配置类,通过springboot的自动配置方式将其注入,最后再exclude出去。也可以使用两个配置类配合@Condition系类的注解达到这个效果。
MapperPlusConfiguration配置类

@MapperScan("com.juphoon.iron.mapper")
@Configuration
public class MapperPlusConfigure {
}

创建spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.xx.xx.config.MapperPlusConfigure

至此,mapperScan的功能也自动配置了进去。
如果不配置数据源的话只需要通过修改application.yml文件

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
      - com.xx.xx.config.MapperPlusConfigure
posted @ 2024-02-26 16:50  CharyGao  阅读(249)  评论(0编辑  收藏  举报