每个方法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