Browse Source

添加用户信息同步

wangmh 8 years ago
parent
commit
73afd66352

+ 26 - 0
sso-server/src/main/java/com/uas/sso/core/ICallable.java

@@ -0,0 +1,26 @@
+package com.uas.sso.core;
+
+import java.util.concurrent.Callable;
+
+/**
+ * 能传入参数执行的callable
+ * 
+ * @author yingp
+ * @see Callable
+ * 
+ * @param <V>
+ *            返回结果类型
+ * @param <T>
+ *            参数类型
+ */
+public interface ICallable<V, T> {
+
+	/**
+	 * 接口回调方法
+	 * @param param 回调参数
+	 * @return
+	 * @throws Exception
+	 */
+	V call(T param) throws Exception;
+
+}

+ 37 - 0
sso-server/src/main/java/com/uas/sso/core/ICallableAdapter.java

@@ -0,0 +1,37 @@
+package com.uas.sso.core;
+
+import java.util.concurrent.Callable;
+
+/**
+ * 代理callable来执行
+ * 
+ * <pre>
+ * 涉及到一个callable对象调用不同参数循环执行的问题,不能直接在ICallable对象里面设置参数,需要代理执行
+ * </pre>
+ * 
+ * @see ICallable
+ * @see Callable
+ * 
+ * @author yingp
+ * 
+ * @param <V>
+ *            返回结果类型
+ * @param <T>
+ *            参数类型
+ */
+public final class ICallableAdapter<V, T> implements Callable<V> {
+
+	private final ICallable<V, T> task;
+	private final T param;
+
+	public ICallableAdapter(ICallable<V, T> task, T param) {
+		this.task = task;
+		this.param = param;
+	}
+
+	@Override
+	public V call() throws Exception {
+		return task.call(param);
+	}
+
+}

+ 87 - 0
sso-server/src/main/java/com/uas/sso/core/MergeTask.java

@@ -0,0 +1,87 @@
+package com.uas.sso.core;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.*;
+
+/**
+ * 任务聚合<br>
+ * 将多个分支任务并行处理,将任务处理的结果合并返回
+ * 
+ * @author yingp
+ *
+ * @param <V>
+ *            返回结果类型
+ * @param <T>
+ *            传递参数类型
+ */
+public class MergeTask<V, T> {
+
+	/**
+	 * 缓冲的线程池
+	 */
+	private final ExecutorService threadPool;
+
+	private final CompletionService<V> service;
+
+	/**
+	 * 定义一个带参有返回的callable
+	 */
+	private final ICallable<V, T> callable;
+
+	private int taskCount = 0;
+
+	public MergeTask(ICallable<V, T> callable) {
+		this.threadPool = Executors.newCachedThreadPool();
+		this.service = new ExecutorCompletionService<V>(threadPool);
+		this.callable = callable;
+	}
+
+	/**
+	 * 添加分支任务
+	 * 
+	 * @param param
+	 *            针对ICallable传递的参数
+	 * @return
+	 */
+	public MergeTask<V, T> join(T param) {
+		service.submit(new ICallableAdapter<V, T>(callable, param));
+		taskCount++;
+		return this;
+	}
+
+	/**
+	 * 获取聚合的结果,结果扔到List里面返回
+	 * 
+	 * @return
+	 */
+	public List<V> execute() {
+		threadPool.shutdown();
+		int finish = 0;
+		List<V> datas = new ArrayList<V>();
+		while (finish < taskCount) {
+			// 非阻塞方式
+			Future<V> future = service.poll();
+			if (future != null) {
+				try {
+					V result = future.get();
+					if (result != null) {
+						datas.add(result);
+					}
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+				finish++;
+			}
+			if (finish < taskCount) {
+				try {
+					// 等待50毫秒再进入下一次查找
+					TimeUnit.MILLISECONDS.sleep(50);
+				} catch (InterruptedException e) {
+				}
+			}
+		}
+		return datas;
+	}
+
+}

+ 9 - 0
sso-server/src/main/java/com/uas/sso/dao/AppDao.java

@@ -3,6 +3,9 @@ package com.uas.sso.dao;
 import com.uas.sso.entity.App;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
 
 /**
  * 应用dao, 应用主键为uid
@@ -12,4 +15,10 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
  */
 public interface AppDao extends JpaRepository<App, String>, JpaSpecificationExecutor<App> {
 
+    /**
+     * 查找左右应用的id
+     * @return
+     */
+    @Query("select t.uid from App t")
+    List<String> findUid();
 }

+ 13 - 0
sso-server/src/main/java/com/uas/sso/dao/SyncLogDao.java

@@ -0,0 +1,13 @@
+package com.uas.sso.dao;
+
+import com.uas.sso.entity.SyncLog;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+/**
+ * @author wangmh
+ * @create 2018-01-22 10:47
+ * @desc
+ **/
+public interface SyncLogDao extends JpaRepository<SyncLog, Long>, JpaSpecificationExecutor<SyncLog> {
+}

+ 129 - 0
sso-server/src/main/java/com/uas/sso/entity/SyncLog.java

@@ -0,0 +1,129 @@
+package com.uas.sso.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+/**
+ * @author wangmh
+ * @create 2018-01-22 9:36
+ * @desc 同步日志
+ **/
+@Entity
+@Table(name = "sso$log$sync")
+public class SyncLog extends BaseLog implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @Column(name = "_id")
+    @SequenceGenerator(name="sso$log$sync_gen", sequenceName="sso$log$sync_seq", allocationSize=1)
+    @GeneratedValue(strategy=GenerationType.IDENTITY, generator="sso$log$sync_gen")
+    private Long id;
+
+    /**
+     * 同步应用uid
+     */
+    @Column(name = "to_app")
+    private String toApp;
+
+    /**
+     * 同步信息描述
+     */
+    @Column(name = "msg")
+    private String msg;
+
+    /**
+     * 同步信息
+     */
+    @Column(name = "msg_detail", length = 1000)
+    private String msgDetail;
+
+    /**
+     * 同步等级(info or error)
+     */
+    @Column(name = "level", nullable = false)
+    private String level;
+
+    /**
+     * 返回信息
+     */
+    @Column(name = "return_msg")
+    private String returnMsg;
+
+    /**
+     * 同步时间
+     */
+    @Column(name = "time")
+    private Timestamp time;
+
+    public SyncLog() {
+    }
+
+    public SyncLog(String appId, String msg, String msgDetail, String level) {
+       this(appId, msg, msgDetail, level, null);
+    }
+
+    public SyncLog(String appId, String msg, String msgDetail, String level, String returnMsg) {
+        this.toApp = appId;
+        this.msg = msg;
+        this.msgDetail = msgDetail;
+        this.returnMsg = returnMsg;
+        this.level = level;
+        this.time = new Timestamp(System.currentTimeMillis());
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getToApp() {
+        return toApp;
+    }
+
+    public void setToApp(String toApp) {
+        this.toApp = toApp;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public String getMsgDetail() {
+        return msgDetail;
+    }
+
+    public void setMsgDetail(String msgDetail) {
+        this.msgDetail = msgDetail;
+    }
+
+    public String getReturnMsg() {
+        return returnMsg;
+    }
+
+    public void setReturnMsg(String returnMsg) {
+        this.returnMsg = returnMsg;
+    }
+
+    public Timestamp getTime() {
+        return time;
+    }
+
+    public void setTime(Timestamp time) {
+        this.time = time;
+    }
+}

+ 19 - 0
sso-server/src/main/java/com/uas/sso/entity/User.java

@@ -414,4 +414,23 @@ public class User implements Serializable {
     public void setUserspaces(List<Userspace> userspaces) {
         this.userspaces = userspaces;
     }
+
+    public UserView toView() {
+        UserView userView = new UserView();
+        userView.setUserUU(this.getUserUU());
+        userView.setVipName(this.getVipName());
+        userView.setMobile(this.getMobile());
+        userView.setMobileArea(this.getMobileArea());
+        userView.setMobileValidCode(this.getMobileValidCode());
+        userView.setPassword(this.getPassword());
+        userView.setSalt(this.getSalt());
+        userView.setRegisterDate(this.getRegisterDate());
+        userView.setEmail(this.getEmail());
+        userView.setEmailValidCode(this.getEmailValidCode());
+        userView.setRealName(this.getRealName());
+        userView.setIdCard(this.getIdCard());
+        userView.setIdentityValidCode(this.getIdentityValidCode());
+        userView.setLock(this.getLock());
+        return userView;
+    }
 }

+ 1 - 1
sso-server/src/main/java/com/uas/sso/entity/UserLog.java

@@ -68,7 +68,7 @@ public class UserLog extends BaseLog implements Serializable {
     @Column(name = "otherMsg", length = 2000)
     private String otherMsg;
 
-    public UserLog() {
+    public UserLog(String appId, String msg, String msgDetail, int returnCode, String returnMsg) {
     }
 
     public UserLog(User user, String level, String type) {

+ 35 - 0
sso-server/src/main/java/com/uas/sso/logging/SyncBufferedLogger.java

@@ -0,0 +1,35 @@
+package com.uas.sso.logging;
+
+import com.alibaba.fastjson.JSON;
+import com.uas.sso.core.Level;
+import com.uas.sso.entity.SyncLog;
+import com.uas.sso.entity.User;
+import com.uas.sso.entity.UserLog;
+import com.uas.sso.service.SyncLogService;
+import com.uas.sso.util.ContextUtils;
+
+/**
+ * @author wangmh
+ * @create 2018-01-22 10:30
+ * @desc 同步日志
+ **/
+public class SyncBufferedLogger extends Logger<SyncLog> {
+
+    private static final int SUCCES_RETURN_CODE = 200;
+
+    SyncBufferedLogger() {
+        super(ContextUtils.getBean(SyncLogService.class));
+    }
+
+    public void error(String appId, String msg, String msgDetail, String returnMsg) {
+        log(new SyncLog(appId, msg, msgDetail, Level.ERROR.getValue(), returnMsg));
+    }
+
+    public void info(String appId, String msg, String msgDetail) {
+        log(new SyncLog(appId, msg, msgDetail, Level.INFO.getValue()));
+    }
+
+    public void info(String appId, User user) {
+        info(appId, "同步用户信息", JSON.toJSONString(user));
+    }
+}

+ 6 - 0
sso-server/src/main/java/com/uas/sso/service/AppService.java

@@ -33,4 +33,10 @@ public interface AppService {
      * @return
      */
     List<App> findAll();
+
+    /**
+     * 查询所有应用的id
+     * @return
+     */
+    List<String> findUid();
 }

+ 11 - 0
sso-server/src/main/java/com/uas/sso/service/SyncLogService.java

@@ -0,0 +1,11 @@
+package com.uas.sso.service;
+
+import com.uas.sso.entity.SyncLog;
+
+/**
+ * @author wangmh
+ * @create 2018-01-22 10:33
+ * @desc 同步日志service
+ **/
+public interface SyncLogService extends BaseLogService<SyncLog> {
+}

+ 5 - 0
sso-server/src/main/java/com/uas/sso/service/impl/AppServiceImpl.java

@@ -34,4 +34,9 @@ public class AppServiceImpl implements AppService {
     public List<App> findAll() {
         return appDao.findAll();
     }
+
+    @Override
+    public List<String> findUid() {
+        return appDao.findUid();
+    }
 }

+ 31 - 0
sso-server/src/main/java/com/uas/sso/service/impl/SyncLogServiceImpl.java

@@ -0,0 +1,31 @@
+package com.uas.sso.service.impl;
+
+import com.uas.sso.dao.SyncLogDao;
+import com.uas.sso.entity.SyncLog;
+import com.uas.sso.service.SyncLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author wangmh
+ * @create 2018-01-22 10:46
+ * @desc
+ **/
+@Service
+public class SyncLogServiceImpl implements SyncLogService {
+
+    @Autowired
+    private SyncLogDao syncLogDao;
+
+    @Override
+    public SyncLog save(SyncLog logger) {
+        return syncLogDao.save(logger);
+    }
+
+    @Override
+    public List<SyncLog> save(Iterable<SyncLog> loggers) {
+        return syncLogDao.save(loggers);
+    }
+}

+ 75 - 4
sso-server/src/main/java/com/uas/sso/service/impl/UserServiceImpl.java

@@ -1,22 +1,27 @@
 package com.uas.sso.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.uas.sso.common.encrypt.MD5;
+import com.uas.sso.common.util.HttpUtil;
 import com.uas.sso.core.Const;
+import com.uas.sso.core.ICallable;
 import com.uas.sso.core.Status;
 import com.uas.sso.core.Type;
 import com.uas.sso.dao.UserDao;
 import com.uas.sso.dao.UserRecordDao;
-import com.uas.sso.entity.User;
-import com.uas.sso.entity.UserAccount;
-import com.uas.sso.entity.UserRecord;
+import com.uas.sso.entity.*;
 import com.uas.sso.exception.VisibleError;
 import com.uas.sso.logging.LoggerManager;
+import com.uas.sso.logging.SyncBufferedLogger;
 import com.uas.sso.logging.UserBufferedLogger;
+import com.uas.sso.service.AppService;
 import com.uas.sso.service.UserService;
 import com.uas.sso.service.UserValidService;
 import com.uas.sso.support.SystemSession;
 import com.uas.sso.util.AccountTypeUtils;
 import com.uas.sso.util.BeanUtil;
+import com.uas.sso.util.ExecuteUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
@@ -24,7 +29,11 @@ import org.springframework.util.StringUtils;
 
 import com.uas.sso.exception.AccountException;
 
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
 import java.sql.Timestamp;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -45,8 +54,13 @@ public class UserServiceImpl implements UserService {
     @Autowired
     private UserValidService userValidService;
 
+    @Autowired
+    private AppService appService;
+
     private UserBufferedLogger userLog = LoggerManager.getLogger(UserBufferedLogger.class);
 
+    private SyncBufferedLogger syncLog = LoggerManager.getLogger(SyncBufferedLogger.class);
+
     @Override
     public User findByMobile(String mobile, String mobileArea) {
         return userDao.findByMobileAndMobileArea(mobile, mobileArea);
@@ -100,6 +114,9 @@ public class UserServiceImpl implements UserService {
 
         userDao.save(user);
         userLog.info(user, Type.UPDATE_REGISTER.getValue());
+
+        // 同步到各个应用
+        syncUserInfo(user.getUserUU());
         return user;
     }
 
@@ -122,7 +139,9 @@ public class UserServiceImpl implements UserService {
 
     @Override
     public User save(User user) {
-        return userDao.save(user);
+        user = userDao.save(user);
+        syncUserInfo(user.toView());
+        return user;
     }
 
     @Override
@@ -291,6 +310,9 @@ public class UserServiceImpl implements UserService {
 
         // 保存日志
         userLog.info(user, Type.UPDATE_MOBILE.getValue());
+
+        // 同步到各个应用
+        syncUserInfo(user.getUserUU());
     }
 
     @Override
@@ -310,5 +332,54 @@ public class UserServiceImpl implements UserService {
 
         // 保存日志
         userLog.info(user, Type.UPDATE_EMAIL.getValue());
+
+        // 同步信息到各应用
+        syncUserInfo(user.getUserUU());
+    }
+
+    /**
+     * 同步用户信息到各个应用
+     * @param userUU 用户uu号
+     */
+    private void syncUserInfo(Long userUU) {
+        syncUserInfo(findOneView(userUU));
+    }
+
+    /**
+     * 同步用户信息到各个应用
+     * @param userView 用户信息视图
+     */
+    private void syncUserInfo(UserView userView) {
+        List<String> apps = appService.findUid();
+
+        ExecuteUtils.execute(new ICallable<Void, String>() {
+
+            @Override
+            public Void call(String appId) {
+                App tempApp = appService.findOne(appId);
+                if (tempApp != null && StringUtils.isEmpty(tempApp.getUserControl())
+                        && !StringUtils.isEmpty(tempApp.getBackUserUrl())) {
+                    String url = tempApp.getBackUserUrl();
+                    JSONObject formData = JSON.parseObject(JSON.toJSONString(userView));
+                    HttpUtil.ResponseWrap res = null;
+                    try {
+                        res = HttpUtil.doPost(url, formData, 30000);
+                        if (!res.isSuccess()) {
+                            syncLog.error(appId, "同步用户信息成功", JSON.toJSONString(userView), res.getContent());
+                        } else {
+                            syncLog.info(appId, "同步用户信息成功", JSON.toJSONString(userView));
+                        }
+                    } catch (Exception e) {
+                        syncLog.error(appId, "同步用户信息失败", JSON.toJSONString(userView), e.getMessage());
+                    }
+                }
+                return null;
+            }
+        }, apps);
+    }
+
+    public UserView findOneView(Long userUU) {
+        User user = findOne(userUU);
+        return user.toView();
     }
 }

+ 30 - 0
sso-server/src/main/java/com/uas/sso/util/ExecuteUtils.java

@@ -0,0 +1,30 @@
+package com.uas.sso.util;
+
+import com.uas.sso.core.ICallable;
+import com.uas.sso.core.MergeTask;
+
+import java.util.Collection;
+import java.util.List;
+
+public class ExecuteUtils {
+
+	public static void asyncExecute(Runnable runnable) {
+		new Thread(runnable).start();
+	}
+
+	/**
+	 * 多任务异步执行,结果以list返回
+	 * 
+	 * @param callable
+	 * @param arguments
+	 * @return
+	 */
+	public static <V, T> List<V> execute(ICallable<V, T> callable, Collection<T> arguments) {
+		MergeTask<V, T> task = new MergeTask<V, T>(callable);
+		for (T arg : arguments) {
+			task.join(arg);
+		}
+		return task.execute();
+	}
+
+}

+ 1 - 1
sso-server/src/main/resources/prod/account.properties

@@ -2,7 +2,7 @@
 sso.app=sso
 # token secretkey
 sso.secretkey=0taQcW073Z7G628g5H
-sso.cookie.domain=ubtob.com
+#sso.cookie.domain=ubtob.com
 sso.cookie.secure=false
 sso.login.url=http://192.168.253.118:3001/
 sso.proxy.uri=http://192.168.253.118:3001/