日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

乐优商城(14)–订单服务

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 乐优商城(14)–订单服务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

樂優商城(14)–訂單服務

一、創建訂單微服務

1.1、創建訂單父module

1.2、創建leyou-order-interface

pom文件:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>leyou-order</artifactId><groupId>com.leyou.order</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>leyou-order-interface</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>javax.persistence</groupId><artifactId>persistence-api</artifactId><version>1.0</version></dependency><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>6.1.6.Final</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.leyou.auth</groupId><artifactId>leyou-auth-common</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies></project>

1.3、創建leyou-order-service

pom文件:

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>leyou-order</artifactId><groupId>com.leyou.order</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>leyou-order-service</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- mybatis啟動器 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!-- 通用Mapper啟動器 --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId></dependency><!-- mysql驅動 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId></dependency><dependency><groupId>com.github.wxpay</groupId><artifactId>wxpay-sdk</artifactId><version>0.0.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>com.leyou.common</groupId><artifactId>leyou-common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.leyou.auth</groupId><artifactId>leyou-auth-common</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.leyou.order</groupId><artifactId>leyou-order-interface</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>com.leyou.item</groupId><artifactId>leyou-item-interface</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies></project>

application.yaml

server:port: 8089 spring:application:name: order-servicedatasource:url: jdbc:mysql://127.0.0.1:3306/leyou?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=trueusername: rootpassword: 123456hikari:max-lifetime: 28830000 # 一個連接的生命時長(毫秒),超時而且沒被使用則被釋放(retired),缺省:30分鐘,建議設置比數據庫超時時長少30秒,參考MySQL wait_timeout參數(show variables like '%timeout%';)maximum-pool-size: 9 # 連接池中允許的最大連接數。缺省值:10;推薦的公式:((core_count * 2) + effective_spindle_count)driver-class-name: com.mysql.jdbc.Driverrabbitmq:host: IP地址username: leyoupassword: leyouvirtual-host: /leyoutemplate:retry:enabled: trueinitial-interval: 10000msmax-interval: 3000000msmultiplier: 2exchange: leyou.item.exchangepublisher-confirm-type: correlatedredis:host: IP地址port: 8975cloud:nacos:discovery:server-addr: IP地址:8848username: nacospassword: nacos mybatis:type-aliases-package: com.leyou.order.pojomapper-locations: mapper/OrderMapper.xmlconfiguration:map-underscore-to-camel-case: true mapper:not-empty: falseidentity: mysql leyou:worker:workerId: 1datacenterId: 1jwt:pubKeyPath: F:\\leyou\\rsa\\rsa.pub # 公鑰地址cookieName: LY_TOKEN # cookie的名稱pay:appId: wx8397f8696b538317 mchId: 1473426802key: T6m9iK73b0kn9g5v426MKfHQH7X8rKwbconnectTimeoutMs: 5000readTimeoutMs: 10000

啟動類

@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class LeyouOrderApplication {public static void main(String[] args) {SpringApplication.run(LeyouOrderApplication.class,args);} }

導入配置

訂單號生成器,攔截器配置,支付配置,swagger配置

屬性讀取

攔截器

支付工具類

添加網關路由

二、實體類及Mapper

2.1、實體類

2.1.1、Order

@Table(name = "tb_order") public class Order {@Idprivate Long orderId;// id@NotNullprivate Long totalPay;// 總金額@NotNullprivate Long actualPay;// 實付金額@NotNullprivate Integer paymentType; // 支付類型,1、在線支付,2、貨到付款private String promotionIds; // 參與促銷活動的idprivate String postFee;// 郵費private Date createTime;// 創建時間private String shippingName;// 物流名稱private String shippingCode;// 物流單號private Long userId;// 用戶idprivate String buyerMessage;// 買家留言private String buyerNick;// 買家昵稱private Boolean buyerRate;// 買家是否已經評價private String receiver; // 收貨人全名private String receiverMobile; // 移動電話private String receiverState; // 省份private String receiverCity; // 城市private String receiverDistrict; // 區/縣private String receiverAddress; // 收貨地址,如:xx路xx號private String receiverZip; // 郵政編碼,如:310001private Integer invoiceType;// 發票類型,0無發票,1普通發票,2電子發票,3增值稅發票private Integer sourceType;// 訂單來源 1:app端,2:pc端,3:M端,4:微信端,5:手機qq端@Transientprivate List<OrderDetail> orderDetails; //訂單信息集合@Transientprivate Integer status; //訂單狀態//get和set }

2.1.2、OrderDetail

@Table(name = "tb_order_detail") public class OrderDetail {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private Long orderId;// 訂單idprivate Long skuId;// 商品idprivate Integer num;// 商品購買數量private String title;// 商品標題private Long price;// 商品單價private String ownSpec;// 商品規格數據private String image;// 圖片//get和set }

2.1.3、OrderStatus

@Table(name = "tb_order_status") public class OrderStatus {@Idprivate Long orderId;/*** 初始階段:1、未付款、未發貨;初始化所有數據* 付款階段:2、已付款、未發貨;更改付款時間* 發貨階段:3、已發貨,未確認;更改發貨時間、物流名稱、物流單號* 成功階段:4、已確認,未評價;更改交易結束時間* 關閉階段:5、關閉; 更改更新時間,交易關閉時間。* 評價階段:6、已評價*/private Integer status;private Date createTime;// 創建時間private Date paymentTime;// 付款時間private Date consignTime;// 發貨時間private Date endTime;// 交易結束時間private Date closeTime;// 交易關閉時間private Date commentTime;// 評價時間//get和set }

一個訂單對應好幾種狀態,通過表tb_order_status來記錄訂單所處的不同狀態;一個訂單有好多訂單項,即多個商品信息,這個用表tb_order_detail來記錄

2.2、Mapper

OrderMapper

/*** Order 的通用mapper*/ public interface OrderMapper extends Mapper<Order> { }

OrderDetailMapper

/*** OrderDetail 的通用mapper*/ public interface OrderDetailMapper extends Mapper<OrderDetail>, InsertListMapper<OrderDetail> { }

OrderStatus

/*** OrderStatus 的通用mapper*/ public interface OrderStatusMapper extends Mapper<OrderStatus> { }

在啟動類中添加mapper掃描:

三、訂單相關接口

3.1、創建訂單

3.1.1、Controller

  • 請求方式:POST
  • 請求路徑:/order
  • 請求參數:order對象(包含訂單、訂單詳情等數據的json對象。)
  • 返回結果:訂單編號
/*** 創建訂單* @param order 訂單對象* @return 訂單編號*/ @PostMapping public ResponseEntity<Long> createOrder(@RequestBody @Valid Order order){Long id = this.orderService.createOrder(order);return new ResponseEntity<>(id, HttpStatus.CREATED); }

3.1.2、Service

public interface OrderService {/*** 創建訂單* @param order 訂單對象* @return 訂單編號*/Long createOrder(Order order); }

實現類:

@Service public class OrderServiceImpl implements OrderService {@Autowiredprivate IdWorker idWorker;@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate OrderStatusMapper orderStatusMapper;@Autowiredprivate OrderDetailMapper orderDetailMapper;private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);@Transactional(rollbackFor = Exception.class)@Overridepublic Long createOrder(Order order) {//1.生成orderIdlong orderId = idWorker.nextId();//2.獲取登錄的用戶UserInfo userInfo = LoginInterceptor.getLoginUser();//3.初始化數據order.setBuyerNick(userInfo.getUsername());order.setBuyerRate(false);order.setCreateTime(new Date());order.setOrderId(orderId);order.setUserId(userInfo.getId());//4.保存數據this.orderMapper.insertSelective(order);//5.保存訂單狀態OrderStatus orderStatus = new OrderStatus();orderStatus.setOrderId(orderId);orderStatus.setCreateTime(order.getCreateTime());//初始狀態未未付款:1orderStatus.setStatus(1);//6.保存數據this.orderStatusMapper.insertSelective(orderStatus);//7.在訂單詳情中添加orderIdorder.getOrderDetails().forEach(orderDetail -> orderDetail.setOrderId(orderId));//8.保存訂單詳情,使用批量插入功能this.orderDetailMapper.insertList(order.getOrderDetails());//9.減庫存logger.debug("生成訂單,訂單編號:{},用戶id:{}", orderId, userInfo.getId());return orderId;} }

基本邏輯:

  • 生成訂單id
  • 獲取登錄用戶的信息
  • 初始化訂單數據:買家昵稱、是否評論、創建時間、訂單號、用戶id
  • 保存訂單數據
  • 初始化訂單狀態數據:訂單id、訂單創建時間、訂單狀態(初始狀態:1,未付款)
  • 保存訂單狀態數據
  • 為訂單詳情中的數據添加訂單號,因為一個訂單下有多個訂單項
  • 保存訂單詳情數據
  • 減庫存

3.2、訂單查詢

3.2.1、Controller

  • 請求方式:GET
  • 請求路徑:/order/{id}
  • 請求參數:id,訂單編號
  • 返回結果:Order,訂單的json對象
/*** 根據訂單id查詢訂單* @param id 訂單編號* @return 訂單對象*/ @GetMapping("/{id}") public ResponseEntity<Order> queryOrderById(@PathVariable("id") Long id){Order order = this.orderService.queryOrderById(id);if (order == null){return ResponseEntity.notFound().build();}return ResponseEntity.ok(order); }

3.2.2、Service

/*** 根據訂單id查詢訂單* @param id 訂單編號* @return 訂單對象*/ Order queryOrderById(Long id);

實現類:

/*** 根據訂單id查詢訂單** @param id 訂單編號* @return 訂單對象*/ @Override public Order queryOrderById(Long id) {//先查詢訂單Order order = this.orderMapper.selectByPrimaryKey(id);//再查詢訂單詳細信息OrderDetail orderDetail = new OrderDetail();orderDetail.setOrderId(id);List<OrderDetail> orderDetails = this.orderDetailMapper.select(orderDetail);if (CollectionUtils.isEmpty(orderDetails)) return null;//order對象填充訂單詳情order.setOrderDetails(orderDetails);// 查詢訂單狀態OrderStatus orderStatus = this.orderStatusMapper.selectByPrimaryKey(id);//order對象設置訂單狀態order.setStatus(orderStatus.getStatus());return order; }

基本邏輯:

  • 根據訂單號查詢訂單對象
  • 根據訂單號查詢訂單詳情
  • 根據訂單號查詢訂單狀態
  • 給已經查詢到的訂單對象填充訂單詳情
  • 給已經查詢到的訂單對象設置訂單狀態

3.3、分頁查詢用戶訂單

3.3.1、Controller

  • 請求方式:Get
  • 請求路徑:/order/list
  • 請求參數:
    • page:當前頁,Integer類型,默認為1
    • rows:每頁大小,Integer類型,默認為5
    • status:訂單狀態,String類型,默認查詢全部狀態訂單
  • 返回結果:PageResult 對象,包含下面屬性:
    • total:總條數
    • items:當前頁訂單數組
      • 訂單對象
/*** 分頁查詢當前已經登錄的用戶訂單* @param page 頁數* @param rows 每頁大小* @param status 訂單狀態* @return*/ @GetMapping("/list") public ResponseEntity<PageResult<Order>> queryOrderList(@RequestParam(value = "page",defaultValue = "1")Integer page,@RequestParam(value = "rows",defaultValue = "5")Integer rows,@RequestParam(value = "status",required = false)Integer status ){PageResult<Order> orders = this.orderService.queryOrderList(page,rows,status);if (null == orders){return new ResponseEntity<>(HttpStatus.NOT_FOUND);}return ResponseEntity.ok(orders); }

3.3.2、Service

/*** 分頁查詢當前已經登錄的用戶訂單* @param page 頁數* @param rows 每頁大小* @param status 訂單狀態* @return*/ PageResult<Order> queryOrderList(Integer page, Integer rows, Integer status);

實現類:

/*** 分頁查詢當前已經登錄的用戶訂單** @param page 頁數* @param rows 每頁大小* @param status 訂單狀態* @return*/ @Override public PageResult<Order> queryOrderList(Integer page, Integer rows, Integer status) {//訂單狀態查詢,需自定義sql//分頁條件try {PageHelper.startPage(page,rows);//獲取用戶idUserInfo userInfo = LoginInterceptor.getLoginUser();//查詢數據Page<Order> pageInfo = (Page<Order>)this.orderMapper.queryOrderList(userInfo.getId(), status);List<Order> orders = pageInfo.getResult();orders.forEach(order -> {Example example = new Example(OrderDetail.class);//查詢該訂單下的所有訂單項example.createCriteria().andEqualTo("orderId",order.getOrderId());//獲取訂單項的具體信息List<OrderDetail> orderDetails = this.orderDetailMapper.selectByExample(example);order.setOrderDetails(orderDetails);});return new PageResult<>(pageInfo.getTotal(),pageInfo.getPages(), orders);} catch (Exception e) {logger.error("查詢訂單出錯",e);return null;} }

基本邏輯:

  • 對結果進行分頁
  • 獲取登錄用戶
  • 根據用戶信息查詢訂單
  • 訂單詳情填充
  • 返回分頁結果

3.3.3、Mapper

訂單的分頁查詢需要根據訂單狀態來篩選,后期要分別對其進行展示,而訂單狀態是在單獨一個表中,要進行分頁查詢的話,只能是tb_order表和tb_order_status兩個表先進行連接,然后對其進行分頁查詢,查詢完畢后再填充訂單詳情。這里用mybatis的xml配置文件方式來進行查詢

對應的mapper.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.leyou.order.mapper.OrderMapper"><resultMap id="orderWithDetail" type="com.leyou.order.pojo.Order" autoMapping="true"><id column="order_id" property="orderId" /><collection property="orderDetails" javaType="List" ofType="com.leyou.order.pojo.OrderDetail" autoMapping="true"><id property="id" column="id" /></collection></resultMap><select id="queryOrderList" resultMap="orderWithDetail">select o.order_id,o.total_pay,o.actual_pay,o.create_time,os.status,od.sku_id,od.num,od.title,od.own_spec,od.price,od.imagefrom tb_order oleft join tb_order_status os on o.order_id = os.order_idleft join tb_order_detail od on o.order_id = od.order_idwhere o.user_id = #{userId}<if test="status != null and status != 0">and os.status = #{status}</if>order by o.create_time desc</select> </mapper>

OrderMapper

/*** 分頁查詢當前用戶訂單* @param userId* @param status* @return*/ List<Order> queryOrderList(@Param("userId")Long userId, @Param("status")Integer status);

3.4、更新訂單狀態

3.4.1、Controller

  • 請求參數:PUT
  • 請求路徑:/order/{id}/{status}
  • 請求參數:
    • id:訂單編號,String類型,不能為空
    • status:訂單狀態,不能為空
  • 返回結果:null
/*** 更新訂單狀態* @param id* @param status* @return*/ @PutMapping("/{id}/{status}") public ResponseEntity<Boolean> updateOrderStatus(@PathVariable("id") Long id,@PathVariable("status") Integer status){Boolean bool = this.orderService.updateOrderStatus(id,status);if (null == bool){//返回400return ResponseEntity.badRequest().build();}//返回204return ResponseEntity.noContent().build(); }

3.4.2、Service

/*** 更新訂單狀態* @param id* @param status* @return*/ Boolean updateOrderStatus(Long id, Integer status);

實現類:

/*** 更新訂單狀態** @param id* @param status* @return*/ @Override public Boolean updateOrderStatus(Long id, Integer status) {OrderStatus orderStatus = new OrderStatus();orderStatus.setOrderId(id);orderStatus.setStatus(status);//根據狀態的不同更新不同的字段switch (status){case 2:orderStatus.setPaymentTime(new Date());//2.付款時間break;case 3:orderStatus.setConsignTime(new Date());//3.發貨時間break;case 4:orderStatus.setEndTime(new Date());//4.確認收貨,訂單結束break;case 5:orderStatus.setCloseTime(new Date());//5.交易失敗,訂單關閉break;case 6:orderStatus.setCommentTime(new Date());//6.評價時間break;default:return null;}return this.orderStatusMapper.updateByPrimaryKeySelective(orderStatus) == 1; }

基本邏輯:

  • 根據用戶id和訂單狀態構造orderStatus對象
  • 根據status的不同判斷是哪一個狀態,然后修改對應的時間
  • 然后返回更新結果

3.5、生成微信支付鏈接

3.5.1、Controller

  • 請求方式:Get
  • 請求路徑:/order/url/{id}
  • 請求參數:id,訂單編號
  • 返回結果:String類型,生成的微信支付鏈接
/*** 根據訂單id生成支付鏈接* @param orderId* @return*/ @GetMapping("/url/{id}") public ResponseEntity<String> generateUrl(@PathVariable("id") Long orderId){//生成付款鏈接String payUrl = this.payHelper.createPayUrl(orderId);if (StringUtils.isBlank(payUrl)){return ResponseEntity.notFound().build();}return ResponseEntity.ok(payUrl); }

3.6、查詢付款狀態

3.6.1、Controller

  • 請求方式: Get
  • 請求路徑: /state/{id}
  • 請求參數: id,訂單編號
  • 返回結果:0, 未支付 1,支付成功 2,支付失敗(查詢失敗,或者訂單過期)
/*** 查詢付款狀態* @param orderId* @return 0, 狀態查詢失敗 1,支付成功 2,支付失敗*/ @GetMapping("/state/{id}") public ResponseEntity<Integer> queryPayState(@PathVariable("id") Long orderId){PayState payState = this.payHelper.queryOrder(orderId);return ResponseEntity.ok(payState.getValue()); }

四、Swagger-UI

4.1、什么是OpenAPI

隨著互聯網技術的發展,現在的網站架構基本都由原來的后端渲染,變成了:前端渲染、前后端分離的形態,而且前端技術和后端技術在各自的道路上越走越遠。 前端和后端的唯一聯系,變成了API接口;API文檔變成了前后端開發人員聯系的紐帶,變得越來越重要。

沒有API文檔工具之前,大家都是手寫API文檔的,在什么地方書寫的都有,而且API文檔沒有統一規范和格式,每個公司都不一樣。這無疑給開發帶來了災難。

OpenAPI規范(OpenAPI Specification 簡稱OAS)是Linux基金會的一個項目,試圖通過定義一種用來描述API格式或API定義的語言,來規范RESTful服務開發過程。目前V3.0版本的OpenAPI規范已經發布并開源在github上 。

官網:https://github.com/OAI/OpenAPI-Specification

4.2、什么是swagger?

OpenAPI是一個編寫API文檔的規范,然而如果手動去編寫OpenAPI規范的文檔,是非常麻煩的。而Swagger就是一個實現了OpenAPI規范的工具集。

官網:https://swagger.io/

看官方的說明:

Swagger包含的工具集:

  • Swagger編輯器: Swagger Editor允許您在瀏覽器中編輯YAML中的OpenAPI規范并實時預覽文檔。
  • Swagger UI: Swagger UI是HTML,Javascript和CSS資產的集合,可以從符合OAS標準的API動態生成漂亮的文檔。
  • **Swagger Codegen:**允許根據OpenAPI規范自動生成API客戶端庫(SDK生成),服務器存根和文檔。
  • **Swagger Parser:**用于解析來自Java的OpenAPI定義的獨立庫
  • **Swagger Core:**與Java相關的庫,用于創建,使用和使用OpenAPI定義
  • Swagger Inspector(免費): API測試工具,可讓您驗證您的API并從現有API生成OpenAPI定義
  • SwaggerHub(免費和商業): API設計和文檔,為使用OpenAPI的團隊構建。

4.3、快速入門

SpringBoot已經集成了Swagger,使用簡單注解即可生成swagger的API文檔。

引入依賴

<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.8.0</version> </dependency> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.8.0</version> </dependency>

編寫配置

@Configuration @EnableSwagger2 public class SwaggerConfig {@Beanpublic Docket api() {return new Docket(DocumentationType.SWAGGER_2).host("localhost:8089").apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.leyou.order.controller")).paths(PathSelectors.any()).build();}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("樂優商城訂單系統").description("樂優商城訂單系統接口文檔").version("1.0").build();} }

接口聲明

在controller的每個handler上添加接口說明注解:

@RestController @RequestMapping("/order") @Api("訂單服務接口") public class OrderController {@Autowiredprivate OrderService orderService;@Autowiredprivate PayHelper payHelper;/*** 創建訂單* @param order 訂單對象* @return 訂單編號*/@PostMapping@ApiOperation(value = "創建訂單的接口,返回訂單編號",notes = "創建訂單")@ApiImplicitParam(name = "order",required = true,value = "訂單的json對象,包含訂單條目和物流信息")@ApiResponses({@ApiResponse(code = 200,message = "購物請求已接受,但是庫存不足"),@ApiResponse(code = 201,message = "訂單成功創建")})public ResponseEntity<Long> createOrder(@RequestBody @Valid Order order){Long id = this.orderService.createOrder(order);return new ResponseEntity<>(id, HttpStatus.CREATED);}/*** 根據訂單id查詢訂單* @param id 訂單編號* @return 訂單對象*/@GetMapping("/{id}")@ApiOperation(value = "根據訂單編號查詢訂單,返回訂單對象",notes = "查詢訂單")@ApiImplicitParam(name = "id",required = true,value = "訂單的編號")@ApiResponses({@ApiResponse(code = 200,message = "訂單查詢成功"),@ApiResponse(code = 404,message = "訂單未找到")})public ResponseEntity<Order> queryOrderById(@PathVariable("id") Long id){Order order = this.orderService.queryOrderById(id);if (order == null){return ResponseEntity.notFound().build();}return ResponseEntity.ok(order);}/*** 分頁查詢當前已經登錄的用戶訂單* @param page 頁數* @param rows 每頁大小* @param status 訂單狀態* @return*/@GetMapping("/list")@ApiOperation(value = "分頁查詢當前用戶訂單,并且可以根據訂單狀態過濾",notes = "分頁查詢當前用戶訂單")@ApiImplicitParams({@ApiImplicitParam(name = "page", value = "當前頁", defaultValue = "1", type = "Integer"),@ApiImplicitParam(name = "rows", value = "每頁大小", defaultValue = "5", type = "Integer"),@ApiImplicitParam(name = "status", value = "訂單狀態:1未付款,2已付款未發貨,3已發貨未確認,4已確認未評價,5交易關閉,6交易成功,已評價", type = "Integer")})@ApiResponses({@ApiResponse(code = 200,message = "訂單的分頁結果"),@ApiResponse(code = 404,message = "沒有查詢到結果"),@ApiResponse(code = 500,message = "查詢失敗")})public ResponseEntity<PageResult<Order>> queryOrderList(@RequestParam(value = "page",defaultValue = "1")Integer page,@RequestParam(value = "rows",defaultValue = "5")Integer rows,@RequestParam(value = "status",required = false)Integer status){PageResult<Order> orders = this.orderService.queryOrderList(page,rows,status);if (null == orders){return new ResponseEntity<>(HttpStatus.NOT_FOUND);}return ResponseEntity.ok(orders);}/*** 更新訂單狀態* @param id* @param status* @return*/@PutMapping("/{id}/{status}")@ApiOperation(value = "根據訂單id更新訂單狀態",notes = "更新訂單狀態")@ApiImplicitParams({@ApiImplicitParam(name = "id",value = "訂單編號",required = true,type = "Long"),@ApiImplicitParam(name = "status",value = "訂單狀態:1未付款,2已付款未發貨,3已發貨未確認,4已確認未評價,5交易關閉,6交易成功,已評價",type = "Integer")})@ApiResponses({@ApiResponse(code = 204,message = "true:修改狀態成功;false:修改狀態失敗"),@ApiResponse(code = 400,message = "請求參數有誤"),@ApiResponse(code = 500,message = "查詢失敗")})public ResponseEntity<Boolean> updateOrderStatus(@PathVariable("id") Long id,@PathVariable("status") Integer status){Boolean bool = this.orderService.updateOrderStatus(id,status);if (null == bool){//返回400return ResponseEntity.badRequest().build();}//返回204return ResponseEntity.noContent().build();}/*** 根據訂單id生成支付鏈接* @param orderId* @return*/@GetMapping("/url/{id}")@ApiOperation(value = "根據訂單編號生成支付鏈接",notes = "生成付款鏈接")@ApiImplicitParam(name = "id",value = "訂單編號",type = "Long")@ApiResponses({@ApiResponse(code = 200,message = "成功生成支付鏈接"),@ApiResponse(code = 404,message = "生成支付鏈接失敗"),@ApiResponse(code = 500,message = "服務器異常")})public ResponseEntity<String> generateUrl(@PathVariable("id") Long orderId){//生成付款鏈接String payUrl = this.payHelper.createPayUrl(orderId);if (StringUtils.isBlank(payUrl)){return ResponseEntity.notFound().build();}return ResponseEntity.ok(payUrl);}/*** 查詢付款狀態* @param orderId* @return 0, 狀態查詢失敗 1,支付成功 2,支付失敗*/@GetMapping("/state/{id}")@ApiOperation(value = "根據訂單編號查詢掃碼支付付款狀態",notes = "查詢付款狀態")@ApiImplicitParam(name = "id",value = "訂單編號",type = "Long")@ApiResponses({@ApiResponse(code = 200,message = "0, 狀態查詢失敗 1,支付成功 2,支付失敗"),@ApiResponse(code = 500,message = "服務器異常")})public ResponseEntity<Integer> queryPayState(@PathVariable("id") Long orderId){PayState payState = this.payHelper.queryOrder(orderId);return ResponseEntity.ok(payState.getValue());} }

常用注解說明:

/**@Api:修飾整個類,描述Controller的作用@ApiOperation:描述一個類的一個方法,或者說一個接口@ApiParam:單個參數描述@ApiModel:用對象來接收參數@ApiProperty:用對象接收參數時,描述對象的一個字段@ApiResponse:HTTP響應其中1個描述@ApiResponses:HTTP響應整體描述@ApiIgnore:使用該注解忽略這個API@ApiError :發生錯誤返回的信息@ApiImplicitParam:一個請求參數@ApiImplicitParams:多個請求參數*/

4.4、啟動測試

4.4.1、錯誤解決

錯誤1

返回401,未授權。因為訂單服務配置了攔截器,來獲取用戶信息,所以會攔截所有訪問該端口的請求,當訪問swagger-ui時直接將請求發送到controller中,導致訪問失敗。

具體看攔截器配置:

這里是攔截了所有請求,這里將該路徑排除攔截即可:

再次訪問http://localhost:8089/swagger-ui.html,不會引發401錯誤了

注意:導致401錯誤還有可能有該注解:@EnableWebMvc

后期在處理Long類型數據以json形式返回時的問題,會配置一個轉換器,要用到這個注解。在進行接口測試時將其注釋掉。

錯誤2

打開瀏覽器查看,可以發現產生這個問題的原因是無法加載swagger的ui文件:

還是因為攔截器的問題,那么過濾掉即可:

錯誤三

打開瀏覽器控制臺查看,還存在一些資源有401錯誤,仔細觀察都是在請求webjars路徑下的資源,攔截器過濾即可:

總結

無法訪問swagger-ui最主要的原因是攔截器的問題:

@Override public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/swagger-ui.html").excludePathPatterns("/swagger-resources/**").excludePathPatterns("/webjars/**"); }

4.4.2、查看接口信息

點擊任意一個接口,即可看到詳細信。

4.5、測試接口

4.5.1、創建訂單接口

可以通過頁面看到接口信息:

  • 請求方式:POST
  • 請求路徑:/order
  • 請求參數:包含訂單、訂單詳情等數據的json對象。
  • 返回結果:訂單編號

點擊Try It Out來測試:

輸入數據:

{"totalPay": 236800,"postFee": 0,"paymentType": 2,"actualPay": 236800,"buyerMessage": null,"buyerNick": "huge","orderDetails": [{"skuId": 3893493,"num": 1,"title": "蘋果(Apple)iPhone 6 (A1586) 16GB 金色 移動聯通電信4G手機3","price": 236800,"ownSpec": "{\"機身顏色\":\"鉆雕藍\",\"內存\":\"4GB\",\"機身存儲\":\"64GB\"}","image": "http://image.leyou.com/images/9/4/1524297342728.jpg"}],"receiver": "銷戶","receiverMobile": "15800000000","receiverState": "上海","receiverCity": "上海","receiverDistrict": "浦東新簽","receiverAddress": "航頭鎮航頭路18號塞上3號樓","receiverZip": "210000","invoiceType": 0,"sourceType":2 }

然后點擊execute:

查看結果:

401 未授權,因為下訂單需要用戶登錄,要攜帶token

通過ApiPost登錄生成token

把token的值手動加入到瀏覽器的cookie中

再次執行

添加成功,響應訂單編號

查看數據庫:

有數據,但是數據不一致,出現了精度損失,后面解決

4.5.2、生成ID的方式

訂單id的特殊性

訂單數據非常龐大,將來一定會做分庫分表。那么這種情況下, 要保證id的唯一,就不能靠數據庫自增,而是自己來實現算法,生成唯一id。

雪花算法

這里的訂單id是通過一個工具類生成的:

而工具類所采用的生成id算法,是由Twitter公司開源的snowflake(雪花)算法。

簡單原理

雪花算法會生成一個64位的二進制數據,為一個Long型。(轉換成字符串后長度最多19) ,其基本結構:

第一位:為未使用

第二部分:41位為毫秒級時間(41位的長度可以使用69年)

第三部分:5位datacenterId和5位workerId(10位的長度最多支持部署1024個節點)

第四部分:最后12位是毫秒內的計數(12位的計數順序號支持每個節點每毫秒產生4096個ID序號)

snowflake生成的ID整體上按照時間自增排序,并且整個分布式系統內不會產生ID碰撞(由datacenter和workerId作區分),并且效率較高。經測試snowflake每秒能夠產生26萬個ID。

使用

需要機器id和序列號:

加載屬性:

@ConfigurationProperties(prefix = "leyou.worker") public class IdWorkerProperties {private long workerId;// 當前機器idprivate long datacenterId;// 序列號public long getWorkerId() {return workerId;}public void setWorkerId(long workerId) {this.workerId = workerId;}public long getDatacenterId() {return datacenterId;}public void setDatacenterId(long datacenterId) {this.datacenterId = datacenterId;} }

編寫配置類:

使用:

4.5.3、查詢訂單接口

接口說明:

  • 請求方式:GET
  • 請求路徑:/order/{id}
  • 請求參數:id,訂單編號
  • 返回結果:Order,訂單的json對象

輸入數據的訂單id,測試:

結果:

4.5.4、更新訂單狀態

  • 請求參數:PUT
  • 請求路徑:/order/{id}/{status}
  • 請求參數:
    • id:訂單編號,String類型,不能為空
    • status:訂單狀態,不能為空
  • 返回結果:null

測試:

結果

數據庫中也發生了改變:

4.5.5、分頁查詢訂單

接口說明:

  • 請求方式:Get
  • 請求路徑:/order/list
  • 請求參數:
    • page:當前頁,Integer類型,默認為1
    • rows:每頁大小,Integer類型,默認為5
    • status:訂單狀態,String類型,默認查詢全部狀態訂單
  • 返回結果:PageResult 對象,包含下面屬性:
    • total:總條數
    • items:當前頁訂單數組
      • 訂單對象

測試

這里status參數未填寫,默認查詢所有訂單

4.5.6、生成微信付款鏈接

接口說明:

  • 請求方式:Get
  • 請求路徑:/order/url/{id}
  • 請求參數:id,訂單編號
  • 返回結果:String類型,生成的微信支付鏈接

測試

結果

微信支付相關

PayHelper支付工具類,PayStatue支付狀態枚舉類

4.5.7、查詢支付狀態

接口說明:

  • 請求方式: Get
  • 請求路徑: /state/{id}
  • 請求參數: id,訂單編號
  • 返回結果:0, 未支付 1,支付成功 2,支付失敗(查詢失敗,或者訂單過期)

未付款查詢

結果

因為尚未付款,所以查詢返回0

已付款查詢

這里打開index.html,輸入生成的微信支付鏈接,會生成一個二維碼:

掃碼支付,然后再次查詢.

這里需要真實付款,就不演示了 0.0,略…

總結

以上是生活随笔為你收集整理的乐优商城(14)–订单服务的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。