idea新建springCloud项目(5)- 订单服务
时间: 2018-08-14来源:OSCHINA
前景提要
「深度学习福利」大神带你进阶工程师,立即查看>>>
1.创建订单api,如下:

2.创建订单实现逻辑

3.新建订单、订单商品表
-- 订单
create table `order_master` (
`order_id` varchar(32) not null,
`buyer_name` varchar(32) not null comment '买家名字',
`buyer_phone` varchar(32) not null comment '买家电话',
`buyer_address` varchar(128) not null comment '买家地址',
`buyer_openid` varchar(64) not null comment '买家微信openid',
`order_amount` decimal(8,2) not null comment '订单总金额',
`order_status` tinyint(3) not null default '0' comment '订单状态, 默认为新下单',
`pay_status` tinyint(3) not null default '0' comment '支付状态, 默认未支付',
`create_time` timestamp not null default current_timestamp comment '创建时间',
`update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',
primary key (`order_id`),
key `idx_buyer_openid` (`buyer_openid`)
);
-- 订单商品
create table `order_detail` (
`detail_id` varchar(32) not null,
`order_id` varchar(32) not null,
`product_id` varchar(32) not null,
`product_name` varchar(64) not null comment '商品名称',
`product_price` decimal(8,2) not null comment '当前价格,单位分',
`product_quantity` int not null comment '数量',
`product_icon` varchar(512) comment '小图',
`create_time` timestamp not null default current_timestamp comment '创建时间',
`update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',
primary key (`detail_id`),
key `idx_order_id` (`order_id`)
);

4.在IDEA新建springCloud项目-订单服务



修改版本,和之前建的eureka项目版本一致,修改完记得刷新:

删除掉不需要的文件:

5.把订单服务注册到eureka上去,启动项目
将application.properties修改为application.yml

记得加上这个注解,再启动项目:

打开8761的eureka,有如下页面则成功将订单服务注册到8761的eureka上:

6.商品业务实现
在pom.xml添加spring-boot-starter-data-jpa和mysql-connector-java依赖,且刷新:

在application.yml配置数据库信息:
(加jpa.show-sql:true,可在测试环境显示sql)

新建订单相关常量:
新建订单支付相关常量:


新建KeyUtil.java,生成唯一的主键,这个不能保证完完全全唯一,只是简单用下,如果是正式项目,需要作为一个独立的服务来生成key:
KeyUtil.java
public class KeyUtil {
/**
* 生成唯一的主键
* 格式: 时间+随机数
*/
public static synchronized String genUniqueKey() {
Random random = new Random();
Integer number = random.nextInt(900000) + 100000;
return System.currentTimeMillis() + String.valueOf(number);
}
}


新建ResultVO.java
ResultVO.java
@Data
public class ResultVO<T> {
private Integer code;
private String msg;
private T data;
}

1) model 配置表对应的实体类,类名、字段最好和表中一致
a.使用这个插件,可以省略getter/setter方法
在pom.xml加入lombok依赖

还需要在idea下载这个插件

只需要在实体类加上@Data注解,就可以不用在实体类生成getter/setter方法了

添加依赖:

新建OrderException.java
OrderException.java
public class OrderException extends RuntimeException {
private Integer code;
public OrderException(Integer code, String message) {
super(message);
this.code = code;
}
public OrderException(ResultEnum resultEnum) {
super(resultEnum.getMessage());
this.code = resultEnum.getCode();
}
}

新建实体类OrderDetail.java、OrderMaster.java、OrderDTO.java
OrderDetail.java
@Data
@Entity
public class OrderDetail {
@Id
private String detailId;
/** 订单id. */
private String orderId;
/** 商品id. */
private String productId;
/** 商品名称. */
private String productName;
/** 商品单价. */
private BigDecimal productPrice;
/** 商品数量. */
private Integer productQuantity;
/** 商品小图. */
private String productIcon;
}

OrderMaster.java
@Data
@Entity
public class OrderMaster {
/** 订单id. */
@Id
private String orderId;
/** 买家名字. */
private String buyerName;
/** 买家手机号. */
private String buyerPhone;
/** 买家地址. */
private String buyerAddress;
/** 买家微信Openid. */
private String buyerOpenid;
/** 订单总金额. */
private BigDecimal orderAmount;
/** 订单状态, 默认为0新下单. */
private Integer orderStatus;
/** 支付状态, 默认为0未支付. */
private Integer payStatus;
/** 创建时间. */
private Date createTime;
/** 更新时间. */
private Date updateTime;
}


OrderDTO.java
@Data
public class OrderDTO {
/** 订单id. */
private String orderId;
/** 买家名字. */
private String buyerName;
/** 买家手机号. */
private String buyerPhone;
/** 买家地址. */
private String buyerAddress;
/** 买家微信Openid. */
private String buyerOpenid;
/** 订单总金额. */
private BigDecimal orderAmount;
/** 订单状态, 默认为0新下单. */
private Integer orderStatus;
/** 支付状态, 默认为0未支付. */
private Integer payStatus;
private List<OrderDetail> orderDetailList;
}

2) dao
新建OrderMasterRepository.java、OrderDetailRepository.java
OrderMasterRepository.java
public interface OrderMasterRepository extends JpaRepository<OrderMaster, String> {
//里面方法是不需要写的,直接用就好了
}

OrderDetailRepository.java
public interface OrderDetailRepository extends JpaRepository<OrderDetail, String> {
List<OrderDetail> findByOrderId(String orderId);
}

3) service


新建OrderService.java、OrderServiceImpl.java
OrderService.java
public interface OrderService {
/**
* 创建订单
* @param orderDTO
* @return
*/
OrderDTO create(OrderDTO orderDTO);
/**
* 完结订单(只能卖家操作)
* @param orderId
* @return
*/
OrderDTO finish(String orderId);
}

OrderServiceImpl.java
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDetailRepository orderDetailRepository;
@Autowired
private OrderMasterRepository orderMasterRepository;
@Autowired
private ProductClient productClient;
@Override
@Transactional
public OrderDTO create(OrderDTO orderDTO) {
String orderId = KeyUtil.genUniqueKey();
//查询商品信息(调用商品服务)
List<String> productIdList = orderDTO.getOrderDetailList().stream()
.map(OrderDetail::getProductId)
.collect(Collectors.toList());
List<ProductInfoOutput> productInfoList = productClient.listForOrder(productIdList);
//计算总价
BigDecimal orderAmout = new BigDecimal(BigInteger.ZERO);
for (OrderDetail orderDetail: orderDTO.getOrderDetailList()) {
for (ProductInfoOutput productInfo: productInfoList) {
if (productInfo.getProductId().equals(orderDetail.getProductId())) {
//单价*数量
orderAmout = productInfo.getProductPrice()
.multiply(new BigDecimal(orderDetail.getProductQuantity()))
.add(orderAmout);
BeanUtils.copyProperties(productInfo, orderDetail);
orderDetail.setOrderId(orderId);
orderDetail.setDetailId(KeyUtil.genUniqueKey());
//订单详情入库
orderDetailRepository.save(orderDetail);
}
}
}
//扣库存(调用商品服务)
List<DecreaseStockInput> decreaseStockInputList = orderDTO.getOrderDetailList().stream()
.map(e -> new DecreaseStockInput(e.getProductId(), e.getProductQuantity()))
.collect(Collectors.toList());
productClient.decreaseStock(decreaseStockInputList);
//订单入库
OrderMaster orderMaster = new OrderMaster();
orderDTO.setOrderId(orderId);
BeanUtils.copyProperties(orderDTO, orderMaster);
orderMaster.setOrderAmount(orderAmout);
orderMaster.setOrderStatus(OrderStatusEnum.NEW.getCode());
orderMaster.setPayStatus(PayStatusEnum.WAIT.getCode());
orderMasterRepository.save(orderMaster);
return orderDTO;
}
@Override
@Transactional
public OrderDTO finish(String orderId) {
//1. 先查询订单
Optional<OrderMaster> orderMasterOptional = orderMasterRepository.findById(orderId);
if (!orderMasterOptional.isPresent()) {
throw new OrderException(ResultEnum.ORDER_NOT_EXIST);
}
//2. 判断订单状态
OrderMaster orderMaster = orderMasterOptional.get();
if (OrderStatusEnum.NEW.getCode() != orderMaster.getOrderStatus()) {
throw new OrderException(ResultEnum.ORDER_STATUS_ERROR);
}
//3. 修改订单状态为完结
orderMaster.setOrderStatus(OrderStatusEnum.FINISHED.getCode());
orderMasterRepository.save(orderMaster);
//查询订单详情
List<OrderDetail> orderDetailList = orderDetailRepository.findByOrderId(orderId);
if (CollectionUtils.isEmpty(orderDetailList)) {
throw new OrderException(ResultEnum.ORDER_DETAIL_NOT_EXIST);
}
OrderDTO orderDTO = new OrderDTO();
BeanUtils.copyProperties(orderMaster, orderDTO);
orderDTO.setOrderDetailList(orderDetailList);
return orderDTO;
}

}

4) form
新建OrderForm.java,需要表单验证,所以不用vo:
OrderForm.java
@Data
public class OrderForm {
/**
* 买家姓名
*/
@NotEmpty(message = "姓名必填")
private String name;
/**
* 买家手机号
*/
@NotEmpty(message = "手机号必填")
private String phone;
/**
* 买家地址
*/
@NotEmpty(message = "地址必填")
private String address;
/**
* 买家微信openid
*/
@NotEmpty(message = "openid必填")
private String openid;
/**
* 购物车
*/
@NotEmpty(message = "购物车不能为空")
private String items;
}

4) form转换dto
新建OrderForm2OrderDTOConverter.java
OrderForm2OrderDTOConverter.java
@Slf4j
public class OrderForm2OrderDTOConverter {
public static OrderDTO convert(OrderForm orderForm) {
Gson gson = new Gson();
OrderDTO orderDTO = new OrderDTO();
orderDTO.setBuyerName(orderForm.getName());
orderDTO.setBuyerPhone(orderForm.getPhone());
orderDTO.setBuyerAddress(orderForm.getAddress());
orderDTO.setBuyerOpenid(orderForm.getOpenid());
List<OrderDetail> orderDetailList = new ArrayList<>();
try {
orderDetailList = gson.fromJson(orderForm.getItems(),
new TypeToken<List<OrderDetail>>() {
}.getType());
} catch (Exception e) {
log.error("【json转换】错误, string={}", orderForm.getItems());
throw new OrderException(ResultEnum.PARAM_ERROR);
}
orderDTO.setOrderDetailList(orderDetailList);
return orderDTO;
}
}


5) controller
新建ProductController.java
ProductController.java
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {
@Autowired
private OrderService orderService;
/**
* 1. 参数检验
* 2. 查询商品信息(调用商品服务)
* 3. 计算总价
* 4. 扣库存(调用商品服务)
* 5. 订单入库
*/
@PostMapping("/create")
public ResultVO<Map<String, String>> create(@Valid OrderForm orderForm,
BindingResult bindingResult) {
if (bindingResult.hasErrors()){
log.error("【创建订单】参数不正确, orderForm={}", orderForm);
throw new OrderException(ResultEnum.PARAM_ERROR.getCode(),
bindingResult.getFieldError().getDefaultMessage());
}
// orderForm -> orderDTO
OrderDTO orderDTO = OrderForm2OrderDTOConverter.convert(orderForm);
if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())) {
log.error("【创建订单】购物车信息为空");
throw new OrderException(ResultEnum.CART_EMPTY);
}
OrderDTO result = orderService.create(orderDTO);
Map<String, String> map = new HashMap<>();
map.put("orderId", result.getOrderId());
return ResultVOUtil.success(map);
}
/**
* 完结订单
* @param orderId
* @return
*/
@PostMapping("/finish")
public ResultVO<OrderDTO> finish(@RequestParam("orderId") String orderId) {
return ResultVOUtil.success(orderService.finish(orderId));
}
}

7.访问成功

科技资讯:

科技学院:

科技百科:

科技书籍:

网站大全:

软件大全:

热门排行