商品模块开发
在这个模块中,有一些地方需要详细说明,不仅是接口的开发,还有数据的添加,配置项的添加等。所以,分几个小节进行描述。
基本的准备工作
准备工作有几个方面,包括添加依赖、添加配置项、新建表以及添加数据。
添加依赖
在下面的依赖中,添加了 MySQL 的依赖,MySQL 驱动的依赖,以及 MyBatis 的依赖。在本案例中,数据库是 MySQL,对数据源的操作使用的是 MyBatis。源码如下所示。
<!--MyBatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!--Mysql连接驱动的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--Mysql的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
添加配置项
在案例中,使用的是 Config 模块,所以 product 使用的配置项直接添加到 Config 中。因此,下面的配置项,MySQL 的连接信息,MyBatis 读取 SQL 的配置信息,以及数据库连接池的配置项都会放在远程 Git 中。
配置项放在 config-repository/productService-dev.properties 中,下面是配置信息。
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3308/test?serverTimezo ne=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
mybatis.mapper-locations=classpath:mapper/*.xml
新建表,以及添加数据
对于表,使用 SQL 可以重现,SQL 代码如下所示。
create table product(
product_id int(32) not null,
product_ename VARCHAR(32) default null,
product_cname VARCHAR(32) default null,
product_quantity int(32) default null,
primary key(product_id)
)engine=INNODB DEFAULT CHARSET=utf8;
给表添加一条记录,方便用于写第一个查询接口,可以查询到基础数据,SQL 代码如下所示。
-- 插入一条商品记录
insert product(product_id,product_ename,product_cname,product_quantity) values (1,"java","代码大全",50);
-- 检验数据是否正确
select * from product;
目前为止,基本的准备工作都做好了。
接口开发
关于需求的几个接口,将会在最后进行说明,因此这里还是按照项目的先后顺序展开,方便读者可以重现代码。
首先,在项目下,新建一个 entity 包,然后在包下新建 Product 类,代码如下所示。
package com.exampleone.product.entity;
public class Product {
//商品ID
private int productId;
//商品的英文名称
private String productEname;
//商品的中文名称
private String productCname;
//商品的数量
private int productQuantity;
//下面是SET和GET以及toString方法,此处忽略\
//……
}
然后,新建一个 mapper 包,在包下新建一个接口,代码如下所示。
package com.exampleone.product.mapper;
@Mapper
public interface ProductMapper {
//查询所有的product
public List<Product> queryAllProduct();
//通过productId查询product
List<Product> queryProductByProductid(int productId);
//插入product
public int insertProduct(Product product);
//更新product
public int updateProduct(Product product);
//删除product
public int deleteProduct(int productId);
}
这是一个接口,并且在接口上有一个 @Mapper 注解。在 sqlSession 对象中 GET 将会是一个实现类,后面的程序中没有手动写实现类,是通过 MyBatis JDK 动态代理在加载配置文件时,根据 mapper 的 XML 生成,节省了很多时间,这就是这个注解的作用。
然后,为了合乎开发规范,再写一层 service,使得服务层与数据库访问层分离。写 service 时,直接使用接口 ProductMapper 中的方法即可,我们可以理解为使用接口的实现类中的方法。首先新建 service 包,再在包下新建 ProductService 类,代码如下所示。
package com.exampleone.product.service;
@Service
public class ProductService {
@Autowired
private ProductMapper productMapper;
//查询所有的product
public List<Product> queryAllProduct(){
return productMapper.queryAllProduct();
}
//通过productId查询product
public List<Product> queryProductByProductid(int productId){
return productMapper.queryProductByProductid(productId);
}
//插入product
public Product insertProduct(Product product){
productMapper.insertProduct(product);
return product;
}
//更新product
public int updateProduct(Product product){
return productMapper.updateProduct(product);
}
//删除product
public int deleteProduct(int productId){
return productMapper.deleteProduct(productId);
}
}
然后,新建 XML 的映射文件。在 Config 中,已经指定 xml 的读取路径是 mapper/**,所以,在 resources 下面新建一个 mapper 目录,然后新建 XML 文件,代码如下所示。
<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD com.example.Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.exampleone.product.mapper.ProductMapper">
<resultMap id="result" type="com.exampleone.product.entity. Product">
<result property="productId" column="product_id"/>
<result property="productEname" column="product_ename"/>
<result property="productCname" column="product_cname"/>
<result property="productQuantity" column="product_quantity"/>
</resultMap>
<select id="queryAllProduct" resultMap="result">
SELECT * FROM product;
</select>
<select id="queryProductByProductid" resultMap="result">
SELECT * FROM product where product_id=#{productId};
</select>
<insert id="insertProduct"
parameterType="com.exampleone.product.entity.Product"
keyProperty="productId" useGeneratedKeys="true">
INSERT INTO
user(product_id,product_ename,product_cname,product_quantity)
VALUES (#{productId},#{productEname,jdbcType=VARCHAR},#{productCname, jdbcType=VARCHAR},#{productQuantity});
</insert>
<delete id=" deleteProduct " parameterType="int">
delete from product where product_id=#{productId};
</delete>
<update id=" updateProduct " parameterType="com.exampleone.product.entity.Product">
update product set
product.product_ename=#{productEname},product.product_cname=#{productCname},product.product_quantity=#{productQuantity} where product.product_id=#{productId};
</update>
</mapper>
在上面的 XML 中,对应了五个接口所有的 XML,即是上面 mapper 接口中的方法。
封装Restful接口
首先,对外提供的接口,我们需要单独放在一个目录下。新建 controller 包,在包下新建一个 productController 类。
查询所有商品接口,这里是完成的第一个接口,用于店家在后台进行操作,代码如下所示。
package com.exampleone.product.controller;
@RestController
//添加一个父url路径
@RequestMapping(value = "/product", method = { RequestMethod.GET, RequestMethod.POST })
public class ProductController {
@Autowired
private ProductService productService;
@RequestMapping("/queryAllProduct")
public List<Product> queryAllProduct(){
return productService.queryAllProduct();
}
}
本接口在16.3.4节进行详细的测试,可以参看下面的章节。
根据条件查询某个商品的具体信息接口。
@RequestMapping("/queryProductByProductid")
@ResponseBody
public List<Product> queryProductByProductid(int productId){
return productService.queryProductByProductid(productId);
}
本接口在16.3.4节进行详细的测试,可以参看下面的章节。
添加商品接口。
@RequestMapping(value = "/insertProduct",method = RequestMethod.POST)
public Product insertProduct(@RequestBody Product product){
return productService.insertProduct(product);
}
本接口在16.3.4节进行详细的测试,可以参看下面的章节。
更新商品信息接口。
@RequestMapping(value = "/updateProduct",method = RequestMethod.PUT)
public int updateProduct(@RequestBody Product product){
return productService.updateProduct(product);
}
本接口在16.3.4节进行详细的测试,可以参看下面的章节。
删除商品接口。
@RequestMapping(value = "/deleteProduct",method = RequestMethod.DELETE)
public int deleteProduct(int productId){
return productService.deleteProduct(productId);
}
Restful接口测试
对于上面 16.3.3 节中写的商品接口,都需要进行测试,确保对外提供的接口可以使用。
查询所有的 product。启动应用,因为这个接口是一个普通的 GET 请求方式,所以我们可以直接使用浏览器进行访问。访问链接 http://localhost:8070/product/queryAllUser ,浏览器上的结果如图16.16所示。

查询某个商品的具体信息。考虑到只有一个商品,测试起来也不知道查询的效果是不是上次的结果,所以,在数据库中再添加一条数据,SQL 代码如下所示。
-- 插入一条商品记录
insert product(product_id,product_ename,product_cname,product_quantity) values (2,"python","python快乐学习",60);
-- 检验数据是否正确
select * from product;
这样,在数据库中就存在两条数据了。
这个接口也是 GET 的请求方式,所以继续使用浏览器进行测试。访问链接: http://localhost:8070/product/queryProductByProductid?productId=2 。运行效果如图16.17所示。

添加商品信息。对于 POST 接口,可以使用 Mock 服务进行测试,也可以使用 Postman 工具进行测试,这里使用 Postman 工具进行测试。
使用链接为 http://localhost:8070/product/insertProduct ,使用格式为Json、Body体,如图16.18所示。

更新商品信息。对于 PUT 的请求方式,继续使用 Postman 工具进行测试。请求参数以及请求链接如图16.19所示。

删除商品信息。对于 DELETE 的请求方式,使用 Postman 工具进行测试,访问链接 http://localhost:8070/product/deleteProduct?productId=3 ,则可以删除数据库中的数据。