• Servlet容器使用Spring容器


    今天在做一个需求的时候,需要在Servlet接口中调用一个Spring的Bean对象,因为Servlet和Spring生命周期不同,所被管理的容器不同,因此不能直接通过@Autowire注入

    以下三个方案,思路分别是:

    • 在初始化这个Servlet类接口的时候,重写init()方法,允许Servlet扫描Bean对象
    • 在初始化这个Servlet类接口的时候,重写init()方法,指定获取bean:getBean()
    • 在利用配置类在装载Servlet的时候,将bean对象地址作为形参传给Servlet

    0.Servlet结构演示

    这里做演示用的StringRedisTemplate 本身不是一个SpringBean对象,但是由于项目中有配置将其扫描为了bean,所以这里直接用StringRedisTemplate 来做演示

    public class ValidateCodeServlet extends HttpServlet {
    //@Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    //    public ValidateCodeServlet() {
    //    }
    //    public ValidateCodeServlet(StringRedisTemplate stringRedisTemplate) {
    //        this.stringRedisTemplate = stringRedisTemplate;
    //    }
    
    
     @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    ....}
    
    
        @Override
        public void init(ServletConfig config) throws ServletException {
    .....
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    1.允许Servlet扫描Bean对象

    @Override
    public void init(ServletConfig config) throws ServletException {
        // 父类不初始化会导致getServletContext()空指针异常
        super.init(config);
        // 将当前this 的 Servlet交给Spring托管,因此该Servlet可以用@Autowired
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    1.1SpringBeanAutowiringSupport类

    通过这个类的名字,结合注释可以知道,这个类主要的作用是对@Autowired进行增强
    看注释中的如下部分,通过@Autowired将Spring的Bean对象解析到当前的Web上下文(Servlet上下文)

    1.2processInjectionBasedOnServletContext

    Servlet注入Spring的Bean对象,最终的执行方法是processInjection()

    1.2.1processInjection()

    2.get指定的bean

    @Override
    public void init(ServletConfig config) throws ServletException {
    
         ServletContext servletContext = this.getServletContext();
         WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
         this.stringRedisTemplate = (StringRedisTemplate) context.getBean("StringRedisTemplate");
         }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果目标类本身没有直接注入Spring容器而是配置扫描,会报错,所以不推荐这种做法,更推荐方法1

    2.1WebApplicationContextUtils工具类

    在SpringBeanAutowiringSupport类的注释中有提到
    WebApplicationContextUtils类允许基于ServletContext轻松访问Spring根web应用程序上下文。

    3.配置类传递bean地址

    bean对象本质上也是一个java的对象,只要能获取其地址值,就可以正常使用


    这样配置就不需要写inti()了

    4.同样的,对于Filter

    Filter也是Servlet的产物,他的上下文环境也不同于Spring上下文,同样还是这个需求里面用的是Filter对其进行校验,也需要注入Srping的Bean对象,当然不能直接@Autowired


    5.普通类调用bean工具类

     @Component
    public class SpringContexUtil implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
    applicationContext = context;
    }
    
    //静态加载applicationContext
    public static ApplicationContext getApplicationContext() {
    return applicationContext;
    }
    //通过反射获取Bean
    public static  T getBean(Class requiredType){
    return getApplicationContext().getBean(requiredType);
    }
    //通过id名获取bean
    public static  T getBean(String name){
    return (T) getApplicationContext().getBean(name);
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    把Servlet或者Filter当普通类,直接用工具类调用即可

    需要注意的点

    因为项目启动时装载在前,很多修改“装载过程”的地方不能通过热部署来reload,需要重启项目

    6.总结

    在使用Servlet对象之前,将其需要注入的SpringBean作为形参,在配置类中(即启动时装载)指定SpringBean对象的地址值给Servlet或Filter的形参即可

  • 相关阅读:
    网站运营怎样才能反超对手呢
    通过正则批量提取PDF中文本信息
    BLE学习(1):蓝牙协议栈的介绍
    中文编程开发语言工具构件说明:屏幕截取构件的编程操作
    Elasticsearch 对比传统数据库:深入挖掘 Elasticsearch 的优势
    深入理解TDD(测试驱动开发):提升代码质量的利器!
    企业工程项目管理系统源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)
    RabbitMQ的工作模式及原理
    SQL SERVER数据库1——创建数据库
    【计算机基础】Git从安装到使用,详细每一步!扩展Github\Gitlab
  • 原文地址:https://blog.csdn.net/m0_56079407/article/details/126100874