Java从零单排 -- 小马哥商城实战(3)

198 阅读4分钟

前言

上一章节,我们通过在html页面上架商品,但是查看上架的商品只能从数据库中,如何通过浏览器查看上架过的商品呢?这里我们需要了解一个html向后台发起请求的技术ajax,由于本系列着重点在Java开始上,前端的知识只会稍微介绍下。在原生的ajax技术,有一个封装好的前端js框架axios,所以接下来我们就用这个技术来遍历我们的商品。

商品列表

请求接口 good/getList

 @GetMapping("getList")
    public List<Good> getList() {
        return goodService.getList();
    }
  
  dao层
   <select id="getList" resultType="com.xiaoma.mall.entity.Good">
            select id,name,remark,image,price from good
    </select>

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>小马哥商城</title>
</head>
<body>
<div id="app">
    <h3>商品上架</h3>
    <form action="good/shelves" method="post" enctype="multipart/form-data">
        <div>商品名称<input name="name"></div>
        <div>商品描述<input name="remark"></div>
        <div>商品价格<input name="price"></div>
        <div>商品图片<input name="file" type="file"></div>
        <div><button type="submit">上架</button></div>
    </form>
    <div style="display:flex;flex-wrap: wrap;">
        <div v-for="item in list" style="border:solid;margin:2px;padding:5px">
            <p>商品名称:{{item.name}}</p>
            <p>商品描述:{{item.remark}}</p>
            <p>商品价格:{{item.price}}</p>
           <image v-if="item.image" :src="'good/getGoodImg/'+item.image" style="width:50px;height:50px"/>
        </div>
    </div>
</div>

</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.1/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.0/axios.min.js"></script>
<script >
   new Vue({
        el:'#app',
        data(){
            return{
                list:[]
            }
        },
        created(){
           axios
             .get('good/getList')
             .then(response => {
                this.list = response.data
             })
        }
   })
</script>
</html>

我们只要关注 axios .get('good/getList') .then(response =>this.list = response.data) ,先后台发起请求,获取接口返回的数据。

 遍历数据
 <div style="display:flex;flex-wrap: wrap;">
        <div v-for="item in list" style="border:solid;margin:2px;padding:5px">
            <p>商品名称:{{item.name}}</p>
            <p>商品描述:{{item.remark}}</p>
            <p>商品价格:{{item.price}}</p>
           <image v-if="item.image" :src="'good/getGoodImg/'+item.image" style="width:50px;height:50px"/>
        </div>
    </div>

值得注意的是 image标签的 src值,在前面我们编写了一个获取图片的接口,那么在image标签上我们就可以直接用上了。

库存

商品列表中还查了一个数量的字段,前面我们表设计的时候 good表 warehouse表是通过goodId关联的,所以我们改动下我们的商品列表SQL的语句

SELECT
	g.id,
	g.NAME,
	g.remark,
	g.image,
	g.price,
    w.amount
FROM
	good g
LEFT JOIN warehouse w on g.id = w.good_id

表名后面字母是表的别名,别名可以随便起的,字段的用表名.字段

warehouse表设计的时候少了amount字段,我们要补上

mybatis返回的对象跟我们good字段不一致,对了一个amount字段,这种情况我们可以在good类中增加一个amount字段,但是这样会破坏good类跟表结构不一致的情况,这里我们就引入一个新的知识点JSONObject。在pom.xml增加依赖

<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.75</version>
		</dependency>

将之前的接口改造下,返回类型变成JSONObject

 @GetMapping("getList")
   public List<JSONObject> getList() {
       return goodService.getList();
   }   

GoodService

 List<JSONObject> getList();

GoodServiceImpl

@Override
    public List<JSONObject> getList() {
        return goodDao.getList();
    }

GoodDao

List<JSONObject> getList();

goodMapper

<select id="getList" resultType="com.alibaba.fastjson.JSONObject">
        SELECT
        g.id,
        g.name,
        g.remark,
        g.image,
        g.price,
        w.amount
        FROM
        good g
        LEFT JOIN warehouse w on g.id = w.good_id
    </select>

index.html 增加数量显示

  <p>商品价格:{{item.price}}</p>
  <p>商品数量:{{item.amount||0}}</p>

库存更新

商品的库存要随时更新的,那么我们要实现一个库存更新接口。 前端页面我们先设计2个按钮,一个是增加,一个是减少。

html部分
 <p>商品数量:{{item.amount||0}}
                <button @click="updateWarehouse(item,0)">+</button>
                <button @click="updateWarehouse(item,1)">-</button>
            </p>
 js部分  
 created(){
           axios
             .get('good/getList')
             .then(response => {
                this.list = response.data
             })
        },
        methods:{
            updateWarehouse(item,type){
            axios
             .post('warehouse/updateWarehouse',{
             goodId:item.id,
             type:type,
             oldAmount:item.amount||0
             }

             )
             .then(response => {
                  axios
                 .get('good/getList')
                 .then(response => {
                    this.list = response.data
                 })
             })
            }
        }

首先我们先思考,进行数据更新的时候需要字段是什么,第一对商品存款更新一定要goodId,然后就是根据实际需要一个类型字段,还有一个是就得库存字段。

那么传到后台的字段为goodId, type,oldAmount。

/**
 * 仓库接口
 * 
 */
@RestController
@RequestMapping("warehouse")
public class WarehouseController {
    @Autowired
    private WarehouseService warehouseService;

    /**
     * 更新商品库存  @RequestBody 注解表示接受一个json数据
     *
     * @param requestJson
     *        goodId 商品id
     *        type   0:存在增加 1:库存减少
     *        oldAmount 旧库存
     * @return
     */
    @PostMapping("updateWarehouse")
    public String updateWarehouse(@RequestBody JSONObject requestJson){
        return warehouseService.updateWarehouse(requestJson);
    }
}

根据前端传进来的字段,从json中一一获取

@Service
public class WarehouseServiceImpl implements WarehouseService {
    @Autowired
    private WarehouseDao warehouseDao;

    @Transactional
    @Override
    public String updateWarehouse(JSONObject requestJson) {
        //从json数据获取字段值
        int goodId = requestJson.getIntValue("goodId");
        int type = requestJson.getIntValue("type");
        int oldAmount = requestJson.getIntValue("oldAmount");
        //先判断有无库存数据
        Warehouse warehouse = warehouseDao.getWarehouseByGoodId(goodId);
        if (warehouse == null) {
            //无库存数据插入一条
            warehouse = new Warehouse();
            warehouse.setGoodId(goodId);
            warehouse.setStatus(0);
            warehouse.setAmount(0);
            warehouse.setCreateTime(new Date());
            warehouse.setCreateUser(1);
            warehouseDao.addWarehouse(warehouse);
        }
        int amount;
        if (type == 0) {//库存增加
            amount = oldAmount + 1;
        } else {//库存减少
            amount = oldAmount - 1;
        }
        warehouseDao.updateWarehouse(goodId, amount, oldAmount);
        return "ok";
    }
}

sql语句为

  <insert id="addWarehouse">
        insert into warehouse(good_id,amount,status,create_time,create_user)
        values(#{goodId},#{amount},#{status},#{createTime},#{createUser})
    </insert>
    <update id="updateWarehouse">
        UPDATE warehouse
            SET amount = #{amount}
        WHERE
            good_id = #{goodId}
            AND amount = #{oldAmount}
    </update>
    <select id="getWarehouseByGoodId" resultType="com.xiaoma.mall.entity.Warehouse">
        select
        id,
        good_id goodId,
        amount
        from warehouse
        where good_id = #{goodId}
    </select>

编写完后,重新启动项目,刷新index页面。点击+ - 按钮就能对商品的库存进行更新了。

小结

sql

  • 表与表之间的关联可以通过left jon ,on为表之间的关联字段
  • 表的别名 ,表名 空格 别名
  • 字段别名, 字段 空格 别名

ajax -- axios

axios默认的请求头为application/json,当我们介绍post数据的时候,要通@RequestBody 注解将数据转换为java中的json对象。