实战项目Day3

63 阅读3分钟

学习String.trim()

trim()方法用于删除字符串的头尾空白符。

String str = '  oh my god!!!  ';
String newStr = str.trim();
System.out.println(str);
System.out.println(newStr);

image.png

接口报错空指针

image.png Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

在面向百度解决问题的时候,有这么两种解决方向:

  1. 注解没写

    Controllor 层引入的 Service 接口上面忘记写 @Resource 或 @Autowired 注解

  2. 调用的私有方法

    层调用的方法是 private 私有的,导致分发失败

但是,我看了我写的接口,没有上述的问题,我就在想会不会是我前端传后端的时候,数据传错了呢,所以我到chrome的开发者模式下,找到了网络,接口看到了下面:

image.png

image.png

可以看到这里接收的是表单数据,但是我后端接口接收的是字符串参数

// 后端代码
@PostMapping("/status/{status}")
    public R<String> updateState(@PathVariable int status,String ids) { 
        // 注意ids没有加注解@RequestParam,所以请求方式应该是:接口地址/status/1?ids=
        // 将多个ids存放到list集合中
        String[] split = ids.trim().split(",");
        List<Long> list = new ArrayList<>();
        for(int i = 0; i < split.length; i++) {
            list.add(Long.parseLong(split[i]));
        }
        // 修改状态
        dishService.updateState(list,status);
        return R.success(status == 0 ? "停售成功" : "起售成功");
    }

我又去postman里面试了一下:

image.png

看来确实是数据传输的方式错了,我写的接口是post方法+params参数,而在一般情况下直接使用post方法,传递的参数为 data 的方式 所以前端的接口应该这样写:

// 正确写法:
export const changeDishStatus = (params) => {
  return request.post(`/dish/status/${params.status}?ids=${params.ids}`)
}

// 不恰当写法:即后端接收不到数据
export const changeDishStatus = (params) => {
  return request.post(`/dish/status/${params.status}`, params.ids)
}

总结

return request({
    url: url,
    method: 'post',
    data: params // data就是body参数
});
return request({
    url: url,
    method: 'post',
    params: params// params就是query参数
});

拼在请求地址上的传参,就是query传参,params的值只能是一个字符串,不能传递对象类型的参数,如果参数中涉及到了传递对象,就要选择body传参。

后端接口@RequestBody的前端就要用data 后端和我这里一样String ids的前端就用query

行内块无法正确显示flex

image.png

我的HTML代码:

<div
    v-for="(item, index) in dishAddList"
    :key="index"
    class="items">
    <el-checkbox
      :key="index"
      :label="item">
      <div class="item">
        <span style="color: pink;flex:3;text-align: left;">{{ item.dishName }}</span>
        <span style="color: yellow">{{ item.status == 0 ? '停售' : '在售' }}</span>
        <span style="color: green">¥{{ Number(item.price)/100 }}</span>
      </div>
    </el-checkbox>
</div>

我的CSS代码:

.addDishCon .leftCont .tabList {
  flex: 1;
  padding: 15px;

  .table {
    border: solid 1px #f4f4f4;
    border-bottom: solid 1px #f4f4f4;

    .items {
      border-bottom: solid 1px #f4f4f4;
      padding: 0 10px;
      display: flex;

      .item {
        display: flex;
        padding-right: 20px;

        span {
          display: inline-block;
          text-align: center;
          flex: 1;
        }
      }
    }
  }
}
.addDishCon .leftCont .tabList .table .items .el-checkbox,.addDishCon .leftCont .tabList .table .items .el-checkbox__label{
  width: 100%;
}

找到原因了,inline-block行内块的宽度设置,默认被子元素撑开,所以造成了flex样式无法正确显示的原因

<style lang="less" scoped>
// 无法显示flex的写法:这是因为.items .el-checkbox__label找不到
.addDishCon .leftCont .tabList .table .items .el-checkbox, .addDishCon .leftCont .tabList .table .items .el-checkbox__label {
    width: 100%;
}
</style>

image.png 当你在页面补充上 width: 100%时,样式就正确显示了 image.png

但是这时候我就会陷入一个新的疑惑:为什么样式写明却没有生效呢?

在交流群里面问了一下大佬,大佬的回答是:看他有没有暴露API 没有就用css选择器找到,用权重覆盖

对于暴露的API我是这么理解的,对于你引用的组件库组件,组件的属性和事件名就是暴露的API。权重的大小即使在less或scss中也是生效的,这是因为less和scss最终都是要编译成css

解决方案一: 深度穿透修改组件样式

.addDishCon .leftCont .tabList .table .items .el-checkbox,.addDishCon .leftCont .tabList .table .items /deep/ .el-checkbox__label{
  width: 100%;
}

补充:/deep/ 也可以写成 >>> 或者 ::v-deep

解决方法二: 全局样式覆盖,不是很推荐,因为组件在不同页面有不同的显示,这样子不利于维护和修改

// global.css
/* 修改el-checkbox__label的宽度 */
.el-checkbox__label {
    width: 100%;
}

最后分享一篇看到的感觉很好的文章 如何覆盖组件库的组件样式

@Transactional是什么

@Transactional 注解,使用默认配置,抛出异常之后,事务会自动回滚,数据不会插入到数据库。 blog.csdn.net/nextyu/arti…

总结

一个正在学习Java试图走全栈的小白,希望大大多多指正。