springcloud3 Seata实现订单、库存、账户3者之间的分布式事务3
创始人
2025-05-31 07:45:20
0

一 案例操作

1.1 背景说明

本案例的操作是在第1篇关于seta博客的基础上,后续进行操作的。

案例逻辑:这里有3个服务:一个订单服务,一个库存服务,一个账户服务

1.当用户下单时,会在订单服务中创建一个订单,

2.然后通过远程调用库存服务来扣减下单商品的库存,

3.再通过远程调用账户服务来扣减用户账户里面的余额,

4.最后在订单服务中修改订单状态为已完成。

1.2 逻辑流程图

1.3 操作案例

1.3.1 创建库,表

1.seata_order   存储订单数据库

CREATE DATABASE seata_order;
USE seata_order;
CREATE TABLE t_order(id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,user_id BIGINT(11) DEFAULT NULL COMMENT '用户id',product_id BIGINT(11) DEFAULT NULL COMMENT '产品id',count INT(11) DEFAULT NULL COMMENT '数量',money DECIMAL(11,0) DEFAULT NULL COMMENT '金额',status INT(1) DEFAULT NULL COMMENT '订单状态:0创建中,1已完结'
)ENGINE=InnoDB AUTO_INCREMENT=7 CHARSET=utf8;

2.seata_storage   存储库存的数据库

CREATE DATABASE seata_storage;
USE seata_storage;
CREATE TABLE t_storage(id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,product_id BIGINT(11) DEFAULT NULL COMMENT '产品id',total INT(11) DEFAULT NULL COMMENT '总库存',used INT(11) DEFAULT NULL COMMENT '已用库存',residue INT(11) DEFAULT NULL COMMENT '剩余库存'
)ENGINE=InnoDB AUTO_INCREMENT=7 CHARSET=utf8;
INSERT INTO t_storage(id, product_id, total, used, residue) VALUES(1,1,100,0,100);

3.seata_account:存储账户信息的数据库

CREATE DATABASE seata_account;
USE seata_account;
CREATE TABLE t_account(id BIGINT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY ,user_id BIGINT(11) DEFAULT NULL COMMENT '用户id',total DECIMAL(10,0) DEFAULT NULL COMMENT '总额度',used DECIMAL(10,0) DEFAULT NULL COMMENT '已用额度',residue DECIMAL(10,0) DEFAULT 0 COMMENT '剩余可用额度'
)ENGINE=InnoDB AUTO_INCREMENT=7 CHARSET=utf8;
INSERT INTO t_account(id, user_id, total, used, residue) VALUES(1,1,1000,0,1000);

4.undo.log表

在3个库中分别建立对应的回滚日志表undo_log:为各个微服务模块的数据库添加事务回滚表 undo_log ,切记用到的微服务都要创建这张表。

-- the table to store seata xid data
-- 0.7.0+ add context
-- you must to init this sql for you business databese. the seata server not need it.
-- 此脚本必须初始化在你当前的业务数据库中,用于AT 模式XID记录。与server端无关(注:业务数据库)
-- 注意此处0.3.0+ 增加唯一索引 ux_undo_logdrop table if exists `undo_log`;
CREATE TABLE `undo_log` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`branch_id` bigint(20) NOT NULL,`xid` varchar(100) NOT NULL,`context` varchar(128) NOT NULL,`rollback_info` longblob NOT NULL,`log_status` int(11) NOT NULL,`log_created` datetime NOT NULL,`log_modified` datetime NOT NULL,`ext` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

5.最后,查看所建立的表

 1.3.2 新建工程seta-order

 1.pom文件

org.mybatis.spring.bootmybatis-spring-boot-starter1.3.2mysqlmysql-connector-javaorg.springframework.cloudspring-cloud-starter-openfeigncom.alibaba.cloudspring-cloud-starter-alibaba-seataio.seataseata-spring-boot-starterio.seataseata-spring-boot-starter1.4.2com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discoveryorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-actuatororg.apache.commonscommons-lang33.4com.fasterxml.jackson.corejackson-corecom.fasterxml.jackson.corejackson-databindcom.fasterxml.jackson.datatypejackson-datatype-joda2.9.6com.fasterxml.jackson.modulejackson-module-parameter-namescom.github.pagehelperpagehelper-spring-boot-starter1.2.5com.alibabadruid-spring-boot-starter1.1.9org.projectlomboklomboktrue

2.application配置文件

# nacos配置
server:port: 6001spring:datasource:name: mysql_testtype: com.alibaba.druid.pool.DruidDataSource#druid相关配置druid:#监控统计拦截的filtersfilters: statdriver-class-name: com.mysql.jdbc.Driver#基本属性url: jdbc:mysql://127.0.0.1:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=trueusername: rootpassword: cloudiip#配置初始化大小/最小/最大initial-size: 1min-idle: 1max-active: 20#获取连接等待超时时间max-wait: 60000#间隔多久进行一次检测,检测需要关闭的空闲连接time-between-eviction-runs-millis: 60000#一个连接在池中最小生存的时间min-evictable-idle-time-millis: 300000validation-query: SELECT 'x'test-while-idle: truetest-on-borrow: falsetest-on-return: false#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为falsepool-prepared-statements: falsemax-pool-prepared-statement-per-connection-size: 20application:name: seata-order-servercloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址#config:# server-addr: localhost:8848 #Nacos作为配置中心地址#file-extension: yaml #指定yaml格式的配置#group: DEV_GROUP_ljf#namespace: 05573840-fcf3-472d-a64a-c66b4fe878f4alibaba:seata: #设置事务分支 默认就是 my_test_tx_grouptx-service-group: default_tx_group
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.ljf.mscloud.modelconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#pagehelper
pagehelper:helperDialect: mysqlreasonable: truesupportMethodsArguments: trueparams: count=countSqlreturnPageInfo: check
seata:enabled: trueenable-auto-data-source-proxy: truetx-service-group: default_tx_group #此处与上面config.txt中的vgroupMapping一致registry:type: nacosnacos:application: seata-server    #服务name要和nacos中保持一致 默认就是seata-serverserver-addr: 127.0.0.1:8848  #根据自己情况调整username: nacos              #根据自己情况调整password: nacos          #根据自己情况调整cluster: defaultgroup: DEV_GROUP_ljfnamespace: 05573840-fcf3-472d-a64a-c66b4fe878f4  #根据自己情况调整config:type: nacosnacos:server-addr: 127.0.0.1:8848 #根据自己情况调整group: DEV_GROUP_ljfusername: nacos       #根据自己情况调整password: nacos         #根据自己情况调整dataId: seata-server.propertiesnamespace: 05573840-fcf3-472d-a64a-c66b4fe878f4    #根据自己情况调整service:vgroup-mapping:default_tx_group: default
feign:hystrix:enabled: false

3.controller

@RestController
public class OrderController {@Resourceprivate OrderService orderService;@GetMapping("/order/create")public CommonResult create(Order order){orderService.create(order);return new CommonResult(200,"订单创建成功");}}

4.service

1.接口

public interface OrderService {void create(Order order);
}

2.实现类

package com.ljf.mscloud.service.impl;import com.ljf.mscloud.dao.OrderDao;
import com.ljf.mscloud.model.Order;
import com.ljf.mscloud.service.AccountService;
import com.ljf.mscloud.service.OrderService;
import com.ljf.mscloud.service.StorageService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.List;/*** @ClassName: OrderServiceImpl* @Description: TODO* @Author: admin* @Date: 2023/03/01 19:05:06 * @Version: V1.0**/
@Service
@Slf4j
public class OrderServiceImpl  implements OrderService {@Resourceprivate OrderDao orderDao;@Resourceprivate StorageService storageService;@Resourceprivate AccountService accountService;/*** 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态* 简单说:下订单->扣库存->减余额->改状态*/@Override//  @GlobalTransactional(name = "fsp-create-order",rollbackFor = Exception.class)public void create(Order order){log.info("----->开始新建订单");//1 新建订单orderDao.create(order);//2 扣减库存log.info("----->订单微服务开始调用库存,做扣减Count");storageService.decreaseStorage(order.getProductId(),order.getCount());log.info("----->订单微服务开始调用库存,做扣减end");//3 扣减账户log.info("----->订单微服务开始调用账户,做扣减Money");accountService.decreaseAccount(order.getUserId(),order.getMoney());log.info("----->订单微服务开始调用账户,做扣减end");//4 修改订单状态,从零到1,1代表已经完成log.info("----->修改订单状态开始");orderDao.update(order.getUserId(),0);log.info("----->修改订单状态结束");log.info("----->下订单结束了,O(∩_∩)O哈哈~");}
}

3.StorageFeginclient:

@FeignClient(value = "seata-storage-server")
public interface StorageService
{@PostMapping(value = "/storage/decrease")CommonResult decreaseStorage(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);
}

4.AccountFeginClient

@FeignClient(value = "seata-account-server")
public interface AccountService
{@PostMapping(value = "/account/decrease")CommonResult decreaseAccount(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money);
}

5.model

1.order

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order
{private Long id;private Long userId;private Long productId;private Integer count;private BigDecimal money;private Integer status; //订单状态:0:创建中;1:已完结
}

2.commonresult

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult
{private Integer code;private String  message;private T       data;public CommonResult(Integer code, String message){this(code,message,null);}
}

6.mapper

1.dao

@Mapper
public interface OrderDao {//1 新建订单void create(Order order);//2 修改订单状态,从零改为1void update(@Param("userId") Long userId, @Param("status") Integer status);
}

2.mapper



insert into t_order (id,user_id,product_id,count,money,status)values (null,#{userId},#{productId},#{count},#{money},0);update t_order set status = 1where user_id=#{userId} and status = #{status};

 7.启动类

@EnableDiscoveryClient
@SpringBootApplication
@EnableAutoDataSourceProxy
@EnableFeignClients
public class App 
{public static void main( String[] args ){SpringApplication.run(App.class, args);System.out.println("服务启动成功!!!!!!!");}
}

1.3.3 工程seta-storage

1.pom文件

org.mybatis.spring.bootmybatis-spring-boot-starter1.3.2mysqlmysql-connector-javaorg.springframework.cloudspring-cloud-starter-openfeigncom.alibaba.cloudspring-cloud-starter-alibaba-seataio.seataseata-spring-boot-starterio.seataseata-spring-boot-starter1.4.2com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discoveryorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-actuatororg.apache.commonscommons-lang33.4com.fasterxml.jackson.corejackson-corecom.fasterxml.jackson.corejackson-databindcom.fasterxml.jackson.datatypejackson-datatype-joda2.9.6com.fasterxml.jackson.modulejackson-module-parameter-namescom.github.pagehelperpagehelper-spring-boot-starter1.2.5com.alibabadruid-spring-boot-starter1.1.9org.projectlomboklomboktrue

2.application配置文件

# nacos配置
server:port: 6002spring:datasource:name: mysql_testtype: com.alibaba.druid.pool.DruidDataSource#druid相关配置druid:#监控统计拦截的filtersfilters: statdriver-class-name: com.mysql.jdbc.Driver#基本属性url: jdbc:mysql://127.0.0.1:3306/seata_storage?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=trueusername: rootpassword: cloudiip#配置初始化大小/最小/最大initial-size: 1min-idle: 1max-active: 20#获取连接等待超时时间max-wait: 60000#间隔多久进行一次检测,检测需要关闭的空闲连接time-between-eviction-runs-millis: 60000#一个连接在池中最小生存的时间min-evictable-idle-time-millis: 300000validation-query: SELECT 'x'test-while-idle: truetest-on-borrow: falsetest-on-return: false#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为falsepool-prepared-statements: falsemax-pool-prepared-statement-per-connection-size: 20application:name: seata-storage-servercloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址#config:# server-addr: localhost:8848 #Nacos作为配置中心地址#file-extension: yaml #指定yaml格式的配置#group: DEV_GROUP_ljf#namespace: 05573840-fcf3-472d-a64a-c66b4fe878f4alibaba:seata: #设置事务分支 默认就是 my_test_tx_grouptx-service-group: default_tx_group
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.ljf.mscloud.modelconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#pagehelper
pagehelper:helperDialect: mysqlreasonable: truesupportMethodsArguments: trueparams: count=countSqlreturnPageInfo: check
seata:enabled: trueenable-auto-data-source-proxy: truetx-service-group: default_tx_group #此处与上面config.txt中的vgroupMapping一致registry:type: nacosnacos:application: seata-server    #服务name要和nacos中保持一致 默认就是seata-serverserver-addr: 127.0.0.1:8848  #根据自己情况调整username: nacos              #根据自己情况调整password: nacos          #根据自己情况调整cluster: defaultgroup: DEV_GROUP_ljfnamespace: 05573840-fcf3-472d-a64a-c66b4fe878f4  #根据自己情况调整config:type: nacosnacos:server-addr: 127.0.0.1:8848 #根据自己情况调整group: DEV_GROUP_ljfusername: nacos       #根据自己情况调整password: nacos         #根据自己情况调整dataId: seata-server.propertiesnamespace: 05573840-fcf3-472d-a64a-c66b4fe878f4    #根据自己情况调整service:vgroup-mapping:default_tx_group: default
feign:hystrix:enabled: false

3.controller

@RestController
public class StorageController {@Autowiredprivate StorageService storageService;/*** 扣减库存*/@RequestMapping("/storage/decrease")public CommonResult decrease(Long productId, Integer count) {storageService.decrease(productId, count);return new CommonResult(200,"扣减库存成功!");}
}

4.service

public interface StorageService {/*** 扣减库存*/void decrease(Long productId, Integer count);
}

5.dao

@Service
public class StorageServiceImpl implements StorageService {private static final Logger LOGGER = LoggerFactory.getLogger(StorageServiceImpl.class);@Resourceprivate StorageDao storageDao;/*** 扣减库存*/@Overridepublic void decrease(Long productId, Integer count) {LOGGER.info("------->storage-service中扣减库存开始");storageDao.decrease(productId,count);LOGGER.info("------->storage-service中扣减库存结束");}
}
UPDATEt_storageSETused = used + #{count},residue = residue - #{count}WHEREproduct_id = #{productId}

6.model

1.Storage

@Data
public class Storage {private Long id;/*** 产品id*/private Long productId;/*** 总库存*/private Integer total;/*** 已用库存*/private Integer used;/*** 剩余库存*/private Integer residue;
}

2.commonResult

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult
{private Integer code;private String  message;private T       data;public CommonResult(Integer code, String message){this(code,message,null);}
}

7.启动类

@EnableDiscoveryClient
@SpringBootApplication
@EnableAutoDataSourceProxy
@EnableFeignClients
public class App 
{public static void main( String[] args ){SpringApplication.run(App.class, args);System.out.println("服务启动成功!!!!!!!");}
}

1.3.4 工程seta-account

1.pom文件

 org.mybatis.spring.bootmybatis-spring-boot-starter1.3.2mysqlmysql-connector-javaorg.springframework.cloudspring-cloud-starter-openfeigncom.alibaba.cloudspring-cloud-starter-alibaba-seataio.seataseata-spring-boot-starterio.seataseata-spring-boot-starter1.4.2com.alibaba.cloudspring-cloud-starter-alibaba-nacos-discoveryorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-actuatororg.apache.commonscommons-lang33.4com.fasterxml.jackson.corejackson-corecom.fasterxml.jackson.corejackson-databindcom.fasterxml.jackson.datatypejackson-datatype-joda2.9.6com.fasterxml.jackson.modulejackson-module-parameter-namescom.github.pagehelperpagehelper-spring-boot-starter1.2.5com.alibabadruid-spring-boot-starter1.1.9org.projectlomboklomboktrue

2.application配置文件

# nacos配置
server:port: 6003spring:datasource:name: mysql_testtype: com.alibaba.druid.pool.DruidDataSource#druid相关配置druid:#监控统计拦截的filtersfilters: statdriver-class-name: com.mysql.jdbc.Driver#基本属性url: jdbc:mysql://127.0.0.1:3306/seata_account?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=trueusername: rootpassword: cloudiip#配置初始化大小/最小/最大initial-size: 1min-idle: 1max-active: 20#获取连接等待超时时间max-wait: 60000#间隔多久进行一次检测,检测需要关闭的空闲连接time-between-eviction-runs-millis: 60000#一个连接在池中最小生存的时间min-evictable-idle-time-millis: 300000validation-query: SELECT 'x'test-while-idle: truetest-on-borrow: falsetest-on-return: false#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为falsepool-prepared-statements: falsemax-pool-prepared-statement-per-connection-size: 20application:name: seata-account-servercloud:nacos:discovery:server-addr: localhost:8848 #Nacos服务注册中心地址#config:# server-addr: localhost:8848 #Nacos作为配置中心地址#file-extension: yaml #指定yaml格式的配置#group: DEV_GROUP_ljf#namespace: 05573840-fcf3-472d-a64a-c66b4fe878f4alibaba:seata: #设置事务分支 默认就是 my_test_tx_grouptx-service-group: default_tx_group
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.ljf.mscloud.modelconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#pagehelper
pagehelper:helperDialect: mysqlreasonable: truesupportMethodsArguments: trueparams: count=countSqlreturnPageInfo: check
seata:enabled: trueenable-auto-data-source-proxy: truetx-service-group: default_tx_group #此处与上面config.txt中的vgroupMapping一致registry:type: nacosnacos:application: seata-server    #服务name要和nacos中保持一致 默认就是seata-serverserver-addr: 127.0.0.1:8848  #根据自己情况调整username: nacos              #根据自己情况调整password: nacos          #根据自己情况调整cluster: defaultgroup: DEV_GROUP_ljfnamespace: 05573840-fcf3-472d-a64a-c66b4fe878f4  #根据自己情况调整config:type: nacosnacos:server-addr: 127.0.0.1:8848 #根据自己情况调整group: DEV_GROUP_ljfusername: nacos       #根据自己情况调整password: nacos         #根据自己情况调整dataId: seata-server.propertiesnamespace: 05573840-fcf3-472d-a64a-c66b4fe878f4    #根据自己情况调整service:vgroup-mapping:default_tx_group: default
feign:hystrix:enabled: false

3.controller

@RestController
public class AccountController {@ResourceAccountService accountService;/*** 扣减账户余额*/@RequestMapping("/account/decrease")public CommonResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money){accountService.decrease(userId,money);return new CommonResult(200,"扣减账户余额成功!");}
}

4.service

public interface AccountService {/*** 扣减账户余额* @param userId 用户id* @param money 金额*/void decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money);
}
/*** 账户业务实现类* Created by zzyy on 2019/11/11.*/
@Service
public class AccountServiceImpl implements AccountService {private static final Logger LOGGER = LoggerFactory.getLogger(AccountServiceImpl.class);@ResourceAccountDao accountDao;/*** 扣减账户余额*/@Overridepublic void decrease(Long userId, BigDecimal money) {LOGGER.info("------->account-service中扣减账户余额开始");//模拟超时异常,全局事务回滚//暂停几秒钟线程//  try { TimeUnit.SECONDS.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); }accountDao.decrease(userId,money);LOGGER.info("------->account-service中扣减账户余额结束");}
}

5..dao

@Mapper
public interface AccountDao {/*** 扣减账户余额*/void decrease(@Param("userId") Long userId, @Param("money") BigDecimal money);
}

6.model

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {private Long id;/*** 用户id*/private Long userId;/*** 总额度*/private BigDecimal total;/*** 已用额度*/private BigDecimal used;/*** 剩余额度*/private BigDecimal residue;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResult
{private Integer code;private String  message;private T       data;public CommonResult(Integer code, String message){this(code,message,null);}
}

7.启动类

@EnableDiscoveryClient
@SpringBootApplication
@EnableAutoDataSourceProxy
@EnableFeignClients
public class App 
{public static void main( String[] args ){SpringApplication.run(App.class, args);System.out.println("服务启动成功!!!!!!!");}
}

1.4  测试环节

1.4.1 服务启动准备阶段

需求先启动nacos,seata这个两个服务,然后启动工程seata-order,seata-storage,seata-account这3个工程。

1.4.2正常访问阶段

1.查看3张表

2请求访问后 

http://localhost:6001/order/create?userId=001&productId=001&count=1&money=400&status=0

访问后,再次观察3张表,均按照:下订单->扣库存->减余额->改状态 流程执行正确无误。

 

 1.4.3 超时异常,没有加@GlobalTransaction

 1.在账户模块中,模拟超时,延迟20s,再次启动账户模块

 2.再次访问,页面报错

 3.查看这3张表,发现库存表实现了减库存,账户实现了减余额操作,新订单表中也新增了1条订单数据,但是订单状态还是0,订单状态没有完成改变。

 4. 原因在于:调用账户模块超时,导致订单模块发生异常,无法进行最后一步修改订单状态逻辑的执行。

  1.4.4 超时异常,添加@GlobalTransaction

1.在订单模块中,执行方法新增 @GlobalTransaction注解,重启order服务

2.多次刷新后,虽然前端还是报错,只是显示问题不管

http://localhost:6001/order/create?userId=001&productId=001&count=1&money=400&status=0

3.可以查看订单表,库存表,账户表均没有发生改变,说明添加@GlobalTransaction

已经启动作用,分布式事务已经起作用。

相关内容

热门资讯

文言文《师说》原文翻译 文言文《师说》原文翻译  《师说》作于唐贞元十八年(公元802年)韩愈任四门博士时,是说明教师的重要...
细柳营的翻译及原文 细柳营的翻译及原文  上自劳军。至霸上及棘门军,直驰入,将以下骑送迎。已而之细柳军,军士吏被甲,锐兵...
文言文桃花源记翻译 文言文桃花源记翻译  导语:桃花源是一种意境,是一种理想,是一个美梦,是一个精神乐园.未必要苦苦寻求...
《西江月·明月别枝惊鹊》辛弃... 《西江月·明月别枝惊鹊》辛弃疾宋词注释翻译赏析  作品原文  西江月·夜行黄沙道中  辛弃疾  明月...
《鱼我所欲也》《万事莫贵于义... 《鱼我所欲也》《万事莫贵于义》比较阅读  《鱼我所欲也》《万事莫贵于义》比较阅读  【甲】鱼,我所欲...
你是人间的四月天原文 你是人间的四月天原文  黄昏吹着风的软,星子在无意中闪,细雨点洒在花前。下面是小编整理的范文,欢迎查...
读《桃花源记》有感 读《桃花源记》有感(通用15篇)  读完一本名著以后,想必你一定有很多值得分享的心得,是时候抽出时间...
《滕王阁序》全诗及名句赏析 《滕王阁序》全诗及名句赏析  无论是在学校还是在社会中,大家总少不了接触作文吧,通过作文可以把我们那...
描写拿的词语 描写拿的词语  1、撒水拿鱼、鹰拿燕雀、拿班作势  2、拿乔、拿斗、缉拿、拿大  3、一地胡拿、碗里...
小学生学雷锋图画 小学生学雷锋图画  雷锋是平凡的,但也是伟大的,同时也是最高尚的。下面是小学生学雷锋图画,和小编一起...
《史记:滑稽列传》原文及注释 《史记:滑稽列传》原文及注释  一、原文:  淳于髡者,齐之赘婿也。长不满七尺,滑稽多辩,数使诸侯,...
《答谢民师书》苏轼文言文原文... 《答谢民师书》苏轼文言文原文注释翻译  在平凡的学习生活中,相信大家一定都记得文言文吧,文言文是中国...
红楼梦读书感悟 红楼梦读书感悟(精选17篇)  在学习、工作、生活中,总有一些事或人让我们感触颇深,这个时候,写篇关...
兰亭集序朗读带字幕 兰亭集序朗读带字幕  关于《兰亭序》,世间流传着形形色色的逸事趣闻。据说当时王羲之写完之后,对自己这...
易经解读:“田”字的文化意义 易经解读:“田”字的文化意义  “于是始作八卦,以通神明之德,以类万物之情。”所以始作八卦,开始画成...
高考语文文言文常识   高考语文中的文言文阅读往往是同学们答题的难点,高考语文文言文常识。下面是小编搜集整理的2017高...
书戴嵩画牛/杜处士好书画原文... 书戴嵩画牛/杜处士好书画原文、翻译及赏析  书戴嵩画牛/杜处士好书画 宋朝 苏轼  蜀中有杜处士,好...
《将进酒》 读后感 《将进酒》 读后感(精选4篇)  品味完一本名著后,相信大家的收获肯定不少,此时需要认真地做好记录,...
易经:仰则观象于天,俯则观法... 易经:仰则观象于天,俯则观法于地  古者包羲氏之王天下也,仰则观象于天,俯则观法于地,观鸟兽之文与地...
再别康桥全文及赏析 再别康桥全文及赏析  《再别康桥》是现代诗人徐志摩脍炙人口的诗篇,是新月派诗歌的代表作品。以下是小编...