day17_订单(结算,提交订单,支付页,立即购买,我的订单)

文章目录

  • 订单模块
  • 1 结算
    • 1.1 需求说明
    • 1.2 获取用户地址
      • 1.2.1 UserAddress
      • 1.2.2 UserAddressController
      • 1.2.3 UserAddressService
      • 1.2.4 UserAddressMapper
      • 1.2.5 UserAddressMapper.xml
    • 1.3 获取购物项数据
      • 1.3.1 CartController
      • 1.3.2 CartService
      • 1.3.3 openFeign接口定义
    • 1.4 环境搭建(service-order)
    • 1.5 后端结算业务接口开发
      • 1.5.1 TradeVo
      • 1.5.2 OrderItem
      • 1.5.3 OrderInfoController
      • 1.5.4 OrderInfoService
      • 1.5.5 服务网关
    • 1.6 openFeign拦截器使用
      • 1.6.1 问题说明
      • 1.6.2 问题解决
  • 2 提交订单
    • 2.1 需求说明
    • 2.2 后端接口
      • 2.2.1 查询用户地址
        • 业务接口开发
          • UserAddressController
          • UserAddressService
          • UserAddressMapper
          • UserAddressMapper.xml
        • openFeign接口开发
      • 2.2.2 业务接口开发
        • OrderInfoDto
        • OrderLog
        • OrderInfoController
        • OrderInfoService
        • Mapper接口
          • OrderInfoMapper
          • OrderItemMapper
          • OrderLogMapper
        • XML映射文件
          • OrderInfoMapper.xml
          • OrderItemMapper.xml
          • OrderLogMapper.xml
      • 2.2.3 清空购物车
        • service-cart
          • CartController
          • CartService
        • openFeign接口
        • service-order
  • 3 支付页
    • 3.1 需求说明
    • 3.2 后端接口
      • 3.2.1 OrderInfoController
      • 3.2.2 OrderInfoService
      • 3.2.3 OrderInfoMapper
      • 3.2.4 OrderInfoMapper.xml
  • 4 立即购买
    • 4.1 需求说明
    • 4.2 后端接口
      • 4.2.1 OrderInfoController
      • 4.2.2 OrderInfoService
  • 5 我的订单
    • 5.1 需求说明
    • 5.2 后端接口
      • 5.2.1 OrderInfoController
      • 5.2.2 OrderInfoService
      • 5.2.3 OrderInfoMapper
      • 5.2.4 OrderInfoMapper.xml
      • 5.2.5 OrderInfo
      • 5.2.6 OrderItemMapper.xml
      • 5.2.7 OrderItemMapper
      • 5.2.4 OrderInfoMapper.xml
      • 5.2.5 OrderInfo
      • 5.2.6 OrderItemMapper.xml
      • 5.2.7 OrderItemMapper

订单模块

1 结算

1.1 需求说明

入口:购物车点击去结算按钮 ,进入结算页面(订单确认页面),如图所示:

在这里插入图片描述

分析页面需要的数据:

1、 用户地址信息列表,结算页选中默认地址

2、 购物车中选择的商品列表,及商品的总金额

查看接口文档:

获取用户地址信息列表接口地址及返回结果:

get /api/user/userAddress/auth/findUserAddressList
返回结果:
{
    "code": 200,
    "message": "操作成功",
    "data": [
        {
            "id": 1,
            "createTime": "2023-05-12 17:50:41",
            "updateTime": "2023-06-02 19:15:17",
            "isDeleted": 0,
            "userId": 1,
            "name": "晴天",
            "phone": "15014526352",
            "tagName": "家",
            "provinceCode": "110000",
            "cityCode": "110100",
            "districtCode": "110114",
            "address": "天通苑大街1号",
            "fullAddress": "北京市北京市昌平区天通苑大街1号",
            "isDefault": 0
        },
        ...
    ]
}

结算接口地址及返回结果:

get api/order/orderInfo/auth/trade
返回结果:
{
    "code": 200,
    "message": "操作成功",
    "data": {
        "totalAmount": 6997.00,
        "orderItemList": [
            {
                "skuId": 1,
                "skuName": "小米 红米Note10 5G手机 颜色:白色 内存:8G",
                "thumbImg": "http://139.198.127.41:9000/spzx/20230525/665832167-5_u_1 (1).jpg",
                "skuPrice": 1999.00,
                "skuNum": 2
            },
            ...
        ]
    }
} 

获取用户地址列表调用流程如下所示:

在这里插入图片描述

获取购物车中选中的商品列表调用流程如下所示:

在这里插入图片描述

1.2 获取用户地址

在service-user模块中开发一个获取地址列表接口,供service-order微服务进行调用。

1.2.1 UserAddress

针对当前要操作的数据定义一个与之对应的实体类:

//com.atguigu.spzx.model.entity.user;
@Data
@Schema(description = "用户地址实体类")
public class UserAddress extends BaseEntity {

   private static final long serialVersionUID = 1L;

   @Schema(description = "用户ID")
   private Long userId;

   @Schema(description = "name")
   private String name;

   @Schema(description = "电话")
   private String phone;

   @Schema(description = "标签名称")
   private String tagName;

   @Schema(description = "provinceCode")
   private String provinceCode;

   @Schema(description = "cityCode")
   private String cityCode;

   @Schema(description = "districtCode")
   private String districtCode;

   @Schema(description = "详细地址")
   private String address;

   @Schema(description = "完整地址")
   private String fullAddress;

   @Schema(description = "是否默认地址(0:否 1:是)")
   private Integer isDefault;

}

1.2.2 UserAddressController

表现层代码:

// com.atguigu.spzx.user.controller;
@Tag(name = "用户地址接口")
@RestController
@RequestMapping(value="/api/user/userAddress")
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserAddressController {
   
   @Autowired
   private UserAddressService userAddressService;

   @Operation(summary = "获取用户地址列表")
   @GetMapping("auth/findUserAddressList")
   public Result<List<UserAddress>> findUserAddressList() {
      List<UserAddress> list = userAddressService.findUserAddressList();
      return Result.build(list , ResultCodeEnum.SUCCESS) ;
   }
}

1.2.3 UserAddressService

业务层代码实现:

//业务接口
public interface UserAddressService {

    List<UserAddress> findUserAddressList();
}

//业务接口实现
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class UserAddressServiceImpl implements UserAddressService {

   @Autowired
   private UserAddressMapper userAddressMapper;

   @Override
   public List<UserAddress> findUserAddressList() {
      Long userId = AuthContextUtil.getUserInfo().getId();
      return userAddressMapper.findByUserId(userId);
   }
}

1.2.4 UserAddressMapper

持久层代码实现:

@Mapper
public interface UserAddressMapper {

    List<UserAddress> findByUserId(Long userId);
}

1.2.5 UserAddressMapper.xml

在映射文件中定义对应的sql语句:

<?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.atguigu.spzx.user.mapper.UserAddressMapper">

   <resultMap id="userAddressMap" type="com.atguigu.spzx.model.entity.user.UserAddress" autoMapping="true">
   </resultMap>
   
   <!-- 用于select查询公用抽取的列 -->
   <sql id="columns">
      id,user_id,name,phone,tag_name,province_code,city_code,district_code,address,full_address,is_default,create_time,update_time,is_deleted
   </sql>

   <select id="findByUserId" resultMap="userAddressMap">
      select <include refid="columns" />
      from user_address
      where
      user_id = #{userId}
   </select>
</mapper>

启动服务进行测试。

1.3 获取购物项数据

在service-cart微服务中开发一个接口,获取当前登录用户选中的购物项列表数据,如下所示:

1.3.1 CartController

表现层接口:

@Operation(summary="选中的购物车")
@GetMapping(value = "/auth/getAllCkecked")
public Result<List<CartInfo>> getAllCkecked() {
    List<CartInfo> cartInfoList = cartService.getAllCkecked() ;
    return Result.build(cartInfoList , ResultCodeEnum.SUCCESS) ;
}

1.3.2 CartService

业务层接口:

// 业务接口
List<CartInfo> getAllCkecked();

// 业务接口实现类
@Override
public List<CartInfo> getAllCkecked() {
    Long userId = AuthContextUtil.getUserInfo().getId();
    String cartKey = getCartKey(userId);
    List<Object> objectList = redisTemplate.opsForHash().values(cartKey);       // 获取所有的购物项数据
    if(!CollectionUtils.isEmpty(objectList)) {
        List<CartInfo> cartInfoList = objectList.stream().map(cartInfoJSON -> JSON.parseObject(cartInfoJSON.toString(), CartInfo.class))
            .filter(cartInfo -> cartInfo.getIsChecked() == 1)
            .collect(Collectors.toList());
        return cartInfoList ;
    }
    return new ArrayList<>() ;
}

1.3.3 openFeign接口定义

步骤:

1、在spzx-service-client模块下创建一个service-cart-client的子模块

2、在service-cart-client模块下定义远程openFeign接口

// com.atguigu.spzx.feign.cart;
@FeignClient(value = "service-cart" , fallback = CartFeignClientFallback.class)
public interface CartFeignClient {

    @GetMapping(value = "/api/order/cart/auth/getAllCkecked")
    public abstract Result<List<CartInfo>> getAllCkecked() ;

}


// com.atguigu.spzx.feign.cart.fallback;
@Slf4j
public class CartFeignClientFallback implements CartFeignClient {

    @Override
    public Result<List<CartInfo>> getAllCkecked() {
        log.info("CartFeignClientFallback...getAllCkecked的方法执行了");
        return Result.build(null , ResultCodeEnum.SUCCESS) ;
    }
}

3、降级类自动化配置

在resources目录下创建一个MATE-INF/spring文件夹,在该文件夹下创建一个

org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,文件的中的内容如下所示:

com.atguigu.spzx.feign.cart.fallback.CartFeignClientFallback

1.4 环境搭建(service-order)

步骤:

1、在spzx-service模块下创建一个service-order微服务,并加入如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、准备application.yml、application-dev.yml、logback-spring.xml、mybatis-config.xml文件。文件内容如下所示:

server:
  port: 8514

spring:
  application:
    name: service-order
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.136.142:8848
    sentinel:
      transport:
        dashboard: localhost:8080
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.136.142:3306/db_spzx?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=true
    username: root
    password: 1234
  data:
    redis:
      host: 192.168.136.142
      port: 6379
      password: 1234

mybatis:
  config-location: classpath:mybatis-config.xml
  mapper-locations: classpath:mapper/*/*.xml
feign:
  sentinel:
    enabled: true

logback-spring.xml修改输出路径:

<property name="log.path" value="D://work//service-order//logs" />

mybatis-config.xml:从之前的模块中进行复制

3、创建启动类

//  com.atguigu.spzx.order;
@SpringBootApplication
@EnableFeignClients(basePackages = {
        "com.atguigu.spzx.feign.cart"
})
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class , args) ;
    }

}

1.5 后端结算业务接口开发

操作模块:service-order

1.5.1 TradeVo

定义一个实体类用来封装结算的参数(根据接口文档进行定义),具体定义如下所示

// com.atguigu.spzx.model.vo.h5
@Data
@Schema(description = "结算实体类")
public class TradeVo {

    @Schema(description = "结算总金额")
    private BigDecimal totalAmount;

    @Schema(description = "结算商品列表")
    private List<OrderItem> orderItemList;

}

1.5.2 OrderItem

定义一个与数据库表相对应的实体类,封装订单明细数据:

 // com.atguigu.spzx.model.entity.order
@Data
@Schema(description = "订单项实体类")
public class OrderItem extends BaseEntity {

   private static final long serialVersionUID = 1L;

   @Schema(description = "订单id")
   private Long orderId;

   @Schema(description = "商品sku编号")
   private Long skuId;

   @Schema(description = "商品sku名字")
   private String skuName;

   @Schema(description = "商品sku图片")
   private String thumbImg;

   @Schema(description = "商品sku价格")
   private BigDecimal skuPrice;

   @Schema(description = "商品购买的数量")
   private Integer skuNum;

}

1.5.3 OrderInfoController

业务层代码实现:

@Tag(name = "订单管理")
@RestController
@RequestMapping(value="/api/order/orderInfo")
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderInfoController {
   
   @Autowired
   private OrderInfoService orderInfoService;

   @Operation(summary = "确认下单")
   @GetMapping("auth/trade")
   public Result<TradeVo> trade() {
      TradeVo tradeVo = orderInfoService.getTrade();
      return Result.build(tradeVo, ResultCodeEnum.SUCCESS);
   }

}

1.5.4 OrderInfoService

业务层代码实现:

//业务接口
public interface OrderInfoService {
    TradeVo getTrade();
}

//业务接口实现
// com.atguigu.spzx.order.service.impl;
@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Autowired
    private CartFeignClient cartFeignClient ;

    @Override
    public TradeVo getTrade() {

        // 获取当前登录的用户的id
        Long userId = AuthContextUtil.getUserInfo().getId();

        // 获取选中的购物项列表数据
        List<CartInfo> cartInfoList = cartFeignClient.getAllCkecked().getData() ;
        List<OrderItem> orderItemList = new ArrayList<>();
        for (CartInfo cartInfo : cartInfoList) {        // 将购物项数据转换成功订单明细数据
            OrderItem orderItem = new OrderItem();
            orderItem.setSkuId(cartInfo.getSkuId());
            orderItem.setSkuName(cartInfo.getSkuName());
            orderItem.setSkuNum(cartInfo.getSkuNum());
            orderItem.setSkuPrice(cartInfo.getCartPrice());
            orderItem.setThumbImg(cartInfo.getImgUrl());
            orderItemList.add(orderItem);
        }

        // 计算总金额
        BigDecimal totalAmount = new BigDecimal(0);
        for(OrderItem orderItem : orderItemList) {
            totalAmount = totalAmount.add(orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum())));
        }
        TradeVo tradeVo = new TradeVo();
        tradeVo.setTotalAmount(totalAmount);
        tradeVo.setOrderItemList(orderItemList);
        return tradeVo;
        
    }

}

1.5.5 服务网关

服务网关中配置service-order微服务的路由规则:

spring:
  cloud:
    gateway:
      routes:
        - id: service-order
          uri: lb://service-order
          predicates:
            - Path=/api/order/orderInfo/**

启动服务进行测试。

1.6 openFeign拦截器使用

1.6.1 问题说明

在测试的时候,那么service-cart微服务会报错,如下所示:

java.lang.NullPointerException: Cannot invoke "com.atguigu.spzx.model.entity.user.UserInfo.getId()" because the return value of "com.atguigu.spzx.common.util.AuthContextUtil.getUserInfo()" is null
	at com.atguigu.spzx.cart.service.impl.CartServiceImpl.getAllCkecked(CartServiceImpl.java:147)

针对service-cart微服务是获取不到当前登录用户的信息。

原因:service-order微服务调用service-cart微服务的时候,是通过openFeign进行调用,openFeign在调用的时候会丢失请求头

1.6.2 问题解决

解决方案:使用feign拦截器拦截请求,获取token,重新传递token

在这里插入图片描述

注意:为了让feign拦截器更加通用,那么此时可以将拦截器定义到common-service模块中

feign拦截器开发:

1、在common-service模块中加入openFeign的依赖

<!-- openfeign依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <scope>provided</scope>
</dependency>

2、定义feign拦截器

// com.atguigu.spzx.common.feign;
public class UserTokenFeignInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        String token = request.getHeader("token");
        requestTemplate.header("token" , token) ;
    }

}

3、定义使用该拦截器的注解

// com.atguigu.spzx.common.anno;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
@Import(value = UserTokenFeignInterceptor.class)
public @interface EnableUserTokenFeignInterceptor {
    
}

4、service-order微服务启动类上使用**@EnableUserTokenFeignInterceptor**注解

2 提交订单

2.1 需求说明

需求说明:用户在结算页面点击提交订单按钮,那么此时就需要保存订单信息(order_info)订单项信息(order_item)记录订单日志(order_log),成功后还需要清空订单对应的购物项,下单成功重定向到订单支付页面

查看接口文档:

下单接口地址及返回结果:

post /api/order/orderInfo/auth/submitOrder
参数:
{
    "orderItemList": [
        {
            "skuId": 6,
            "skuName": "小米 红米Note10 5G手机 颜色:黑色 内存:18G",
            "thumbImg": "http://139.198.127.41:9000/spzx/20230525/665832167-1_u_1.jpg",
            "skuPrice": 2999,
            "skuNum": 1
        },
        ...
    ],
    "userAddressId": 2,
    "feightFee": 0,
    "remark": "赶快发货"
}
返回结果(订单id){
    "code": 200,
    "message": "操作成功",
    "data": 1
}

调用流程如下所示:

在这里插入图片描述

2.2 后端接口

2.2.1 查询用户地址

业务接口开发

操作模块:service-user

UserAddressController

表现层代码:

@Operation(summary = "获取地址信息")
@GetMapping("getUserAddress/{id}")
public UserAddress getUserAddress(@PathVariable Long id) {
   return userAddressService.getById(id);
}
UserAddressService

业务层代码实现:

//业务接口
UserAddress getById(Long id);

//业务接口实现
@Override
public UserAddress getById(Long id) {
   return userAddressMapper.getById(id);
}
UserAddressMapper

持久层代码实现:

UserAddress getById(Long id);
UserAddressMapper.xml

在映射文件中定义对应的sql语句:

<select id="getById" resultMap="userAddressMap">
   select <include refid="columns" />
   from user_address
   where
   id = #{id}
</select>

启动程序进行测试。

openFeign接口开发

步骤如下:

1、在spzx-service-client模块下创建一个service-user-client的子模块

2、在service-user-client模块下定义远程openFeign接口

// com.atguigu.spzx.feign.user;
@FeignClient(value = "service-user" , fallback = UserFeignClientFallback.class)
public interface UserFeignClient {

    @GetMapping("/api/user/userAddress/getUserAddress/{id}")
    public abstract Result<UserAddress> getUserAddress(@PathVariable Long id) ;

}


// com.atguigu.spzx.feign.user.fallback;
@Slf4j
public class UserFeignClientFallback implements UserFeignClient {

    @Override
    public Result<UserAddress> getUserAddress(Long id) {
        log.info("UserFeignClientFallback...getUserAddress的方法执行了");
        return Result.build(null , ResultCodeEnum.SUCCESS) ;
    }

}

3、降级类自动化配置

在resources目录下创建一个MATE-INF/spring文件夹,在该文件夹下创建一个

org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,文件的中的内容如下所示:

com.atguigu.spzx.feign.user.fallback.UserFeignClientFallback

4、修改service-order微服务

pom.xml文件中加入依赖:

<dependency>
    <groupId>com.atguigu.spzx</groupId>
    <artifactId>service-user-client</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

启动类修改:

@EnableFeignClients(basePackages = {
        "com.atguigu.spzx.feign.cart",
        "com.atguigu.spzx.feign.user"
})

2.2.2 业务接口开发

操作模块:service-order

OrderInfoDto

定义一个实体类用来封装下单的参数,具体定义如下所示

@Data
public class OrderInfoDto {

    //送货地址id
    private Long userAddressId;

    //运费
    private BigDecimal feightFee;
    //备注
    private String remark;
    //订单明细
    private List<OrderItem> orderItemList;
}
OrderLog

订单日志体类定义:

@Data
@Schema(description = "订单日志实体对象")
public class OrderLog extends BaseEntity {

   private static final long serialVersionUID = 1L;

   @Schema(description = "订单id")
   private Long orderId;

   @Schema(description = "操作人:用户;系统;后台管理员")
   private String operateUser;

   @Schema(description = "订单状态")
   private Integer processStatus;

   @Schema(description = "备注")
   private String note;

}
OrderInfoController

表现层代码:

@Operation(summary = "提交订单")
@PostMapping("auth/submitOrder")
public Result<Long> submitOrder(@Parameter(name = "orderInfoDto", description = "请求参数实体类", required = true) @RequestBody OrderInfoDto orderInfoDto) {
   Long orderId = orderInfoService.submitOrder(orderInfoDto);
   return Result.build(orderId, ResultCodeEnum.SUCCESS);
}
OrderInfoService

业务层代码实现:

//业务接口
Long submitOrder(OrderInfoDto orderInfoDto);

//业务接口实现
@Transactional
@Override
public Long submitOrder(OrderInfoDto orderInfoDto) {

    // 数据校验
    List<OrderItem> orderItemList = orderInfoDto.getOrderItemList();
    if (CollectionUtils.isEmpty(orderItemList)) {
        throw new GuiguException(ResultCodeEnum.DATA_ERROR);
    }
    for (OrderItem orderItem : orderItemList) {
        ProductSku productSku = productFeignClient.getBySkuId(orderItem.getSkuId()).getData();
        if(null == productSku) {
            throw new GuiguException(ResultCodeEnum.DATA_ERROR);
        }
        if(orderItem.getSkuNum().intValue() > productSku.getStockNum().intValue()) {
            throw new GuiguException(ResultCodeEnum.STOCK_LESS);
        }
    }

    // 构建订单数据,保存订单
    UserInfo userInfo = AuthContextUtil.getUserInfo();
    OrderInfo orderInfo = new OrderInfo();
    String orderNo = IdUtil.createSnowflake(1L, 1L).nextIdStr();
    orderInfo.setOrderNo(orderNo);
    orderInfo.setUserId(userInfo.getId());
    orderInfo.setNickName(userInfo.getUsername());

    UserAddress userAddress = userFeignClient.getUserAddress(orderInfoDto.getUserAddressId()).getData();
    orderInfo.setReceiverName(userAddress.getName());
    orderInfo.setReceiverPhone(userAddress.getPhone());
    orderInfo.setReceiverTagName(userAddress.getTagName());
    orderInfo.setReceiverProvince(userAddress.getProvinceCode());
    orderInfo.setReceiverCity(userAddress.getCityCode());
    orderInfo.setReceiverDistrict(userAddress.getDistrictCode());
    orderInfo.setReceiverAddress(userAddress.getFullAddress());

    BigDecimal totalAmount = new BigDecimal(0);
    for (OrderItem orderItem : orderItemList) {
        totalAmount = totalAmount.add(orderItem.getSkuPrice().multiply(new BigDecimal(orderItem.getSkuNum())));
    }
    orderInfo.setTotalAmount(totalAmount);
    orderInfo.setCouponAmount(new BigDecimal(0));
    orderInfo.setOriginalTotalAmount(totalAmount);
    orderInfo.setFeightFee(orderInfoDto.getFeightFee());
    orderInfo.setPayType(2);
    orderInfo.setOrderStatus(0);
    orderInfoMapper.save(orderInfo);

    //保存订单明细
    for (OrderItem orderItem : orderItemList) {
        orderItem.setOrderId(orderInfo.getId());
        orderItemMapper.save(orderItem);
    }

    //记录日志
    OrderLog orderLog = new OrderLog();
    orderLog.setOrderId(orderInfo.getId());
    orderLog.setProcessStatus(0);
    orderLog.setNote("提交订单");
    orderLogMapper.save(orderLog);
    
    // TODO 远程调用service-cart微服务接口清空购物车数据
    return orderInfo.getId();
}

在ResultCodeEnum类添加枚举

STOCK_LESS( 219, "库存不足"),
Mapper接口

持久层代码实现:

OrderInfoMapper
@Mapper
public interface OrderInfoMapper {

    void save(OrderInfo orderInfo);
}
OrderItemMapper
@Mapper
public interface OrderItemMapper {
    void save(OrderItem orderItem);
}
OrderLogMapper
@Mapper
public interface OrderLogMapper {
    void save(OrderLog orderLog);
}
XML映射文件

在映射文件中定义对应的sql语句

OrderInfoMapper.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.atguigu.spzx.order.mapper.OrderInfoMapper">

   <resultMap id="orderInfoMap" type="com.atguigu.spzx.model.entity.order.OrderInfo" autoMapping="true">
   </resultMap>
   
   <!-- 用于select查询公用抽取的列 -->
   <sql id="columns">
      id,user_id,nick_name,order_no,coupon_id,total_amount,coupon_amount,original_total_amount,feight_fee,pay_type,order_status,receiver_name,receiver_phone,receiver_tag_name,receiver_province,receiver_city,receiver_district,receiver_address,payment_time,delivery_time,receive_time,remark,cancel_time,cancel_reason,create_time,update_time,is_deleted
   </sql>

   <insert id="save" useGeneratedKeys="true" keyProperty="id">
      insert into order_info (
         id,
         user_id,
         nick_name,
         order_no,
         coupon_id,
         total_amount,
         coupon_amount,
         original_total_amount,
         feight_fee,
         pay_type,
         order_status,
         receiver_name,
         receiver_phone,
         receiver_tag_name,
         receiver_province,
         receiver_city,
         receiver_district,
         receiver_address,
         payment_time,
         delivery_time,
         receive_time,
         remark,
         cancel_time,
         cancel_reason
      ) values (
         #{id},
         #{userId},
         #{nickName},
         #{orderNo},
         #{couponId},
         #{totalAmount},
         #{couponAmount},
         #{originalTotalAmount},
         #{feightFee},
         #{payType},
         #{orderStatus},
         #{receiverName},
         #{receiverPhone},
         #{receiverTagName},
         #{receiverProvince},
         #{receiverCity},
         #{receiverDistrict},
         #{receiverAddress},
         #{paymentTime},
         #{deliveryTime},
         #{receiveTime},
         #{remark},
         #{cancelTime},
         #{cancelReason}
      )
   </insert>
</mapper>
OrderItemMapper.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.atguigu.spzx.order.mapper.OrderItemMapper">

   <resultMap id="orderItemMap" type="com.atguigu.spzx.model.entity.order.OrderItem" autoMapping="true">
   </resultMap>
   
   <!-- 用于select查询公用抽取的列 -->
   <sql id="columns">
      id,order_id,sku_id,sku_name,thumb_img,sku_price,sku_num,create_time,update_time,is_deleted
   </sql>

   <insert id="save" useGeneratedKeys="true" keyProperty="id">
      insert into order_item (
         id,
         order_id,
         sku_id,
         sku_name,
         thumb_img,
         sku_price,
         sku_num
      ) values (
         #{id},
         #{orderId},
         #{skuId},
         #{skuName},
         #{thumbImg},
         #{skuPrice},
         #{skuNum}
      )
   </insert>
</mapper>
OrderLogMapper.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.atguigu.spzx.order.mapper.OrderLogMapper">

   <resultMap id="orderLogMap" type="com.atguigu.spzx.model.entity.order.OrderLog" autoMapping="true">
   </resultMap>
   
   <!-- 用于select查询公用抽取的列 -->
   <sql id="columns">
      id,order_id,operate_user,process_status,note,create_time,update_time,is_deleted
   </sql>

   <insert id="save" useGeneratedKeys="true" keyProperty="id">
      insert into order_log (
         id,
         order_id,
         operate_user,
         process_status,
         note
      ) values (
         #{id},
         #{orderId},
         #{operateUser},
         #{processStatus},
         #{note}
      )
   </insert>

</mapper>

2.2.3 清空购物车

需求说明:订单生成成功以后,需要调用service-cart微服务的接口清空选中的购物车数据。

service-cart

在service-cart微服务中开发一个清空购物车的接口供service-order微服务进行调用:

CartController
// com.atguigu.spzx.cart.controller.CartController
@GetMapping(value = "/auth/deleteChecked")
public Result deleteChecked() {
    cartService.deleteChecked() ;
    return Result.build(null , ResultCodeEnum.SUCCESS) ;
}
CartService
// com.atguigu.spzx.cart.service.impl.CartServiceImpl
@Override
public void deleteChecked() {
    Long userId = AuthContextUtil.getUserInfo().getId();
    String cartKey = getCartKey(userId);
    List<Object> objectList = redisTemplate.opsForHash().values(cartKey);       // 删除选中的购物项数据
    if(!CollectionUtils.isEmpty(objectList)) {
        objectList.stream().map(cartInfoJSON -> JSON.parseObject(cartInfoJSON.toString(), CartInfo.class))
            .filter(cartInfo -> cartInfo.getIsChecked() == 1)
            .forEach(cartInfo -> redisTemplate.opsForHash().delete(cartKey , String.valueOf(cartInfo.getSkuId())));
    }
}
openFeign接口

在service-cart-client模块CartFeignClient中定义删除选中的购物车数据的远程接口方法:

// com.atguigu.spzx.feign.cart
@FeignClient(value = "service-cart" , fallback = CartFeignClientFallback.class)
public interface CartFeignClient {
    
    @GetMapping(value = "/api/order/cart/auth/deleteChecked")
    public abstract Result deleteChecked() ;

}
service-order

改造service-order微服务的下单接口方法,添加清空选中购物车数据的远程调用代码:

// com.atguigu.spzx.order.service.impl.OrderInfoServiceImpl
@Transactional
@Override
public Long submitOrder(OrderInfoDto orderInfoDto) {

    // 1、数据校验
    // 2、构建订单数据,保存订单
    // 3、保存订单明细
    // 4、记录日志
    // 5、清空购物车数据
    cartFeignClient.deleteChecked() ;
    
    return orderInfo.getId();
}

3 支付页

3.1 需求说明

提交订单成功,跳转到支付页面,根据订单id获取订单详细信息,展示订单支付信息

查看接口文档:

根据订单id获取订单信息接口地址及返回结果:

get /api/order/orderInfo/auth/{orderId}
返回结果(订单id){
    "code": 200,
    "message": "成功",
    "data": {
        "id": 194,
        "createTime": "2023-06-14 19:29:31",
        "userId": 1,
        "nickName": "test",
        "orderNo": "1686713371363",
        "couponId": null,
        "totalAmount": 2999,
        "couponAmount": 0,
        "originalTotalAmount": 2999,
        "feightFee": 0,
        "payType": 2,
        "orderStatus": 0,
        "receiverName": "张三",
        "receiverPhone": "15012563333",
        "receiverTagName": "公司",
        "receiverProvince": "130000",
        "receiverCity": "130700",
        "receiverDistrict": "130724",
        "receiverAddress": "河北省张家口市沽源县快乐家园1号",
        "paymentTime": null,
        "deliveryTime": null,
        "receiveTime": null,
        "remark": null,
        "cancelTime": null,
        "cancelReason": null
    }
}

3.2 后端接口

3.2.1 OrderInfoController

表现层代码:

@Operation(summary = "获取订单信息")
@GetMapping("auth/{orderId}")
public Result<OrderInfo> getOrderInfo(@Parameter(name = "orderId", description = "订单id", required = true) @PathVariable Long orderId) {
   OrderInfo orderInfo = orderInfoService.getOrderInfo(orderId);
   return Result.build(orderInfo, ResultCodeEnum.SUCCESS);
}

3.2.2 OrderInfoService

业务层代码实现:

//业务接口
OrderInfo getOrderInfo(Long orderId);

//业务接口实现
@Override
public OrderInfo getOrderInfo(Long orderId) {
    return orderInfoMapper.getById(orderId);
}

3.2.3 OrderInfoMapper

持久层代码实现:

OrderInfo getById(Long orderId);

3.2.4 OrderInfoMapper.xml

在映射文件中定义对应的sql语句:

<select id="getById" resultMap="orderInfoMap">
   select <include refid="columns" />
   from order_info
   where
   id = #{id}
</select>

4 立即购买

4.1 需求说明

入口:商品详情页,点击“立即购买”按钮

立即购买直接进入结算页,不经过购物车,结算页返回数据与正常下单结算数据一致,提交订单接口不变,如图所示:

在这里插入图片描述

查看接口文档:

立即购买接口地址及返回结果:

get /api/order/orderInfo/auth/buy/{skuId}
返回结果:
{
    "code": 200,
    "message": "操作成功",
    "data": {
        "totalAmount": 6997.00,
        "orderItemList": [
            {
                "skuId": 1,
                "skuName": "小米 红米Note10 5G手机 颜色:白色 内存:8G",
                "thumbImg": "http://139.198.127.41:9000/spzx/20230525/665832167-5_u_1 (1).jpg",
                "skuPrice": 1999.00,
                "skuNum": 2
            },
            ...
        ]
    }
}

4.2 后端接口

4.2.1 OrderInfoController

表现层代码:

@Operation(summary = "立即购买")
@GetMapping("auth/buy/{skuId}")
public Result<TradeVo> buy(@Parameter(name = "skuId", description = "商品skuId", required = true) @PathVariable Long skuId) {
   TradeVo tradeVo = orderInfoService.buy(skuId);
   return Result.build(tradeVo, ResultCodeEnum.SUCCESS);
}

4.2.2 OrderInfoService

业务层代码实现:

//业务接口
TradeVo buy(Long skuId);

//业务接口实现
@Override
public TradeVo buy(Long skuId) {

    // 查询商品
    ProductSku productSku = productFeignClient.getBySkuId(skuId).getData();
    List<OrderItem> orderItemList = new ArrayList<>();
    OrderItem orderItem = new OrderItem();
    orderItem.setSkuId(skuId);
    orderItem.setSkuName(productSku.getSkuName());
    orderItem.setSkuNum(1);
    orderItem.setSkuPrice(productSku.getSalePrice());
    orderItem.setThumbImg(productSku.getThumbImg());
    orderItemList.add(orderItem);

    // 计算总金额
    BigDecimal totalAmount = productSku.getSalePrice();
    TradeVo tradeVo = new TradeVo();
    tradeVo.setTotalAmount(totalAmount);
    tradeVo.setOrderItemList(orderItemList);

    // 返回
    return tradeVo;
}

5 我的订单

5.1 需求说明

我的订单根据订单状态展示列表,如图所示:

在这里插入图片描述

查看接口文档:

我的订单接口地址及返回结果:

get /api/order/orderInfo/auth/{page}/{limit}?orderStatus={orderStatus}
返回结果:
{
    "code": 200,
    "message": "成功",
    "data": {
        "total": 63,
        "list": [
            {
                "id": 194,
                "createTime": "2023-06-14 19:29:31",
                "userId": 1,
                "nickName": "test",
                "orderNo": "1686713371363",
                "couponId": null,
                "totalAmount": 2999.00,
                "couponAmount": 0.00,
                "originalTotalAmount": 2999.00,
                "feightFee": 0.00,
                "payType": 2,
                "orderStatus": 0,
                "receiverName": "张三",
                "receiverPhone": "15012563333",
                "receiverTagName": "公司",
                "receiverProvince": "130000",
                "receiverCity": "130700",
                "receiverDistrict": "130724",
                "receiverAddress": "河北省张家口市沽源县快乐家园1号",
                "paymentTime": null,
                "deliveryTime": null,
                "receiveTime": null,
                "remark": null,
                "cancelTime": null,
                "cancelReason": null,
                "orderItemList": [
                    {
                        "id": 428,
                        "createTime": "2023-06-14 19:29:31",
                        "orderId": 194,
                        "skuId": 6,
                        "skuName": "小米 红米Note10 5G手机 颜色:黑色 内存:18G",
                        "thumbImg": "http://139.198.127.41:9000/spzx/20230525/665832167-1_u_1.jpg",
                        "skuPrice": 2999.00,
                        "skuNum": 1
                    }
                ]
            },
            ...
        ],
        "pageNum": 1,
        "pageSize": 10,
        "size": 6,
        "startRow": 1,
        "endRow": 6,
        "pages": 7,
        "prePage": 0,
        "nextPage": 2,
        "isFirstPage": true,
        "isLastPage": false,
        "hasPreviousPage": false,
        "hasNextPage": true,
        "navigatePages": 10,
        "navigatepageNums": [
            1,
            2,
            3,
            4,
            5,
            6,
            7
        ],
        "navigateFirstPage": 1,
        "navigateLastPage": 7
    }
}

5.2 后端接口

5.2.1 OrderInfoController

表现层代码:

@Operation(summary = "获取订单分页列表")
@GetMapping("auth/{page}/{limit}")
public Result<PageInfo<OrderInfo>> list(
      @Parameter(name = "page", description = "当前页码", required = true)
      @PathVariable Integer page,

      @Parameter(name = "limit", description = "每页记录数", required = true)
      @PathVariable Integer limit,

      @Parameter(name = "orderStatus", description = "订单状态", required = false)
      @RequestParam(required = false, defaultValue = "") Integer orderStatus) {
   PageInfo<OrderInfo> pageInfo = orderInfoService.findUserPage(page, limit, orderStatus);
   return Result.build(pageInfo, ResultCodeEnum.SUCCESS);
}

5.2.2 OrderInfoService

业务层代码实现:

//业务接口
PageInfo<OrderInfo> findUserPage(Integer page, Integer limit, Integer orderStatus);

//业务接口实现
@Override
public PageInfo<OrderInfo> findUserPage(Integer page, Integer limit, Integer orderStatus) {
    PageHelper.startPage(page, limit);
    Long userId = AuthContextUtil.getUserInfo().getId();
    List<OrderInfo> orderInfoList = orderInfoMapper.findUserPage(userId, orderStatus);
    return new PageInfo<>(orderInfoList, limit);
}

5.2.3 OrderInfoMapper

持久层代码实现:

List<OrderInfo> findUserPage(Long userId, Integer orderStatus);

5.2.4 OrderInfoMapper.xml

在映射文件中定义对应的sql语句:

<resultMap id="orderInfoMap" type="com.atguigu.spzx.model.entity.order.OrderInfo" autoMapping="true">
   <!--id:表示主键 property:表示实体类的属性名 column:表示通过sql 执行以后查询出来的字段名-->
   <id property="id" column="id"></id>

   <!-- 一对多 -->
   <collection property="orderItemList" ofType="com.atguigu.spzx.model.entity.order.OrderItem" autoMapping="true"
            column="{orderId = id}"
            select="com.atguigu.spzx.order.mapper.OrderItemMapper.findByOrderId">
   </collection>
</resultMap>
<select id="findUserPage" resultMap="orderInfoMap">
   select <include refid="columns" />
   from order_info
   <where>
      <if test="userId != null">
         and user_id = #{userId}
      </if>
      <if test="orderStatus != null">
         and order_status = #{orderStatus}
      </if>
      and is_deleted = 0
   </where>
   order by id desc
</select>

5.2.5 OrderInfo

订单实体添加属性:

@Schema(description = "订单项列表")
private List<OrderItem> orderItemList;

5.2.6 OrderItemMapper.xml

在映射文件中定义对应的sql语句:

<select id="findByOrderId" resultMap="orderItemMap">
   select <include refid="columns" />
   from order_item
   where
      order_id = #{orderId}
      and is_deleted = 0
   order by id desc
</select>

5.2.7 OrderItemMapper

持久层代码实现:

List<OrderItem> findByOrderId(Long orderId);

Mapper

持久层代码实现:

List<OrderInfo> findUserPage(Long userId, Integer orderStatus);

5.2.4 OrderInfoMapper.xml

在映射文件中定义对应的sql语句:

<resultMap id="orderInfoMap" type="com.atguigu.spzx.model.entity.order.OrderInfo" autoMapping="true">
   <!--id:表示主键 property:表示实体类的属性名 column:表示通过sql 执行以后查询出来的字段名-->
   <id property="id" column="id"></id>

   <!-- 一对多 -->
   <collection property="orderItemList" ofType="com.atguigu.spzx.model.entity.order.OrderItem" autoMapping="true"
            column="{orderId = id}"
            select="com.atguigu.spzx.order.mapper.OrderItemMapper.findByOrderId">
   </collection>
</resultMap>
<select id="findUserPage" resultMap="orderInfoMap">
   select <include refid="columns" />
   from order_info
   <where>
      <if test="userId != null">
         and user_id = #{userId}
      </if>
      <if test="orderStatus != null">
         and order_status = #{orderStatus}
      </if>
      and is_deleted = 0
   </where>
   order by id desc
</select>

5.2.5 OrderInfo

订单实体添加属性:

@Schema(description = "订单项列表")
private List<OrderItem> orderItemList;

5.2.6 OrderItemMapper.xml

在映射文件中定义对应的sql语句:

<select id="findByOrderId" resultMap="orderItemMap">
   select <include refid="columns" />
   from order_item
   where
      order_id = #{orderId}
      and is_deleted = 0
   order by id desc
</select>

5.2.7 OrderItemMapper

持久层代码实现:

List<OrderItem> findByOrderId(Long orderId);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/440673.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LVS集群(Linux Virtual server)介绍----及LVS的NAT模式部署(一)

群集的含义 ●Cluster&#xff0c;集群、群集由多台主机构成&#xff0c;但对外只表现为一个整体&#xff0c;只提供访问入口(域名或IP地址)&#xff0c;相当于一台大型计算机 问题&#xff1a; 互联网应用中&#xff0c;随着站点对硬件性能、响应速度、服务稳定性、数据可靠…

15. C++泛型与符号重载

【泛型编程】 若多组类型不同的数据需要使用相同的代码处理&#xff0c;在C语言中需要编写多组代码分别处理&#xff0c;这样做显然太过繁琐&#xff0c;C增加了虚拟类型&#xff0c;使用虚拟类型可以实现一组代码处理多种类型的数据。 虚拟类型是暂时不确定的数据类型&#…

uniapp在页面中中获取pages.json下pages设置navigationBarTitleText这个值?uniapp获取页面标题

一、问题描述 有个需求就是,在app.vue页面中首先会隐藏所有页面的title,然后在相应的页面会判断当前环境是否是在微信浏览器内&#xff0c;如果不是&#xff0c;则还原标题。 二、解决方法 在 pages.json 文件中设置 navigationBarTitleText&#xff0c;例如&#xff1a; {&qu…

OpenCascade源码剖析:Handle类

Handle其实就是智能指针的上古版本&#xff0c;了解一点C11的应该对shared_ptr非常熟悉&#xff0c;那么你就把Handle当做shared_ptr来理解就没有任何问题了。 不过OCCT的Handles是侵入式的实现&#xff0c;前面讲过Standard_Transient类提供了引用计数机制&#xff0c;这个就…

Missing type map configuration or unsupported mapping

今天开发的时候突然遇到这么一个问题&#xff0c;可以确定的是不是AutoMap的问题&#xff0c;因为项目中其他接口都是好好的&#xff0c;只有新加的这个控制器不行&#xff0c;排查了一下&#xff0c;少了映射配置&#xff0c;在这里加上映射关系即可&#xff0c;大意了。

egg如何写单元测试

优秀的代码需要有单元测试进行质量保证&#xff0c;每个测试用例都给应用的稳定性提供了一层保障。 测试目录结构 我们约定 test 目录为存放所有测试脚本的目录&#xff0c;测试所使用到的 fixtures 和相关辅助脚本都应该放在此目录下。 测试文件的目录和我们需要测试的文件目…

HTML—常用标签

常用标签&#xff1a; 标题标签&#xff1a;<h1></h1>......<h6></h6>段落标签&#xff1a;<p></p>换行标签&#xff1a;<br/>列表&#xff1a;无序列表<ul><li></li></ul> 有序列表<ol>&…

Python的数据库编程基础知识

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;如果停止&#xff0c;就是低谷&#xf…

[HackMyVM]靶场 Zeug

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…

力扣hot100:240.搜索二维矩阵II(脑子)

吉大21级算法分析与设计的一道大题&#xff0c;由于每一行都是排好序的直接逐行二分 可以达到&#xff1a;O(mlogn)。但是这里追求更广的思路可以使用其他方法。 矩阵四分&#xff1a; 在矩阵中用中心点比较&#xff0c;如果target大于中心点的值&#xff0c;则由于升序排列&am…

排序二叉树

参考 Binary Search Tree Visualization (usfca.edu) 一、构建排序二叉树 注意引用 tree /*** 构造二叉排序树* param tree* param x*/ void buildTree(BSTree &tree,ElementType &x){if (treeNULL){tree(BSTree) calloc(1, sizeof(BSTNode));tree->datax;//注意ret…

Python算法题集_搜索二维矩阵

Python算法题集_搜索二维矩阵 题51&#xff1a;搜索二维矩阵1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【矩阵展开为列表二分法】2) 改进版一【行*列区间二分法】3) 改进版二【第三方模块】 4. 最优算法5. 相关资源 本文为Python算法题集之…

bugku-misc隐写

下载文件&#xff0c;解压得到图片 没看到信息&#xff0c;试着查看图片属性 看到图片宽高不一致&#xff0c;猜测可能需要改变图片长度或者宽度 试着把图片变大&#xff0c;十进制500转16进制 得到1f4 用010打开图片 第二行第一个为宽&#xff0c;第二个为高&#xff0c;A…

【计网】TCP协议安全与风险:深入探讨网络通信的基石

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Linux ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 &#x1f310;前言 &#x1f512;正文 TCP (Transmission Control Protocol): UDP (User Datagram Protocol): HTTP (Hypertext Transfer …

WordPress建站入门教程:如何创建菜单和设置前端导航菜单?

前面我们跟大家分享了WordPress如何上传安装WordPress主题&#xff0c;但是启用主题后前端没有看到有导航菜单&#xff0c;这是因为我们还没有创建菜单和设置导航菜单。 JianYue主题导航菜单和右上角菜单 今天boke112百科就继续跟大家分享WordPress站点如何创建菜单和设置前端…

java-抢红包一些简单概念

抢红包&#xff0c;比如微信中抢红包&#xff0c;红包金额分配使用的是二倍均值算法。 二倍均值拆包&#xff1a; 拆包要求:所有人抢到的金额之和等于红包总额&#xff0c;每个人最少抢到 0.01 元&#xff0c;每个人抢到的红包金额不要相差太大二倍均值法:假设红包总金额是X&…

2024最新版正规视频影视系统源码/APP+H5视频影视源码

全新魅思V20正规视频影视系统源码&#xff0c;APPH5视频影视源码。会员花费三千购入的&#xff0c;具体搭建教程放压缩包了&#xff01; 有兴趣的下载自行研究吧&#xff0c;搭建一共要用到3个域名&#xff0c;可以拿二级域名搭建。

奖励建模(Reward Modeling)实现人类对智能体的反馈

奖励建模&#xff08;Reward Modeling&#xff09;是强化学习中的一个重要概念和技术&#xff0c;它主要用于训练智能体&#xff08;如AI机器人或大型语言模型&#xff09;如何更有效地学习和遵循人类期望的行为。在强化学习环境中&#xff0c;智能体通过尝试不同的行为获得环境…

4月9日至10日Hack.Summit 2024亚洲首秀:Web3开发者齐聚香港数码港

Hack.Summit() 是一系列 Web3 开发者大会。本届活动将于 2024 年 4 月 9 日至 4 月 10 日在香港数码港举行。自十年前首次举办以来&#xff0c;此次会议标志着 Hack.Summit() 首次在亚洲举办&#xff0c;香港被选为首次亚洲主办城市&#xff0c;这对 Hack VC 和该地区都具有重要…

【Servlet】Servlet 详解(使用+原理)

文章目录 1. Servlet 介绍1.1 什么是 Servlet1.2 Servlet 的主要工作 2. Servlet 程序创建步骤2.1 创建项目2.2 引入依赖2.3 创建目录2.4 编写代码2.5 打包程序2.6 部署程序2.7 验证程序 3. 使用 Smart Tomcat 进行部署3.1 安装 Smart Tomcat3.2 配置 Smart Tomcat3.3 使用 Sma…