精华内容
下载资源
问答
  • Get与Post请求及Get缓存

    2021-04-23 17:16:19
    一、get与post的区别 get传参方式是通过地址栏URL传递,是可以直接看到get传递的参数。post传参方式参数URL不可见。get把请求的数据在URL后面...get请求可以被缓存post不可以被缓存。 get请求只可以URL编码,post

    一、get与post的区别

    1. get传参方式是通过地址栏URL传递,是可以直接看到get传递的参数。post传参方式参数URL不可见。get把请求的数据在URL后面通过?连接,通过&进行参数分割。post将参数存放在HTTP的包体内。
    2. get传递参数是通过URL进行传递,对传递的数据长度是受到URL大小的限制,URL最大长度是2048个字符。post没有长度限制。
    3. get后退不会有影响,post后退会重新进行提交。
    4. get请求可以被缓存,post不可以被缓存。
    5. get请求只可以URL编码,post支持多种编码方式。
    6. get请求的记录会留在历史记录中,post请求不会留在历史记录。
    7. get只支持ASCLL字符,post没有字符类型限制。

    二、Get缓存

    1. 什么是http缓存?
      http缓存指的是:当客户端向服务器请求资源时,会先抵达浏览器缓存,如果浏览器有“要请求资源”的副本,就可以直接从浏览器缓存中提取而不是从原始服务器中提取这个资源。
      常见的http缓存只能缓存get请求响应的资源,对于其他类型的响应无能为力。http缓存都是从第二次请求开始的,第一次请求的时候浏览器把返回的数据记录下来,再次发送请求的时候,浏览器并不是真的再发送这条请求,而是从历史记录里把这个数据读出来。
    2. get缓存如何生效?
      get请求并不是默认就能够缓存数据。打开控制台,查看get请求里面的response header。
      在这里插入图片描述
      此时cache-control为no-cache,expires为0,查阅文档得知no-cache的意思是告知服务器不直接使用缓存,要求向原服务器发起请求;expires设置缓存过期时间,给出的时间/日期之后再次向服务器发送请求更新数据。
      若后端在这个接口里面设置断点,每次前端刷新页面,都会进入断点里面。说明get方法并没有使用缓存。
      后端重新配置response header:
    response.setDateHeader('Expires',System.currentTimeMillis()+1000*60*60*24);//24小时
    response.setHeader('Cache-control','max-age=60'); //60秒(优先级更高)
    

    再次刷新页面发送请求,后端代码进入断点,释放代码之后,控制台查看response header,cache- control和expires都配置成功了。
    在这里插入图片描述
    再刷新页面,NetWork重新调用接口,后端并没有进入断点,一分钟后再次刷新页面,后端进入断点。 此时缓存设置的一分钟到期了,才会再次请求服务器。
    3. 后端设置了缓存,浏览器如何禁用?
    浏览器有一个功能,打开控制台可以设置禁用缓存,点击NetWork里面的Disabled cache。此时每次刷新页面请求接口的时候,后端都会进入断点。
    在这里插入图片描述
    4. 防止浏览器缓存的方法
    防止浏览器缓存的方法是设置response header,告诉浏览器不要缓存数据,或者给一个校验,比较靠谱的方法是每次都让get的数据不一样:

    Get  http://localhost/api?_t=时间戳
    

    添加一个后端直接忽略的参数,每次都不一样,这样浏览器就认为每次都是不同的请求,就不会从历史记录里读取数据了。

    展开全文
  • Android App网络缓存实践为什么要做网络缓存?OkHttp的网络缓存OkHttp的限制如何实现Post缓存我的缓存方案如何识别需要缓存的接口 为什么要做网络缓存? 网络缓存可以提高接口的响应速度,节省服务器资源,因为有些...

    *代码已上传github,需要源码的可以去这里看看NetCache

    为什么要做网络缓存?

    网络缓存可以提高接口的响应速度,节省服务器资源,因为有些数据比如用户信息之类的,很久都不会有什么修改,那么这种情况就没必要每次都从服务器拉取数据,完全可以使用本地的缓存,当用户信息有更新时,我们再将从服务器获取的数据覆盖本地缓存并使用。
    期次对于某些需要用来做界面展示的数据,当手机没有网络的时候可以使用其缓存快速展示给用户,避免界面出现空屏无数据的尴尬。
    相信以上两点足以证明网络缓存的必要性。

    OkHttp的网络缓存

    OKHttp应该都不陌生,现在大部分Android开发应该都在使用它或者封装了它的Retrofit做网络处理,OKHttp的功能非常强大,它可以说是Android目前最好的网络框架了,那么这么强大的框架,自然是支持网络缓存的,有关介绍OkHttp网络缓存的博客网上有很多,随便一篇都能教你怎么开启使用。

    OkHttp的限制

    那么既然已经有现成的方案可以使用了,我还写这篇博客干嘛,直接用现成的不香吗?不不不,虽然OKHttp的网络缓存很香,但是它也是有限制的,最大一点就是它只支持Get请求方式缓存,不支持Post缓存,这点它的源码里有注明。

    if (!requestMethod.equals("GET")) {
          //不要缓存非GET响应。 从技术上讲,我们可以缓存
          //HEAD请求和一些POST请求,但是这样做很复杂
          //因此高,而收益低。
          // Don't cache non-GET responses. We're technically allowed to cache
          // HEAD requests and some POST requests, but the complexity of doing
          // so is high and the benefit is low.
          return null;
        }
    

    其实它不支持Post缓存也无可厚非,毕竟Post请求是表单操作,它是用户与服务器交互,向服务器提交数据的一种方式,既然是提交数据,那它返回的数据也是跟着用户提交的数据实时变化的,没必要进行缓存。
    但是,就怕但是,遇到浪的,放着Get不用转而都去用Post方法请求接口的,比如我们公司的项目,。。好家伙,直接把路给你封的死死的,现有的OKHttp缓存是别想用了,除非把接口改成Get请求方式,emmm。。。还是算了。

    如何实现Post缓存

    既然OKHttp缓存这条路被堵死,那我们只能另辟蹊径了,喂喂,可不是让你去干改OKHttp源码,绕开判断这种事情的啊,写这篇博客之前我也在网上看了不少如何实现Post缓存这类文章,除了大部分挂羊头卖狗肉的文章外,其余的看完后我直接好家伙,真是神仙过海,各显神通,比如上面说的改源码、绕判断这种,尤其是绕判断这块,感觉没个十年脑栓根本想不出。
    不过我没有去使用这些方案,总感觉不靠谱,而且放出的代码有限,博主自己也说方案有缺陷,并不能覆盖所有的缓存场景,也没有放出结果证实自己方案的可行性,所以就当个扩展思维的文章看吧~
    思考一番过后,我选择仿照OKHttp通过拦截器实现自己的缓存方案。

    我的缓存方案

    在讲我的缓存方案之前,我先大致说一下OKHttp是如何实现缓存的,OKHttp的网络缓存是通过拦截器将request和response缓存在本地文件实现的,那么我也可以仿照它的思路在拦截器实现对接口返回数据Json字符串的缓存。
    先上张我的缓存流程图
    缓存流程图
    整个流程中最关键的就是红圈圈起来的地方,因为不是所有的接口请求都需要做缓存,同时就算是需要缓存的接口在有些情况下也不需要缓存,比如有些列表接口只需要缓存第一页的数据,又或者是同一个接口需要缓存不同参数下的数据,例如不同类型的新闻,如何判断一个请求的接口是否需要缓存是非常重要的,如果不能准确的识别,那么后面缓存流程中的存或取都将没有意义。

    如何识别需要缓存的接口

    因为我们项目用的是Retrofit做网络请求,Retrofit中的接口都是统一定义在一个接口类中的,所以我打算用注解的方式,标注需要缓存的接口,在程序运行时再遍历所有接口,把需要缓存的接口放到一个map集合中进行管理。当有接口请求时在拦截器里用当前请求接口的url去map集合里匹配,如果有则意味这个接口需要缓存。

    注解标记

    @Inherited
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NetCache {
    	//接口为请求列表时标记需缓存的页码,默认为0时不作处理
        String cachePageIndex() default "0";
        //对指定字段的不同参数都做缓存,默认为空字符串时不作处理
        String multipleCacheIdentificationParameter() default "";
    }
    

    上边就是我定义的注解,目前包含两个参数,如果有其他需要,后期可以再向里加参数。

    筛选需要缓存的接口

    接下来就是写一个注解解析器,去遍历所有接口筛选出我们需要缓存的部分了。

    public class NetCacheProcess {
    
        /**
         * 已Http请求url的md5值为key
         */
        public static HashMap<String, NetCacheModel> cacheModels = new HashMap<>();
    
        public static void init(Application context, String baseUrl) {
            if (context == null || baseUrl == null) {
                Log.e(NetCacheUtil.NET_CACHE_TAG, "NetCacheProcess初始化失败,context和baseUrl不能为Null!");
                return;
            }
            try {
                cacheModels.clear();
                Class<YSApi> objectClass = YSApi.class;
                Method[] methods = objectClass.getMethods();
                for (Method method : methods) {
                    NetCache netCache = method.getAnnotation(NetCache.class);
                    if (netCache != null) {
                        POST post = method.getAnnotation(POST.class);
                        if (post != null) {
                            Log.e(NetCacheUtil.NET_CACHE_TAG, "POST:" + post.value());
                            if (!TextUtils.isEmpty(post.value())) {
                                addNetCacheModel(baseUrl + post.value(), netCache);
                            }
                        } else {
                            GET get = method.getAnnotation(GET.class);
                            if (get != null) {
                                Log.e(NetCacheUtil.NET_CACHE_TAG, "GET:" + get.value());
                                if (!TextUtils.isEmpty(get.value())) {
                                    addNetCacheModel(baseUrl + get.value(), netCache);
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                CrashHelper.respData(e);
            }
        }
    
        private static void addNetCacheModel(String key, NetCache netCache) {
            NetCacheModel model = new NetCacheModel();
            model.cacheUrl = key;
            model.cachePageIndex = netCache.cachePageIndex();
            model.identificationParameter = netCache.multipleCacheIdentificationParameter();
            cacheModels.put(MD5Util.encodeBy32BitMD5(key), model);
        }
    }
    
    public class NetCacheModel {
    
        public String cacheUrl;
        public String cachePageIndex;
        public String identificationParameter;
    }
    

    这个类干的事就是利用反射把接口类里的所有方法取出来遍历,将含有NetCache注解的接口转换成对应的数据模型并以接口url为key保存到map集合中。
    接着找几个接口添加一下注解,测试一下。
    在这里插入图片描述
    ok,需要缓存的几个接口都添加进来了,接下来就是在拦截器里判断请求的接口是否需要缓存了。

    判断请求是否需要缓存

    public static NetCacheModel checkCacheEnable(Request request) {
            NetCacheModel model = null;
            try {
                String key = "";
                String url = request.url().toString();
                if ("GET".equalsIgnoreCase(request.method())) {
                    String[] split = url.split("\\?");
                    key = MD5Util.encodeBy32BitMD5(split[0]);
                } else if ("POST".equalsIgnoreCase(request.method())){
                    key = MD5Util.encodeBy32BitMD5(url);
                }
                if (NetCacheProcess.cacheModels.containsKey(key)) {
                    model = getNewModel(NetCacheProcess.cacheModels.get(key));
                    //需要接口标识请求参数时,直接将需要区别的参数加到缓存url标识后面
                    if (!TextUtils.isEmpty(model.identificationParameter)) {
                        String value = getRequestParameter(request, model.identificationParameter);
                        model.cacheUrl = model.cacheUrl + value;
                    }
                    //列表请求时过滤不需要缓存的页码数据
                    if (!model.cachePageIndex.equals("0")) {
                        String value = getRequestParameter(request, "page");
                        if (!model.cachePageIndex.equals(value)) {
                            model = null;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return model;
        }
    

    这里判断的条件就是request的url 是否存在map集合中,如果存在则返回对应的数据模型,否则返回null,表示此请求不需要缓存,在判断之前需要对Post和Get请求的url做些处理,Post直接获取request的url就可以,但是为Get方式时需要把url附带的参数截掉,因为我们map集合中的url都是纯url,不带任何参数的。接下来就是之前讲的对同一接口多份缓存和过滤非指定页码缓存的处理。

    在拦截器对数据进行缓存与读取

    请求是否需要缓存的判断有了后,再加上对Json数据的缓存和读取就完成了,缓存和读取都是一些流的操作,存的时候在子线程操作并且对对Json字符串做了压缩,取的时候再解压就行了。
    下面是拦截器完整的代码

    public class NetCacheInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Response response = null;
            NetCacheModel cacheModel = HttpInterceptorUtil.checkCacheEnable(request);
            //无网络时并且此接口可缓存时尝试获取缓存返回
            if (!NetUtil.checkNet(MyApplication.sApplication) && cacheModel != null) {
                String cache = NetCacheUtil.loadCache(cacheModel.cacheUrl, new NetCacheLoadListener());
                //缓存不为空时创建response返回
                if (!TextUtils.isEmpty(cache)) {
                    Response.Builder builder = new Response.Builder()
                            .request(request)
                            .protocol(Protocol.HTTP_1_1)
                            .message("use net cache")
                            .code(200)
                            .body(ResponseBody.create(MediaType.parse("application/json"), cache));
                    response = builder.build();
                    return response;
                }
            }
            response = chain.proceed(request);
            //此接口可缓存并且请求成功时尝试将数据缓存本地
            if (cacheModel != null && response != null && response.code() == 200) {
                String key = cacheModel.cacheUrl;
                String responseInfo = HttpInterceptorUtil.getResponseInfo(response);
                if (TextUtils.isEmpty(responseInfo)) {
                    Log.e(NetCacheUtil.NET_CACHE_TAG, "缓存失败,responseInfo为null");
                } else {
                    NetCacheUtil.saveCacheAsync(key, responseInfo, new NewCacheSaveListener());
                }
            }
            return response;
        }
    }
    

    最后再把拦截器添加到OKhttp里,记得用addInterceptor(),千万别用addNetworkInterceptor(),要是用了后者,没网的时候,就直接返回没网络的response了,不会走我们的缓存拦截器。

    是骡子是马?

    写了这么多代码,到底能不能按预期产出(废话,不能产出我还写这篇博客干啥)?看到结果前我也不知道,是骡子是马还得牵出来溜溜,拿两个接口试试。

    @NetCache(cachePageIndex = "1",multipleCacheIdentificationParameter = "business_type")
        @FormUrlEncoded
        @POST("study_plan_task")
        Observable<HttpResponse<StudyData>> study_plan_task();
        
     @NetCache
        @FormUrlEncoded
        @POST("study/head")
        Observable<HttpResponse<MyStudyHeadBean>> getMyStudyHeadData();
    

    缓存本地

    接口请求后打印的log
    在这里插入图片描述
    去手机文件夹里查看一下缓存文件
    在这里插入图片描述

    读取本地缓存

    断了网请求缓存过的接口试试读取好不好使
    在这里插入图片描述
    在这里插入图片描述

    大功告成

    至此,Post请求的缓存就完成了,虽然自己动手麻烦了点,但是看到成果的那一刻还是挺值得的,其实写代码倒没什么,主要是整个缓存流程的梳理和设计思路的构想,办法有了,困难就自然而然解决了~

    展开全文
  • 我用OkHttp向我的服务器发出一些POST请求.这很好用.现在我想使用OkHttp的缓存缓存请求的响应,并在设备脱机时使用它们.我从其他问题尝试了很多解决方案,但没有一个能起作用.我使用OkHttp 2.5.0使用下面的代码,当...

    我用OkHttp向我的服务器发出一些POST请求.这很好用.

    现在我想使用OkHttp的缓存来缓存请求的响应,并在设备脱机时使用它们.

    我从其他问题尝试了很多解决方案,但没有一个能起作用.

    我使用OkHttp 2.5.0

    使用下面的代码,当设备可以访问互联网时,我会得到有效的响应.

    但是,如果我关闭互联网,它会抛出java.net.UnknownHostException:无法解析主机“example.com”:没有与主机名关联的地址

    这是我当前的代码,它不起作用:

    用于重写缓存头的拦截器:

    private final Interceptor mCacheControlInterceptor = new Interceptor() {

    @Override

    public Response intercept(Chain chain) throws IOException {

    Request request = chain.request();

    if (isOnline()) {

    request.newBuilder()

    .header("Cache-Control", "public, only-if-cached, max-stale=7887")

    .build();

    } else {

    request.newBuilder()

    .header("Cache-Control", "public, max-stale=2419200")

    .build();

    }

    Response response = chain.proceed(request);

    // Re-write response CC header to force use of cache

    return response.newBuilder()

    .header("Cache-Control", "public, max-age=86400") // 1 day

    .build();

    }

    };

    获取客户端的方法:

    private OkHttpClient getHttpClient() {

    if (mHttpClient == null) {

    mHttpClient = new OkHttpClient();

    mHttpClient.setConnectTimeout(CONNECT_TIMEOUT, TimeUnit.MILLISECONDS);

    File cacheDir = mContext.getDir(CACHE_NAME, Context.MODE_PRIVATE);

    mHttpClient.setCache(new Cache(cacheDir, CACHE_SIZE));

    mHttpClient.networkInterceptors().add(mCacheControlInterceptor);

    }

    return mHttpClient;

    }

    提出要求:

    RequestBody body = RequestBody.create(TEXT, data);

    Request request = new Request.Builder()

    .url(url)

    .post(body)

    .build();

    Response response = getHttpClient().newCall(request).execute();

    展开全文
  • 测试兄弟今天提了个 BUG,发现在 IE 下...但终其原因,还是代码编写上没有对 GET 请求进行缓存清理配置(同一个请求调用多次没有唯一标识)。 然后测试取消勾选了 Chrome 的 Disable cache 再试一下,还是正常的,这又

    测试兄弟今天提了个 BUG,发现在 IE 下修改列表数据后再重新查询,列表没有变化,而 Chrome 浏览器上正常。

    经确认,是浏览器缓存所致,因为测试的时候习惯性打开 F12,勾选了 Disable cache(禁用缓存),所以没注意到。

    而 IE 浏览器不常用,并且设置禁用缓存的方式没有 Chrome 那么方便。

    但终其原因,还是代码编写上没有对 GET 请求进行缓存清理配置(同一个请求调用多次没有唯一标识)。

    然后测试取消勾选了 Chrome 的 Disable cache 再试一下,还是正常的,这又要说到浏览器对于 GET 请求的区别对待了(主要是 IE)

    浏览器对于 GET 请求会将请求结果缓存起来,而 POST 不会。其中更具体的细节是:

    • Chrome 和 Firefox 会检测 GET 请求的如果是静态资源才会缓存,如果是数据则不会缓存。
    • IE 浏览器则会将 GET 请求全部缓存,不会检测请求的是什么。

    所以对于 GET 请求,最好还是在请求拦截器中加个时间戳吧。

    关于 IE 如何禁用缓存:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 最近在逛知乎的时候发现一个有趣的问题:《公司规定所有接口都用 post 请求,这是为什么?》原问题:zhihu.com/question/336797348看到这个问题的时候其实我也挺有感...
  • 大家好,我是前端岚枫,一枚二线城市的程序媛,今天主要跟大家分享我整理的笔记2021前端面试题系列:HTTP请求和HTTP缓存控制,此方面内容在我们的工作中常用到, 也是面试官经常提问的问题,希望下面文章对大家有所...
  • Ajax处理get请求AJAX GET 请求 发送请求}}}}Ajax对json数据的响应方法:1、手动转换2、自动转换AJAX GET 请求}}Json-server.js//1、引入expressconst express=require(‘express’);//2、创建应用对象const app=...
  • 浏览器对于 GET 请求会将请求结果缓存起来,而 POST 不会。 其中更具体的细节是: Chrome 和 Firefox 会检测 GET 请求的如果是静态资源才会缓存,如果是数据则不会缓存。 IE 浏览器则会将 GET 请求全部缓存不会...
  • 我有一个Django项目,我目前正在工作,我希望能够将产品...这是我第一次使用Django,所以我不确定这里出了什么问题。以下是我目前掌握的代码:我的索引.html页码:23/46Create product here{% csrf_token %} Name: d...
  • Android网络请求&缓存

    2021-06-05 05:06:17
    本文主要介绍Android网络请求中的一些基础知识及缓存的应用目录http请求&响应相关知识okhttp&Interceptorretrofit+ okhttp + rxjava的缓存实现http相关知识直接贴上jude的图,jude是我的好老师请求包.png例子...
  • ajax的get请求缓存处理解决方法本文实例讲述了ajax的get请求缓存处理解决方法。分享给大家供大家参考。具体分析如下:很多时候在Ajax的get方法调用的时候由于缓存的原因无法及时获取正确的数据,这里就来分析...
  • post请求的header

    2021-04-27 06:53:39
    HTTP Headers 中的 HTTP请求Accept-EncodingAccept-Encoding: gzip,deflate大部分的现代浏览器都支持gzip压缩,并会把这一信息报告给服务器。这时服务器就会压缩过的HTML发送给浏览器。这可以减少近80%的文件大小,...
  • VSCode——明明设置的是post请求为什么参数是get请求形式组装的? 今天跟正常一样复制粘贴了一个方法,原来的是get请求,我修改为post请求,如下: export function getTemplates(params) { return request({ ...
  • POST 相对于 GET 更 安全,因为 POST请求 的数据在地址栏上不可见, 而 GET请求 参数直接暴露在 url 中,故不能用来传递敏感信息; 本质区别 GET 是用来从服务器上 获得 数据, 而 POST 是用来向服务器上 传递
  • 最近在逛知乎的时候发现一个有趣的问题:《公司规定所有接口都用 post 请求,这是为什么?》原问题:https://www.zhihu.com/question/336797348看到这个...
  • 区别:1、GET请求的数据会暴露在地址栏中,而POST请求不会;2、Get请求传输数据量小,Post请求传输数据量大;3、POST的安全性比GET的高。本教程操作环境:windows10系统、Lenovo 小新Air14电脑。POST与GET两种请求...
  • 一. 概述本文的内容源自... HTTP 的请求报文首先我们要解决的第一个问题是:GET 和 POST什么?GET 和 POST 其实都是 HTTP 的请求方法。除了这 2 个请求方法之外,HTTP 还有 HEAD、PUT 、DELETE、TRACE、CONNECT...
  • POST请求导出Excel

    千次阅读 2021-03-22 12:22:31
    目的:使用POST请求导出Excel文档。起因:在使用Java导出Excel时,笔者在上一篇文章中使用的导出POJO或者BSONDocument类型的Excel文档的方法,其实使用的是GET请求,因为当时前端传的参数也不多,并不会因为浏览器对...
  • 1.get请求一般是去取获取数据(其实也可以提交,但常见的是获取数据); post请求一般是去提交数据。 2.get因为参数会放在url...4.get请求可以被缓存post请求不会被缓存。 5.get请求会保存在浏览器历史记录当中,p
  • 背景:用户支付成功后的回调是个静态页面。由于from表单连续提交是post方式,所以...因为默认情况下,nginx、apache、IIs等web服务无法响应静态页面的post请求,后端用来处理post请求,生产环境中不会有此问题(一般都...
  • 但是很多时候又想在H5不知情的情况下获取H5内部请求的参数,这应该怎么做到呢?带着这个疑问,就有了这篇博客。实现过程:方案一:最开始想到的方案是直接拦截H5中所有的请求:webView.setWebViewClient(new ...
  • 1:如果一个URL重复提交,...会走浏览缓存,问题解决如下:$.getJSON("/importsAction.action?iw.submitFlag=imports&iw.flag=77&iw.ymd="+ymd+"&date="+new Date(),function(data){//不处理});加一个提...
  • 通过浏览器缓存策略可以把从服务器请求的数据缓存在浏览器端;再次请求相同数据,不用发送http请求去服务器端获取数据,第一节省带宽,第二 如果数据量大 也能提高用户体验。 对概念的消化必须建立在实际应用之上;...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 217,780
精华内容 87,112
关键字:

为什么post请求不会被缓存