最后
为什么我不完全主张自学?
①平台上的大牛基本上都有很多年的工作经验了,你有没有想过之前行业的门槛是什么样的,现在行业门槛是什么样的?以前企业对于程序员能力要求没有这么高,甚至十多年前你只要会写个“Hello World”,你都可以入门这个行业,所以以前要入门是完全可以入门的。
②现在也有一些优秀的年轻大牛,他们或许也是自学成才,但是他们一定是具备优秀的学习能力,优秀的自我管理能力(时间管理,静心坚持等方面)以及善于发现问题并总结问题。
如果说你认为你的目标十分明确,能做到第②点所说的几个点,以目前的市场来看,你才真正的适合去自学。
除此之外,对于绝大部分人来说,报班一定是最好的一种快速成长的方式。但是有个问题,现在市场上的培训机构质量参差不齐,如果你没有找准一个好的培训班,完全是浪费精力,时间以及金钱,这个需要自己去甄别选择。
我个人建议线上比线下的性价比更高,线下培训价格基本上没2W是下不来的,线上教育现在比较成熟了,此次疫情期间,学生基本上都感受过线上的学习模式。相比线下而言,线上的优势以我的了解主要是以下几个方面:
①价格:线上的价格基本上是线下的一半;
②老师:相对而言线上教育的师资力量比线下更强大也更加丰富,资源更好协调;
③时间:学习时间相对而言更自由,不用裸辞学习,适合边学边工作,降低生活压力;
④课程:从课程内容来说,确实要比线下讲的更加深入。
应该学哪些技术才能达到企业的要求?(下图总结)
本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录
需要这份系统化的资料的朋友,可以点击这里获取
OkHttp3中RequestBody有三种创建方式
①方式一:
-
public static RequestBody create(MediaType contentType, String content) {
-
Charset charset = Util.UTF_8;
-
if (contentType != null) {
-
charset = contentType.charset();//MediaType的为请求头中的ContentType创建方式:public static final MediaType TEXT =
-
//MediaType.parse(“text/plain; charset=utf-8”)
-
if (charset == null) {
-
charset = Util.UTF_8;//如果contentType中没有指定charset,默认使用UTF-8
-
contentType = MediaType.parse(contentType + “; charset=utf-8”);
-
}
-
}
-
byte[] bytes = content.getBytes(charset);
-
return create(contentType, bytes);
-
}
②方式二:FormBody表单创建,我们来看一下
FormBody用于普通post表单上传键值对,我们先来看一下创建的方法,再看源码
-
RequestBody formBody=new FormBody.Builder()
-
.add(“name”,“maplejaw”)
-
.add(")
-
…
-
.build();
FormBody源码
-
public final class FormBody extends RequestBody {
-
private static final MediaType CONTENT_TYPE =
-
MediaType.parse(“application/x-www-form-urlencoded”);
-
private final List encodedNames;
-
private final List encodedValues;
-
private FormBody(List encodedNames, List encodedValues) {
-
this.encodedNames = Util.immutableList(encodedNames);
-
this.encodedValues = Util.immutableList(encodedValues);
-
}
-
public int size() {
-
return encodedNames.size();
-
}
-
public String encodedName(int index) {
-
return encodedNames.get(index);
-
}
-
public String name(int index) {
-
return percentDecode(encodedName(index), true);
-
}
-
public String encodedValue(int index) {
-
return encodedValues.get(index);
-
}
-
public String value(int index) {
-
return percentDecode(encodedValue(index), true);
-
}
-
@Override public MediaType contentType() {
-
return CONTENT_TYPE;
-
}
-
@Override public long contentLength() {
-
return writeOrCountBytes(null, true);
-
}
-
@Override public void writeTo(BufferedSink sink) throws IOException {
-
writeOrCountBytes(sink, false);
-
}
-
private long writeOrCountBytes(BufferedSink sink, boolean countBytes) {
-
long byteCount = 0L;
-
Buffer buffer;
-
if (countBytes) {
-
buffer = new Buffer();
-
} else {
-
buffer = sink.buffer();
-
}
-
, size = encodedNames.size(); i < size; i++) {
-
) buffer.writeByte(‘&’);
-
buffer.writeUtf8(encodedNames.get(i));
-
buffer.writeByte(‘=’);
-
buffer.writeUtf8(encodedValues.get(i));
-
}
-
if (countBytes) {
-
byteCount = buffer.size();
-
buffer.clear();
-
}
-
return byteCount;
-
}
-
public static final class Builder {
-
private final List names = new ArrayList<>();
-
private final List values = new ArrayList<>();
-
public Builder add(String name, String value) {
-
names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, false, false, true, true));
-
values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, false, false, true, true));
-
return this;
-
}
-
public Builder addEncoded(String name, String value) {
-
names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, true, false, true, true));
-
values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, true, false, true, true));
-
return this;
-
}
-
public FormBody build() {
-
return new FormBody(names, values);
-
}
-
}
-
}
``````````````我们主要来看一下方法````````````````writeOrCountBytes``````````````````````````````,通过
③方式三:MultipartBody分块表单创建
``MultipartBody
-
public static Part createFormData(String name, String filename, RequestBody body) {
-
if (name == null) {
-
throw new NullPointerException(“name == null”);
-
}
-
StringBuilder disposition = new StringBuilder(“form-data; name=”);
-
appendQuotedString(disposition, name);
-
if (filename != null) {
-
disposition.append(“; filename=”);
-
appendQuotedString(disposition, filename);
-
}
-
return create(Headers.of(“Content-Disposition”, disposition.toString()), body);
-
}
我们来看这个方法,我们是addPart还是addFormDataPart最终都走到了这个方法,封装成一个Part对象,也就是实体内容中
````````````````MultipartBody和FormBody大体上相同,主要区别在于`writeOrCountBytes方法,分块表单主要是将每个块的大小进行累加来求出请求体大小,如果其中有一个块没有指定大小,就会返回-1。所以分块表单中如果包含文件,默认是无法计算出大小的,除非你自己给文件的RequestBody指定contentLength。`````````````````
-
private long writeOrCountBytes(BufferedSink sink, boolean countBytes) throws IOException {
-
long byteCount = 0L;
-
Buffer byteCountBuffer = null;
-
if (countBytes) {
-
//如果是计算大小的话,就new个
-
sink = byteCountBuffer = new Buffer();
-
}
-
//循环块
-
, partCount = parts.size(); p < partCount; p++) {
-
Part part = parts.get§;
-
//获取每个块的头
-
Headers headers = part.headers;
-
//获取每个块的请求体
-
RequestBody body = part.body;
-
//写 --xxxxxxxxxx 边界
-
sink.write(DASHDASH);
-
sink.write(boundary);
-
sink.write(CRLF);
-
//写块的头
-
if (headers != null) {
-
, headerCount = headers.size(); h < headerCount; h++) {
-
sink.writeUtf8(headers.name(h))
-
.write(COLONSPACE)
-
.writeUtf8(headers.value(h))
-
.write(CRLF);
-
}
-
}
-
//写块的Content_Type
-
MediaType contentType = body.contentType();
-
if (contentType != null) {
-
sink.writeUtf8("Content-Type: ")
-
.writeUtf8(contentType.toString())
-
.write(CRLF);
-
}
-
//写块的大小
-
long contentLength = body.contentLength();
-
) {
-
sink.writeUtf8("Content-Length: ")
-
.writeDecimalLong(contentLength)
-
.write(CRLF);
-
} else if (countBytes) {
-
// We can’t measure the body’s size without the sizes of its components.
-
//如果有个块没有这名大小,就返回-1.
-
byteCountBuffer.clear();
-
return -1L;
-
}
-
sink.write(CRLF);
-
//如果是计算大小就累加,否则写入BufferedSink
-
if (countBytes) {
-
byteCount += contentLength;
-
} else {
-
body.writeTo(sink);
-
}
-
sink.write(CRLF);
-
}
-
//写 --xxxxxxxxxx-- 结束边界
-
sink.write(DASHDASH);
-
sink.write(boundary);
-
sink.write(DASHDASH);
-
sink.write(CRLF);
-
if (countBytes) {
-
byteCount += byteCountBuffer.size();
-
byteCountBuffer.clear();
-
}
-
return byteCount;
-
}
4.CacheControl
( 1) Cache-Control:
Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令有下几种:
-
Public:所有内容都将被缓存(客户端和代理服务器都可缓存)。
-
Private:内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)
-
no-cache:请求或者响应消息不能缓存
-
no-store:不使用缓存,也不存储缓存
-
max-age:缓存的内容将在指定时间(秒)后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较高
-
在 xxx 秒后,浏览器重新发送请求到服务器,指定时间(秒)内,客户端会直接返回cache而不会发起网络请求,若过期会自动发起网络请求
-
min-fresh:指示客户端可以接收响应时间小于当前时间加上指定时间的响应。
-
max-stale:指示客户端可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
(2)CacheControl类
①常用的函数
-
final CacheControl.Builder builder = new CacheControl.Builder();
-
builder.noCache();//不使用缓存,全部走网络
-
builder.noStore();//不使用缓存,也不存储缓存
-
builder.onlyIfCached();//只使用缓存
-
builder.noTransform();//禁止转码
-
builder.maxAge(, TimeUnit.MILLISECONDS);//指示客户机可以接收生存期不大于指定时间的响应。
-
builder.maxStale(, TimeUnit.SECONDS);//指示客户机可以接收超出超时期间的响应消息
-
builder.minFresh(, TimeUnit.SECONDS);//指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
-
CacheControl cache = builder.build();//cacheControl
②CacheControl的两个常量:
-
public static final CacheControl FORCE_NETWORK = new Builder().noCache().build();//不使用缓存
-
public static final CacheControl FORCE_CACHE = new Builder()
-
.onlyIfCached()
-
.maxStale(Integer.MAX_VALUE, TimeUnit.SECONDS)
-
.build();//只使用缓存
③请求时如何使用:
最后
大家看完有什么不懂的可以在下方留言讨论也可以关注。
觉得文章对你有帮助的话记得关注我点个赞支持一下!
本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录
需要这份系统化的资料的朋友,可以点击这里获取
al CacheControl FORCE_CACHE = new Builder()
-
.onlyIfCached()
-
.maxStale(Integer.MAX_VALUE, TimeUnit.SECONDS)
-
.build();//只使用缓存
③请求时如何使用:
最后
在面试前我整理归纳了一些面试学习资料,文中结合我的朋友同学面试美团滴滴这类大厂的资料及案例
[外链图片转存中…(img-A2kPDDML-1714925352744)]
[外链图片转存中…(img-fmmSjcFj-1714925352745)]
由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
大家看完有什么不懂的可以在下方留言讨论也可以关注。
觉得文章对你有帮助的话记得关注我点个赞支持一下!
本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录