实用编码技巧

每个方法try for if 等层级最好不要超过3个
选中代码块 -- 右键 -- refactor --extract --method 可以自动生成方法
code style -- java -- 把数量改成100可以防止导包的时候导入*
经常使用的重复字符串用static final变量定义

idea打包方式(依赖包和本地包打在一起):project structure -- +Artifacts -- from modules with... -- 选中Module,入口类,--extract to the target...  --- 改变MANIFEST.MF文件路径(不要用默认) --  修改 Output directory -- 将available Elements中的依赖包put into

idea打包把依赖包分开:.MF文件不要使用默认路径,比如改为resources路径下idea基于spring boot的依赖分开打包 - 喵喵扑 - 博客园

注入抽象类的所有实现可以通过一下方式
@Autowired
private Map<String, AbstractCacheService> beans = new HashMap<>();

对象json字符串互转(com.alibaba:fastjson:1.2.70)
JSON.toJSONString(obj)
JSON.parseObject(str, new TypeReference<Map<String, Obj>>(){})
list转json时,如果list中两个对象是同一个引用,json转出来只会转一个,另外一个会是引用格式,如下:
[{"name":"sfsf"},{"$ref":"$[0]"}]

日志使用LomBok的@Slf4j

ConcurrentSkipListSet是线程安全的有序的集合,适用于高并发的场景

判断字符串是否为空使用StringUtils,空格也算空(Spring的同名工具类空格不算空)
compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
空字符串可以使用StringUtils.EMPTY代替
StringUtils.substringBeforeLast
StringUtils.substringAfterLast


判断数组是否为空可以使用Spring的ObjectUtils,普通对象只用判断是否null就行,判断集合使用CollectionUtils

尽量使用foreach迭代,lambda表达式不能改变外部变量的值且性能不如foreach
迭代器迭代
Iterator<Entry<String, Object>> iterator = list.entrySet().iterator();
        while (iterator.hasNext()) {
            Entry<String, Object> next = iterator.next();
            String key = next.getKey();
            String value = (String) next.getValue();
}

字符串拼接用StringBuilder(StringBuffer线程安全但性能会差一些)

取不到值就创建新map map.computeIfAbsent(key, k -> new HashMap<>())
过滤掉空值
putIfAbsent   如果传入key对应的value已经存在,就返回存在的value,不进行替换。如果不存在,就添加key和value,返回null
compile('com.fasterxml.jackson.core:jackson-databind:2.9.9.1')
compile('com.fasterxml.jackson.core:jackson-core:2.9.9')
compile('com.fasterxml.jackson.core:jackson-annotations:2.9.9')
@JsonInclude(JsonInclude.Include.NON_EMPTY) //属性为空("")或者为NULL,数组长度为0都不序列化,可用于接口入参出参过滤

接收、返回的组装类没必要实现Serializable

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
这组lombok注解可以使用构造者模式创建对象

访问域名中有没有后缀通过server.context-path属性判断

引入开源组件mock做测试很方便,测试的时候方法覆盖最好100%
compile('org.mockito:mockito-all:1.10.19')
compile("org.powermock:powermock-api-mockito:1.7.4")
compile("org.powermock:powermock-module-junit4:1.7.4")

流式函数编程过滤数据、组装数据结构很方便,作为函数,并不改变入参本身的数据
list转map  list.stream().collect(Collectors.toMap(UcpDocParamDTO:: getName, UcpDocParamDTO::getVal))
可以通过list.stream().distinct().collect(Collectors.toList())结合重写对象equals(),hashCode()方法实现去重
分组Map<String, List<Obj>> map = objList.stream().collect(Collectors.groupingBy(Obj::getId))

public class UcpDocVerQueryDTO {
    private String docCode; 
    private Integer version;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        UcpDocVerQueryDTO queryDTO = (UcpDocVerQueryDTO) o;
        return Objects.equals(docCode, queryDTO.docCode) &&
                Objects.equals(version, queryDTO.version);
    }

    @Override
    public int hashCode() {
        return Objects.hash(docCode, version);
    }
}

内存分页的原理是算出索引边界,然后subList,PageMethod基于sql分页,通过拦截mybatis
字符串为json类型的话可以直接转成JSONObject直接用
JSONObject.parseObject(str,Feature.OrderedField) //属性保持原来顺序

不使用父类属性作为Equals和HashCode方法的盐,@EqualsAndHashCode(callSuper = false)
用于json转对象时json字符串中的字段数量多于类的字段,在类上加@JsonIgnoreProperties(ignoreUnknown = true)


Spring的@Validated和hibernate包中的@NotBlank等注解结合使用可用于验证入参并返回错误信息
@Validated(SaveRecord.class) @RequestBody和@NotBlank(message = "是否展示标识为空,Y/N",groups = {SaveRecord.class})  结合使用,相当于做了分组 SaveRecord定义成接口就行,实体类中需要定义                                                                                                        @NotBlank(message = "省份信息不能为空",groups = {SaveRecord.class})
private String province;


3000元/并发 是指一个并发一个月3000块,比如平台分配并发数7,那么一秒钟只能接收7个请求(但实际处理能力可能达不到),超过了就被拒绝,每月成本7*3000

jdk的Base64Encoder主要不是用来加密,因为他的算法是公开的,调用decode就解密了,主要用途是把一些二进制数转成普通字符用于网络传输。 由于一些二进制字符在传输协议中属于控制字符,不能直接传送需要转换一下

@Resource不指定属性的话先byName,再byType
synchronized(class)  拦截类锁,所有线程得顺序执行同步块

双重检查模式,外层判断考虑性能,内层判断考虑安全,成本员变量加volatile保证强制对工作内存的修改操作立即写入主内存,并且让其他CPU中对应的缓存行无效
volatile缺点是没有原子性,使用场景:对变量的写操作不依赖于当前值,比如i=i++就不适用,常用与标记变量控制while循环或者双重检查模式
private static volatile ExecutorService executor = null;
    
public static ExecutorService init() {
    if (executor == null) {
        synchronized (IMClientUtil.class) {
            if (executor == null) {
                executor = Executors.newFixedThreadPool(10);
            }
        }
    }
    return executor;
}

使用线程池
Future<JSONObject> future = ExecutorService.submit(() -> {
    //调用方法,返回result
    return result;
});
try {
 result = future.get(超时时间, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
    //log
} catch (ExecutionException e) {
    //log
} catch (TimeoutException e) {
    future.cancel(true); // 取消没有执行完的任务,设置为true说明任务能被中断,否则执行中的任务要完成
    //log
}

根据入参动态调用反射set
public final static void invokeSetMethod(Object o, String property, Object param)
            throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        if (StringUtils.isNotBlank(property)) {
            // 生成SET方法名称 第一位转为大写
            String methodName = "set"
                    + property.substring(STRING_FIRST_INDEX, STRING_SECOND_INDEX).toUpperCase()
                    + property.substring(STRING_SECOND_INDEX);
            // 执行SET 方法
            if (null != o) {
                //获取所有Method
                Method[] methods = o.getClass().getMethods();
                for (Method method : methods) {
                    // 方法名相同执行
                    if (method.getName().equals(methodName)) {
                        method.invoke(o, new Object[] { param });
                    }
                }

            }
        }

    }
    
私有的静态内部类常用于需要一个更小的,功能单一的小模块。并且这个模块是不需要实体化的,例如这个模块的功能是字符串加密机,因为是加密机,尽量不让其他模块访问这个功能,就可以这么定义为私有的,静态保证可以直接用
/**
 * 延迟初始化单例模式
 */
class PasswordManageService {
private static class SingletonHandler {
        final static PasswordManageService INSTANCE = new PasswordManageService();
    }
    public static PasswordManageService getInstance() {
        return SingletonHandler.INSTANCE;
    }
}    

out.flush()不加也不会影响。方法的作用是更新缓存中的数据到文件。执行Close也会做同样的操作。当需要保存文件,但又不能文件关闭的时候可以用Flush方法

@RequestBody可用于直接接收转化http请求入参,@Validated @RequestBody可以联合使用
接收普通参数直接用@RequestParam

str.getBytes(StandardCharsets.UTF_8) //得到Charset,获取byte[] 最好指定编码,且编码在jdk中有定义

Collections.singletonList //这个方法主要用于只有一个元素的优化,减少内存分配,无需分配额外的内存,ArrayList的DEFAULT_CAPACITY=10

@ConfigurationProperties是springboot提供读取配置文件的一个注解,esg.properties中syncproptopmsdto.cluster=green
@Data
@Component
@ConfigurationProperties(prefix = "syncproptopmsdto")
public class SyncPropToPmsDto {
    private String cluster;
}
    
spring中很多bean并没有加组件注解,但是可以直接通过注解的方式引入    
数组转为集合Arrays.asList(String[] a)
将obj1中的属性赋值到obj2的技巧Obj2 obj2 = JSON.parseObject(JSON.toJSONString(obj1), Obj2.class);
获取cookie属性@CookieValue(value = "umid",required = false) String umid
把List<String>用,拼接起来StringUtils.join(list,",")
对stream的任何修改都不会修改背后的数据源,stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行
List<Obj>转化为List<String>  objList.stream().map(Obj::getName).collect(Collectors.toList())
也可以调用方法
private List<Boolean> execute(List<List> result){
    return result.stream().map(this::transactionExecute).collect(Collectors.toList());
}
protected abstract Boolean transactionExecute(List list);

动态刷新的类标注@RefreshScope注解,一般和@ConfigurationProperties结合使用

telnet不通也可能是没开白名单

spring的BeanUtils.copyProperties(obj1,obj2)拷贝对象很好用,不能拷贝Map,可以用putAll拷贝Map

springCloud客户端
@FeignClient(name = "PH-UAMP")
public interface UampFeignClient {

    @PostMapping(value = "/openApi/roleAuthInfoQuery")
    AuthorityQueryResponse roleAuthInfoQuery(RoleQueryRequest request);

}

redis重新set , getset会重置过期时间,使用list hset不会清除过期时间

通过实现ApplicationContextAware可以得到ApplicationContextUtil用来获得Bean的工具
@Component
public class SpringContextUtil implements ApplicationContextAware{

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }

    public static <T> T getBean(String name, Class<T> requiredType) throws BeansException {
        return applicationContext.getBean(name, requiredType);
    }

    public static <T> T getBean(Class<T> requiredType) throws BeansException {
        return applicationContext.getBean(requiredType);
    }

}

F5是物理转发,nginx是软件转发,F5很贵
e.printStackTrace不会打印到日志文件中,使用log.error("...", e);

//定义在方法上,如果捕获到异常就执行errorMethod,常用于超时熔断,压测,启动类加上@EnableHystrix
@HystrixCommand(fallbackMethod = "errorMethod")
Object method(Object[] args){...}
Object errorMethod(Object[] args,Throwable e)

private < 无(包访问权限) < protected < public
commons-lang还有个好用的方法 Date addMinutes(Date date, int amount)  ,amount可正可负

生成常量集合Collections.unmodifiableList(Arrays.asList(T... a)) //List<T> asList(T... a)

在使用阻塞等待获取锁的方式中,必须在try代码块之外,并且在加锁方法与try代码块之间没有任何可能抛出异常的方法调用,避免加锁成功。如果加锁放在try块中有可能因为其他代码产生异常导致本来没加锁,但是在finally中调用解锁

所有的包装类对象之间值的比较,全部使用equals方法比较

线程池不允许使用Executors去创建

使用instant代替Date, LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值