启动时从数据库初始化SpringWeb应用程序

启动时从数据库初始化SpringWeb应用程序,spring,jakarta-ee,spring-mvc,Spring,Jakarta Ee,Spring Mvc,Spring 3.1+Tomcat 我这里有一个设计问题: 在数据库中指定了一组类别。这些类别可以被认为是全球性的,因为它们可以在整个webapp中使用。我想做的是在服务器启动时阅读这些类别,并用Java填充某种类型的集合。在启动时只需从数据库中读取一次,就可以将其视为初始化类型。 我可以想到两个选择: 1) 我应该使用非延迟初始化的bean吗 或 2) 修改web.xml 我真的不确定什么是首选方法,任何关于如何执行建议的操作的说明都将不胜感激。谢谢 您提供的选项是最常用的: 使用带有@Pos

Spring 3.1+Tomcat

我这里有一个设计问题:

在数据库中指定了一组类别。这些类别可以被认为是全球性的,因为它们可以在整个webapp中使用。我想做的是在服务器启动时阅读这些类别,并用Java填充某种类型的集合。在启动时只需从数据库中读取一次,就可以将其视为初始化类型。

我可以想到两个选择:

1) 我应该使用非延迟初始化的bean吗

2) 修改web.xml


我真的不确定什么是首选方法,任何关于如何执行建议的操作的说明都将不胜感激。谢谢

您提供的选项是最常用的:

  • 使用带有
    @PostConstruct
    注释的方法的单例非惰性bean(但要注意
    @Transactional
    )。使用这样的初始化例程可以有几个bean

  • 扩展
    org.springframework.web.context.ContextLoaderListener
    并在
    web.xml
    中使用它。我发现这个解决方案不那么优雅,而且还推广了糟糕的编程风格(通过调用
    super
    来扩展以增强基类)


  • 我使用了一个
    控制器
    ,它实现了
    ServletContextAware
    初始化bean
    。控制器在应用程序启动时运行,我在
    AfterPropertieSet
    方法中运行参数加载代码,以便正确注入ServletContext。然后,这些属性可以从ServletContext在整个应用程序中使用。代码:

    @Controller
    public class ParameterizationController implements ServletContextAware , InitializingBean  {
    
    protected final Log logger = LogFactory.getLog(getClass());
    public static final String PARAMETERS_SC_ATTRIBUTE = "allProps";
    
    private ServletContext sc;
    
    public ParameterizationController() {
        logger.info("inside ParameterizationController...");
    }
    
    @Autowired
    private SomeService someService;
    
    @RequestMapping("/loadparams.do")
    public String formHandler(
            Model model) {
        String forwardValue = "/loadparams";
        // an admin can also call this page to reload props at runtime
        this.sc.setAttribute(PARAMETERS_SC_ATTRIBUTE, loadProperties());
        return forwardValue;
    }
    
    private HashMap<Integer, HashMap<String, String>> loadProperties() {
        return someService.loadProperties();
    }
    
    // makes sure the SC is injected for use
    public void setServletContext(ServletContext sc) {
        this.sc = sc;
    }
    
    // only runs after all injections have been completed
    public void afterPropertiesSet() throws Exception {
        this.sc.setAttribute(PARAMETERS_SC_ATTRIBUTE, loadProperties());
    }
    
    @控制器
    公共类ParameterizationController实现ServletContextAware,初始化bean{
    受保护的最终日志记录器=LogFactory.getLog(getClass());
    公共静态最终字符串参数\u SC\u ATTRIBUTE=“allProps”;
    私人服务;
    公共参数化控制器(){
    logger.info(“内部参数化控制器…”);
    }
    @自动连线
    私人服务;
    @RequestMapping(“/loadparams.do”)
    公共字符串formHandler(
    (模型){
    String forwardValue=“/loadparams”;
    //管理员也可以调用此页面在运行时重新加载道具
    this.sc.setAttribute(PARAMETERS_sc_属性,loadProperties());
    返回值;
    }
    私有HashMap loadProperties(){
    返回someService.loadProperties();
    }
    //确保注入SC以供使用
    公共void setServletContext(ServletContext sc){
    这个.sc=sc;
    }
    //仅在完成所有注射后运行
    public void afterPropertieSet()引发异常{
    this.sc.setAttribute(PARAMETERS_sc_属性,loadProperties());
    }
    
    我使用了方法1,但我没有使用PostContrust,而是在bean定义中使用了init Method属性,这似乎是我所需要的。是的,这是完全相同的。事实上,
    init Method
    入侵性最小(您也可以实现
    初始化bean
    ),因为它完全不依赖于您的bean。