文章

fastjson => jackson

零拷贝

Json序列化

//User 类序列化成 { “userName”:”张三”},又要将 { “name”:”张三”} 序列化成 User类。

  1. //gson
  2. class User{
  3. @SerializedName(value="userName",alternate={"name"})
  4. private String userName;
  5. }
  6. //fastjson
  7. @JSONField(name = "project")

1.fastjson List转JSONArray
List list = new ArrayList();
JSONArray array= JSONArray.parseArray(JSON.toJSONString(list));

2.fastjson JSONArray转List
JSONArray array = new JSONArray();
List list = JSONObject.parseArray(array.toJSONString(), EventColAttr.class);

3.fastjson 字符串转List
String str = "";
List list = JSONObject.parseArray(str,T.class);

切面表达式:
https://cloud.tencent.com/developer/article/1497814

通过切面解决认证问题:
1.认证失效(账号被顶/过期);捕获到认证失效异常后,调用认证逻辑,携带最新Token再次执行业务逻辑并返回;

  1. iotAuthImpl.java
  2. AuthInvalidAop.java

Swagger

Swagger自动转驼峰 问题(Action ==> swagger ==> action)
不可取、待确认是否是该原因: mapStruct 貌似也是通过 get,set方法去识别;
1.通过FastJson的@JSONField注解解决/
2.仅返回对应的泛型类,实际可返回new JSONArray();

DateMath

  1. import cn.hutool.core.date.LocalDateTimeUtil;
  2. import cn.hutool.core.math.MathUtil;
  3. import cn.hutool.core.util.NumberUtil;
  4. import java.time.LocalDate;
  5. import java.time.LocalDateTime;
  6. import java.time.ZoneId;
  7. import java.util.Locale;
  8. public class test{
  9. public static void main(String[] args) {
  10. double v = DateTimeMathUtil.todayInMothPercent();
  11. System.out.println("v = " + v);
  12. double div = NumberUtil.div(20, 29, 4);
  13. System.out.println("div = " + div);
  14. //68.965515
  15. System.out.println((float) 20 / (float) 29 * 100);
  16. //68.96551724137932
  17. System.out.println((double) 20 / (double) 29 * 100);
  18. String time = LocalDateTimeUtil.format(LocalDateTime.now(ZoneId.of("Asia/Shanghai")), "yyyyMMddHHmmss");
  19. System.out.println(time.toUpperCase(Locale.ROOT));
  20. int dayOfMonth = LocalDateTimeUtil.now().getDayOfMonth();
  21. System.out.println("dayOfMonth = " + dayOfMonth);
  22. LocalDate date = LocalDate.of(2020, 2, 20);
  23. System.out.println("============");
  24. //第20天
  25. System.out.println(date.getDayOfMonth());
  26. //最多29天
  27. System.out.println(date.getMonth().maxLength());
  28. //至少28天
  29. System.out.println(date.getMonth().minLength());
  30. //当前月有29天
  31. System.out.println(date.getMonth().length(date.isLeapYear()));
  32. // DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  33. // LocalDateTime parse = LocalDateTime.parse("2020-08-08 00:00:00",df);
  34. // int dayOfMonth1 = parse.getDayOfMonth();
  35. // int length = parse.getMonth().length(LocalDate.now().isLeapYear());
  36. // System.out.println("length = " + length);
  37. // System.out.println("dayOfMonth1 = " + dayOfMonth1);
  38. // System.out.println("time = " + time);
  39. }
  40. }

工具类

  1. package com.time.common.utils.date;
  2. import cn.hutool.core.util.NumberUtil;
  3. import java.time.LocalDate;
  4. /**
  5. * @author yx.Jiang
  6. * @desc 日期/时间计算工具类
  7. * @date 2021-09-01 16:18
  8. */
  9. public class DateTimeMathUtil {
  10. /**
  11. * 已过日期占比(Percentage of elapsed time)
  12. *
  13. * @return 默认保留四位小数【四舍五入】
  14. */
  15. public static double todayInMothPercent() {
  16. return dayInMothPercent(LocalDate.now(), 4);
  17. }
  18. /**
  19. * 已过日期占比(Percentage of elapsed time)
  20. *
  21. * @param scale 小数位
  22. * @return 默认保留四位小数【四舍五入】
  23. */
  24. public static double todayInMothPercent(int scale) {
  25. return dayInMothPercent(LocalDate.now(), scale);
  26. }
  27. /**
  28. * 已过日期占比(Percentage of elapsed time)
  29. *
  30. * @param localDate 日期
  31. * @return 默认保留四位小数【四舍五入】
  32. */
  33. public static double dayInMothPercent(LocalDate localDate) {
  34. return dayInMothPercent(localDate, 4);
  35. }
  36. /**
  37. * 已过日期占比(Percentage of elapsed time)
  38. *
  39. * @param localDateTime 日期
  40. * @param scale 小数位
  41. * @return 默认保留四位小数【四舍五入】
  42. */
  43. public static double dayInMothPercent(LocalDate localDateTime, int scale) {
  44. int today = localDateTime.getDayOfMonth();
  45. int maxDays = localDateTime.getMonth().maxLength();
  46. return NumberUtil.div(today, maxDays, scale);
  47. }
  48. }

并行流

Arrays.stream(values())
👍 Stream.of(values()).parallel()

非并行流
1927
1238
1212
1173
1009

并行流
1755
947
975
1013
999
878

[2021-09-02 17:29:18.259 http-nio-8088-exec-10
[2021-09-02 17:29:18.261 http-nio-8088-exec-10
[2021-09-02 17:29:18.263 ForkJoinPool.commonPool-worker-1
[2021-09-02 17:29:18.264 ForkJoinPool.commonPool-worker-1
[2021-09-02 17:29:18.265 ForkJoinPool.commonPool-worker-1
[2021-09-02 17:29:18.265 ForkJoinPool.commonPool-worker-1
[2021-09-02 17:29:18.266 ForkJoinPool.commonPool-worker-0
[2021-09-02 17:29:18.266 ForkJoinPool.commonPool-worker-0
[2021-09-02 17:29:18.266 ForkJoinPool.commonPool-worker-0
[2021-09-02 17:29:18.265 http-nio-8088-exec-10
[2021-09-02 17:29:18.268 ForkJoinPool.commonPool-worker-3
[2021-09-02 17:29:18.268 ForkJoinPool.commonPool-worker-0
[2021-09-02 17:29:18.269 http-nio-8088-exec-10
[2021-09-02 17:29:18.271 http-nio-8088-exec-10
[2021-09-02 17:29:18.332 ForkJoinPool.commonPool-worker-0
[2021-09-02 17:29:18.332 ForkJoinPool.commonPool-worker-0
[2021-09-02 17:29:18.665 http-nio-8088-exec-10
[2021-09-02 17:29:18.666 http-nio-8088-exec-10
[2021-09-02 17:29:19.134 ForkJoinPool.commonPool-worker-1
[2021-09-02 17:29:19.136 ForkJoinPool.commonPool-worker-1
[2021-09-02 17:29:19.138 http-nio-8088-exec-10
[2021-09-02 17:29:19.139 http-nio-8088-exec-10

日期

计算当前日期的一周前:
LocalDate today = LocalDate.now();
LocalDate aWeekAgo= today.minus(1, ChronoUnit.WEEKS);

String format = LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(“format = “ + format);
输出:
format = 2021-09-02

RestTemplate

自动URLEncode

  1. import cn.hutool.crypto.digest.DigestUtil;
  2. import cn.hutool.crypto.digest.HMac;
  3. import org.springframework.beans.factory.annotation.Value;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.stereotype.Component;
  6. import java.io.UnsupportedEncodingException;
  7. import java.net.URLEncoder;
  8. import java.nio.charset.StandardCharsets;
  9. import java.time.Instant;
  10. import java.util.*;
  11. import java.util.stream.Collectors;
  12. import static cn.hutool.crypto.digest.HmacAlgorithm.HmacSHA1;
  13. /**
  14. * @author yx.Jiang
  15. * @desc 天氣API
  16. * @date 2021-09-03 15:40
  17. */
  18. @Configuration
  19. public class WeatherSignUtil {
  20. /**
  21. * 新知天气公钥
  22. * https://docs.seniverse.com/api/start/key.html
  23. */
  24. private static String publicKey;
  25. @Value("${weather.publicKey}")
  26. public void setPublicKey(String publicKey) {
  27. WeatherSignUtil.publicKey = publicKey;
  28. }
  29. /**
  30. * 新知天气私钥
  31. * https://docs.seniverse.com/api/start/key.html
  32. */
  33. private static String privateKey;
  34. @Value("${weather.privateKey}")
  35. public void setPrivateKey(String privateKey) {
  36. WeatherSignUtil.privateKey = privateKey;
  37. }
  38. /**
  39. * 生成签名
  40. *
  41. * @return sign
  42. */
  43. public static String genSign() {
  44. HashMap<String, Object> map = new HashMap<>();
  45. //时间戳
  46. map.put("ts", Instant.now().getEpochSecond());
  47. //sign有效期
  48. map.put("ttl", 1_800);
  49. //公钥
  50. map.put("uid", publicKey);
  51. String rawStr = map.keySet()
  52. .stream()
  53. .sorted(String::compareTo)
  54. .map(key -> key + "=" + map.get(key))
  55. .collect(Collectors.joining("&", "", ""));
  56. String sign = genSign(rawStr);
  57. System.out.println("sign1 = " + sign);
  58. try {
  59. sign = URLEncoder.encode(sign, StandardCharsets.UTF_8.name());
  60. } catch (UnsupportedEncodingException e) {
  61. e.printStackTrace();
  62. }
  63. System.out.println("sign2 = " + sign);
  64. return rawStr + "&sig=" + sign;
  65. }
  66. /**
  67. * 生成签名
  68. *
  69. * @param rawStr 原始串
  70. * @return sign
  71. */
  72. private static String genSign(String rawStr) {
  73. //HMAC-SHA1 —— 私钥加密
  74. HMac hmac = DigestUtil.hmac(HmacSHA1, privateKey.getBytes(StandardCharsets.UTF_8));
  75. return hmac.digestBase64(rawStr, Boolean.FALSE);
  76. }
  77. }

restTemplate请求接口 响应 403 异常;
org.springframework.web.client.HttpClientErrorException$Forbidden: 403 Forbidden
以为是生成的sign有问题,再三确认后(单独拿生成的sign自行拼接URL在浏览器请求无问题后);
image.png
debug中的实际请求URL为(URLEncode后的结果):
https://api.seniverse.com/v3/weather/hourly.json?ts%3D1630664408%26ttl%3D1800%26uid%3DPOOzALiQ_Pcb1qPPM%26sig%3DZw7gxWoLf629a0OIuCq16p5%252FF%252F4%253D&language%3Dzh-Hans%26location%3D%E4%B8%8A%E6%B5%B7%26unit%3Dc&start=0&hours=24

将其decode后
http://tool.chinaz.com/tools/urlencode.aspx
image.png
这是
结果如上图所示:
https://api.seniverse.com/v3/weather/hourly.json?ts=1630664408&ttl=1800&uid=POOzALiQ_Pcb1qPPM&sig=Zw7gxWoLf629a0OIuCq16p5%2FF%2F4%3D&language=zh-Hans&location=上海&unit=c&start=0&hours=24

j将解码后的URL输入浏览器,可正常返回结果:
image.png

接下来就是要:避免RestTemplate的UrlEncode, 参考链接https://blog.csdn.net/wangooo/article/details/117161950

仅urlEncode请求中的特殊字符(如:汉字、sign(28bit—base64));
image.png

finalize

  1. @Deprecated
  2. class HashDemo {
  3. public static HashDemo save = null;
  4. public void isA() {
  5. System.out.println("111-isA");
  6. }
  7. @Override
  8. protected void finalize() throws Throwable {
  9. super.finalize();
  10. System.out.println("ddd-finalize");
  11. HashDemo.save = this;
  12. }
  13. public static void main(String[] args) throws InterruptedException {
  14. save = new HashDemo();
  15. save = null;
  16. System.gc();
  17. Thread.sleep(500);
  18. if (save != null) {
  19. save.isA();
  20. } else {
  21. System.out.println("222---111");
  22. }
  23. save = null;
  24. System.gc();
  25. Thread.sleep(500);
  26. if (save != null) {
  27. save.isA();
  28. } else {
  29. System.out.println("222---222");
  30. }
  31. }
  32. }
  33. //输出结果
  34. ddd-finalize
  35. 111-isA
  36. 222---222

FastJson

  1. import com.alibaba.fastjson.JSON;
  2. import com.alibaba.fastjson.annotation.JSONField;
  3. import lombok.Data;
  4. import java.time.LocalDate;
  5. import java.time.LocalDateTime;
  6. public static void main(String[] args) {
  7. User user = new User();
  8. user.setName("测试序列化");
  9. user.setBirthday(LocalDateTime.now());
  10. user.setTime(LocalDateTime.now());
  11. user.setDate(LocalDate.now());
  12. String s = JSON.toJSONStringWithDateFormat(user, "yyyy-MM-dd HH:mm:ss");
  13. System.out.println(s);
  14. //{"birthday":"2021-09-24 19:31:23","date":"2021-09-24","name":"测试序列化","time":"19:31"}
  15. }
  16. @Data
  17. static class User {
  18. private String name;
  19. private LocalDateTime birthday;
  20. @JSONField(format = "HH:mm")
  21. private LocalDateTime time;
  22. private LocalDate date;
  23. }