Java Web技术经验总结(十三)

  1. 设计表的时候,主键的选择,如果业务字段是bigint类型,可以含义不会改变,则可以用作主键;更普遍的做法是,选择单独的id字段作为表的主键(为了考虑后续水平扩展的需求,要求全局唯一,即用发号器获取);业务主键如果是字符串类型的,也不能作为表的逻辑主键使用,因为太占用空间、效率低。关于这个主题的探讨,可以参考:数据库的唯一标示符(ID)的选择
  2. 在Mybatis中,一般会将SQL语句以K-V对写在xxxMapper.xml文件中,关于$和#两种符号的区别:$符号表示MyBatis在动态替换过程中的字符串替换;#符号是参数占位符,表示SQL语句的参数替换。参见:mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译
  3. Mybatis经典文章:《终结篇:MyBatis原理深入解析(一)》,这个系列的其他两篇文章也非常不错。
  4. 千万级的数据集合如何去重?思路1:最朴素的思路是利用Java 8的集合API进行操作,这种情况下,如下程序跑完一次去重需要6s(我的机器是Mac Pro),那么总共需要6000s,大概两个小时;思路二:如果两个集合的字符串序列都能有序,就可以用位图算法进行标记,但是发现瓶颈在排序;思路三:借助外部系统,例如MySQL,将这批数据存放在表中,并建立索引,借助一个版本号进行标记。在实际项目中,我们评估了MySQL进群的处理能力,选择了思路三,这和思路二一样,都是换一种数据结构去思考和解决
package org.java.learn.collection;
import java.util.*;
public class ARemoveBListExample {
    public static void main(String[] args) {
        Set<String> aSet = new HashSet<>();
        Set<String> bSet = new HashSet<>();
        for (int i = 0; i < 10000; i++) {
            String str = UUID.randomUUID().toString();
            aSet.add(str);
            bSet.add(str);
        }
        for (int i = 0; i < 10000000; i++) {
            aSet.add(UUID.randomUUID().toString());
        }
        //求A集合到B集合的差
        long start = System.currentTimeMillis();
//        List<String> result = aSet.parallelStream().filter(a -> !bSet.contains(a)).collect(Collectors.toList());
        aSet.removeIf(a -> bSet.contains(a));
        long end = System.currentTimeMillis();        System.out.println("cost: " + (end-start) + "ms, result size:" + aSet.size());
    }
}
  1. 在构建REST服务时,需要提供统一的异常处理、统一的请求参数、统一的响应结构,利用基于注解的AOP可以实现这个功能。
  2. BasicThreadFactory 的实例不会直接创建线程,其内部使用的builder构建器负责创建线程,通过构建器模式可以为要创建的线程配置很多属性:命名规则、是否精灵进程,以及线程的优先级等熟悉。
  3. 在业务开发中,会有如下的应用场景:服务A有个线程池不断消费来自MQ推送的消息,只有消费完给MQ发出response之后才能继续消费新的消息;为了不让消息堆积,我们需要尽可能加快这个线程的处理能力,必要的时候需要将该线程中能异步做的工作异步掉,例如请求远端的HTTP接口。这种场景下,就需要使用httpclient的异步调用,直接使用httpclient有点麻烦,最近接触的vert.x提供了一个不错的方法,可以参考:Vert.x HTTP Client
  4. MyBatis应用技巧:传入多个参数时,在xml文件中如何获得参数?参考:MyBatis传入多个参数的问题
  5. MyBatis应用技巧:如何在应用程序中配置多数据源?参考:MyBatis多数据源配置(读写分离)
  6. 利用curl测试自己的服务接口:curl发送POST请求

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JavaEdge

线程安全与锁优化1 线程安全2 锁优化

34990
来自专栏Java学习123

Python3.4+Django1.7+SQLite3实现增删改查

38650
来自专栏安恒网络空间安全讲武堂

堆利用之double-free

38140
来自专栏JAVA高级架构开发

成为Java顶尖程序员,先过了下面问题!

ArrayList和LinkedList内部的实现大致是怎样的?他们之间的区别和优缺点?

29500
来自专栏码洞

Java高阶必备之Netty基础原理

Netty是Java程序员通向高阶之路必须要过的门槛之一。干了几年的Java程序员发现业务开发似乎就是在SSH的世界里摸滚打爬的时候,会开始感到迷茫,难道程序员...

11220
来自专栏Golang语言社区

Go Channel 应用模式(一)

Channel是Go中的一种类型,和goroutine一起为Go提供了并发技术, 它在开发中得到了广泛的应用。Go鼓励人们通过Channel在goroutine...

22420
来自专栏一个会写诗的程序员的博客

CAS指令与MESI缓存一致性协议、 “轻量级锁” 与原子操作CAS指令与MESI缓存一致性协议、 “轻量级锁” 与原子操作

CAS指令,在Intel CPU上称为CMPXCHG。最常见的原子操作有Compare and Exchange,Self Increase/Decrease等...

24550
来自专栏Java帮帮-微信公众号-技术文章全总结

JavaWeb13-设计模式案例实现(Java真正的全栈开发)

? JavaWeb设计模式&案例 一.JavaWeb的设计模式 1. jsp模式介绍 SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一...

34860
来自专栏Java后端技术栈

Java多线程编程-(13)-从volatile和synchronized的底层实现原理看Java虚拟机对锁优化所做的努力

对于Java来说我们知道,Java代码首先会编译成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化为汇编指令在CPU上进行执行。

10010
来自专栏Linux驱动

第3阶段——内核启动分析之start_kernel初始化函数(5)

内核启动分析之start_kernel初始化函数(init/main.c) stext函数启动内核后,就开始进入start_kernel初始化各个函数, 下面只...

329100

扫码关注云+社区

领取腾讯云代金券