java tricky
1、根据枚举的name获取枚举类:
private static SmsProviderType fromName(String spName) {
return Stream.of(SmsProviderType.values()).filter(sp -> StringUtils.equals(sp.name(), spName)).findFirst().orElse(null);
}
2、字符串转成int(注意给默认值):NumberUtils.toInt
3、collect(Collectors.joining()) 表示把所有字符串连接起来
4、把null转成empty:nullToEmpty()方法
5、joiner.join可以用分隔符把元素连接在一起
6、实体类转为Map形式:
obj -> jsonStr -> map
7、Optional
Optional.ofNullable(...) 入参为null则返回null,否则返回入参
ofNullable(...).ifPresent() 如果ofNullable的结果不是空,则调用ifPresent
Optional.orElse(value) 如果optional保存的是null,返回value。如果保存的不是null,返回option自己的值
Optional.orElseGet(...) 和orElse一样,只是入参是对象
一般从stream中选出个体,就要调用stream的findFirst()方法,然后orElse
firstNonEmpty(T... values)方法,第一个入参不为空则返回 为空则判断后面的 以此类推
isPresent() 返回boolean,如果值存在则方法会返回true,否则返回 false
anyMatch(): stream中任何一个元素满足即返回true
allMatch(): stream中所有元素都满足即返回true
.findAny().isPresent() 和 anyMatch的含义一样
8、forEach和forEachOrder区别:两者完成的功能类似,主要区别在并行处理上,forEachOrdered()将始终按照流(stream)中元素的遇到顺序执行给定的操作,而forEach()方法是不确定的。
9、sorted中可以把Comparator.comparing()的结果作为入参。Comparator.comparing().thenComparing() 可以定义多个排序规则
10、Exception: e.getClass().getSimpleName()可以拿到具体异常的类型
11、Sets.difference(set1, set2) 可以获取元素:在set1中存在但是在set2中不存在。Set的retainAll方法:求交集
12、@RestController注解相当于@ResponseBody + @Controller
13、idea或eclipse的jvm arguments加入 -Dfuck.abc="1234" 在代码中System.getProperty("fuck.abc")可以获取这个值。-D是用来在启动java程序时设置系统属性的
接口中的default方法会被实现类直接继承
14、Random r = new Random() nextInt(bound) 会生成0到bound的值 每次不一样
Random r = new Random(100) 指定种子后,nextInt(bound) 会生成0到bound的值 每次都一样
15、去掉字符串指定的前缀:StringUtils.removeStart(fullNumber, "+")
16、日期转换,SimpleDateFormat线程不安全,要使用LocalDateTime和DateTimeFormatter
localDatetime和毫秒数转化
LocalDateTime end = LocalDateTime.of(2020, 3, 3, 18, 38, 00);
System.out.println(end.toInstant(ZoneOffset.of("+8")).toEpochMilli());
// 使用localDatetime,进行Date和字符串转换
LocalDate localDate = LocalDate.parse(dateStr, DATE_FORMATTER_YYYYMMDD);
LocalDateTime localDateTime = localDate.atStartOfDay();
Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
return date;
}
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
return localDateTime.format(DATE_FORMATTER_YYYYMMDD);
}
localDatetime校验日期字符串是否符合格式
commonParamCheck(startTimeTemporal == null, "开始日期格式不正确,正确格式为yyyyMMdd");
//把yyyy-MM-dd HH:mm:ss转化为Date类型
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date myDate2 = dateFormat2.parse("2020-04-25 05:20:01");
System.out.println(myDate2);
System.out.println(myDate2.getTime());
//把Date类型转化为yyyyMMdd字符串
SimpleDateFormat resultFormat = new SimpleDateFormat("yyyyMMdd");
Date date = new Date();
String result = resultFormat.format(date);
17、编码
http的queryString中内容(即?后的内容)和www-form-urlencoded form表单中的内容,经过http请求后会自动被urlEncode编码。urlencode会把/转为%2F,+转为%2B
如果某个字符串需要放入http请求参数中,比如想把某个字符串放在?后, 需要把字符串经过Base64.encodeBase64URLSafeString, 否则会有字符丢失。
Base64非url safe的编码结果,会有+等内容。
Base64.encodeBase64URLSafeString() 方法可以实现+转化为-,/转化为_ 并去掉==。
Base64.encodeBase64URLSafeString()和Base64.encodeBase64String() 生成的字符串 用Base64.decodeBase64() 生成的结果是一样的
对于url safe编码,不管编码多少次,都能用Base64.decodeBase64成功解码
base64编码会让数据扩大1/3
18、IOUtils读取文件
//读取file
String photoPath = "abc";
File photo = new File(photoPath);
byte[] bytes = FileUtils.readFileToByteArray(photo);
//读取inputStream
List<String> words = IOUtils.readLines(ChengYuClickCaptchaTest.class.getResourceAsStream("/words.txt"), "UTF-8")
19、
retrofit2 Response 拿到所有response header:
Headers headersFromResponse = httpRsult.headers();
拿到指定header:
String requestId = String.valueOf(headersFromResponse.get("X-Ca-Request-Id"));
20、retrofit2的http相关注解
@QueryMap Map<String, Integer> map 可传多个参数,都以?形式拼接
如果url中?sig=... @Query("sig") 可传入一个参数对应
@HeaderMap 表示http头部传多个参数
如果@POST("/{indexes}/{type}), @Path("indexes") String indexes 即表示传入参数
@Body 可传入requestBody
21、jdk8 stream
peek: 不能修改流中的元素,只能对元素进行打印输出或者改变引用类型的属性。peek入参是consumer
filter(strategy -> strategy != null) 可用filter(Objects::nonNull)代替
stream代替for循环:IntStream.range(0, 100).forEach()
22、ImageIO生成图片
ImageIO.read可以传入InputStream对象,生成BufferedImage即图片,参考验证码中台ShadowLineamentGeneratorTest
也可以传入file对象
22、查看数据或图片大小:转为byte[]数组,数组长度即代表多少byte,除以1024可得出kb
23、try (ByteArrayInputStream in = new ByteArrayInputStream(image)) try-with-resource可以自动关闭流
24、
@ExceptionHandler此注解使用在方法级别,声明对Exception的处理逻辑。可以指定目标Exception
@ResponseBody此注解用在请求handler方法上。和@RequestBody作用类似,用于将方法的返回对象直接输出到http响应中。
@RestControllerAdvice此注解用于class上,相当于同时引入了@ControllerAdvice和@ResponseBody两个注解。
在Spring里,我们可以使用@ControllerAdvice来声明一些全局性的东西,最常见的是结合@ExceptionHandler注解用于全局异常的处理。
@ExceptionHandler注解标注的方法:用于捕获Controller中抛出的不同类型的异常,从而达到异常全局处理的目的;
@ControllerAdvice("com.cmos.edcreg.web.controller") 可以声明该类要处理的包路径
ResponseBodyAdvice 接口是在 Controller 执行 return 之后,在 response 返回给客户端之前,执行的对 response 的一些处理,可以实现对 response 数据的一些统一封装或者加密等操作。比如可以实现ResponseBodyAdvice接口,在实现类中获取api controller的返回值。
详见:https://www.cnblogs.com/goloving/p/15045736.html
25、java对象转成json成立的基本条件只需要有get方法
public class ResultView<DATA> {
public long getTimestamp() {
return System.currentTimeMillis();
}
public String getHostname() {
return HostInfo.getHostName();
}
}
则ObjectMapperUtils.toJSON(resultView)的结果是{hostname":"MacBook-Pro.local","timestamp":1650543262512},所以get方法可以把java对象可自动转为json
ajax参数 contentType表示告诉服务器请求数据的类型
dataType表示告诉服务器,我要想什么类型的数据
27、@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8"):
private Date createTime;
表示序列化时,将createTime字段转为yyyy-MM-dd HH:mm:ss格式
28、@JsonValue: 序列化时,将枚举序列化为code或name,反序列化时,由code或name反序列化成枚举
public enum GridElement {
/**
* 商业化元素
*/
BUSINESS_ELEMENT(6, "商业化元素"),
;
private int intValue;
private String desc;
@JsonValue
public String getDesc() {
return desc;
}
}
表示BUSINESS_ELEMENT序列化的结果是「商业化元素」,也可以由「商业化格元素」反序列化得到BUSINESS_ELEMENT
29、@JsonUnwrapped注解:将嵌套的对象平铺展开
https://juejin.cn/post/7067812048419160071
30、hive解析json:https://blog.csdn.net/qq_34105362/article/details/80454697
get_json_object(response_detail, '$.body.messages[0].status') = 6
mysql解析json:https://blog.csdn.net/unity_zyc/article/details/80654442
31、java类转为json字符串,下列条件需要满足一个:
a、对应字段需要有set和get方法,否则该字段转化的结果为空。
b、如果没有get和set方法,可以用@JsonProperty注解,也可以达到将类转为json字符串效果
32、jackson在反序列化时,默认使用对象的默认构造函数,如果默认构造函数不存在,jackson会报错。
33、@JsonProperty和@JSONField注解
作用:此注解用于属性上,作用是把该属性的名称A序列化为另外一个名称B,反序列化时可以把新名称B转换为属性名称A
区别:@JsonProperty位于jackson包中,搭配ObjectMapper().writeValueAsString(Object) 和ObjectMapper().readValue(str, Class)使用
@JSONField位于fastjson包中,搭配JSON.toJSONString(Object) 和 JSON.parseObject(str, Class)使用
34、在某字段上注释@JsonIgnore,可以在json序列化时忽略此字段
35、@JsonCreator注解其作用是,指定对象反序列化时的构造函数或者工厂方法,如果默认构造函数无法满足需求,或者说我们需要在构造对象时做一些特殊逻辑,可以使用该注解。该注解需要搭配@JsonProperty使用。
@JsonCreator
public Person(@JsonProperty("age") int age, @JsonProperty("name") String name) {
this.age = age;
this.name = name;
}
如果不使用JsonCreator,那么需要提供无参构造函数以及对应的setter方法
36、json序列化:SerializationFeature.FAIL_ON_EMPTY_BEANS的值默认为true,该属性的意思是,如果一个对象中没有任何的属性,那么在序列化的时候就会报错。如果设置mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS),那么序列化就不会报错了。在类上面加注解@JsonIgnoreProperties(ignoreUnknown = true) 也可以解决此错误
37、@JsonIgnoreProperties(value = {"name","age"}) 可以注解在类上面,意味着忽略了name和age属性,在序列化的时候,会忽略这两个属性,只序列化其他属性
38、@JsonIgnoreProperties(ignoreUnknown = true) 主要用在反序列化上。正常情况下,如果我们json串中有一些key值和我们的POJO对象不匹配,那么将会抛出异常。
比如json串中有个key名称为height222,pojo中字段为height111,反序列化就会抛异常。如果加上此注解则不会抛异常了。使用 mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 也可以达到同样的目的
39、@JsonSerialize:json序列化注解,用于字段或get方法上,作用于getter()方法,将java对象序列化为json数据
@JsonDeserialize:json反序列化注解,用于字段或set方法上,作用于setter()方法,将json数据反序列化为java对象
40、@JsonInclude:
JsonJsonInclude.Include.ALWAYS 这个是默认策略,任何情况下都序列化该字段,和不写这个注解是一样的效果。
JsonJsonInclude.Include.NON_NULL这个最常用,即如果加该注解的字段为null,那么就不序列化这个字段了。
JsonJsonInclude.Include.NON_EMPTY 这个属性包含NON_NULL,NON_ABSENT之后还包含如果字段为空也不序列化。这个也比较常用
JsonJsonInclude.Include.NON_DEFAULT 这个也好理解,如果字段是默认值的话就不序列化
public class Employee2 {
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private String name;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private String dept;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private Integer salary;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private boolean fullTime;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private List<String> phones;
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
private Date dateOfBirth;
}
public class ExampleMain2 {
public static void main(String[] args) throws IOException {
Employee2 employee = new Employee2();
employee.setName("Trish");
employee.setFullTime(false);
employee.setPhones(new ArrayList<>());
employee.setSalary(Integer.valueOf(0));
employee.setDateOfBirth(new Date(0));
ObjectMapper om = new ObjectMapper();
String jsonString = om.writeValueAsString(employee);
System.out.println(jsonString);
}
}
输出结果是{"name":"Trish"},因为Employee2的其他字段都是默认值
41、@RequestParam可以从request里面取出请求参数
如果是get,则@RequestParam可以取出url?后的参数,例如:?token=xxx,则后端用@RequestParam(value = "token")承接
如果是post,则@RequestParam可以取出curl -d或者--data-raw 指定的参数,如:
curl -v 'https://g-zt.snackvideo.com/rest/zt/captcha/sliding/config' \
--data-raw 'captchaSession=abc' \
--compressed
则后端用@RequestParam(value = "captchaSession")承接
除了用注解,server也可以用request.getParameter(“参数名”)取出请求参数
42、
@POST("/{indexes}/{type}/_search")
search(@Path("indexes") String indexes, @Path("type") String type, @Body RequestBody body);
@Path表示请求路径中的参数,@Body表示请求body
43、request.getParameter方法:接收post请求参数,发送端content-Type必须设置为application/x-www-form-urlencoded;否则会接收不到
44、计算机器的qps:
单线程执行时间500ms 机器上有200线程
qps:1000 / 500 * 200 = 400
qps和并发数的计算关系:
单线程执行时间200ms,并发数300,qps = 1000 / 200 * 300 = 1500
45、Broken pipe分析
java.io.IOException: Broken pipe
Broken pipe产生原因分析
1.当访问某个服务突然服务器挂了,就会产生Broken pipe
2.客户端读取超时关闭了连接,这时服务器往客户端再写数据就发生了broken pipe异常!(如果线程池打满,线程都处于block状态,也会产生Broken pipe
,如果向serveletResponse中写入数据时没flush,可能导致response缓冲区一直没填满,导致客户端读取超时关闭连接,产生Broken pipe)
1.问题一分析服务器为什么挂了。
2.问题二使用jps/jstack分析线程栈,看是不是有线程阻塞。
46、数组转为流:Arrays.stream或者Stream.of
flatMap:即对流中每个元素进行平铺后,形成多个流合在一起
47、泛型中ResultView<?> 问号 表示赋值的类型不确定
48、map的computeIfAbsent和putIfAbsent
java computeIfAbsent:对hashMap中指定key的值进行重新计算,如果不存在这个key,则添加到hashMap中。如果存在这个key,则返回次key对应的value
HashMap<String, Integer> prices = new HashMap<>();
// 往HashMap中添加映射项
prices.put("Shoes", 200);
prices.put("Bag", 300);
prices.put("Pant", 150);
prices.computeIfAbsent("Shirt", key -> 280);
{Pant=150, Shirt=280, Bag=300, Shoes=200}
java putIfAbsent:如果所指定的key在HashMap中存在,返回和这个key对应的value, 如果所指定的key不在HashMap 中,则返回 null。
HashMap<Integer, String> sites = new HashMap<>();
// 往 HashMap 添加一些元素
sites.put(1, "Google");
sites.put(2, "Runoob");
sites.put(3, "Taobao");
// HashMap 不存在该key
sites.putIfAbsent(4, "Weibo");
sites.putIfAbsent(2, "Wiki");
此时map的结果为1=Google, 2=Runoob, 3=Taobao, 4=Weibo}
49、可以在类中定义Supplier,延迟加载。对于会消耗较多资源的对象:这不仅能够节省一些资源,同时也能够加快对象的创建速度,从而从整体上提升性能
private static final Supplier<PhoneNumberUtil> PHONE_NUMBER_UTIL_SUPPLIER = memoize(PhoneNumberUtil::getInstance);
50、把单个对象封装成list:Collections.singleton
51、ApplicationRunner接口:springboot中提供的,该接口中只有一个run方法,他执行的时机是:spring容器启动完成之后,就会紧接着执行这个接口实现类的run方法。在启动时候初始化一些信息 , 比如数据库连接 , 或者自定义的一些配置
52、ksboot yml指定服务启动端口:
server:
port: 8080
53、stream把list按字段聚合成map
Map<Integer, List<LiveBenefits>> type2List = allBenefits.stream().collect(Collectors.groupingBy(LiveBenefits::getType));
54、idea code style设置:https://blog.csdn.net/A_Java_Dog/article/details/115617705