Spring Mvc - 创建自定义注释以从数据库中读取应用程序属性

Posted

技术标签:

【中文标题】Spring Mvc - 创建自定义注释以从数据库中读取应用程序属性【英文标题】:Spring Mvc - Creating Custom Annotation For Reading Application Properties From Database 【发布时间】:2019-12-31 13:11:57 【问题描述】:

我开发了 Spring-Mvc 项目,这个项目的应用属性太重要了。此外,我无法在程序运行期间更改此属性。所以,我想从数据库中获取这些属性并分配给类的成员。

现在,我使用服务从数据库中获取这些属性,但我不认为,这段代码是可重用的。我想知道,是否有任何方法可以通过自定义注释将此属性提供给成员?

ApplicationPropertiesDao.java

@Repository
public class ApplicationPropertiesDao implements IApplicationPropertiesDao
    @Value("#appProperties.instanceName")
    private String instanceName;

    @Override
    @Cacheable("applicationProperties")
    public HashMap<String, String> getApplicationPropertiesFromDB()
        Map<String, Object> inputMap = new HashMap<String, Object>();
        inputMap.put("instanceName", instanceName);

        String sql = getSQL("getApplicationProperties");
        Map<String, String> list = new HashMap<String, String>();

        getNamedParameterJdbcTemplate().query(sql, inputMap, new ResultSetExtractor<Map<String, String>>() 
            @Override
            public Map<String, String> extractData(ResultSet resultSet) throws SQLException, DataAccessException 
                while (resultSet.next()) 
                    list.put( resultSet.getString("NAME"),resultSet.getString("VALUE"));
                
                return list;
            
        );
        return (HashMap<String, String>) list;
    

ApplicationPropertiesService.java

@Service
public class ApplicationPropertiesService implements IApplicationPropertiesService
    @Autowired
    private IApplicationPropertiesDao applicationPropertiesDao;

    public HashMap<String, String> getApplicationPropertiesFromDB()
        return applicationPropertiesDao.getApplicationPropertiesFromDB();
    

    public Object getApplicationPropertyByName(String name, ApplicationPropertyValueTypeEnum applicationPropertyValueTypeEnum)
        String value = getApplicationPropertiesFromDB().get(name);

        if (applicationPropertyValueTypeEnum.name().equals(ApplicationPropertyValueTypeEnum.INTEGER.toString()))
            return Integer.parseInt(value);
        else if(applicationPropertyValueTypeEnum.name().equals(ApplicationPropertyValueTypeEnum.BOOLEAN.toString()))
            String upperCaseValue = value.toUpperCase(Locale.ENGLISH);
            return upperCaseValue.equals("TRUE") ? Boolean.TRUE : Boolean.FALSE;
        
        return value;
    

我可以为这种情况创建如下所示的自定义注释吗?如果有,我会很高兴。我怎么能做这个?

@Service
public class Demo
    private String val;
    @Autowired
    public ApplicationPropertiesService applicationPropertiesService;

    @GetPropertyFromDB(key = "val", type = "String")
    public getVal()
        //set(applicationPropertiesService.getApplicationPropertyByName("val", "String"));
        return this.val;
    

    public void setVal(String val)
         this.val = val;
    

感谢您的帮助。

【问题讨论】:

【参考方案1】:

我认为您需要 DB PropertyPlaceholderConfigurer。 像这样的东西: Spring PropertyPlaceholderConfigurer load from DB

如果您集成自定义 DB PropertyPlaceholderConfigurer。 (见https://www.baeldung.com/properties-with-spring)

@Bean
public static PropertySourcesPlaceholderConfigurer properties()
    return new MyDBPlaceholderConfigurer();

您将能够使用标准的@Value 和@ConfigurationProperties 注释。

【讨论】:

【参考方案2】:

我在开始时使用这个类来配置属性,但我无法在特定时间段从数据库中加载这些属性。此类作品仅开始。我可以在不重新启动程序的情况下每分钟调用一次这个 loadProperties 方法吗?

DbPropertyPlaceholderConfigurer.java

@Service
public class DbPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer 
private DataSource dataSource;
private String key = "NAME";
private String value = "VALUE";
private String table = "APPLICATION_PROPERTIES";
private String instanceName;


@Override
protected void loadProperties(final Properties props) throws IOException 
    if (null == props) 
        throw new IOException("No properties passed by Spring framework - cannot proceed.");
    

    String sql = String.format("SELECT %s, %s FROM %s where INSTANCE_NAME = '%s'", key, value,
            table, instanceName);

    try 
        JdbcTemplate t = new JdbcTemplate(dataSource);
        t.query(sql, new RowCallbackHandler() 
            @Override
            public void processRow(ResultSet rs) throws SQLException 
                String auxKey = rs.getString(key);
                String auxValue = rs.getString(value);

                if (null == auxKey || null == auxValue) 
                    throw new SQLException("Configuration database contains empty data. Name='" + (auxKey == null ? "" : auxKey)
                            + "', Value='" + (auxValue == null ? "" : auxValue) + "'.");
                

                props.setProperty(auxKey, auxValue);
            
        );
     catch (Exception e) 
        logger.error("There is an error in the configuration database.");
        throw new IOException(e);
    

    if (props.size() == 0) 
        logger.error("The configuration database could not be reached or does not contain any properties in '" + table
                + "'.");
     else 
        logger.info("Application config info loaded from configuration database.");
    


public void setDataSource(DataSource dataSource) 
    this.dataSource = dataSource;


public void setInstanceName(String instanceName) 
    this.instanceName = instanceName;

applicationContext.xml

<bean id="placeholderPropertiesDatabase" class="com.common.DbPropertyPlaceholderConfigurer" >
    <property name="dataSource" ref="dataSource" />
    <property name="instanceName" value="instance1" />

    <property name="placeholderPrefix" value="$db" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="ignoreUnresolvablePlaceholders" value="false" />
    <property name="order" value="1" />
</bean>

【讨论】:

以上是关于Spring Mvc - 创建自定义注释以从数据库中读取应用程序属性的主要内容,如果未能解决你的问题,请参考以下文章

通过注释的 Spring 授权不适用于自定义身份验证

Gradle 如何配置构建文件以从同一项目创建 Spring boot jar 和 spring web-mvc war

Spring MVC 返回自定义 HTTP 状态码(无错误)

未调用自定义 Spring 注释

spring 将两个验证注释合二为一

Spring MVC 中的自定义授权