首页 > 其他分享 >知识总结

知识总结

时间:2023-06-18 22:34:23浏览次数:34  
标签:总结 String 知识 json new 序列化 class name

jsp以reqBody传给后端 后端用@RequestParam分别接收参数
curl -X GET \
http://bjfk-staging-ls508.yz02:9494/rest/infra/id/card/user/bind/account?uid=xxx&name=xxx&identity=xxx&appType=xxx
后端使用@RequestParam分别承接几个参数即可

@RequestParam只应用于content-type为application/x-www-form-urlencoded(传统表单方式)的场景或者是请求url ?后的参数

ajax默认的格式为application/x-www-form-urlencoded,相当于(username="admin"&password=123)来传递数据,当ajax为默认格,后端可以用两种方式:1、@RequestParam分别接收参数。2、可以封装为对象接收或者单个参数接收

如果前端传参方式为 -d '{"user":"wer", "pwd":"123"}',后端只能用jsonParam或者@RequestBody

Content-Type使用application/json的时候,data为json字符串(JSON.stringify(xxx)), 后端用@RequestBody 方式接收,参数必须是实体类或者map形式,不能单独设置参数,例如public void test(@RequestBody User user)或者public void test(@RequestBody Map map)

http请求头:application/json;charset=utf-8 表示告诉服务端消息主体是json类型的

collect(Collectors.joining()) 表示把所有字符串连接起来

ObjectUtils.isNotEmpty可以判断数组是否为空,字符串长度等

NumberUtils.toLong() 可以避免判断是否为空
String.valueOf() 可以避免是否判断为空

字符串转成int(注意给默认值):NumberUtils.toInt

@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格式

@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

@JsonInclude:
JsonJsonInclude.Include.ALWAYS 这个是默认策略,任何情况下都序列化该字段,和不写这个注解是一样的效果。
JsonJsonInclude.Include.NON_NULL这个最常用,即如果加该注解的字段为null,那么就不序列化这个字段了。
JsonJsonInclude.Include.NON_EMPTY 这个属性包含NON_NULL,NON_ABSENT之后还包含如果字段为空也不序列化。这个也比较常用
JsonJsonInclude.Include.NON_DEFAULT 这个也好理解,如果字段是默认值的话就不序列化
在属性上使用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的其他字段都是默认值

@JsonUnwrapped注解:将嵌套的对象平铺展开
https://juejin.cn/post/7067812048419160071

涉及数字转换 要用NumberUtils工具

把null转成empty:nullToEmpty()方法

parameterMap.put("mobile", joiner.join(requests.stream().map(request -> joiner.join(request.getMobiles().stream().map(SmsCommon.CellPhoneNumber::getNumber).collect(toList()))).collect(toList())))

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的含义一样


forEach和forEachOrder区别:两者完成的功能类似,主要区别在并行处理上,forEachOrdered()将始终按照流(stream)中元素的遇到顺序执行给定的操作,而forEach()方法是不确定的。

sorted中可以把Comparator.comparing()的结果作为入参
Comparator.comparing().thenComparing() 可以定义多个排序规则

ajax JSON.stringify 后端要用实体类或者Map<String, Object>接收
ajax参数 contentType表示告诉服务器请求数据的类型
dataType表示告诉服务器,我要想什么类型的数据

http建立连接timeout: connect timeout
http读取数据timeout: socket timeout

Exception: e.getClass().getSimpleName()可以拿到具体异常的类型

Sets.difference(set1, set2) 可以获取元素:在set1中存在但是在set2中不存在
Set的retainAll方法:求交集

http表单格式:application/x-www-form-urlencoded

@RestController注解相当于@ResponseBody + @Controller

线程池用法:TestAsyncSend类

idea或eclipse的jvm arguments加入 -Dfuck.abc="1234" 在代码中System.getProperty("fuck.abc")可以获取这个值
-D是用来在启动java程序时设置系统属性的

接口中的default方法会被实现类直接继承

Random r = new Random() nextInt(bound) 会生成0到bound的值 每次不一样
Random r = new Random(100) 指定种子后,nextInt(bound) 会生成0到bound的值 每次都一样

ip号段:
103.107.217.0/24 表示
103.107.217.0 到 103.107.217.255

对Map的每个entry操作:
1、map.entryset().stream().foreach()
2、map.foreach()

@POST("/{indexes}/{type}/_search")
search(@Path("indexes") String indexes, @Path("type") String type, @Body RequestBody body);
@Path表示请求路径中的参数,@Body表示请求body

localDatetime和毫秒数转化
LocalDateTime end = LocalDateTime.of(2020, 3, 3, 18, 38, 00);
System.out.println(end.toInstant(ZoneOffset.of("+8")).toEpochMilli());


三个元素的if else:
SmsConstants的userIpV4InString方法


去掉字符串指定的前缀:
StringUtils.removeStart(fullNumber, "+")

//日期转化
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());

//如果string类型日期想转格式:
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日");
Date parsedDate = formatter.parse(date);

SimpleDateFormat resultFormat = new SimpleDateFormat("yyyyMMdd");
String result = resultFormat.format(parsedDate);

// 时间戳转为年月日
SimpleDateFormat MONTH_DAY_FORMAT = new SimpleDateFormat("M月dd日");
Date date = new Date(timestamp);
String result = MONTH_DAY_FORMAT.format(date);


UrlEncode会把/变为%2f

springmvc restful接口 @PathVariable("urlTail") 这样只能映射abcd这样的,不能映射abcd/edf/hik这样多级路径的

zsh: command not found
vim ~/.zshrc
在文件末尾添加上 source ~/.bash_profile 保存即可

可以 open ~/.zshrc 然后添加source ~/.bash_profile


图片转byte数组:
String photoPath = "/home/web_server/files/jiaboyu/src/infra-id-card-verify/infra-id-card-verify-common/4115500_491115.jpg";
File photo = new File(photoPath);

FileInputStream fis = new FileInputStream(photo);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1)
{
bos.write(b, 0, n);
}
fis.close();
bos.close();
byte[] buffer = bos.toByteArray();

使用IOUtils
String photoPath = "abc";
File photo = new File(photoPath);
byte[] bytes = FileUtils.readFileToByteArray(photo);

实体类转为Map形式:
obj -> jsonStr -> map


curl -X GET \
http://bjfk-rs5034.yz02:9494/rest/infra/id/card/external/enterpriselicense/Fr3TNaD%2FsYjP1%2FmNk3LENt9PXl%2FoUlcoZZ24XZl8grZgBrREI%2FdtNKB1WRxxJg%2Bs \
http请求路径中不能带%,否则会报400 bad request

curl -X GET \
http://bjfk-rs5034.yz02:9494/rest/infra/id/card/external/enterpriselicense?token=M0Hy9_h4QnAseJ_D7nSbQoWqI0wVluBYldPDCcl4-mrHYtlZcVtHrx9C6p63dr6aXR71W0olcgvNXY0hc65m-M2WJJ9aOAEoYS3OCYmxJ3U --output licen.jpg


如果某个字符串需要放入http请求参数中,如?后内容 需要把字符串经过Base64.encodeBase64URLSafeString, 否则会有字符丢失
Base64.encodeBase64URLSafeString() 方法可以实现+转化-,/转化_ 并去掉==

Base64.encodeBase64URLSafeString()和Base64.encodeBase64String() 生成的字符串 用Base64.decodeBase64() 生成的结果是一样的

?后的参数,在经过http请求时会自动urlencode编码

urlencode会把/转为%2F,+转为%2B

http的queryString中内容(即?后的内容)和www-form-urlencoded form表单中的内容,经过http请求后会自动被urlEncode编码
Base64非url safe的编码,会有+等内容,对应的解码方式是Base64.getDecoder().decode()
Base64的url safe编码,会把+,/, ==等转化,对应解码方式是Base64.decodeBase64
Base64.decodeBase64对url safe和url 非safe都是兼容的
url safe编码后 用Base64.getDecoder().decode()解码是不兼容的
对于url safe编码,不管编码多少次,都能用Base64.decodeBase64成功解码

hive解析json:https://blog.csdn.net/qq_34105362/article/details/80454697
get_json_object(response_detail, '$.body.messages[0].status') = 6

hive substr:substr(p_date, 1, 6) 表示截取第1到6位

retrofit2 Response 拿到所有response header:
Headers headersFromResponse = httpRsult.headers();
拿到指定header:
String requestId = String.valueOf(headersFromResponse.get("X-Ca-Request-Id"));

admin重启即为执行apache的startup.sh,所以可以直接执行apacha的脚本


retrofit2.http相关注解:
@QueryMap Map<String, Integer> map 可传多个参数,都以?形式拼接
如果url中?sig=... @Query("sig") 可传入一个参数,对应
@HeaderMap 表示http头部传多个参数
如果@POST("/{indexes}/{type}), @Path("indexes") String indexes 即表示传入参数
@Body 可传入requestBody


根据字符串获取枚举值:
Enums.getIfPresent(ProductPlatform.Platform.class, getValueFromRequest(request, "platform"))
.or(UNKNOWN_PLATFORM)

EnumUtils.fromValue(DrawPrizeExtParam.class, val, UNKNOWN)


peek: 不能修改流中的元素,只能对元素进行打印输出或者改变引用类型的属性。peek入参是consumer
filter(strategy -> strategy != null) 可用filter(Objects::nonNull)代替

java8 stream代替for循环:
IntStream.range(0, 100).forEach()
IntStream.rangeClosed(1, this.5).boxed() boxed表示把int转为Integer

ImageIO.read可以传入InputStream对象,生成BufferedImage即图片,参考验证码中台ShadowLineamentGeneratorTest
也可以传入file对象

IOUtils读取文件:
1、读取File
String photoPath = "abc";
File photo = new File(photoPath);
byte[] bytes = FileUtils.readFileToByteArray(photo);
2、读取inputStream
List<String> words = IOUtils.readLines(ChengYuClickCaptchaTest.class.getResourceAsStream("/words.txt"), "UTF-8")


查看mysql存储数据或图片大小:转为byte[]数组,数组长度即代表多少byte,除以1024可得出kb

scp一般利用ssh传输文件
ssh免密操作:假设本地机器为local,远程服务器为remote,用户均为user。
1、user在local机器上通过ssh-keygen生成一个非对称密钥对(假设公钥key.pub,私钥为key.pri)
2、user通过ssh命令登录user@remote(该阶段需要输入密码),并将key.pub拷贝到remote机器上的/home/user/.ssh/authorized_keys文件中(添加一行即可);该步也可通过ssh-copy-id命令直接操作
3、当user再次从local执行ssh remote的时候,不需要输入任何密码即可登录
该原理也可利用在机器之间传输文件

base64编码会让数据扩大1/3

如果api服务直接抛出异常 前端看到的状态码是500,如果用handler统一处理 会返回http200

为远程分支创建本地分支
git checkout --track origin/01-11-lzb-add-get
git checkout --track origin/jiaby_0530_draw

根据远程分支创建新的本地分支
git checkout -b newbranch origin/master


try (ByteArrayInputStream in = new ByteArrayInputStream(image))
try-with-resource可以自动关闭流


request.getParameter方法:接收post请求参数,发送端content-Type必须设置为application/x-www-form-urlencoded;否则会接收不到


maven去掉依赖:如果我们不想通过 A->B->C->D1 引入 D1 的话,那么我们在声明引入 A 的时候将 D1 排除掉,例如
<dependency>
<groupId>in.zapr.druid</groupId>
<artifactId>druidry</artifactId>
<version>2.12</version>
<exclusions>
<exclusion>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
</exclusions>


<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
该插件和打war包有关

Maven项目默认的资源文件夹是 src/main/resources,编译后会出现在WAR文件的target/classes 和 zt-captcha-api-1.0-SNAPSHOT/WEB-INF/classes中。WAR插件可以使用webResources参数来包含默认资源文件夹以外的资源
例如:
<webResources>
<resource>
<directory>extra-config</directory>
<targetPath>/WEB-INF/extra-config</targetPath>
</resource>
</webResources>
可以把extra-config里的内容输出到zt-captcha-api-1.0-SNAPSHOT/WEB-INF/extra-config里面
项目本地编译后会在zt-captcha-api模块的target目录下生成zt-captcha-api-1.0-SNAPSHOT,在WEB-INF目录下包含classes,extra-config,lib目录,这也是zt-captcha-api.war包解压后的结果

war插件里的
<outputDirectory>${basedir}/../target/${artifactId}</outputDirectory>
<warName>${artifactId}</warName>
可以给war命名并指定输出位置
war插件文章参考:
https://www.cnblogs.com/larryzeal/p/6181555.html

mvn -pl:在指定模块上执行
-am: 构建指定模块,同时构建指定模块依赖的其他模块


CaptchaType.forNumber() 可以根据pb枚举的数字获取验证码类型

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分析线程栈,看是不是有线程阻塞。

ab压测:
测试机上发压即可,本地配置环境难度较大
ab -c 400 -n 240000 -t 10 http://zt.test.gifshow.com/rest/zt/captcha/sliding/cutPic?captchaSn=Cgp6dC5jYXB0Y2hhEvkBwPfNwTAuXa-Zw3udUMG4kfjpYsOJUtvSPL57VKw24b65ODfJYBNdNgqcMNPjGO3hhuCUc-ksdNnen9P2ffcBZhYpkUm56rLJlHHwTSyfuO715jysECs14_IAZl9eZpAB4A2khTK0J87eCRwiG-k6JW5EjrDw5QWbRVb2kENFuaAdQ01UiU0x1vLUUEKhBhtDNQYoo8U_wa9ZjQa6O1D33qgxS1U2ohAp6Tj_7v1KlftBWondggvN2q3qws5sDLOiaYq-c6pZbIH1ZWjk1xLIwzQMEH15KIgr1fw3sFdTG1FG6OZqLvhQ7giohBgrQUQkyEE4w8OkEfhxGhIUZA-c6Wohnx-s4Cp9V_FC4gIoCjAC


计算机器的qps:
单线程执行时间500ms 机器上有200线程
qps:1000 / 500 * 200 = 400

qps和并发数的计算关系:
单线程执行时间200ms,并发数300,qps = 1000 / 200 * 300 = 1500

在Spring里,我们可以使用@ControllerAdvice来声明一些全局性的东西,最常见的是结合@ExceptionHandler注解用于全局异常的处理。
@ExceptionHandler注解标注的方法:用于捕获Controller中抛出的不同类型的异常,从而达到异常全局处理的目的;
@ControllerAdvice("com.cmos.edcreg.web.controller") 可以声明该类要处理的包路径

java枚举在db中存储一般用tinyint,从性能角度考虑 VARCHAR (N) 会比 TINYINT 略差,主要表现在 JOIN 和 ORDER BY 的操作上。首先 TINYINT 的字节数很小,只占 1 个字节。

引入依赖后可能会自动装配某些interceptor 导致健康检查失败等

// 查询某个表中时间最近的记录
SELECT * from package_record A, (SELECT status, max(update_time) max_update_time FROM package_record where status = 6) B
where A.status = B.status and A.update_time = B.max_update_time;

我们用Java编写的文件都是.java文件,JVM在编译项目时,会主动将.java文件编译成 .class文件。class文件才能被jvm运行。jvm会把编译好的class文件和resources目录下的文件一起放在 target/classes目录下,target/classes即classpath

getResourceAsStream方法寻找文件的起点是JAVA项目编译之后的根目录,比如一般maven项目编译之后根目录都是target/classes这个文件
当java读取resources里的文件,
1、如果在本地执行(不在服务器上执行),可以输入绝对路径读取文件
File file = new File("src/main/resources/properties/test.properties");
2、如果在服务器上读取:JavaWeb项目部署服务器中,会将项目打包成Jar包或者war包,此时就不会存在 src/main/resources 目录,resources 下的静态文件会存放在 target/classes目录下。
InputStream in = xxx.class.getResourceAsStream("/properties/test.properties");

class.getResourceAStream() 与 class.getClassLoader().getResorceAsStream() 的区别?
class 是获取当前类的 class 对象,getClassLoader()是获取当前的类加载器,什么是类加载器?简单点说,就是用来加载java类的,类加载器就是负责把class文件加载进内存中,并创建一个java.lang.Class类的一个实例也就是class对象,并且每个类的类加载器都不相同,getResourceAsStream(path)是用来获取资源的。类加载器默认是从 classPath 下获取资源的,因为这下面有class文件。
a、class.getClassLoader().getResourceAsStream(String name) 默认则是从ClassPath根下获取(文件放在resources目录下),name不能带"/",否则会抛空指针。采用相对路径, "/"就相当于当前进程的根目录,即项目根目录;
b、class.getResourceAsStream(String name) 是采用绝对路径,绝对路径是相对于 classpath 根目录的路径,"/" 就代表着 classpath,所以 name 属性需要前面加上 "/";getResourceAsStream()不带"/"时候是从当前类所在包路径去获取资源

getResourceAsStream() 方法仅仅是获取对应路径文件的输入流,在路径的用法上与getResource()一致

getResource读取资源文件详见:
https://blog.csdn.net/weixin_43291944/article/details/106802630

BuilderDemo.class.getResource("")
BuilderDemo.class.getResource("/")的输出分别是
file:/Users/jiaboyu/javacode/program-demo/target/classes/jdk8demo/
file:/Users/jiaboyu/javacode/program-demo/target/classes/
getResource("")不带"/“时候是从当前类所在包路径去获取资源
getResource("/")带”/"时候是从classpath的根路径获取

BuilderDemo.class.getClassLoader().getResource("")
BuilderDemo.class.getClassLoader().getResource("/")的输出分别是
file:/Users/jiaboyu/javacode/program-demo/target/classes/
null
getClassLoader().getResource("")不带"/“时候是从classpath的根路径获取
getClassLoader().getResource("/")带有”/"打印为null,路径中无法带有"/"

数组转为流:Arrays.stream或者Stream.of

将string类型list转为long类型list,使用mapToLong后需要使用boxed。
mapToLong只是把流转换为 LongStream 类型。
调用 LongStream.boxed 方法将LongStream转为为 Stream<Long> 类型
collect(Collectors.toList())把 Stream<Long> 转换为 List
List<Long> longList = NUMBERS_LIST.stream().mapToLong(Long::valueOf).boxed().collect(Collectors.toList());


flatMap:即对流中每个元素进行平铺后,形成多个流合在一起

-Denforcer.skip=true 可以跳过enforcer插件执行

java -D是用于设置环境属性值的重要方式。

java类转为json字符串,下列条件需要满足一个:
1、对应字段需要有set和get方法,否则该字段转化的结果为空。
2、如果没有get和set方法,可以用@JsonProperty注解,也可以达到将类转为json字符串效果

jackson在反序列化时,默认使用对象的默认构造函数,如果默认构造函数不存在,jackson会报错。

@JsonCreator注解,其作用就是,指定对象反序列化时的构造函数或者工厂方法,如果默认构造函数无法满足需求,或者说我们需要在构造对象时做一些特殊逻辑,可以使用该注解。该注解需要搭配@JsonProperty使用。
@JsonCreator
public Person(@JsonProperty("age") int age, @JsonProperty("name") String name) {
this.age = age;
this.name = name;
}

如果不使用JsonCreator,那么需要提供无参构造函数以及对应的setter方法

@JsonProperty注解作用:此注解用于属性上,作用是把该属性的名称序列化为另外一个名称。

在某字段上注释@JsonIgnore,可以在json序列化时忽略此字段

json序列化:SerializationFeature.FAIL_ON_EMPTY_BEANS的值 默认为true,该属性的意思是,如果一个对象中没有任何的属性,那么在序列化的时候就会报错
如果设置mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS),那么序列化就不会报错了。
在类上面加注解@JsonIgnoreProperties(ignoreUnknown = true) 也可以解决此错误

@JsonIgnoreProperties(value = {"name","age"}) 可以注解在类上面,意味着忽略了name和age属性,在序列化的时候,会忽略这两个属性,只序列化其他属性

@JsonIgnoreProperties(ignoreUnknown = true) 主要用在反序列化上。正常情况下,如果我们json串中有一些key值和我们的POJO对象不匹配,那么将会抛出异常。
比如json串中有个key名称为height222,pojo中字段为height111,反序列化就会抛异常。如果加上此注解则不会抛异常了。使用 mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); 也可以达到同样的目的

@JsonSerialize:json序列化注解,用于字段或get方法上,作用于getter()方法,将java对象序列化为json数据
@JsonDeserialize:json反序列化注解,用于字段或set方法上,作用于setter()方法,将json数据反序列化为java对象

swagger本地启动域名:http://localhost:8080/swagger-ui.html#/

Caused by异常:https://monkeysayhi.github.io/2017/10/02/%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BC%9A%E9%98%85%E8%AF%BBJava%E7%9A%84%E5%BC%82%E5%B8%B8%E4%BF%A1%E6%81%AF%E5%90%97%EF%BC%9F/

logback框架会默认加载classpath下命名为logback-spring或logback或logback-test的配置文件
<configuration>:有三个属性:
scan:当scan被设置为true时,当配置文件发生改变,将会被重新加载,默认为true
scanPeriod:检测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认为毫秒,当scan=true时这个值生效,默认时间间隔为1分钟
debug:当被设置为true时,将打印出logback内部日志信息,实时查看logback运行信息,默认为false
<root>标签:用来指定最基础的日志输出级别,也是<logger>元素,它是根logger,只有一个level属性,因为它的name就是ROOT
<appender>标签:通过使用该标签指定日志的收集策略,name属性指定appender命名,class属性指定输出策略,通常有两种,控制台输出和文件输出,文件输出就是将日志进行一个持久化。ConsoleAppender将日志输出到控制台
<filter>:通过使用该标签指定过滤策略
<rollingPolicy>:标签指定收集策略,比如基于时间进行收集
<logger>:用来设置某一个包或者具体某一个类的日志打印级别、以及指定<appender>。<logger>可以包含零个或者多个<appender-ref>元素,标识这个appender将会添加到这个logger。logger有一个name属性、一个可选的level属性和一个可选的additivity属性,表示会把name这个类的日志打出来
<logger name="org.apache.kafka" level="error" additivity="true">
<appender-ref ref="stdout"/>
</logger>
<turboFilter>中引入的类是TurboFilter的子类,可以重写decide方法,改变日志打印的级别

Filters决定日志事件能否被输出。过滤条件有三个值:ACCEPT(接受),DENY(拒绝),NEUTRAL(中立)
过滤器ACCEPT和DENY之后,后续的过滤器就不会执行了,只有在NEUTRAL的时候才会执行后续的过滤器


异步输出日志:之前的日志配置方式是基于同步的,每次日志输出到文件都会进行一次磁盘IO。采用异步写日志的方式而不让此次写日志发生磁盘IO,阻塞线程从而造成不必要的性能损耗。异步输出日志的方式很简单,添加一个基于异步写日志的appender,并指向原先配置的appender即可


SPI(Service Provider Interface)是调用方来制定接口规范,提供给外部来实现,调用方在调用时则选择自己需要的外部实现。从使用人员上来说,SPI 被框架扩展人员使用。
实现:
1、定义个接口:
public interface UploadCDN {
void upload(String url);
}

2、定义实现类:
public class QiyiCDN implements UploadCDN { //上传爱奇艺cdn
@Override
public void upload(String url) {
System.out.println("upload to qiyi cdn");
}
}

public class ChinaNetCDN implements UploadCDN {//上传网宿cdn
@Override
public void upload(String url) {
System.out.println("upload to chinaNet cdn");
}
}

3、在resources目录下新建META-INF/services目录,并且在这个目录下新建一个文件,文件名是接口的全路径名称:
com.kuaishou.cny2022.tiger.infra.util.UploadCDN。

4、文件中写入接口实现类的全路径名:
com.kuaishou.cny2022.tiger.infra.util.QiyiCDN
com.kuaishou.cny2022.tiger.infra.util.ChinaNetCDN

5、调用方式:
public static void main(String[] args) {
ServiceLoader<UploadCDN> uploadCDN = ServiceLoader.load(UploadCDN.class);
for (UploadCDN u : uploadCDN) {
u.upload("filePath");
}
}

6、输出:
upload to qiyi cdn
upload to chinaNet cdn

 

当进程有OOM等异常出现时,jvm就会将当前的虚拟机的堆等信息放入hprof文件中, 名字是大概java_pid加上进程号
服务进程一直反复重启,可能是OOM了,需要看下每分钟gc次数的监控,并调大内存

git merge request 点revert可以去掉此次提交

MoreFunctions.catching 需要有返回值
MoreFunctions.runCatching 可以没有返回值
MoreFunctions.catchingOptional 可以对产生的异常做兜底处理 详见春节工程

Iterables.getLast可以拿到末尾节点


LoadingCache参数含义:
1、maximumSize:设定缓存项的数目的最大值,当数目空间不足时,会使用LRU策略进行回收
2、expireAfterxxx:过期逐出,例如expireAfterWrite设置为10分钟,则写入十分钟后过期
4、refreshAfterWrite:例如设置为10分钟,则10分钟内没有写操作,则刷新。在到达过期时间后,对cache进行get操作依然可以返回当前已经过期的值,同时触发load操作
5、cache加载方式:
1)load/loadAll:当获取的缓存值不存在时调用,在load操作完成前,调用者会被阻塞。如果有多个线程同时获取同一个key的操作,只会进行一次load;如果load操作失败抛出异常,调用者也会抛异常
2)reload:cache中有数据,但是设置了refreshAfterWrite行为,则会触发reload操作;如果没有设置,则reload不会被使用。 reload操作返回的是一个Future而非结果值。reload操作如果还没有完成,或者reload失败,则依然会返回先前的旧值。reload的默认行为依然是阻塞的,它直接调用了load方法。框架中有一个AsyncReloadCacheLoader是一个使用单独的线程池中执行reload操作的实现,不阻塞用户请求。
6、建议expireAfterXXX和refreshAfterWrite搭配使用,并设置refreshAfterWrite参数的时间小于expireAfterXXX参数的时间。比如refreshAfterWrite=5s,expireAfterXXX = 10s。这样在触发refresh操作的时候cache中数据还没有过期,只需一个线程执行reload


LoadingCache和ReloadableCache的区别
1、LoadingCache主要用来缓存热点数据,而ReloadableCache是用来缓存全量数据的。例:每个用户的profile页数据适合使用LoadingCache,魔表信息适合使用ReloadableCache。
2、LoadingCache有LRU策略,ReloadableCache没有缓存淘汰,所以需要关注内存开销,如果过大的话,可能会造成JVM的GC压力过大。
3、ReloadableCache可以定时刷新或者数据变更时出发通知更新,LoadingCache是请求触发数据更新。

 

@ExceptionHandler此注解使用在方法级别,声明对Exception的处理逻辑。可以指定目标Exception
@ResponseBody此注解用在请求handler方法上。和@RequestBody作用类似,用于将方法的返回对象直接输出到http响应中。

@RestControllerAdvice此注解用于class上,同时引入了@ControllerAdvice和@ResponseBody两个注解。

 

SpringBoot 的 ApplicationRunner 接口可以让项目在启动时候初始化一些信息,比如预热服务等

JsonParam参数使用条件:需要加入JsonParamAnnotationResolver,还需加入一些其他的过滤器和拦截器


泛型中ResultView<?> 问号 表示赋值的类型不确定

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}

 

可以在类中定义Supplier,延迟加载。对于会消耗较多资源的对象:这不仅能够节省一些资源,同时也能够加快对象的创建速度,从而从整体上提升性能
private static final Supplier<PhoneNumberUtil> PHONE_NUMBER_UTIL_SUPPLIER = memoize(PhoneNumberUtil::getInstance);

web.xml配置:
创建Servlet实例有两个时机:
1、客户端第一次请求某个Servlet时,系统创建该Servlet的实例,大部分Servlet都是这种Servlet。
2、Web应用启动时立即创建Servlet实例,即load-on-start Servlet。
<servlet>
<servlet-name>zt-captcha-api-gateway</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-name>用来定义servlet的名称,该名称在整个应用中必须是惟一的
<load-on-startup>1</load-on-startup>表示启动容器时,初始化Servlet

web.xml中可以注册过滤器,比如定义了一个类TestFilter1
<filter>
<filter-name>testFilter1</filter-name>
<filter-class>com.scorpios.filter.TestFilter1</filter-class>
</filter>
<filter-mapping>
<filter-name>testFilter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

 


logback.xml
<property name="ASYNC_APPENDER_INCLUDE_CALLER_DATA" value="false"/> 可以禁止日志输出行号


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


ResponseBodyAdvice 接口是在 Controller 执行 return 之后,在 response 返回给客户端之前,执行的对 response 的一些处理,可以实现对 response 数据的一些统一封装或者加密等操作。比如可以实现ResponseBodyAdvice接口,在实现类中获取api controller的返回值。
详见:https://www.cnblogs.com/goloving/p/15045736.html

把单个对象封装成list:Collections.singleton

ApplicationRunner接口:springboot中提供的,该接口中,只有一个run方法,他执行的时机是:spring容器启动完成之后,就会紧接着执行这个接口实现类的run方法。

http请求返回502,是因为转发问题,可能后端路由配置有问题,请求还没到后端

ksboot yml指定服务启动端口:
server:
port: 8080

标签:总结,String,知识,json,new,序列化,class,name
From: https://www.cnblogs.com/MarkLeeBYR/p/17489895.html

相关文章

  • C++基础知识总结
    2023/6/18本篇章记录学习过程C++的基础概念和代码测试实现,还有很多需要补充。一是还不清楚,二是还没有学到。打算学习过程中后面再做补充。先看完《C++primer》书之后再慢慢来添加补充1.函数重载一个函数名可以实现多个功能,这取决于函数参数不同来实现判断对应的功能,与返回......
  • 本周总结(6.18)
    总结1、数据结构小学期第一阶段的四道题目全部完成啦!就是还需要进行一定的复习,以应对接下来的数据结构答辩啦!2、ppt和计划书仍旧在努力阶段3、小程序情况基本上完成了登录界面和主界面的内容,但是下面的内容还没有填.........
  • BUAA OO 总结
    正向建模和开发本单元通过学习三种UML图,在具体写代码之前先对架构进行构建。理论上讲,这样是可以节省很多时间并优化架构的,但是我实际执行过程中,经常遇到原来的UML图架构考虑不周,而不得不根据代码反过来修改UML图,最后第一次作业基本上就和先写代码没有区别,好在第二,三次迭代时这样......
  • Redis的设计与实现-总结
    个人真的很喜欢这本书,从对C语言一窍不通,到发现C语言竟然如此简洁,以至于我喜欢上了C!对此前面的底层数据结构也读了几次,大致整理了书里的内容,后面的就粗略看了一下,不再细细整理了.Redis的设计与实现(1)-SDS简单动态字符串Redis的设计与实现(2)-链表Redis的设计与实......
  • 第三十节:EFCore7.x版本新功能总结
    一.linq改进1.GroupBy(1).可以直接GroupBy进行toList()输出了. PS:从EFCore3.x--6.x不能直接groupby进行输出了。(2).这种类型的GroupBy不会直接转换为SQL,因此EFCore对返回的结果进行分组。但是,这不会导致从服务器传输任何其他数据。toList()才会查询。(3).案......
  • 算法题总结-吃苹果(有序处理)
    原题https://leetcode.cn/problems/maximum-number-of-eaten-apples/有一棵特殊的苹果树,一连n天,每天都可以长出若干个苹果。在第i天,树上会长出apples[i]个苹果,这些苹果将会在days[i]天后(也就是说,第i+days[i]天时)腐烂,变得无法食用。也可能有那么几天,树上不会长出新的......
  • 测量项目总结
    和朋友合作开发一个测量机产品,用于测量汽车零件形位公差,客户的客户是电动汽车第一品牌,我负责上位机开发,历时2个月,完成上百次的commit.时间虽紧,但代码质量上没有妥协,软件层次划分合理,后续考虑做成系列产品.开发利器感恩这个时代,现在的软件开发开发体验真好,可以......
  • TensorFlow05.3 神经网络反向传播算法-多层感知机梯度(理论知识)
    首先这个是链式法则:如果扩展到多层感知机的话:我们在学这个的时候首先知道一个东西:所以这个整体的步骤就是:1.2.3.......
  • 运算符重载知识点总结
    #运算符重载在数学上,两个复数可以直接进行+、-等运算。但在C++中,直接将+或-用于复数对象是不允许的。•有时会希望,让对象也能通过运算符进行运算。这样代码更简洁,容易理解。•例如:complex_a和complex_b是两个复数对象;求两个复数的和,希望能直接写:complex_a+complex_b在数学上......
  • k8s 梳理及使用总结
    ---1.Kubernetes概述1.最初Google开发了1个叫Borg的系统(现在命名为Omega),来调度近20多亿个容器从2014年第1个版本发布以来,迅速得到了开源社区的追捧,?前,k8s已经成为了发展最快、市场占有率最高的容器编排引擎产品。---2.特点轻量级,资源消耗小开源弹性伸缩负载均衡IPVS---3.重要......