分享

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

 WindySky 2017-11-03

用户类

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

预初始化

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

  1. public class UserJedisPoolManager extends BasicModule{  
  2.       
  3.     private static final Logger log = LoggerFactory.getLogger(UserJedisPoolManager.class);  
  4.       
  5.     private static final String OF_ALL_USER = "select username, encryptedPassword, name, email, moblie, creationDate, modificationDate from ofuser";  
  6.     private static final String OF_USER_VCARD = "select username, vcard from ofvcard";  
  7.     private static final String OF_PRESENCE = "select username, offlinePresence, offlineDate from ofPresence";  
  8.       
  9.       
  10.     //private static final String REDIS_USER = "REDIS_USER";  
  11.     private static final Integer timeout = 1000*10;  
  12.     private static final int maxActive = 5000 * 10;  
  13.     private static final int maxIdle = 50;  
  14.     private static final long maxWait = (1000 * 100);  
  15.       
  16.     private static JedisPool pool;  
  17.     private static XMPPServer loaclserver;  
  18.     private static JedisPoolConfig configs;  
  19.       
  20.     public UserJedisPoolManager() {  
  21.         super("User redis manager");  
  22.     }  
  23.   
  24.     private static JedisPoolConfig createConfig() {  
  25.         configs = new JedisPoolConfig();  
  26.         configs.setMaxActive(maxActive);  
  27.         configs.setMaxIdle(maxIdle);  
  28.         configs.setMaxWait(maxWait);  
  29.         configs.setTestOnBorrow(false);  
  30.         return configs;  
  31.     }  
  32.       
  33.     private void createJedisPool() {  
  34.         RedisConfig redisConfig = loaclserver.getJedisConfDao().getRedisConfig("REDIS_USER");  
  35.         if (redisConfig != null) {  
  36.                     + " ,auto:" + redisConfig.getAuto());  
  37.             System.out.println(redisConfig.getAuto() .equals("") );  
  38.             pool = new JedisPool(createConfig(), redisConfig.getIp(), Integer.valueOf(redisConfig.getPort().trim()),   
  39.                     timeout, redisConfig.getAuto().equals("")  ? null : redisConfig.getAuto());  
  40.             Jedis jedis = pool.getResource();  
  41.             jedis.select(0);  
  42.             if(!jedis.exists("OFUSER:admin")) {  
  43.                 DefaultAuthProvider dup = new DefaultAuthProvider();  
  44.                 try {  
  45.                     String password = dup.getPassword("admin");  
  46.                     password = AuthFactory.encryptPassword(password);  
  47.                     Map<String, String> map = new HashMap<String, String>();  
  48.                     map.put("NAME", "admin");  
  49.                     map.put("PASSWORD", password);  
  50.                     map.put("CREATIONDATE", "0");  
  51.                     map.put("MODIFICATIONDATE", "0");  
  52.                     jedis.hmset("OFUSER:admin", map);  
  53.                 } catch (UserNotFoundException e) {  
  54.                     e.printStackTrace();  
  55.                 }finally{  
  56.                     pool.returnResource(jedis);  
  57.                 }           }  
  58.         }  
  59.     }  
  60.   
  61.     private void poolInit() {  
  62.         createJedisPool();  
  63.     }  
  64.   
  65.     public Jedis getJedis() {  
  66.         if (pool == null)  
  67.         {  
  68.             poolInit();  
  69.         }  
  70.         Jedis jedis = pool.getResource();  
  71.         jedis.select(0);  
  72.         return jedis;  
  73.     }  
  74.   
  75.     public void returnRes(Jedis jedis) {  
  76.         pool.returnResource(jedis);  
  77.     }  
  78.       
  79.     @Override  
  80.     public void initialize(XMPPServer server) {  
  81.         super.initialize(server);  
  82.         loaclserver = server;  
  83.         poolInit();  
  84.         log.info("UserManager By Redis: start init....");  
  85.           
  86.     }  
  87.       
  88.     public Collection<User> getAllUser() {  
  89.         Collection<User> users = new ArrayList<User>();  
  90.         PreparedStatement pstmt = null;  
  91.         Connection con = null;  
  92.         ResultSet rs = null;  
  93.         try {  
  94.             con = (Connection) DbConnectionManager.getConnection();  
  95.             pstmt = con.prepareStatement(OF_ALL_USER);  
  96.             rs = pstmt.executeQuery();  
  97.             while(rs.next()) {  
  98.                 User user = new User();  
  99.                 user.setUsername(rs.getString(1));  
  100.                 user.setPassword(rs.getString(2));  
  101.                 user.setName(rs.getString(3));  
  102.                 user.setEmail(rs.getString(4));  
  103.                 user.setMoblie(rs.getString(5));  
  104.                 user.setCreationDate(rs.getString(6));  
  105.                 user.setModificationDate(rs.getString(7));  
  106.                 users.add(user);  
  107.             }  
  108.         }catch (Exception e) {  
  109.              log.info( e.getMessage());  
  110.              e.printStackTrace();  
  111.          }  
  112.          finally {  
  113.              DbConnectionManager.closeConnection(pstmt, con);  
  114.          }  
  115.         return users;  
  116.     }  
  117.       
  118.     public Collection<UserVcard> getUserVcard() {  
  119.         Collection<UserVcard> userVcards = new ArrayList<UserVcard>();  
  120.         PreparedStatement pstmt = null;  
  121.         Connection con = null;  
  122.         ResultSet rs = null;  
  123.         try {  
  124.             con = (Connection) DbConnectionManager.getConnection();  
  125.             pstmt = con.prepareStatement(OF_USER_VCARD);  
  126.             rs = pstmt.executeQuery();  
  127.             while(rs.next()) {  
  128.                 UserVcard user = new UserVcard();  
  129.                 user.setUsername(rs.getString(1));  
  130.                 user.setVcard(rs.getString(2));  
  131.                 userVcards.add(user);  
  132.             }  
  133.         }catch (Exception e) {  
  134.              log.info( e.getMessage());  
  135.              e.printStackTrace();  
  136.          }  
  137.          finally {  
  138.              DbConnectionManager.closeConnection(pstmt, con);  
  139.          }  
  140.         return userVcards;  
  141.     }  
  142.       
  143.     public Collection<Presence> getPresences() {  
  144.         ......  
  145.     }  
  146. }  

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

用户认证

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

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

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

RedisAuthProvider

  1. public class RedisAuthProvider implements AuthProvider{  
  2.   
  3.     private static final Logger log = LoggerFactory.getLogger(RedisAuthProvider.class);  
  4.     private static HmThreadPool threadPool = new HmThreadPool(3);  
  5.     ......  
  6.   
  7.     @Override  
  8.     public void authenticate(String username, String password)  
  9.             throws UnauthorizedException, ConnectionException,  
  10.             InternalUnauthenticatedException {  
  11.         ......  
  12.     }  
  13.   
  14.     @Override  
  15.     public void authenticate(String username, String token, String digest)  
  16.             throws UnauthorizedException, ConnectionException,  
  17.             InternalUnauthenticatedException {  
  18.         ......  
  19.     }  
  20.   
  21.     @Override  
  22.     public String getPassword(String username) throws UserNotFoundException,  
  23.             UnsupportedOperationException {  
  24.         Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();  
  25.         try {  
  26.             String pw = jedis.hmget("OFUSER:" + username, "PASSWORD").get(0);  
  27.             if (pw == null) {  
  28.                 String userid = jedis.get("MOBILE:" + username);  
  29.                 pw = jedis.hmget("OFUSER:" + userid, "PASSWORD").get(0);  
  30.             }  
  31.             return AuthFactory.decryptPassword(pw);  
  32.         } finally {  
  33.             XMPPServer.getInstance().getUserJedis().returnRes(jedis);  
  34.         }  
  35.     }  
  36.   
  37.     @Override  
  38.     public void setPassword(String username, String password)  
  39.             throws UserNotFoundException, UnsupportedOperationException {  
  40.         Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();  
  41.         try {  
  42.             password = AuthFactory.encryptPassword(password);  
  43.             jedis.hset("OFUSER:" + username, "PASSWORD", password);  
  44.         } finally {  
  45.             XMPPServer.getInstance().getUserJedis().returnRes(jedis);  
  46.         }  
  47.         threadPool.execute(createTask(XMPPServer.getInstance().getJedisConfDao().getAuthProvider(), username, password));  
  48.     }  
  49.   
  50.     @Override  
  51.     public boolean supportsPasswordRetrieval() {  
  52.         // TODO Auto-generated method stub  
  53.         return true;  
  54.     }  
  55.       
  56.     private static final String UPDATE_PASSWORD =  
  57.             "UPDATE ofUser SET encryptedPassword=? WHERE username=?";  
  58.       
  59.     private Runnable createTask(final AuthProvider edp, final String username,   
  60.                                             final String password) {     
  61.         return new Runnable() {     
  62.             public void run() {  
  63.                 try {  
  64.                     //edp.setPassword(username, password);  
  65.                       
  66.                     Connection con = null;  
  67.                     PreparedStatement pstmt = null;  
  68.                     try {  
  69.                         con = DbConnectionManager.getConnection();  
  70.                         pstmt = con.prepareStatement(UPDATE_PASSWORD);  
  71.                         if (password == null) {  
  72.                             pstmt.setNull(1, Types.VARCHAR);  
  73.                         }  
  74.                         else {  
  75.                             pstmt.setString(1, password);  
  76.                         }  
  77.                         pstmt.setString(2, username);  
  78.                         pstmt.executeUpdate();  
  79.                     }  
  80.                     catch (SQLException sqle) {  
  81.                         throw new UserNotFoundException(sqle);  
  82.                     }  
  83.                     finally {  
  84.                         DbConnectionManager.closeConnection(pstmt, con);  
  85.                     }  
  86.                       
  87.                 } catch (UserNotFoundException e) {  
  88.                     log.info("UserNotFoundException: " + username);  
  89.                 }  
  90.             }     
  91.        };     
  92.    }   
  93. }  

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

provider.auth.className

org.jivesoftware.util.redis.expand.RedisAuthProvider


RedisUserProvider:

  1. public class RedisUserProvider implements UserProvider{  
  2. ......  
  3.     public User loadUser(String username) throws UserNotFoundException {  
  4.         if(username.contains("@")) {  
  5.             if (!XMPPServer.getInstance().isLocal(new JID(username))) {  
  6.                 throw new UserNotFoundException("Cannot load user of remote server: " + username);  
  7.             }  
  8.             username = username.substring(0,username.lastIndexOf("@"));  
  9.         }  
  10.           
  11.         Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();  
  12.           
  13.         try {  
  14.             Map<String, String> map = jedis.hgetAll("OFUSER:" + username);  
  15.             String usernames = username;  
  16.             if (map.isEmpty()) {  
  17.                 String userid = jedis.get("OFUSER:" + username);  
  18.                 map = jedis.hgetAll("OFUSER:" + userid);  
  19.                 if (map.isEmpty()) {  
  20.                     return XMPPServer.getInstance().getJedisConfDao().getUserProvider().loadUser(username);  
  21.                 }  
  22.                 usernames = userid;  
  23.             }  
  24.             String name = map.get("NAME");  
  25.             String email = map.get("EMAIL");  
  26.             String mobile = map.get("MOBILE");  
  27.             String creationDate = map.get("CREATIONDATE");  
  28.             String modificationDate = map.get("MODIFICATIONDATE");  
  29.               
  30.             User user = new User(usernames, name, email, mobile, new Date(Long.parseLong(creationDate.equals("0")||creationDate.equals("") ? StringUtils.dateToMillis(new Date()) : creationDate)),   
  31.                     new Date(Long.parseLong(modificationDate.equals("0")||modificationDate.equals("") ? StringUtils.dateToMillis(new Date()) : modificationDate)));  
  32.               
  33.             return user;  
  34.               
  35.         } finally {  
  36.             XMPPServer.getInstance().getUserJedis().returnRes(jedis);  
  37.         }  
  38.           
  39.     }  
  40.   
  41.     public User createUser(String username, String password, String name, String email)  
  42.             throws UserAlreadyExistsException  
  43.     {  
  44.         return createUser(username, password, name, email, null);  
  45.     }  
  46.   
  47.     public User createUser(String username, String password, String name, String email, String moblie)  
  48.             throws UserAlreadyExistsException{  
  49.         try {  
  50.             loadUser(username);  
  51.             // The user already exists since no exception, so:  
  52.             throw new UserAlreadyExistsException("Username " + username + " already exists");  
  53.         }  
  54.         catch (UserNotFoundException unfe) {  
  55.    
  56.             Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();  
  57.               
  58.             Map<String, String> hash = new HashMap<String, String>();  
  59.               
  60.             password = AuthFactory.encryptPassword(password);  
  61.               
  62.             hash.put("PASSWORD", password);  
  63.             if (name != null && !"".equals(name))  
  64.                 hash.put("NAME", name);  
  65.             if (email != null && !"".equals(email))   
  66.                 hash.put("EMAIL", email);  
  67.             if (moblie != null && !"".equals(moblie))   
  68.                 hash.put("MOBILE", moblie);  
  69.    
  70.             Date now = new Date();  
  71.             hash.put("CREATIONDATE", StringUtils.dateToMillis(now));  
  72.             hash.put("MODIFICATIONDATE", StringUtils.dateToMillis(now));  
  73.               
  74.             try {  
  75.                 jedis.hmset("OFUSER:" + username, hash);  
  76.             } finally {  
  77.                 XMPPServer.getInstance().getUserJedis().returnRes(jedis);  
  78.             }  
  79.   
  80.             threadPool.execute(createTaskAddUser(username, null, password, name, email, moblie));  
  81.             return new User(username, name, email, moblie, now, now);  
  82.         }  
  83.     }  
  84.       
  85.     private Runnable createTaskAddUser(final String username, final String password, final String encryptedPassword,   
  86.             final String name, final String email, final String moblie) {  
  87.             return new Runnable() {  
  88.                 public void run () {  
  89.                     .....  
  90.                 }  
  91.             };  
  92.     }  
  93.       
  94.     public void deleteUser(String username) {  
  95.         ......  
  96.     }  
  97.   
  98.     public int getUserCount() {  
  99.         int count = 0;  
  100.         Connection con = null;  
  101.         PreparedStatement pstmt = null;  
  102.         ResultSet rs = null;  
  103.         try {  
  104.             con = DbConnectionManager.getConnection();  
  105.             pstmt = con.prepareStatement(USER_COUNT);  
  106.             rs = pstmt.executeQuery();  
  107.             if (rs.next()) {  
  108.                 count = rs.getInt(1);  
  109.             }  
  110.         }  
  111.         catch (SQLException e) {  
  112.             Log.error(e.getMessage(), e);  
  113.         }  
  114.         finally {  
  115.             DbConnectionManager.closeConnection(rs, pstmt, con);  
  116.         }  
  117.         return count;  
  118.     }  
  119.   
  120.     public Collection<User> getUsers() {  
  121.         Collection<String> usernames = getUsernames(0, Integer.MAX_VALUE);  
  122.         return new UserCollection(usernames.toArray(new String[usernames.size()]));  
  123.     }  
  124.   
  125.     public Collection<String> getUsernames() {  
  126.         return getUsernames(0, Integer.MAX_VALUE);  
  127.     }  
  128.   
  129.     private Collection<String> getUsernames(int startIndex, int numResults) {  
  130.         ......  
  131.     }  
  132.   
  133.     public Collection<User> getUsers(int startIndex, int numResults) {  
  134.         Collection<String> usernames = getUsernames(startIndex, numResults);  
  135.         return new UserCollection(usernames.toArray(new String[usernames.size()]));  
  136.     }  
  137.   
  138.     public void setName(String username, String name) throws UserNotFoundException {  
  139.         ......  
  140.     }  
  141.   
  142.     public void setEmail(String username, String email) throws UserNotFoundException {  
  143.         ......  
  144.     }  
  145.   
  146.     public void setCreationDate(String username, Date creationDate) throws UserNotFoundException {  
  147.         ......  
  148.     }  
  149.   
  150.     public void setModificationDate(String username, Date modificationDate) throws UserNotFoundException {  
  151.         ......  
  152.     }  
  153.   
  154.     public Set<String> getSearchFields() throws UnsupportedOperationException {  
  155.         return new LinkedHashSet<String>(Arrays.asList("Username", "Name", "Email"));  
  156.     }  
  157.   
  158.     public Collection<User> findUsers(Set<String> fields, String query) throws UnsupportedOperationException {  
  159.         return findUsers(fields, query, 0, 100);  
  160.     }  
  161.   
  162.     public Collection<User> findUsers(Set<String> fields, String query, int startIndex,  
  163.             int numResults) throws UnsupportedOperationException  
  164.     {  
  165.         ......  
  166.     }  
  167.     /** 
  168.      * Make sure that Log.isDebugEnabled()==true before calling this method. 
  169.      * Twenty elements will be logged in every log line, so for 81-100 elements 
  170.      * five log lines will be generated 
  171.      * @param listElements a list of Strings which will be logged  
  172.      */  
  173.     private void LogResults(List<String> listElements) {  
  174.       ......  
  175.     }  
  176.   
  177.     @Override  
  178.     public void setMoblie(String username, String moblie)  
  179.             throws UserNotFoundException {  
  180.        ......  
  181.     }  
  182. }  

注意:这里有个moblie字段。在原来openfire用户认证表里面是没有这个字段的。这里是本人新加的字段。方便手机登陆。看各自的页面场景啦。



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多