vue:axios拦截器

摘要:
让我们分析一下项目中的请求拦截器//请求拦截器服务。拦截器。要求use(config=>{if(store.getters.token){config.headers〔'Authorization’〕=getToken()//让每个请求携带一个自定义令牌。请根据实际情况进行修改。}//params参数code leturl=config.url;

拦截器分两类:请求拦截器和响应拦截器

一、请求拦截器

在请求发出之前设置一些信息。比如说设置请求头,

vue:axios拦截器第1张

use方法参数即第一个函数的形参中通过config来做信息的配置,配置完之后,必须把config返回,这样才能完成拦截器的功能。第二个函数用于处理错误的信息。

用拦截器的方式配置请求头会更加灵活。拦截器中可以通过config获取更多的信息,比如url地址,这样就可以根据url作出判断,某些url可以添加一个请求头,而别的url不添加请求头。

vue:axios拦截器第2张

 vue:axios拦截器第3张

通过拦截器,我们可以控制所有的请求。

下面来分析项目中的请求拦截器

// request拦截器
service.interceptors.request.use(

  config => {
    if (store.getters.token) {
      config.headers['Authorization'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
    }

    // params参数编码
    let url = config.url;
    console.log(url)

    if (config.params) {
      console.log(config.params)
      url += '?';
      let keys = Object.keys(config.params);
      console.log(keys)
      for (let key of keys) {
        if (config.params[key] !== null && config.params[key] !== "") {
          url += `${key}=${encodeURIComponent(config.params[key])}&`;
        }
      }
      console.log(url)
      url = url.substring(0, url.length - 1);
      console.log(url)
      config.params = {};
    }
    config.url = url;
    return config;
  },
  error => {
    console.log(error) // for debug
    Promise.reject(error)
  }
)

下面来分析代码:

medMaterial.getAuditorsByPrepareId({
prepareId: edit.id,
productId: edit.productId,
enterpriseId: edit.enterpriseId1
}).then(res => {
if (res.success) {
.........

js中的代码为:

getAuditorsByPrepareId(query){
    return request({
      url: '/medMaterial/getAuditorsByPrepareId',
      method: 'post',
      params: query
    })
  },

后台:

@PostMapping("/getAuditorsByPrepareId")
    public Result getAuditorsByPrepareId(@RequestParam(required = false) String productId,@RequestParam String enterpriseId,@RequestParam String prepareId) {
    。。。。。
    }

当我们发出上面的一个请求,请求拦截器就会将参数的值进行编码,然后将参数通过?号拼接到url中。拼接后的url如下所示:

http://localhost:8008/api/medMaterial/getAuditorsByPrepareId?prepareId=444&productId=20663&enterpriseId=81

1、先判断token是否存在,如果存在,让每个url都添加请求头Authorization

vue:axios拦截器第4张

2、通过config获取url:/medMaterial/getAuditorsByPrepareId

3、通过url获取params:{prepareId: 444, productId: 20663, enterpriseId: 81}

4、先给url拼接一个?号:/medMaterial/getAuditorsByPrepareId?

5、获取config中参数params中所有的key即keys:["prepareId", "productId", "enterpriseId"]

6、遍历keys,如果params中key的值不为null或不为空字符串,先对key的值进行encodeURIComponent编码,编码后的结果放入${}中,key不编码。由于该方法encodeURIComponent不会对 ASCII 字母和数字进行编码,故对value进行编码后的结果url仍然为:/medMaterial/getAuditorsByPrepareId?prepareId=444&productId=20663&enterpriseId=81&

7、去掉最后的&得到的url:/medMaterial/getAuditorsByPrepareId?prepareId=444&productId=20663&enterpriseId=81

再比如备货详情中,点击查看按钮,发送的请求如下:

const query = { type: row.type,materialName: row.materialName,materialCode: row.materialCode,batch: row.originalBase }
        console.log(query)
        prepare.queryFullChain(query).then(response => {
          console.log(response)
          if(response.success){

js中的代码如下:

queryFullChain(query) {
    return request({
      url: '/prepare/queryFullChain',
      method: 'post',
      params: query
    });
  },

1、先判断token是否存在,如果存在,让每个url都添加请求头Authorization

vue:axios拦截器第5张

2、通过config获取url:/prepare/queryFullChain

3、通过url获取params:{type: "0", materialName: "天麻", materialCode: "TM001", batch: "11"}

4、先给url拼接一个?号:/prepare/queryFullChain?

5、获取config中参数params中所有的key即keys:["type", "materialName", "materialCode", "batch"]

6、遍历keys,如果params中key的值不为null或不为空字符串,先对key的值进行encodeURIComponent编码,编码后的结果放入${}中,key不编码。由于该方法encodeURIComponent不会对 ASCII 字母和数字进行编码,故对value进行编码后的结果url为:/prepare/queryFullChain?type=0&materialName=%E5%A4%A9%E9%BA%BB&materialCode=TM001&batch=11&,注意对中文进行了编码。

7、去掉最后的&得到的url:/prepare/queryFullChain?type=0&materialName=%E5%A4%A9%E9%BA%BB&materialCode=TM001&batch=11

以上分析可知:当在向后台发起请求时,config中存在params时,参数会被拼接到url中,后台只能用@RequestParam来接收参数。

当向后台发起请求时,没有params,而是data,如下所示:

saveList(query) {
    return request({
      url: '/intelDrugStore/saveList',
      method: 'post',
      data: query
    })
  },

请求参数在JSON中,故后台只能用@RequestBody接收参数。

后台

@PostMapping("/saveList")
    @ResponseBody
    public Result saveList(@RequestBody List<IntelDrugStore> listData) {
    。。。。
    }

二、响应拦截器

浏览器在获取响应数据之前对数据做一些加工处理。

vue:axios拦截器第6张

Use方法的第一个参数即第一个函数的形参res表示后台返回的具体数据信息。res并不是实际的数据,而是axios包装的对象,通过对象中的data才能拿到数据。这和之前获取后台数据的时候是一样的。

如果在调用接口的时候,只关心实际的数据而不需要包装对象,故可以集中的在响应拦截器做一些加工。如下所示

vue:axios拦截器第7张

这样再次发请求调接口的时候,最终拿到的就是实际的数据了。

这样的话,以后我们调用任何接口,所有then当中得到的数据,都是我们实际需要的后台返回来的数据。不需要再通过点data的方式获取数据了

 项目中的响应拦截器如下:

// response 拦截器
service.interceptors.response.use(
  response => {
    /**
     * code为非20000是抛错 可结合自己业务进行修改
     */
    const headers = response.headers
    // 此类为下载流文件,不拦截
    if (headers['content-type'] === 'application/octet-stream;charset=utf-8') {
      return response
    }
    if (headers['content-type'] === 'arrayBuffer;charset=UTF-8') {
      return response
    }
    const res = response.data
    if (res.code !== 1) {
      if(res.code === 301){
        Message({
          message: res.msg,
          type: 'error',
          duration: 5 * 1000
        })
        location.reload()
      }

      // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        MessageBox.confirm(
          '你已被登出,可以取消继续留在该页面,或者重新登录',
          '确定登出',
          {
            confirmButtonText: '重新登录',
            cancelButtonText: '取消',
            type: 'warning'
          }
        ).then(() => {
          store.dispatch('FedLogOut').then(() => {
            location.reload() // 为了重新实例化vue-router对象 避免bug
          })
        })
      }
      return Promise.reject('请重新登录')
    } else {
      return response.data
    }
  },
  error => {
    console.log('err' + error) // for debug
    Message({
      message: '请求超时,请联系管理员!',
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

 响应拦截器代码分析:

1、由于后台EasyPOIUtils在下载Excel时,设置了响应头,如下:

response.setHeader("Content-type", "text/html;charset=UTF-8");
            response.setCharacterEncoding("utf-8");//设置编码集,文件名不会发生中文乱码

            response.setContentType("application/force-download");//
            response.setHeader("content-type", "application/octet-stream");
            response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes(), "utf-8"));// 设置文件名
            response.addHeader("Content-Length", "" + file.length());
            response.setHeader("Access-Control-Allow-Origin", "*");

vue:axios拦截器第8张

 故响应拦截器不拦截。

2、由于在下载图片时,PtsFileController中设置了响应头,

@RequestMapping(value = "/picDownload")
    public void picDownload(  String filePath,HttpServletResponse response)throws Exception{
        File file = new File(filePath);
        ServletOutputStream  out = null ;
        BufferedInputStream buf  = null ;
        response.setHeader("Content-Type","arrayBuffer");
        try{
            buf = new BufferedInputStream(new FileInputStream(file));
            out = response.getOutputStream();
            byte[] buffer =  new byte[1024];
            while(buf.read(buffer) != -1){
                out.write(buffer);

            }
            out.flush();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(buf!= null){
                buf.close();
            }
            if(out != null){
                out.close();
            }
        }
    }

 故响应拦截器不拦截。

3、response并不是实际的数据,而是axios包装的对象,通过对象中的data才能拿到数据.

4、由于后台ResultCode类中设置请求成功的code为1,

/**
     * 请求成功Result
     */
    public static final int SUCCESS=1;

当我们要返回数据给前端时,会设置code为success

result.setSuccess(false);
                result.setMsg("请修改密码后再登录!");
                result.setCode(ResultCode.SUCCESS);
                return result;

此时res.code等于1,返回response.data给前端。

如果res.code不等于1,由于后台设置了用户登录超时的code为301

/**
     * 用户未登录或登录超时
     */
    public static final int NO_LOGIN = 301;

当我们要返回数据给前端时,会设置ResultCode为NO_LOGIN

User u = (User) redisService.get(pre + "TPS-TOKEN" + token);
            if (null == u) {
                rs.setSuccess(false);
                rs.setCode(ResultCode.NO_LOGIN);
                rs.setMsg("非法登录或者token已失效!");
                return rs;
            }

此时res.code为301,则进行错误消息的提示,type为error,message为后台返回的消息,duration为持续的时长,这里为5s.

location.reload()方法用于刷新当前文档。reload() 方法类似于你浏览器上的刷新页面按钮。

免责声明:文章转载自《vue:axios拦截器》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇7z 压缩命令行工具Ubuntu 安装不同版本的 gcc/g++ 编译器下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Apache环境下强制http跳转至https的配置总结

一. 简单实例介绍一般来说,apache配置好http和https后,如果想要做http强转到https,需要设置url重定向规则,大致需要下面几个步骤即可完成配置: 1)在httpd.conf文件里使下面模块生效 [root@back ~]# cat /usr/local/apache/conf/httpd.conf ..... LoadModule s...

element 导航菜单 控制路由跳转

首先复制官网的例子,在这基础上再修改成我们想要的样子。 <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect"> <el-menu-item index="1">处理中心</el...

利用PHP判断iPhone、iPad、Android、PC设备

首页那张大图确实是一个比较头疼的问题 在PC上显示是没问题的,可是到手机上就会超出页面一大截,如果做自适应,图片会被强制压缩 无奈只能用wp_is_mobile()函数在手机上隐藏了这张图,可是这函数似乎对iPad不管用 在iPad Air等高分辨率设备还好,在iPad2这类低分辨率设备上可就惨了 于是我决定自写一段代码解决这个问题 判断代码 我将使用W...

MVC中两种实体:View Model和Business Model的简化(转载)

在MVC的Model中,我们可以定义很多与视图相关的元数据,这些元数据对我们开发视图起着相当重要的作用,特别是在数据验证方面。这些元数据一般情况下我们是不会定义在业务实体(或持久化实体)上面,所以很多情况下,我们会需要开发两种实体:View Model和Business Model。这样就造成,在Action与View的沟通当中,我们需要使用View Mo...

centos7搭建DVWA环境

///首先先下载好dvwa这个压缩包,去晚上搜一下就有了,话不多说,开始干活 第一步: #yum install -y mariadb* php* httpd安装好数据库,php和apache 第二步: 然后将下载好的DVWA-master.zip解压#unzip DVWA-master.zip //解压 #mv DVWA-master.zip DVWA...

Bootstrap-treeView 实际操作总结

由于功能性需求:需要展示一个树状结构的导航界面 1.进行资源引用 <!-- Required Stylesheets --> <link href="http://t.zoukankan.com/bootstrap.css" rel="stylesheet"> <!-- Required Javascript --> &...