OpenFire源码学习之二十一:openfie对用户的优化(上)

用户类

优化用户主要是要解决用户的连接量。已经对用户的访问速度和吞吐量。

预初始化

在前面的带面中提出来了用户的预初始化。这里就不在贴出来了。下面将redis用户库连接池处理贴出来UserJedisPoolManager

public class UserJedisPoolManager extends BasicModule{private static final Logger log = LoggerFactory.getLogger(UserJedisPoolManager.class);private static final String OF_ALL_USER = "select username, encryptedPassword, name, email, moblie, creationDate, modificationDate from ofuser";private static final String OF_USER_VCARD = "select username, vcard from ofvcard";private static final String OF_PRESENCE = "select username, offlinePresence, offlineDate from ofPresence";//private static final String REDIS_USER = "REDIS_USER";private static final Integer timeout = 1000*10;private static final int maxActive = 5000 * 10;private static final int maxIdle = 50;private static final long maxWait = (1000 * 100);private static JedisPool pool;private static XMPPServer loaclserver;private static JedisPoolConfig configs;public UserJedisPoolManager() {super("User redis manager");}private static JedisPoolConfig createConfig() {configs = new JedisPoolConfig();configs.setMaxActive(maxActive);configs.setMaxIdle(maxIdle);configs.setMaxWait(maxWait);configs.setTestOnBorrow(false);return configs;}private void createJedisPool() { RedisConfig redisConfig = loaclserver.getJedisConfDao().getRedisConfig("REDIS_USER");if (redisConfig != null) {+ " ,auto:" + redisConfig.getAuto());System.out.println(redisConfig.getAuto() .equals("") );pool = new JedisPool(createConfig(), redisConfig.getIp(), Integer.valueOf(redisConfig.getPort().trim()),timeout, redisConfig.getAuto().equals("") ? null : redisConfig.getAuto());Jedis jedis = pool.getResource();jedis.select(0);if(!jedis.exists("OFUSER:admin")) {DefaultAuthProvider dup = new DefaultAuthProvider();try {String password = dup.getPassword("admin");password = AuthFactory.encryptPassword(password);Map<String, String> map = new HashMap<String, String>();map.put("NAME", "admin");map.put("PASSWORD", password);map.put("CREATIONDATE", "0");map.put("MODIFICATIONDATE", "0");jedis.hmset("OFUSER:admin", map);} catch (UserNotFoundException e) {e.printStackTrace();}finally{pool.returnResource(jedis);}}}}private void poolInit() {createJedisPool();}public Jedis getJedis() {if (pool == null){poolInit();}Jedis jedis = pool.getResource();jedis.select(0);return jedis;}public void returnRes(Jedis jedis) {pool.returnResource(jedis);}@Overridepublic void initialize(XMPPServer server) {super.initialize(server);loaclserver = server;poolInit();log.info("UserManager By Redis: start init….");}public Collection<User> getAllUser() {Collection<User> users = new ArrayList<User>();PreparedStatement pstmt = null;Connection con = null;ResultSet rs = null;try {con = (Connection) DbConnectionManager.getConnection();pstmt = con.prepareStatement(OF_ALL_USER);rs = pstmt.executeQuery();while(rs.next()) {User user = new User();user.setUsername(rs.getString(1));user.setPassword(rs.getString(2));user.setName(rs.getString(3));user.setEmail(rs.getString(4));user.setMoblie(rs.getString(5));user.setCreationDate(rs.getString(6));user.setModificationDate(rs.getString(7));users.add(user);}}catch (Exception e) {log.info( e.getMessage());e.printStackTrace(); } finally {DbConnectionManager.closeConnection(pstmt, con); }return users;}public Collection<UserVcard> getUserVcard() {Collection<UserVcard> userVcards = new ArrayList<UserVcard>();PreparedStatement pstmt = null;Connection con = null;ResultSet rs = null;try {con = (Connection) DbConnectionManager.getConnection();pstmt = con.prepareStatement(OF_USER_VCARD);rs = pstmt.executeQuery();while(rs.next()) {UserVcard user = new UserVcard();user.setUsername(rs.getString(1));user.setVcard(rs.getString(2));userVcards.add(user);}}catch (Exception e) {log.info( e.getMessage());e.printStackTrace(); } finally {DbConnectionManager.closeConnection(pstmt, con); }return userVcards;}public Collection<Presence> getPresences() {……}}

在上面createJedisPool方法中预置了管理员的账号。这是因为我们需要修改openfire的用户认证dao。也就是说web控制台的管理员。在登陆web页面的时候,我们认证也是先走redis验证的。

用户认证

用户认证,首先需要重新实现AuthProvider。Openfire当中默认使用的是DefaultAuthProvider来操作数据层。当然他也提供了其他的方式实现接口,比如:HybridAuthProvider、JDBCAuthProvider、NativeAuthProvider、POP3AuthProvider等。

写完AuthProvider的Redis实现后,接下来需要基于Redis的用户DAO。

下面是两个类的源码清单:

RedisAuthProvider

public class RedisAuthProvider implements AuthProvider{private static final Logger log = LoggerFactory.getLogger(RedisAuthProvider.class);private static HmThreadPool threadPool = new HmThreadPool(3);……@Overridepublic void authenticate(String username, String password)throws UnauthorizedException, ConnectionException,InternalUnauthenticatedException {……}@Overridepublic void authenticate(String username, String token, String digest)throws UnauthorizedException, ConnectionException,InternalUnauthenticatedException {……}@Overridepublic String getPassword(String username) throws UserNotFoundException,UnsupportedOperationException {Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();try {String pw = jedis.hmget("OFUSER:" + username, "PASSWORD").get(0);if (pw == null) {String userid = jedis.get("MOBILE:" + username);pw = jedis.hmget("OFUSER:" + userid, "PASSWORD").get(0);}return AuthFactory.decryptPassword(pw);} finally {XMPPServer.getInstance().getUserJedis().returnRes(jedis);}}@Overridepublic void setPassword(String username, String password)throws UserNotFoundException, UnsupportedOperationException {Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();try {password = AuthFactory.encryptPassword(password);jedis.hset("OFUSER:" + username, "PASSWORD", password);} finally {XMPPServer.getInstance().getUserJedis().returnRes(jedis);}threadPool.execute(createTask(XMPPServer.getInstance().getJedisConfDao().getAuthProvider(), username, password));}@Overridepublic boolean supportsPasswordRetrieval() {// TODO Auto-generated method stubreturn true;}private static final String UPDATE_PASSWORD ="UPDATE ofUser SET encryptedPassword=? WHERE username=?";private Runnable createTask(final AuthProvider edp, final String username,final String password) {return new Runnable() {public void run() {try {//edp.setPassword(username, password);Connection con = null;PreparedStatement pstmt = null;try {con = DbConnectionManager.getConnection();pstmt = con.prepareStatement(UPDATE_PASSWORD);if (password == null) {pstmt.setNull(1, Types.VARCHAR);}else {pstmt.setString(1, password);}pstmt.setString(2, username);pstmt.executeUpdate();}catch (SQLException sqle) {throw new UserNotFoundException(sqle);}finally {DbConnectionManager.closeConnection(pstmt, con);}} catch (UserNotFoundException e) {log.info("UserNotFoundException: " + username);}}};} }

用户认证写完后,要记得修改系统属性表:ofProperty

provider.auth.className

org.jivesoftware.util.redis.expand.RedisAuthProvider

人生就像是一场旅行,遇到的既有感人的,

OpenFire源码学习之二十一:openfie对用户的优化(上)

相关文章:

你感兴趣的文章:

标签云: