最新消息:20210917 已从crifan.com换到crifan.org

【已解决】vue-admin-template中如何用vuejs去发送REST的api的POST请求并返回和解析json字符串

JS crifan 649浏览 0评论
折腾:
【未解决】Mac中用vue-admin-template实现智能电力前端页面功能模块
期间,需要去此处vue-admin-template中,实现http的rest的api的post调用
并解析返回的json
就像postman中的:
此处找到,现有的post的http的请求:
src/client/vue-admin-template/src/api/user.js
import request from '@/utils/request'

export function login(data) {
  return request({
    url: '/vue-admin-template/user/login',
    method: 'post',
    data
  })
}
用的是/utils/request
src/client/vue-admin-template/src/utils/request.js
import axios from 'axios'

import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'


// create an axios instance
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})

...
用的是axios
src/client/vue-admin-template/src/api/iec104.js
import request from '@/utils/request'

export function addIEC104(iec104DataStr) {
  console.log('iec104DataStr=%s', iec104DataStr)


  return request({
    url: 'http://localhost:8080/iec104/add/',
    method: 'post',
    data: {
      'data': iec104DataStr
    }
  })
}
但是却不知道如何被页面中调用。
看到另外一个table中
src/client/vue-admin-template/src/views/table/index.vue
是:
<script>
import { getList } from '@/api/table'
所以也去试试
src/client/vue-admin-template/src/views/form/index.vue
<script>
import { addIEC104 } from '@/api/iec104'

export default {
...
  methods: {
    onSubmit() {
      console.log('this.form.iec104DataStr=%s', this.form.iec104DataStr)
      addIEC104(this.form.iec104DataStr).then(response => {
        console.log('response=%s', response)
        const { data } = response
        console.log('data=%s', data)
      })


      this.$message('submit!')
    },
结果调试报错:
【已解决】vuejs中调用本地localhost的api报错:Access to XMLHttpRequest at from origin has been blocked by CORS policy
不过又出现别的错误了:
去看看什么情况
2020-02-25 20:06:59,290 INFO  IEC104Controller.java:47 - post iec104: payload={data={
    "data": "68 59 F0 D2 00 00 15 A6 14 00 05 00 01 07 00 02 00 00 00 00 00 CF 5D 96 5D B2 5D 45 00 01 00 FE FF 7C 00 84 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 13 00 00 02 00 00 00 00 00 FE FF 00 00 00 00 98 00 00 00 00 00 02 00 00 00 00 00 "
}}
2020-02-25 20:06:59,291 INFO  IEC104Controller.java:57 - filted104DataStr={
    "data":"6859F0D2000015A614000500010700020000000000CF5D965DB25D45000100FEFF7C008402000000000000000000000000000000000000000000000000000086130000020000000000FEFF00000000980000000000020000000000"
}
2020-02-25 20:06:59,294 ERROR IEC104Controller.java:62 - IllegalFormatException: error=非法报文。报文应为16进制数字组成,并且由0x68或者0x10为报文头,0x16为报文尾(104规约无)。
非法报文。报文应为16进制数字组成,并且由0x68或者0x10为报文头,0x16为报文尾(104规约无)。
    at com.crifan.xxx.analysis.protocol104.Analysis.analysis(Analysis.java:32)
去看看代码
原理是:
后端代码:
src/server/xxx/xxx/src/main/java/com/crifan/xxx/IEC104Controller.java
  @PostMapping(path="/add") // Map ONLY POST Requests
  // public @ResponseBody String addNewIEC104 (
  public @ResponseBody IEC104 addNewIEC104 (
            // @RequestParam String data
          // @RequestParam String data,
          // @RequestParam String parseResult
          @RequestBody Map<String, Object> payload
      ) {
    // @ResponseBody means the returned String is the response, not a view name
    // @RequestParam means it is a parameter from the GET or POST request


    logger.info("post iec104: payload={}", payload);


    String dataStr = (String) payload.get("data");


    IEC104 newIec104 = new IEC104();
    newIec104.setData(dataStr);


    // String parseResult = "待解析成结果 to replace parsed result";
    String parseResult = "";
    String filted104DataStr = dataStr.replaceAll(" ", "");
    logger.info("filted104DataStr={}", filted104DataStr);
    try{
      parseResult = Analysis.analysis(filted104DataStr);
      logger.info("parseResult={}", parseResult);
输出的dataStr,却还是带了data的字符串的:
2020-02-25 20:06:59,290 INFO  IEC104Controller.java:47 - post iec104: payload={data={
    "data": "68 59 F0 D2 00 00 15 A6 14 00 05 00 01 07 00 02 00 00 00 00 00 CF 5D 96 5D B2 5D 45 00 01 00 FE FF 7C 00 84 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 13 00 00 02 00 00 00 00 00 FE FF 00 00 00 00 98 00 00 00 00 00 02 00 00 00 00 00 "
}}
所以,回头找vuejs部分,发现是:
src/client/vue-admin-template/src/api/iec104.js
  return request({
    url: 'http://localhost:8080/iec104/add/',
    method: 'post',
    data: {
      'data': iec104DataStr
    }
  })
看起来是:
此处data中不需要额外加上data的
那去看看request中,此处的data参数,难道不是POST的body吗??
去加上调试log看看
src/client/vue-admin-template/src/utils/request.js
// request interceptor
service.interceptors.request.use(
  config => {
    // do something before request is sent


    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['X-Token'] = getToken()
    }


    console.log('config=%o', config)


    return config
  },
看到object是:
其中有个data
还是很奇怪
axios post data
axios POST提交数据的三种请求方式写法 – 全栈工程师进阶 – SegmentFault 思否
import axios from 'axios'
let data = {"code":"1234","name":"yyyy"};
axios.post(`${this.$url}/test/testRequest`,data)
.then(res=>{
    console.log('res=>',res);            
})
对啊,这个data就只是参数名,而不是data字符串本身
Unable to POST data in axios · Issue #1195 · axios/axios
axios/axios: Promise based HTTP client for the browser and node.js
// Send a POST request
axios({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});
对啊,只是post的参数data而已
使用说明 · Axios 中文说明 · 看云
Axios Cheat Sheet – Kapeli
此处,两边都改为dataStr,看看结果如何
后端:
    logger.info("post iec104: payload={}", payload);

    String dataStr = (String) payload.get("dataStr");
    logger.info("dataStr={}", dataStr);
前端测试:
可以看出,的确是多个一个data
难道是此处的vuejs的模板中的requests额外加的?
算了,改为:
export function addIEC104(iec104DataStr) {
  console.log('iec104DataStr=%s', iec104DataStr)


  const postData = {
    'dataStr': iec104DataStr
  }


  return request({
    url: 'http://localhost:8080/iec104/add/',
    method: 'post',
    // data: {
    //   'data': iec104DataStr
    // }
    postData
  })
}
结果:
变成400了:
其中可见,data是空的
postData是有值的。
  const postData = {
    'dataStr': iec104DataStr
  }


  return request({
    url: 'http://localhost:8080/iec104/add/',
    method: 'post',
    data: postData
  })
}
结果:
data好像
"{"dataStr":"{\n\t\"dataStr\": \"68 59 F0 D2 00 00 15 A6 14 00 05 00 01 07 00 02 00 00 00 00 00 CF 5D 96 5D B2 5D 45 00 01 00 FE FF 7C 00 84 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 13 00 00 02 00 00 00 00 00 FE FF 00 00 00 00 98 00 00 00 00 00 02 00 00 00 00 00 \"\n}"}"
多了个回车和换行
但是也还是多了个dataStr的外层包裹
-》很是奇怪。
然后才明白:
是此处自己搞错了:
自己的vuejs的前端,自己额外输入的是带key的字符串:
{
    "dataStr": "68 59 F0 D2 00 00 15 A6 14 00 05 00 01 07 00 02 00 00 00 00 00 CF 5D 96 5D B2 5D 45 00 01 00 FE FF 7C 00 84 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 13 00 00 02 00 00 00 00 00 FE FF 00 00 00 00 98 00 00 00 00 00 02 00 00 00 00 00 "
}
去掉后:
68 59 F0 D2 00 00 15 A6 14 00 05 00 01 07 00 02 00 00 00 00 00 CF 5D 96 5D B2 5D 45 00 01 00 FE FF 7C 00 84 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 13 00 00 02 00 00 00 00 00 FE FF 00 00 00 00 98 00 00 00 00 00 02 00 00 00 00 00
应该就可以了。
data是dataStr的json了。
但是还是报错
不过看server端,是正常解析了:
看来是前端返回的值的处理的问题。
去看代码
src/client/vue-admin-template/src/utils/request.js
// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */


  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  response => {
    const res = response.data
...
所以此处可以根据提示
// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */


  response => response,


  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  // response => {
  //   const res = response.data


  //   // if the custom code is not 20000, it is judged as an error.
  //   if (res.code !== 20000) {
  //     Message({
  //       message: res.message || 'Error',
  //       type: 'error',
  //       duration: 5 * 1000
  //     })


  //     // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
  //     if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  //       // to re-login
  //       MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
  //         confirmButtonText: 'Re-Login',
  //         cancelButtonText: 'Cancel',
  //         type: 'warning'
  //       }).then(() => {
  //         store.dispatch('user/resetToken').then(() => {
  //           location.reload()
  //         })
  //       })
  //     }
  //     return Promise.reject(new Error(res.message || 'Error'))
  //   } else {
  //     return res
  //   }
  // },


  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)
或者进一步的:
  // response => response,
  response => {
    console.log('response=%o', response)


    return response
  },
去调试看看
至少不报错了。
再去写代码解析返回的结果:
    onSubmit() {
      console.log('this.form.iec104DataStr=%s', this.form.iec104DataStr)
      addIEC104(this.form.iec104DataStr).then(response => {
        console.log('response=%o', response)
        const { data } = response
        console.log('data=%o', data)
        const parseResult = data.parseResult
        console.log('parseResult=%s', parseResult)


        this.form.respJson = data
      })
已经可以返回:
但是最后会报错:
很明显是:
this.form.respJson = data
赋值是不对的。
所以去:
【已解决】vuejs中把json对象转换为json字符串且格式化带缩进
【总结】
最后用代码:
后端server:
src/server/xxx/xxx/src/main/java/com/crifan/xxx/IEC104Controller.java
...
import org.springframework.web.bind.annotation.CrossOrigin;
...
@Controller // This means that this class is a Controller
@CrossOrigin
@RequestMapping(path="/iec104") // This means URL's start with / (after Application path)
public class IEC104Controller {
    private static Logger logger = LoggerFactory.getLogger(IEC104Controller.class.getName());


  @Autowired // This means to get the bean called userRepository
         // Which is auto-generated by Spring, we will use it to handle the data
  private IEC104Repository iec104Repository;


  @PostMapping(path="/add") // Map ONLY POST Requests
  // public @ResponseBody String addNewIEC104 (
  public @ResponseBody IEC104 addNewIEC104 (
            // @RequestParam String data
          // @RequestParam String data,
          // @RequestParam String parseResult
          @RequestBody Map<String, Object> payload
      ) {
    // @ResponseBody means the returned String is the response, not a view name
    // @RequestParam means it is a parameter from the GET or POST request


    logger.info("post iec104: payload={}", payload);


    String dataStr = (String) payload.get("dataStr");
    logger.info("dataStr={}", dataStr);


    IEC104 newIec104 = new IEC104();
    newIec104.setData(dataStr);
...
前端vuejs:
src/client/vue-admin-template/src/api/iec104.js
import request from '@/utils/request'

export function addIEC104(iec104DataStr) {
  console.log('iec104DataStr=%s', iec104DataStr)

  const postData = {
    'dataStr': iec104DataStr
  }

  return request({
    url: 'http://localhost:8080/iec104/add/',
    method: 'post',
    data: postData
  })
}
src/client/vue-admin-template/src/utils/request.js

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */


  // response => response,
  response => {
    console.log('response=%o', response)


    return response
  },


  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  // response => {
  //   const res = response.data


  //   // if the custom code is not 20000, it is judged as an error.
  //   if (res.code !== 20000) {
  //     Message({
  //       message: res.message || 'Error',
  //       type: 'error',
  //       duration: 5 * 1000
  //     })


  //     // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
  //     if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
  //       // to re-login
  //       MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
  //         confirmButtonText: 'Re-Login',
  //         cancelButtonText: 'Cancel',
  //         type: 'warning'
  //       }).then(() => {
  //         store.dispatch('user/resetToken').then(() => {
  //           location.reload()
  //         })
  //       })
  //     }
  //     return Promise.reject(new Error(res.message || 'Error'))
  //   } else {
  //     return res
  //   }
  // },


  error => {
    console.log('err' + error) // for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)
src/client/vue-admin-template/src/views/form/index.vue
<template>
  <div class="app-container">
    <el-form ref="form" :model="form" label-width="120px">
      <!-- <el-form-item label="Activity name">
        <el-input v-model="form.name" />
      </el-form-item>
      <el-form-item label="Activity zone">
        <el-select v-model="form.region" placeholder="please select your zone">
          <el-option label="Zone one" value="shanghai" />
          <el-option label="Zone two" value="beijing" />
        </el-select>
      </el-form-item>
      <el-form-item label="Activity time">
        <el-col :span="11">
          <el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%;" />
        </el-col>
        <el-col :span="2" class="line">-</el-col>
        <el-col :span="11">
          <el-time-picker v-model="form.date2" type="fixed-time" placeholder="Pick a time" style="width: 100%;" />
        </el-col>
      </el-form-item>
      <el-form-item label="Instant delivery">
        <el-switch v-model="form.delivery" />
      </el-form-item>
      <el-form-item label="Activity type">
        <el-checkbox-group v-model="form.type">
          <el-checkbox label="Online activities" name="type" />
          <el-checkbox label="Promotion activities" name="type" />
          <el-checkbox label="Offline activities" name="type" />
          <el-checkbox label="Simple brand exposure" name="type" />
        </el-checkbox-group>
      </el-form-item>
      <el-form-item label="Resources">
        <el-radio-group v-model="form.resource">
          <el-radio label="Sponsor" />
          <el-radio label="Venue" />
        </el-radio-group>
      </el-form-item> -->
      <el-form-item label="IEC 104数据">
        <el-input v-model="form.iec104DataStr" autosize type="textarea" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">新增数据并解析</el-button>
        <el-button @click="onClear">清空</el-button>
      </el-form-item>
      <el-form-item label="返回结果">
        <el-input v-model="form.respJson" autosize type="textarea" />
      </el-form-item>
    </el-form>
  </div>
</template>


<script>
import { addIEC104 } from '@/api/iec104'
import { Message } from 'element-ui'


export default {
  data() {
    return {
      form: {
        // name: '',
        // region: '',
        // date1: '',
        // date2: '',
        // delivery: false,
        // type: [],
        // resource: '',
        iec104DataStr: '',
        respJson: ''
      }
    }
  },
  methods: {
    onSubmit() {
      console.log('this.form.iec104DataStr=%s', this.form.iec104DataStr)
      addIEC104(this.form.iec104DataStr).then(response => {
        console.log('response=%o', response)
        const { data } = response
        console.log('data=%o', data)
        const parseResult = data.parseResult
        console.log('parseResult=%s', parseResult)


        // this.form.respJson = JSON.stringify(data, null, 2)
        this.form.respJson = parseResult
      })


      Message({
        message: '已提交',
        type: 'info',
        duration: 1.5 * 1000
      })


      // this.$message('已提交!')
    },


    onClear() {
      this.form.iec104DataStr = ''
      this.form.respJson = ''


      // this.$message({
      //   message: '已清除!',
      //   type: 'warning'
      // })


      Message({
        message: '已清除',
        type: 'warning',
        duration: 1.5 * 1000
      })
    }
  }
}
</script>


<style scoped>
.line{
  text-align: center;
}
</style>
即可实现:
页面中输入:
68 59 F0 D2 00 00 15 A6 14 00 05 00 01 07 00 02 00 00 00 00 00 CF 5D 96 5D B2 5D 45 00 01 00 FE FF 7C 00 84 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 86 13 00 00 02 00 00 00 00 00 FE FF 00 00 00 00 98 00 00 00 00 00 02 00 00 00 00 00
然后点击按钮,正常发送到后端,后端解析返回结果,呈现到对应输入框内:

转载请注明:在路上 » 【已解决】vue-admin-template中如何用vuejs去发送REST的api的POST请求并返回和解析json字符串

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
92 queries in 0.180 seconds, using 23.41MB memory