开发工具分享
  • 首页
  • 计算科学
  • 文化旅游
  • 项目和网站
    • OSSEZ 计算技术
    • USRealEstate 社区
    • 地区文化
    • CWIKI.US
    • BUG.OSSEZ.COM
    • RSS.OSSEZ.COM
CWIKIUS.CN
一个有独立思考和温度的清新站
Computer Science

微信用户分析的返回数据

微信 API 中,针对用户数据统计可以获得用户增减数据,同时还可以获得用户累计数据。 分别是 2 个 API ,但是返回是下面 2 个对象。   2023-04-24_11-58-061024×758 35.9 KB   用户分析微信官方的 API 文档链接地址为:微信开放文档 其中一个 API 的返回的字符串。 { "list": [ { "ref_date": "2023-04-20", "user_source": 0, "new_user": 0, "cancel_user": 0 }, { "ref_date": "2023-04-21", "user_source": 0, "new_user": 0, "cancel_user": 0 }, { "ref_date": "2023-04-22", "user_source": 0, "new_user": 0, "cancel_user": 0 }, { "ref_date": "2023-04-23", "user_source": 0, "new_user": 0, "cancel_user": 0 } ] } 微信数据统计的问题 在微信数据统计的时候,如果你的请求日期是当天的话,API 会提示数据错误。 这是因为微信的数据统计不能提供当前的数据。 你将看到下面的错误提示: {"errcode":61501,"errmsg":"date range error rid: 6446a7e2-6382ec81-1f9d72d2"}     出现这个提示的原因是你的查询数据日期不正确,微信没有办法正确的返回数据。   https://www.ossez.com/t/topic/14398

2023年04月25日 0Comments 828Browse 0Like Read more
Computer Science

Retrofit 在 JSON 反序列化的时候提示 UnrecognizedPropertyException 异常

提示的异常信息如下: java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "new_user" (class com.ossez.wechat.common.model.res.UserSummaryResponse$UserData), not marked as ignorable (5 known properties: "cancel_user", "new_users", "ref_date", "user_source", "cumulate_user"]) at [Source: (okhttp3.ResponseBody$BomAwareReader); line: 1, column: 63] (through reference chain: com.ossez.wechat.common.model.res.UserSummaryResponse["list"]->java.util.ArrayList[0]->com.ossez.wechat.common.model.res.UserSummaryResponse$UserData["new_user"]) at io.reactivex.internal.util.ExceptionHelper.wrapOrThrow(ExceptionHelper.java:46) at io.reactivex.internal.observers.BlockingMultiObserver.blockingGet(BlockingMultiObserver.java:93)     问题和解决 这是因为 retrofit 在反序列化的时候,如果没有找到对应的对象名,将会报错。 关键是在下面这句话: .addConverterFactory(JacksonConverterFactory.create())     需要做的也非常简单,只需要将上面的 Jackson 的 mapper 对象映射过来就可以了。     在 ObjectMapper 对象中,我们可以定义是不是忽略没有找到的字段。 就是下面这句话: mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 这样我们就不会因为没有找到字段而出现异常的问题了。   https://www.ossez.com/t/retrofit-json-unrecognizedpropertyexception/14399

2023年04月25日 0Comments 838Browse 0Like Read more
Computer Science

TestNG 中使用 Guice 来进行依赖注入

Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IOC)。 Guice非常小而且快。Guice是类型安全的,它能够对构造函数,属性,方法(包含任意个参数的任意方法,而不仅仅是setter方法)进行注入。 Guice采用Java加注解的方式进行托管对象的配置,充分利用IDE编译器的类型安全检查功能和自动重构功能,使得配置的更改也是类型安全的。 Guice提供模块对应的抽象module,使得架构和设计的模块概念产物与代码中的module类一一对应,更加便利的组织和梳理模块依赖关系,利于整体应用内部的依赖关系维护,而其他IOC框架是没有对应物的。 此外,借助privateModule的功能,可以实现模块接口的明确导出和实现封装,使得支持多数据源这类需求实现起来异常简单。 定义一个 Guice Module 这个 Guice Model 会实现 Module 接口。   2023-04-23_15-32-551123×764 92.8 KB   然后对需要注入的类进行绑定。 绑定的语句在这里: binder.bind(TestConfigStorage.class).toInstance(config); binder.bind(WeChatOfficialAccountService.class).toInstance(weChatOfficialAccountService); binder.bind(WeChatMsgService.class).toInstance(weChatMsgService); 测试中使用 因为我们需要在测试中使用,所以我们会使用 testNG 的 Guice 注解。   2023-04-23_15-34-45825×442 33 KB   使用下面的语句直接注入到模块中。 然后把需要的服务,注入进来就可以了。 @Inject protected WeChatOfficialAccountService wxService; 是不是非常简单。   2023-04-23_15-34-45825×442 33 KB   相对 Junit 测试框架来说,TestNG 使用 Guice 更加方便。 如何在 Junit 中使用 Guice ,请参考文章:Junit 5 如何使用 Guice DI 中的内容。 https://www.ossez.com/t/testng-guice/14396  

2023年04月24日 0Comments 1611Browse 0Like Read more
Computer Science

Junit 5 如何使用 Guice DI

Guice 是一个依赖注入的小清新工具。 相比 Spring 的依赖管理来说,这个工具更加小巧,我们可以在测试中直接使用。 Junit 5 在 Junit 中使用就没有那么方便了,因为 Junit 没有 Guice 的注解。 你需要手动写一个类,在这个类中,对 Injector 的模块进行配置。 例如我们下面的代码: package com.ossez.wechat.oa.api.test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.ossez.wechat.common.exception.WxRuntimeException; import com.ossez.wechat.oa.api.WeChatOfficialAccountService; import com.ossez.wechat.oa.api.impl.okhttp.WeChatMsgService; import com.ossez.wechat.oa.api.impl.okhttp.WeChatOfficialAccountServiceOkHttp; import org.apache.commons.lang3.ObjectUtils; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.io.SAXReader; import org.junit.jupiter.api.BeforeAll; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.locks.ReentrantLock; /** * Init Guice DI * * @author YuCheng */ public class TestBase { private static final Logger log = LoggerFactory.getLogger(TestBase.class); private static final String TEST_CONFIG_XML = "test-config.xml"; private static final Injector injector = Guice.createInjector(new AbstractModule() { @Override public void configure() { try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(TEST_CONFIG_XML)) { if (ObjectUtils.isEmpty(inputStream)) { throw new WxRuntimeException("测试配置文件【" + TEST_CONFIG_XML + "】未找到,请参照test-config-sample.xml文件生成"); } // Init WeChat config for testing Document document = new SAXReader().read(inputStream); TestConfigStorage config = new TestConfigStorage(); config.setAppId(document.getRootElement().element("appId").getText()); config.setSecret(document.getRootElement().element("secret").getText()); config.setToken(document.getRootElement().element("token").getText()); config.setOpenid(document.getRootElement().element("openid").getText()); config.setAccessTokenLock(new ReentrantLock()); // Init WeChat Service WeChatOfficialAccountService weChatOfficialAccountService = new WeChatOfficialAccountServiceOkHttp(); weChatOfficialAccountService.setWxMpConfigStorage(config); weChatOfficialAccountService.addConfigStorage("another", config); // Init WeChatMsgService WeChatMsgService weChatMsgService = new WeChatMsgService(weChatOfficialAccountService); bind(TestConfigStorage.class).toInstance(config); bind(WeChatOfficialAccountService.class).toInstance(weChatOfficialAccountService); bind(WeChatMsgService.class).toInstance(weChatMsgService); } catch (IOException e) { log.error(e.getMessage(), e); } catch (DocumentException e) { throw new RuntimeException(e); } } }); @BeforeAll public void setup() { injector.injectMembers(this); } } 在这个代码中,我们定义了一个 TestBase 的类,然后在测试启动的时候对齐进行了初始化和配置。 最主要的就是这个方法:`private static final Injector injector = Guice.createInjector(new AbstractModule() {}     在测试中使用 在测试中使用就比较简单了。 首先需要继承这个 TestBase,然后对需要的类进行注入后就可以直接使用了。     如上图,注入后直接使用。   https://www.ossez.com/t/junit-5-guice-di/14395

2023年04月24日 0Comments 818Browse 0Like Read more
Computer Science

Spring 的 IoC(控制反转)

IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,也是一个概念,同时是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序。 在这里说 IoC 之前,你需要完全理解一个概念 DI(依赖注入)。   当你理解依赖注入以后,对控制反转就非常简单了,只是一个概念而已。  什么是依赖注入,请参考文章:Java 依赖注入(DI) 控制反转 用土话来说就是本来应该是用你自己程序解决的依赖注入,我们现在把这个权力交给 Spring 来进行管理。 由 Spring 来管理所有的对象,因为你的权力下放给 Spring 了,Spring 就来进行控制了。 这个现象就叫做控制反转。 所以控制反转只是对一个现象的定义,Spring 是这个现象的具体实现罢了。 Spring 通过 IoC 容器来管理所有 Java 对象的实例化和初始化,控制对象与对象之间的依赖关系。我们将由 IoC 容器管理的 Java 对象称为 Spring Bean,它与使用关键字 new 创建的 Java 对象没有任何区别。 IoC 容器是 Spring 框架中最重要的核心组件之一,它贯穿了 Spring 从诞生到成长的整个过程。 如果你特别牛逼,你也弄个框架,让大家把对象的控制权都给你,那么你做的事情也就是在实现控制反转。 https://www.ossez.com/t/spring-ioc/14391

2023年04月22日 0Comments 894Browse 0Like Read more
Computer Science

Discourse Google Analytics 3 的升级提示

根据 Google 官方的消息: Google Analytics(分析)4 是我们的新一代效果衡量解决方案,即将取代 Universal Analytics。自 2023 年 7 月 1 日起,标准 Universal Analytics 媒体资源将停止处理新的命中数据。如果您仍在使用 Universal Analytics,我们建议您为以后使用 Google Analytics(分析)4 做好准备 Discourse 也顺其自然的有了下面的提示: Your Discourse is currently using Google Analytics 3, which will no longer be supported after July 2023. Upgrade to Google Analytics 4 now to continue receiving valuable insights and analytics for your website's performance.     如果通过管理员登录到后台就可以看见了。 解决办法 解决办法也非常简单,只需要升级到 4 就可以了。 进入Admin > Settings 然后找到 ga version 的站点设置 如果你现在还使用的是 v3_analytics 的话,切换到 v4_gtag     然后再刷新管理员控制台界面就会发现没有这个提示了。 https://www.ossez.com/t/discourse-google-analytics-3/14389

2023年04月22日 0Comments 593Browse 0Like Read more
Computer Science

Java 把 Map 的值(Value)转换为 Array, List 或 Set

概述 在这篇短文中,我们将会展示如何把 Map 中的值取出来,转换为一个 Array,、List 或者一个 Set。   当然,你可以使用 Java JDK 来进行转换,你也可以使用 Guava 来进行转换。   首先,让我们来看看,如何使用原生的 Java JDK把一个 Map 的值换行为 Array。 @Test public final void givenUsingCoreJava_whenMapValuesConvertedToArray_thenCorrect() { final Map<Integer, String> sourceMap = createMap(); final Collection<String> values = sourceMap.values(); final String[] targetArray = values.toArray(new String[0]); } 在上面的代码中,我们使用了 values.toArray(new String[0]); 来对数组变量进行初始化。 根据: Arrays of Wisdom of the Ancients 文章中的内容,使用 toArray(new T[0]) 来对数组对象进行初始化更加高效和干净。 Map 的值转换为 List 下面,让我们看看如何使用原生 Java 来把一个 Map 中的值转换为 List。 @Test public final void givenUsingCoreJava_whenMapValuesConvertedToList_thenCorrect() { final Map<Integer, String> sourceMap = createMap(); final List<String> targetList = new ArrayList<>(sourceMap.values()); } 可以看到,我们还是使用了 Map 中提供的 values 方法。 使用 Guava @Test public final void givenUsingGuava_whenMapValuesConvertedToList_thenCorrect() { final Map<Integer, String> sourceMap = createMap(); final List<String> targetList = Lists.newArrayList(sourceMap.values()); } 简单来说,我们只是使用 Guava 的 Lists 方法进行了下包装,核心还是使用 Map 自带的 values 方法。 Map 的值转换为 Set 最后,让我们来看看如何使用原生 Java 来把 Map 中的值转换为 Set。 @Test public void givenUsingCoreJava_whenMapValuesConvertedToS_thenCorrect() { Map<Integer, String> sourceMap = createMap(); Set<String> targetSet = new HashSet<>(sourceMap.values()); } 结论 通过上面的代码,我们可以看到 Java 是非常容易把 Map 中的值取出来转换为其他集合的。     其中核心的方法就是其自带的 values() 方法。 然后使用其他的类包装下。   https://www.ossez.com/t/java-map-value-array-list-set/14388#h-1

2023年04月22日 0Comments 569Browse 0Like Read more
Computer Science

Discourse 服务器上手动升级

  Discourse 如果没有办法通过 Web 界面进行升级的话,可以通过服务器上命令来进行手动升级。 升级的命令分别如下: cd /var/discourse git pull ./launcher rebuild app 在服务器上执行就可以了。     这个升级通常比较耗时,需要在个 10 多分钟。 https://www.ossez.com/t/discourse/14387  

2023年04月22日 0Comments 621Browse 0Like Read more
Computer Science

JavaSE 和 Java EE 分别是什么

Java 作为最流行的编程语言受到了许多人的喜爱,其在编程中的地位自不必多说。 对于许多才刚刚入门 Java 的朋友来讲,常常会产生这样的困惑,JavaEE是什么?JavaSE又是什么? Java SE Java SE 是 Java Platform, Standard Edition 的简写。 简称就是 Java 的标准版。 如上面的图片,上面就是定义了一个 JDK,JDK 有 Java 运行时和 Java SE API。 我们都知道装 Java 的时候需要装 JDK,等于就是在你的计算机上装了这么一堆东西。 Java EE Java EE 是 Java Platform, Enterprise Edition (Java EE) 的简写。 Java Platform, Enterprise Edition (Java EE) 是基于 JDK 运行的,没有 JDK 你照样用不了 Java EE。 在 JDK 中,我们看到了 Java SE 的 API,通常这部分的 API 是基本的 API,有些企业级的应用不在这个 API 里面。 这部企业级的应用,我们就放到了 Java EE 中了。 比如说,非常古老的 EJB,就在 Java EE 里面。     Java EE 通常使用 Javax 为包的名称。 Spring 如果你想跑企业应用,光有 JDK 是不够的,最开始的时候 Java 是设计是用 EJB 的。 比如说重量级的应用服务器和容器:Weblogic 和 JBoss 就是能够支持 Java EE 的。 但是 EJB 实在太难用了,结果就有了 Spring 框架,这个框架不需要 EJB 也可以跑,结果就是 Java EE API 就从你的项目中比重直接下降。 目前开发的主流还是使用 Spring。 但是 Java EE 这套东西并没有完全丢弃,还在持续开发。 总结 Spring 就是使用 JDK 可以跑起来的企业应用。 最开始的设计初衷就是丢掉麻烦笨重的 Java EE。 https://www.ossez.com/t/javase-java-ee/14385

2023年04月21日 0Comments 541Browse 0Like Read more
Computer Science

Jakarta EE - Java EE的又一个名字

Jakarta EE并不是新技术,他的前身就是大家熟悉的Java EE,老一辈的程序员可能还记得J2EE,是的,他们都是同一个东西,至于为什么会改来改去,这里面就有很多故事了。 1998年12月,SUN公司发布了JDK1.2,开始使用Java 2 这一名称,第二年Sun公司联合IBM、Oracle、BEA等大型企业应用系统开发商共同制订了一个基于Java组件技术的企业应用系统开发规范,名字很自然就取为Java 2 Platform Enterprise Edition简称J2EE。 后面的事情大家也知道,JDK 版本升的很快,J2EE名称如果跟着Java 版本走必然会给开发人员造成困惑不利于该技术的推广,终于在 2006年,SUN公司在发布Java 5 后正式将J2EE改名为Java EE(Java Platform, Enterprise Edition),很多早期 J2EE 开发者虽然现在用的是最新的 Java EE 标准但他们还是认为自己在用 J2EE,当然,只是名称的改变并没有给开发者带来什么麻烦,相比之下下面这个就是要命。 2009 年,Oracle宣布收购 SUN,Java 相关技术自然归 Oracle 所有,在 2017 年,Oracle 宣布开源 Java EE 并将项目移交给 Eclipse 基金会。 但Oracle移交的很不痛快,提了很多要求,其中就包括不能再使用 Java EE这个 名称,虽然有点无理但Eclipse 基金会还是接受了这个要求并且改名为 Jakarta EE,经历了从 J2EE 到 Java EE的改名再经历一次似乎也无所谓,但要命的是 Oracle 要求 Jakarta EE 不能修改 javax 命名空间,这个就意味着 Java EE 移交后代码就此封版,如果想修改代码,不好意思,请另起炉灶。 我们也写了一篇: J2EE,Java EE,Jakarta EE 命名之间的恩恩怨怨 文章。 根据Oracle的要求 Jakarta EE不能修改 javax 命名空间。 那么 Jakarta EE 只能将代码中 javax 修改为 jakarta ,因此最新版本Jakarta Maven描述是长这样的: <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-api</artifactId> <version>10.0.0</version> <scope>provided</scope> </dependency> 根据 Java Docs 网站的内容,新的 jakarta 包中的内容长的是这样的。 https://javadoc.io/doc/jakarta.platform/jakarta.jakartaee-api/latest/index.html     从上面我们可以看到,新的包完全没有使用 javax 的定义了。 所以,如果你开始使用 jakarta.jakartaee-api 的话,那么包的命名空间就为:jakarta 这个名字确实比 javax 麻烦点,谁都知道这 Oracle 就这个尿性,所以体谅下,有比没有强。 https://www.ossez.com/t/jakarta-ee-java-ee/14384

2023年04月21日 0Comments 694Browse 0Like Read more
1…9091929394…309
Archives
  • July 2026
  • June 2026
  • May 2026
  • April 2026
  • March 2026
  • February 2026
  • January 2026
  • December 2025
  • November 2025
  • October 2025
  • September 2025
  • August 2025
  • July 2025
  • June 2025
  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • May 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • May 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
Categories
  • Computer Science (2,385)
    • Confluence (663)
    • Gradle (12)
  • U.S. (557)
  • 文化旅游 (146)

COPYRIGHT © 2020 CWIKIUS. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

湘ICP备2020018253号-1