关于微信开发时候的UnionId问题

什么是unionId?

微信为了将同一个公司/实体的不同应用里的同一个用户关联起来。(好绕)

为什么要有unionId这个东西?

定义的很清楚,因为账户系统需要知道从公司的各个微信应用中(小程序、网页、APP)进来的用户是同一个。便于账号管理,否则可能会出现同一个人由于使用不同的应用造成多个账号的问题。对用户来说,最好是无感的。

实际情况中,很常见的一种情况:先有公众号,网页开发,一段时间,然后上线小程序或者APP。这时候就必须将原有的网页授权信息补充unionid,因为原来可能是没有的。可以通过微信API批量地获取「已关注公众号」用户的unionId并更新到系统里。

但是,之前的授权信息可能是单次授权,用户并没有关注公众号,那么对于这部分用户,是无法通过微信的API获得unionId的。

这时候,就需要在系统逻辑中兼容这种情况,即下次这些用户登录时候,如果unionId没有,就要顺便将unionId更新上。但是,如果这些人通过小程序或者APP进来呢?因为之前的账户信息没有unionId,所以小程序登录后无法通过unionId关联到之前的账号(而之前的账号有可能是有资产的,比如余额、积分、券)。

一种解决办法是:检查所有没有unionId,也没有关注公众号的用户,将信息删除掉。这样下次这部分用户直接就有unionId,重建账号。缺点是:如果用户账号里有资产,这样就不合适了。:-p

另一种解决办法:账号体系强制关联手机号码(前提是从系统建立之初就是这个规则),这样就可能通过手机号进行一次关联,如果关联到,则将新的小程序或者APP指向手机号码指向的用户。缺点:前提可能并不存在 – 毕竟没有必要强制做手机号码关联这件事。

没有其他解决办法了。

这种问题的产生原因就非常蛋疼。

junit单元测试基类

自己写了一个用来简化代码的单元测试基类,省的每次都要初始化spring和获取相应的bean对象。

public class BaseTest {
    static ApplicationContext ac = null;
    static {
        ac = new ClassPathXmlApplicationContext(
                new String[] {"/test-*.xml"});
    }
    protected C target;
    public BaseTest() {
    }
    @Before
    public void setUp(){
        Class targetClz = (Class) ((ParameterizedType) getClass()
                .getGenericSuperclass()).getActualTypeArguments()[0];
        String targetClzName = targetClz.getSimpleName();
        String arg0 = targetClzName.substring(0,1).toLowerCase()+targetClzName.substring(1);
        target = (C)ac.getBean(arg0);
    }
}

这样,在测试用例类里就比较简单了:

public class XXXDaoImplTest extends BaseTest{
    @Test
    public void testFindAll() {
        List l = target.findAll();
        assertTrue(l.size()>0);
    }
}

这样做的前提是一定要遵循命名规则 – bean的id是相应类的名的首字母小写,比如 AbcDao的实现是AbcDaoImpl,声明测试类时要给出AbcDao作为泛型参数。当然BaseTest的内容很简单,如果需要定制也很方便。

关于对象图(object graph)的idea

可能一说object graph,有sense的人就想到ognl。没错应该是这样,我在一开始遇到这个问题也是一样的想法。我的最初想法是:有没有一个工具可以把一个实例对象的对象图“路径”全部列出来呢。比如,类Father:

class Father{
String name;
List<Child> children;

}
class Child{
String name,age;
Father father;

}

现在有一个叫王二猫的father,有两个孩子,那么我要的就是:

father.name
father.child[0].name
father.child[0].age
father.child[1].name
father.child[1].age

我不需要知道具体的内容,只需要上面的这些object graph里的路径,当然我会用这些路径获取相应的属性值。ognl和commons-beanutils是把这些路径作为参数来获取相应的属性值,而我想要的就是根据一个存在的对象来生成所有可能的路径串。这样作有甚么意义呢?可能很多人不是很明白我到底想要干什么。其实由来是:我想要动态的方式去遍历对象的所有属性(包括nested属性),然后统一处理,比如想要比较两个对象我不许要写一大堆代码去一个个遍历每个属性,而是根据object graph的路径去动态获取。

可能是“成长”了,最近想的东西很多都是关于动态,脚本。btw,BeanUtils.describe是做不到的,因为得不到nested属性 – 不过似乎可以用它来遍历对象图. – 这样好吗?

Spring SimpleFormController Cheatsheet

pdf下载