java状态机方案解决订单状态扭转示例详解
作者:德哥很ok 发布时间:2022-01-10 02:55:43
状态机机制
状态机机制是一种常用的解决状态扭转问题的方法,通过定义状态以及状态之间的转移规则来控制状态的流转。对于订单系统,我们可以使用状态机机制来管理订单状态的扭转。
具体来说,我们可以使用状态机框架来实现订单状态的控制,比如使用 Spring State Machine 框架。以下是使用 Spring State Machine 框架来控制订单状态的示例:
定义订单状态
我们可以定义订单的各种状态,如下所示:
javaCopy code
public enum OrderState {
CREATED, // 订单已创建
PAID, // 订单已支付
SHIPPED, // 订单已发货
DELIVERED, // 订单已送达
CANCELED, // 订单已取消
CLOSED // 订单已关闭
}
定义状态机配置
我们需要定义状态机的配置,包括各个状态和状态之间的转移规则,如下所示:
javaCopy code
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderEvent> {
@Override
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
transitions
.withExternal()
.source(OrderState.CREATED).target(OrderState.PAID).event(OrderEvent.PAY)
.and()
.withExternal()
.source(OrderState.PAID).target(OrderState.SHIPPED).event(OrderEvent.SHIP)
.and()
.withExternal()
.source(OrderState.SHIPPED).target(OrderState.DELIVERED).event(OrderEvent.DELIVER)
.and()
.withExternal()
.source(OrderState.CREATED).target(OrderState.CANCELED).event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderState.PAID).target(OrderState.CANCELED).event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderState.SHIPPED).target(OrderState.CANCELED).event(OrderEvent.CANCEL);
}
}
定义事件
我们需要定义各种事件,如支付、发货、取消等事件,如下所示:
javaCopy code
public enum OrderEvent {
PAY, // 支付
SHIP, // 发货
DELIVER, // 送达
CANCEL // 取消
}
创建状态机
我们可以使用状态机工厂来创建状态机,如下所示:
javaCopy code
@Configuration
public class OrderStateMachineFactory {
@Autowired
private StateMachineFactory<OrderState, OrderEvent> stateMachineFactory;
public StateMachine<OrderState, OrderEvent> createStateMachine() {
StateMachine<OrderState, OrderEvent> stateMachine = stateMachineFactory.getStateMachine();
stateMachine.start();
return stateMachine;
}
}
处理状态机事件
当订单发生某种事件时,我们可以使用状态机来处理事件,如下所示:
确定事件:首先,您需要确定可能发生的事件。对于订单状态机,可能的事件可能包括创建订单、付款、取消订单等。
定义状态:然后,您需要定义订单状态。对于订单系统,可能的状态包括待付款、待发货、待收货、已完成、已取消等。
设计状态转换:接下来,您需要设计状态转换,以便在事件发生时自动更改订单状态。例如,当用户完成支付时,订单状态将从待付款转换为待发货。
实现状态机:最后,您需要使用代码实现状态机。在Java中,您可以使用开源库如Spring Statemachine、Squirrel-foundation等来实现状态机。您需要定义状态机的状态、事件和状态转换,以便自动处理订单状态的变化。
以下是一个简单的状态机示例,展示了订单状态的定义和转换:
scssCopy code
public enum OrderState {
CREATED,
PAID,
CANCELLED,
SHIPPED,
COMPLETED
}
public enum OrderEvent {
PAY,
CANCEL,
SHIP,
COMPLETE
}
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
transitions
.withExternal().source(OrderState.CREATED).target(OrderState.PAID).event(OrderEvent.PAY)
.and()
.withExternal().source(OrderState.PAID).target(OrderState.SHIPPED).event(OrderEvent.SHIP)
.and()
.withExternal().source(OrderState.SHIPPED).target(OrderState.COMPLETED).event(OrderEvent.COMPLETE)
.and()
.withExternal().source(OrderState.CREATED).target(OrderState.CANCELLED).event(OrderEvent.CANCEL)
.and()
.withExternal().source(OrderState.PAID).target(OrderState.CANCELLED).event(OrderEvent.CANCEL)
.and()
.withExternal().source(OrderState.SHIPPED).target(OrderState.CANCELLED).event(OrderEvent.CANCEL);
}
public void onPay() {
// 订单支付成功
}
public void onShip() {
// 订单发货
}
public void onComplete() {
// 订单完成
}
public void onCancel() {
// 订单取消
}
在此示例中,我们定义了订单状态(OrderState)和事件(OrderEvent)。然后,我们使用withExternal()方法定义状态转换,并指定源状态、目标状态和触发转换的事件。最后,我们定义了处理不同事件的方法。
当某个事件发生时,状态机会自动触发状态转换,并调用相应的事件处理方法,从而更改订单状态。
如果需要实现一个高可用的状态机,可以考虑使用分布式状态机,例如使用 ZooKeeper 或 etcd 实现分布式协同。在这种情况下,每个节点都可以处理事件并更新状态,节点之间可以通过协同算法保持一致性。这种方式可以保证状态机的可靠性和高可用性,但需要考虑一些复杂性,例如如何处理网络分区和节点故障等问题。
好的,下面是一个使用 ZooKeeper 实现分布式状态机的示例:
首先,需要引入 ZooKeeper 的 Java 客户端库:
xmlCopy code
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.3</version>
</dependency>
在代码中创建 ZooKeeper 客户端:
javaCopy code
public class ZooKeeperClient {
private static final String CONNECTION_STRING = "localhost:2181";
private static final int SESSION_TIMEOUT_MS = 5000;
private static final int CONNECT_TIMEOUT_MS = 5000;
private static final String BASE_PATH = "/order-state";
private final ZooKeeper zooKeeper;
public ZooKeeperClient() throws IOException {
this.zooKeeper = new ZooKeeper(CONNECTION_STRING, SESSION_TIMEOUT_MS, new Watcher() {
@Override
public void process(WatchedEvent event) {
// handle event
}
});
}
public void close() throws InterruptedException {
zooKeeper.close();
}
public String createNode(String path, byte[] data) throws KeeperException, InterruptedException {
return zooKeeper.create(BASE_PATH + path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
}
public byte[] getData(String path) throws KeeperException, InterruptedException {
return zooKeeper.getData(BASE_PATH + path, false, null);
}
public void setData(String path, byte[] data) throws KeeperException, InterruptedException {
zooKeeper.setData(BASE_PATH + path, data, -1);
}
public void deleteNode(String path) throws KeeperException, InterruptedException {
zooKeeper.delete(BASE_PATH + path, -1);
}
}
这个类封装了 ZooKeeper 客户端的一些基本操作,例如创建节点、获取数据、更新数据和删除节点等。
创建一个订单状态机
javaCopy code
public class OrderStateMachine {
private final ZooKeeperClient client;
private final String orderId;
private final Map<OrderState, Set<OrderState>> transitions;
private OrderState currentState;
public OrderStateMachine(ZooKeeperClient client, String orderId) {
this.client = client;
this.orderId = orderId;
this.transitions = new HashMap<>();
this.currentState = OrderState.CREATED;
// Define transitions
transitions.put(OrderState.CREATED, EnumSet.of(OrderState.PAYED, OrderState.CANCELED));
transitions.put(OrderState.PAYED, EnumSet.of(OrderState.SHIPPED, OrderState.CANCELED));
transitions.put(OrderState.SHIPPED, EnumSet.of(OrderState.DELIVERED, OrderState.CANCELED));
transitions.put(OrderState.DELIVERED, EnumSet.noneOf(OrderState.class));
transitions.put(OrderState.CANCELED, EnumSet.noneOf(OrderState.class));
// Initialize state
try {
byte[] data = client.getData(orderId);
if (data != null) {
this.currentState = OrderState.valueOf(new String(data));
}
} catch (Exception e) {
// Handle exception
}
}
public synchronized void handleEvent(OrderEvent event) {
Set<OrderState> validTransitions = transitions.get(currentState);
if (validTransitions != null && validTransitions.contains(event.getTargetState())) {
try {
// Update state in ZooKeeper
client.setData(orderId, event.getTargetState().name().getBytes());
// Update local state
currentState = event.getTargetState();
} catch (Exception e) {
// Handle exception
}
创建订单状态机的过程可以分为以下几个步骤:
确定状态和事件
首先,需要确定订单状态和可能触发的事件。对于一个简单的订单系统,可能的状态和事件如下:
订单已创建(CREATED)支付(PAY)取消(CANCEL)
订单已支付(PAID)发货(SHIP)取消(CANCEL)
订单已发货(SHIPPED)确认收货(RECEIVE)取消(CANCEL)
订单已完成(RECEIVED)
设计状态转移图
然后,根据状态和事件,设计状态转移图。状态转移图用于表示状态之间的转换关系,以及何时触发转换。
下图是一个简单的订单状态转移图:
luaCopy code
+-------+
| |
| 待支付 +---------+
| | |
+-------+ |
| |
| |
v |
+-------+ |
| | |
| 已支付 +------+ |
| | | |
+-------+ | |
| | |
| | |
v | |
+-------+ | |
| | | |
| 已发货 +------+ |
| | |
+-------+ |
| |
| |
v |
+-------+ |
| | |
| 已收货 | <---------+
| |
+-------+
在状态转移图中,每个圆圈代表一个状态,每个箭头代表一条转移。箭头上标注的是触发转移的事件。
实现状态机
最后,使用代码实现状态机。具体实现方式可能因编程语言和状态机库而异,这里以 Java 和 Spring 状态机为例:
scssCopy code
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderStatus, OrderEvent> {
@Override
public void configure(StateMachineStateConfigurer<OrderStatus, OrderEvent> states) throws Exception {
states.withStates()
.initial(OrderStatus.CREATED)
.states(EnumSet.allOf(OrderStatus.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderEvent> transitions) throws Exception {
transitions
.withExternal()
.source(OrderStatus.CREATED).target(OrderStatus.PAID).event(OrderEvent.PAY)
.and()
.withExternal()
.source(OrderStatus.PAID).target(OrderStatus.SHIPPED).event(OrderEvent.SHIP)
.and()
.withExternal()
.source(OrderStatus.SHIPPED).target(OrderStatus.RECEIVED).event(OrderEvent.RECEIVE)
.and()
.withExternal()
.source(OrderStatus.CREATED).target(OrderStatus.CANCELED).event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderStatus.PAID).target(OrderStatus.CANCELED).event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderStatus.SHIPPED).target(OrderStatus.CANCELED).event(OrderEvent.CANCEL);
}
}
以下是一个基于 Java 和 Spring 状态机的订单状态机的代码示例:
javaCopy code@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderStatus, OrderEvent> {
@Autowired
private OrderStateChangeInterceptor orderStateChangeInterceptor;
@Override
public void configure(StateMachineConfigurationConfigurer<OrderStatus, OrderEvent> config) throws Exception {
config
.withConfiguration()
.autoStartup(true)
.listener(orderStateChangeInterceptor);
}
@Override
public void configure(StateMachineStateConfigurer<OrderStatus, OrderEvent> states) throws Exception {
states
.withStates()
.initial(OrderStatus.CREATED)
.state(OrderStatus.PAID)
.state(OrderStatus.CONFIRMED)
.state(OrderStatus.SHIPPED)
.state(OrderStatus.DELIVERED)
.end(OrderStatus.COMPLETED)
.end(OrderStatus.CANCELED);
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderEvent> transitions) throws Exception {
transitions
.withExternal()
.source(OrderStatus.CREATED)
.target(OrderStatus.PAID)
.event(OrderEvent.PAY)
.and()
.withExternal()
.source(OrderStatus.PAID)
.target(OrderStatus.CONFIRMED)
.event(OrderEvent.CONFIRM)
.and()
.withExternal()
.source(OrderStatus.CONFIRMED)
.target(OrderStatus.SHIPPED)
.event(OrderEvent.SHIP)
.and()
.withExternal()
.source(OrderStatus.SHIPPED)
.target(OrderStatus.DELIVERED)
.event(OrderEvent.DELIVER)
.and()
.withExternal()
.source(OrderStatus.DELIVERED)
.target(OrderStatus.COMPLETED)
.event(OrderEvent.COMPLETE)
.and()
.withExternal()
.source(OrderStatus.CREATED)
.target(OrderStatus.CANCELED)
.event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderStatus.PAID)
.target(OrderStatus.CANCELED)
.event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderStatus.CONFIRMED)
.target(OrderStatus.CANCELED)
.event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderStatus.SHIPPED)
.target(OrderStatus.CANCELED)
.event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderStatus.DELIVERED)
.target(OrderStatus.CANCELED)
.event(OrderEvent.CANCEL);
}
}
在这个示例中,我们定义了订单状态机的状态和事件。在 configure(
StateMachineConfigurationConfigurer<OrderStatus, OrderEvent> config) 方法中,我们配置了状态机的启动和事件 * 。在 configure(StateMachineStateConfigurer<OrderStatus, OrderEvent> states) 方法中,我们定义了订单状态机的状态。在 configure(StateMachineTransitionConfigurer<OrderStatus, OrderEvent> transitions) 方法中,我们定义了状态机的事件和状态之间的转换。在 source 中指定起始状态,在 target 中指定目标状态,在 event 中指定事件。
最后,我们还需要创建一个状态机事件 * ,用于在状态机状态转换时执行自定义逻辑,比如修改订单状态、记录状态转换日志等。下面是
以下是一个简单的状态机事件 * 的代码示例:
javaCopy codepublic class OrderStateChangeInterceptor extends StateMachineInterceptorAdapter<OrderStatus, OrderStatusChangeEvent> {
@Override
public void preStateChange(State<OrderStatus, OrderStatusChangeEvent> state, Message<OrderStatusChangeEvent> message, Transition<OrderStatus, OrderStatusChangeEvent> transition, StateMachine<OrderStatus, OrderStatusChangeEvent> stateMachine) {
// 根据状态转移情况更新订单状态
if (transition.getTarget().getId() == OrderStatus.PAID) {
// 更新订单为已支付状态
updateOrderStatus(message.getHeaders().get("orderId"), OrderStatus.PAID);
} else if (transition.getTarget().getId() == OrderStatus.CANCELED) {
// 更新订单为已取消状态
updateOrderStatus(message.getHeaders().get("orderId"), OrderStatus.CANCELED);
}
// 记录状态转移日志
recordStateChangeLog(message.getHeaders().get("orderId"), transition.getSource().getId(), transition.getTarget().getId());
}
private void updateOrderStatus(String orderId, OrderStatus status) {
// 执行更新订单状态的业务逻辑
}
private void recordStateChangeLog(String orderId, OrderStatus fromStatus, OrderStatus toStatus) {
// 记录状态转移日志的业务逻辑
}
}
在 * 的 preStateChange 方法中,我们可以根据状态转移情况执行自定义的业务逻辑,比如更新订单状态、记录状态转移日志等。在这个示例中,我们根据状态转移目标状态更新订单状态,并记录状态转移日志。在具体业务实现中,我们可以根据需要扩展 * 的逻辑。
完整的状态机实现和 * 代码示例如下:
javaCopy code
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderState, OrderEvent> {
@Autowired
private OrderService orderService;
@Override
public void configure(StateMachineConfigurationConfigurer<OrderState, OrderEvent> config) throws Exception {
config
.withConfiguration()
.autoStartup(true)
.listener(new StateMachineListenerAdapter<OrderState, OrderEvent>() {
@Override
public void stateChanged(State<OrderState, OrderEvent> from, State<OrderState, OrderEvent> to) {
log.info("Order status changed from {} to {}", from.getId(), to.getId());
}
});
}
@Override
public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {
states
.withStates()
.initial(OrderState.SUBMITTED)
.state(OrderState.PAID)
.state(OrderState.FULFILLED)
.state(OrderState.CANCELLED)
.end(OrderState.COMPLETED);
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
transitions
.withExternal()
.source(OrderState.SUBMITTED).target(OrderState.PAID).event(OrderEvent.PAY)
.and()
.withExternal()
.source(OrderState.PAID).target(OrderState.FULFILLED).event(OrderEvent.FULFILL)
.and()
.withExternal()
.source(OrderState.SUBMITTED).target(OrderState.CANCELLED).event(OrderEvent.CANCEL)
.and()
.withExternal()
.source(OrderState.PAID).target(OrderState.CANCELLED).event(OrderEvent.CANCEL);
}
@Bean
public StateMachineInterceptor<OrderState, OrderEvent> stateMachineInterceptor() {
return new StateMachineInterceptorAdapter<OrderState, OrderEvent>() {
@Override
public void preStateChange(State<OrderState, OrderEvent> state, Message<OrderEvent> message, Transition<OrderState, OrderEvent> transition, StateMachine<OrderState, OrderEvent> stateMachine) {
OrderState targetState = transition.getTarget().getId();
Order order = stateMachine.getExtendedState().get("order", Order.class);
if (order != null) {
order.setState(targetState);
orderService.updateOrder(order);
log.info("Order status updated to {}", targetState);
log.info("Record order state change log, from {} to {}", state.getId(), targetState);
}
}
};
}
@Override
public void configure(StateMachineInterceptorConfigurer<OrderState, OrderEvent> interceptors) throws Exception {
interceptors
.withInterceptor(stateMachineInterceptor())
.order(-1);
}
}
在上述示例中,我们创建了一个 Spring 状态机,并定义了四个订单状态:SUBMITTED、PAID、FULFILLED 和 CANCELLED。我们还定义了三个状态转移事件:PAY、FULFILL 和 CANCEL。
我们在 * 的 preStateChange 方法中,根据状态转移目标状态更新订单状态,并记录状态转移日志。在具体业务实现中,我们可以根据需要扩展 * 的逻辑。
好的,我们可以在 * 的 preStateChange 方法中,根据状态转移目标状态更新订单状态,并记录状态转移日志。在具体业务实现中,我们可以根据需要扩展 * 的逻辑。以下是示例代码:
javaCopy code@Component
public class OrderStateChangeInterceptor extends StateMachineInterceptorAdapter<OrderStates, OrderEvents> {
@Autowired
private OrderService orderService;
@Override
public void preStateChange(State<OrderStates, OrderEvents> state, Message<OrderEvents> message, Transition<OrderStates, OrderEvents> transition, StateMachine<OrderStates, OrderEvents> stateMachine) {
// 获取订单号
String orderId = message.getHeaders().get(OrderConstant.ORDER_ID_HEADER, String.class);
// 获取目标状态
OrderStates targetState = transition.getTarget().getId();
// 更新订单状态
orderService.updateOrderStatus(orderId, targetState);
// 记录状态转移日志
orderService.saveOrderLog(orderId, targetState);
}
}
在上述示例中,我们通过 OrderService 来更新订单状态和保存状态转移日志。具体的实现可以根据业务需求自行实现。
然后,我们需要将 * 配置到状态机中,如下所示:
javaCopy code@Configuration
@EnableStateMachine
public class StateMachineConfig extends StateMachineConfigurerAdapter<OrderStates, OrderEvents> {
// ... 状态机配置代码 ...
@Autowired
private OrderStateChangeInterceptor orderStateChangeInterceptor;
@Override
public void configure(StateMachineInterceptorConfigurer<OrderStates, OrderEvents> configurer) throws Exception {
configurer
.withInterceptor(orderStateChangeInterceptor);
}
}
在上述示例中,我们将 * 通过 withInterceptor 方法添加到状态机中。这样,在状态转移时,就会触发 * 中的 preStateChange 方法,从而执行自定义的业务逻辑。
是的,当状态机执行状态转移时,会调用 * 中的 preStateChange 方法,从而执行自定义的业务逻辑。 * 可以在状态转移前后执行逻辑,比如记录日志、更新状态等,从而实现状态机的扩展。在具体的业务场景中,我们可以根据需要扩展 * 的逻辑,以满足具体的需求。
需要注意的是, * 中的业务逻辑应该尽量简单,不要耗时过长,以避免影响状态转移的性能。同时, * 中的逻辑也应该考虑异常情况的处理,比如事务回滚、异常记录等。
总的来说,状态机是一种非常强大的工具,可以用于实现复杂的业务逻辑。在实际应用中,我们应该根据具体的业务场景选择合适的状态机库,并结合 * 、事件等机制,以实现状态机的灵活性和可扩展性。
来源:https://juejin.cn/post/7207410405786255420
猜你喜欢
- 我们在编写Web应用时,经常需要对页面做一些安全控制,比如:对于没有访问权限的用户需要转到登录表单页面。要实现访问控制的方法多种多样,可以通
- 目录了解程序集如何在C#.NET中加载程序集,模块和引用.NET中的程序集绑定绑定重定向当问题开始发生时故障排除边注References了解
- 目录SpringBoot 配置文件加密编码其他SpringBoot 配置文件加密本章将对SpringBoot配置文件中的数据加密做自定义开发
- 一、简介   Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布
- Java去掉指定字符串的开头的指定字符/** * 去掉指定字符串的开头的指定字符 *
- 1. 需求和思路最近要用java制作一个数据集,每一行是一个样本,格式是csv。用了一下java类的相关概念,把csv文件里的每一行,即每一
- 1. 开方:Math.sqrt(x);2. x的a方:Math.pow(x,a);3. 绝对值:Math.abs(x);4. BigInte
- 1.重载重载指在一个类中,具有多个相同名称的方法,他们的参数列表却不相同(参数类型不同、参数个数不同甚至是参数顺序不同)重载对返回类型没有要
- 一、前言之前介绍了JMeter engine启动原理,但是里面涉及到HashTree这个类结构没有给大家详细介绍,这边文章就详细介绍JMet
- 简介MapStruct 是一个代码生成器(可以生成对象映射转换的代码),它基于约定优于配置的方法,极大地简化了 Java bean 类型之间
- 1 前言前文已经讲述了Spring BeanFactory 与 FactoryBean 的区别详情,
- MyBatis核心配置文件<?xml version="1.0" encoding="UTF-8&quo
- 本文实例讲述了Java实现特定范围的完数输出算法。分享给大家供大家参考,具体如下:题目内容:一个正整数的因子是所有可以整除它的正整数。而一个
- 本文实例讲述了Java线程之守护线程(Daemon)用法。分享给大家供大家参考。具体如下:守护线程(Daemon)Java有两种Thread
- 一、方法的定义1.方法体中最后返回值可以使用return, 如果使用了return, 那么方法体的返回值类型一定要指定2.如果方法体重没有r
- 今天给大家介绍一下Java实现钢琴的小程序,程序虽小,功能挺多,支持循环播放,录音等功能,首先简单介绍下源码结构:先看看钢琴界面实现,添加相
- String类基本概念String类属于引用数据类型,不属于基本数据类型。在Java中只要是" "(双引号)中的,都是S
- 项目中经常会使用到一对多的查询场景,但是PageHelper对这种嵌套查询的支持不够,如果是一对多的列表查询,返回的分页结果是不对的参考Gi
- RabbitMQ的示例,涉及到Direct、Fanout、Topic和Headers交换机以及普通队列、延迟队列和死信队列在pom.xml文
- 将JavaDoc 注释 生成API文档1. 打开java代码,编写JavaDoc 注释,只有按照java的规范编写注释,才能很好的生成API