关于react、vue中 pathRwrite

260 阅读5分钟

举个例子开头

前端

配置文件

一个前端vue中的配置,给出三种情况 vue.config.js

    proxy: {
      '/api/test': {     //这里最好有一个 /
        target: 'http://192.168.115.115:8888',  // 后台接口域名
        // ws: true,        //如果要代理 websockets,配置这个参数
        // secure: false,  // 如果是https接口,需要配置这个参数
        changeOrigin: true,  //是否跨域
        pathRewrite: {
          '^/api/test': '/api/test'
        }
      }
    }

这种情况的解释就是前端调用的地方(看下面),axios匹配到/api/test的时候, 这里的pathRewrite是和target打配合使用的,就好比英雄联盟里面的ADC和辅助,target+pathRewrite 就是应对/api/test的最终解释。

因此我们就直接找到http://192.168.115.115:8888/api/test 这个后台接口

    proxy: {
      '/api/test': {     //这里最好有一个 /
        target: 'http://192.168.115.115:8888/api/test',  // 后台接口域名
        // ws: true,        //如果要代理 websockets,配置这个参数
        // secure: false,  // 如果是https接口,需要配置这个参数
        changeOrigin: true,  //是否跨域
        pathRewrite: {
          '^/api/test': '/'
        }
      }
    }

这种情况的解释就是前端调用的地方(看下面),axios匹配到/api/test的时候, 这里的pathRewrite是和target打配合使用的,就好比英雄联盟里面的ADC和辅助,target+pathRewrite 就是应对/api/test的最终解释。由于pathRewrite为/ ,那么就不会配合出个花样来,因此,为了保证能够够到后台,只能在target中写多一点喽

因此我们就直接找到http://192.168.115.115:8888/api/test 这个后台接口

    proxy: {
      '/api/test': {     //这里最好有一个 /
        target: 'http://192.168.115.115:8888/api/test',  // 后台接口域名
        // ws: true,        //如果要代理 websockets,配置这个参数
        // secure: false,  // 如果是https接口,需要配置这个参数
        changeOrigin: true,  //是否跨域
        pathRewrite: {
          '^/api/test': ''
        }
      }
    }

这种情况和上面的一模一样。最终目的都是为了和后台交流好。

当然好奇者也可以关注一下下面几个情况,最后练习有讲解

    proxy: {
      '/api/test': {     //这里最好有一个 /
        target: 'http://192.168.115.115:8888/api/test',  // 后台接口域名
        // ws: true,        //如果要代理 websockets,配置这个参数
        // secure: false,  // 如果是https接口,需要配置这个参数
        changeOrigin: true,  //是否跨域
        pathRewrite: {
          '^': ''
        }
      }
    }
    proxy: {
      '/api/test': {     //这里最好有一个 /
        target: 'http://192.168.115.115:8888/api/test',  // 后台接口域名
        // ws: true,        //如果要代理 websockets,配置这个参数
        // secure: false,  // 如果是https接口,需要配置这个参数
        changeOrigin: true,  //是否跨域
        pathRewrite: {
          '^': '/'
        }
      }
    }

上面两个一模一样

    proxy: {
      '/api/test': {     //这里最好有一个 /
        target: 'http://192.168.115.115:8888/api/test',  // 后台接口域名
        // ws: true,        //如果要代理 websockets,配置这个参数
        // secure: false,  // 如果是https接口,需要配置这个参数
        changeOrigin: true,  //是否跨域
        pathRewrite: {
          '^/api/test': '/api/test'
        }
      }
    }

这种拼接的地址就是http://192.168.115.115:8888/api/test/api/test

在浏览器请求的preview中可以看到

 {timestamp: "2021-10-22T03:03:32.899+00:00", status: 404, error: "Not Found", message: "",…}
   error"Not Found"
   message: ""
   path"/api/test/api/test"
   status404
 

接口声明

前端中的调用,调用的地方 接口声明文件: /api/testApi.js

import axios from 'axios'

export function list(params) {
  return axios({
    url: '/api/test',
    method: 'get',
    params
  })
}

export function fetched(params) {
  return axios({
    url: '/api/test/' + params,
    method: 'get'
  })
}

export function updated(data) {
  return axios({
    url: '/api/test',
    method: 'put',
    data
  })
}

export function created(data) {
  return axios({
    url: '/api/test',
    method: 'post',
    data
  })
}

export function deleted(data) {
  // const { id } = data
  return axios({
    url: `/api/test/${data}`,
    method: 'delete',
    // params: data
  })
}

直接调用

(我们这种情况是调用和声明接口分离的情况下,解耦合要求)

调用文件

hello.vue

<script>
import * as testApi from '@/api/testApi'
import { parseTime } from '@/utils'
import Pagination from '@/components/Pagination'
  created() {
    this.getData()
  },
  export default{
  methods: {
    getData() {
      const { total, ...page } = this.pageConfig
      const params = { ...page, ...this.searchQuery }
      this.loading = true
      testApi.list(params).then(response => {
        const data = response.data.data
      })
    },

    //  新增
    add() {
         testApi.created(params).then((response) => {
          })
        }
      })
    },
    //  删除
    handleDelete(row) {
      testApi.deleted(id).then(response => {
        this.$notify({
          title: 'Success',
          message: '删除成功',
          type: 'success',
          duration: 2000
        })
        this.getData()
      })
    },
    //  编辑
    handleEdit(row) {
      testApi.updated(data)
    },

    }
  }
}
</script>

后台实际的swagger 接口

java

package com..controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.api.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Set;


@RestController
@RequestMapping("/api/test")
public class TestController extends BaseController {

    @GetMapping
    public R<IPage<Test>> selectAll() {
       
    }

    @GetMapping("/all")
    public R<List<Test>> select(String i) {
        
    }

    @GetMapping("{id}")
    public R<Test> selectOne(@PathVariable Serializable id) {
    }

   
    @PostMapping
    public R insert(@RequestBody Test t) {
    }

  
    @PutMapping
    public R<Boolean> update(@RequestBody Test t) {
    }

    @DeleteMapping("{id}")
    public R<Boolean> delete(@PathVariable long id) {
    }

  
    @PostMapping("/test")
    public R<Boolean> test(@RequestBody Test t)  

    }

}

谨记

学习这个属性之前,请记住一句话,

pathRewrite 这个属性就是和后台打交道,和nginx打交道, proxy就是nginx里面要用到的配置;

和浏览器输入栏中的地址打交道的是一个叫router的东西;

这两个东西不是一个玩意,

直接在浏览器或者postman上使用,就可以看到已经定义好的后端接口。

http://192.168.115.115:8888

这个地址前提下可以进行curd的相关操作。

增:http://192.168.115.115:8888/api/test

删:http://192.168.115.115:8888/api/test\{id}

改:http://192.168.115.115:8888/api/test

查全部:http://192.168.115.115:8888/api/test

查一个:http://192.168.115.115:8888/api/test/{id}

后端已经定了,前端调用的地方,调用的代称是/api/test.

所以我们调回去看配置文件

总结(前端后端,nginx配置一条龙服务)

1.router(路由)是用来处理跳转的,它管的范围就是浏览器框,讲明白一点就是浏览器上那一个框,那个框的展示就是前端router里控制的

2.pathRewrite,以及它外面的proxy(代理),它管的范围就是浏览器F12中的网络选项。这时就会有人想,这个属性或者proxy这个属性全部,就是看着网络里的地址改变,binggo,对了。所以只要proxy中,代理的地址写好之后,在网络选项那里就看到这个,是固定的。pathRwrite不会影响网络里的地址的展示。

proxy 配置的key也不能随便写啊,得看后台地址

拼了命的拼接出可以正常使用的后台接口。你在F12的网络和地址栏,哪儿都看不到,人家就是和nginx和swagger暧昧,其他的人哪凉快去哪玩。另外 proxy pathRewrite 这两个属性是不可见的。

3.nginx中只关心proxy定义的key以及最后拼接出来的后端地址,

下面就是开头的例子 demo针对文章开头例子

    location /api/test  {   // 这个命名是不能随便写的
    
        proxy_pass http://192.168.115.115:8888/api/test;  //直接拿pathRewrite之后拼接后的东西,最终结果复制到这里。

        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;

    }

nginx中的代理和前端工程中的代理和请求是不能随便写的,必须看好后端的文档或者swagger,必须得是正确的后台地址。

几个练习题:

按照上面的理解这些题应该是下面这样的结果。

   前空后空
   dev: {
    '/api/a': {
      target: 'http://192.168.115.115:8000',
      changeOrigin: true,
      pathRewrite: { '^': '' },  这种情况和 pathRewrite: { '^': '/' },  一毛一样
    },
    
    拼出来的地址 http://192.168.115.115:8000
    
    前空后不空
    '/api/b': {
      target: 'http://192.168.115.115:8001',
      changeOrigin: true,
      pathRewrite: { '^': '/api/b' },
    },
    
    拼出来的地址 http://192.168.115.115:8001/api/b,但是这种情况不要使用,这是找死,不能这样使用
    
     前不空后空
    '/api/c': {
      target: 'http://192.168.115.115:8002',
      changeOrigin: true,
      pathRewrite: { '^/api/c': '' },
    },
    
   拼出来的地址 http://192.168.115.115:8002
    
    前不空后不空
    '/api/d': {
      target: 'http://192.168.115.115:8003',
      ws: true,
      changeOrigin: true,
      pathRewrite: { '^/api/d': '/api/rest_j/v1' },
    },
    
  拼出来的地址 http://192.168.115.115:8001/api/rest_j/v1