close

  斷續踹了兩三天,搞定使用Annotation配置Data Tier,作為Spring-Security驗證來源。一樣用jdbc.properties對定義連線資訊,和applicationContext.xml放同一處可以被classpath找到,是故在applicationContext.xml設定如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="
http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">   
    <context:component-scan base-package="com.foo" use-default-filters="false">
        <context:include-filter type="regex" expression="com.foo.bar.*Config"/>
    </context:component-scan>
    <util:properties id="jdbcProperties" location="classpath:jdbc.properties"/>
    <aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>

  接著設定DataSource的Bean,在AppConfig內容如下:

public class AppConfig {
    private static Logger logger = LoggerFactory.getLogger(AppConfig.class);
    private @Value("#{jdbcProperties.driverClassName}") String driverClass;
    private @Value("#{jdbcProperties.url}") String jdbcUrl;
    private @Value("#{jdbcProperties.username}") String username;
    private @Value("#{jdbcProperties.password}") String password;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(this.driverClass);
        dataSource.setUrl(this.jdbcUrl);
        dataSource.setUsername(this.username);
        dataSource.setPassword(this.password);
        logger.debug("init dataSource");
        return dataSource;
    }
}

  AppConfig上頭沒放@Component,照樣被Spring找到@Bean,而@Value是讀jdbc.properties內容載入後面的String變數,jdbcProperties對映到applicationContext.xml的<util:properties>標籤的id屬性,而jdbcProperties.後面接的屬性即是jdbc.properties的key name。

  接著是寫Dao去引用AppConfig的Data Source @Bean,我是繼承Spring-Security的UserDetailsService當DAO用:

@Repository
public class UserDetailsServiceImpl implements UserDetailsService {
    private static Logger logger = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
   
private SimpleJdbcTemplate simpleJdbcTemplate;
    @Autowired
    public void init(DataSource datasource) {
        this.simpleJdbcTemplate = new SimpleJdbcTemplate(datasource);
        logger.debug("init: after new JdbcTemplate");
    }
   
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException {
        String sql = "select * from accounts where username=? ";
        RowMapper<UserDetails> mapper = new ParameterizedRowMapper<UserDetails>()
{
            public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
               
String username = rs.getString("username");
                String password = rs.getString("password");
                logger.debug("id/pwd=" + username + "/" + password);
                UserDetailsImpl user = new UserDetailsImpl(username, password);
                return user;
            }
        };

        UserDetails user = this.simpleJdbcTemplate.queryForObject(sql, mapper, username);
        if (user == null) throw new UsernameNotFoundException(username + " not found!");
        return user;
    }
}

  類別宣告為@Repository,效果和@Component一樣,除了是標明為DAO功能外,還真不知和@Component有哪裡不同。也許不同處就再下面的@Autowired後接的method,它傳入一個DataSource的參數,正是來自dataSource @Bean注入的。而使用Composited模式放JdbcTemplate是Spring3官方文件所建議的Best Practices,因為是使用SimpleJdbcTemplate,較之JdbcTempalte語法乾淨,從第三個參數起可帶無不限個數的參數。

simpleJdbcTemplate.queryForObject(SQL字串, RowMapper實作, …)

arrow
arrow
    全站熱搜

    Jemmy 發表在 痞客邦 留言(0) 人氣()