基于springboot框架的电脑商城项目(十)

简介: 创建订单(一)创建数据库在store数据库中创建t_order和t_order_item数据表

创建订单

(一)创建数据库

在store数据库中创建t_order和t_order_item数据表

CREATE TABLE t_order (
  oid INT AUTO_INCREMENT COMMENT '订单id',
  uid INT NOT NULL COMMENT '用户id',
  recv_name VARCHAR(20) NOT NULL COMMENT '收货人姓名',
  recv_phone VARCHAR(20) COMMENT '收货人电话',
  recv_province VARCHAR(15) COMMENT '收货人所在省',
  recv_city VARCHAR(15) COMMENT '收货人所在市',
  recv_area VARCHAR(15) COMMENT '收货人所在区',
  recv_address VARCHAR(50) COMMENT '收货详细地址',
  total_price BIGINT COMMENT '总价',
  status INT COMMENT '状态:0-未支付,1-已支付,2-已取消,3-已关闭,4-已完成',
  order_time DATETIME COMMENT '下单时间',
  pay_time DATETIME COMMENT '支付时间',
  created_user VARCHAR(20) COMMENT '创建人',
  created_time DATETIME COMMENT '创建时间',
  modified_user VARCHAR(20) COMMENT '修改人',
  modified_time DATETIME COMMENT '修改时间',
  PRIMARY KEY (oid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE t_order_item (
  id INT AUTO_INCREMENT COMMENT '订单中的商品记录的id',
  oid INT NOT NULL COMMENT '所归属的订单的id',
  pid INT NOT NULL COMMENT '商品的id',
  title VARCHAR(100) NOT NULL COMMENT '商品标题',
  image VARCHAR(500) COMMENT '商品图片',
  price BIGINT COMMENT '商品价格',
  num INT COMMENT '购买数量',
  created_user VARCHAR(20) COMMENT '创建人',
  created_time DATETIME COMMENT '创建时间',
  modified_user VARCHAR(20) COMMENT '修改人',
  modified_time DATETIME COMMENT '修改时间',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

(二)创建实体类

在entity包下创建Order实体类并继承BaseEntity类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order extends baseEntity{
    private Integer oid;
    private Integer uid;
    private String recvName;
    private String recvPhone;
    private String recvProvince;
    private String recvCity;
    private String recvArea;
    private String recvAddress;
    private Long totalPrice;
    private Integer status;
    private Date orderTime;
    private Date payTime;
}

在com.cy.store.entity包下创建OrderItem实体类并继承BaseEntity类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class OrderItem extends baseEntity{
    private Integer id;
    private Integer oid;
    private Integer pid;
    private String title;
    private String image;
    private Long price;
    private Integer num;
}

(三)创建订单(持久层)

1.规划sql

插入订单数据的SQL语句

inert into t_order (aid除外的所有字段) values (字段的值)

插入某一个订单中商品数据的SQL语句

inert into t_order (id除外的所有字段) values (字段的值)

2.实现接口和抽象方法

在mapper包下创建OrderMapper接口并在接口中添加抽象方法

public interface OrderMapper {
    /**
     * 插入订单数据
     * @param order 订单数据
     * @return 受影响的行数
     */
    Integer addOrder(Order order);
    /**
     * 插入某一个订单中商品数据
     * @param orderItem 订单中商品数据
     * @return 受影响的行数
     */
    Integer addOrderItem(OrderItem orderItem);
}


(四)创建订单(业务层)

1.规划异常

无异常需要规划


2.实现接口和抽象方法及实现

在IAddressService接口添加getByAid()方法来获取选中的收货地址的详细数据

    //根据aid查询
    Address getByAid(Integer uid,Integer aid);

在AddressServiceImpl类中实现接口中的getByAid()抽象方法

  @Override
    public Address getByAid(Integer uid, Integer aid) {
        Address address = addressMapper.findByAid(aid);
        if (address==null){
            throw new AddressNotFoundException("收货地址不存在");
        }
        if (!address.getUid().equals(uid)){
            throw new AccessDeniedException("非法数据访问");
        }
        address.setProvinceCode(null);
        address.setCityCode(null);
        address.setAreaCode(null);
        address.setCreatedUser(null);
        address.setCreatedTime(null);
        address.setModifiedUser(null);
        address.setModifiedTime(null);
        return address;
    }

在service包下创建IOrderService业务层接口并添加抽象方法用于创建订单

返回值是Order是因为还要在下个页面展示订单详细信息

public interface IOrderService {
    Order addOrder(Integer aid,Integer[] cids,Integer uid,String username);
}

在impl包下创建OrderServiceImpl并编写代码实现订单和订单中所有商品数据的插入操作

@Service
public class OrderServiceImpl implements IOrderService {
   @Resource
    private IAddressService addressService;
    @Autowired
    private ICartService cartService;
    @Resource
    private OrderMapper orderMapper;
@Autowired
private IUserService userService;
    @Override
    public Order addOrder(Integer aid, Integer[] cids, Integer uid, String username) {
        List<CartVo> list = cartService.getByCids(uid, cids);
       Long totalPrice=0L;
        for (CartVo c:list
             ) {
          totalPrice+= c.getRealPrice()*c.getNum();
        }
        Address address = addressService.getByAid(uid, aid);
Order order=new Order();
order.setUid(uid);
order.setRecvProvince(address.getProvinceName());
order.setRecvName(address.getName());
order.setRecvCity(address.getCityName());
order.setRecvArea(address.getAreaName());
order.setRecvAddress(address.getAddress());
order.setRecvPhone(address.getPhone());
order.setOrderTime(new Date());
order.setTotalPrice(totalPrice);
order.setModifiedUser(username);
order.setModifiedTime(new Date());
order.setCreatedTime(new Date());
order.setStatus(0);
order.setCreatedUser(username);
        Integer integer = orderMapper.addOrder(order);
if (integer!=1){
    throw new InsertException("订单显示错误");
}
        for (CartVo c:list
             ) {
            OrderItem orderItem=new OrderItem();
            orderItem.setOid(order.getOid());
            orderItem.setTitle(c.getTitle());
            orderItem.setPrice(c.getRealPrice());
            orderItem.setPid(c.getPid());
            orderItem.setNum(c.getNum());
            orderItem.setImage(c.getImage());
            orderItem.setCreatedTime(new Date());
            orderItem.setCreatedUser(username);
            orderItem.setModifiedTime(new Date());
            orderItem.setModifiedUser(username);
            Integer integer1 = orderMapper.addOrderItem(orderItem);
            if (integer1!=1){
                throw new InsertException("订单项插入产生异常");
            }
        }
        return order;
    }
}

(五)创建订单(控制层)

1.处理异常

无异常需要处理

2.设计请求

请求路径:/orders/create

请求方式:GET

请求参数:Integer aid, Integer[] cids, HttpSession session

响应结果:JsonResult< Order>

3.处理请求

controller包下创建OrderController类,并继承自BaseController类,在类中编写请求方法

@RestController
@RequestMapping("/orders")
public class OrderController extends BaseController{
    @Autowired
    private IOrderService orderService;
    @GetMapping("/create")
    public JsonResult<Order> createOrder(Integer[] cids, Integer aid, HttpSession session){
        Order order = orderService.addOrder(aid, cids, getuidfromsession(session), getusernamesession(session));
        return new JsonResult<>(ok,order);
    }
}

(六)创建订单(前端页面)

在orderConfirm.html页面编写js代码,(请求参数是通过字符串拼接得到的,那么就必须用get请求,因为post请求不能拼接字符串)

$("#btn-create-order").click(function() {
    var aid = $("#address-list").val();//12
    var cids = location.search.substr(1);//cids=4&cids=6&cids=8
    $.ajax({
        url: "/orders/create",
        data: "aid=" + aid + "&" + cids,//aid=12&cids=4&cids=6&cids=8
        type: "GET",
        dataType: "JSON",
        success: function(json) {
            if (json.state == 200) {
                location.href = "payment.html";
            } else {
                alert("创建订单失败!" + json.message);
            }
        },
        error: function(xhr) {
            alert("创建订单数据时产生未知的异常" + xhr.status);
        }
    });
});


AOP

检测项目所有业务层方法的耗时(开始执行时间和结束执行时间只差值),再在不改变项目主体流程代码的前提条件下完成此功能,就要用到AOP

如果我们想对业务某一些方法同时添加相同的功能需求,并且在不改变业务功能逻辑的基础之上进行完成,就可以使用AOP的切面编程进行开发

(一)Spring AOP

AOP:面向切面(Aspect)编程。AOP并不是Spring框架的特性(Spring已经被整合到了SpringBoot中,所以如果AOP是Spring框架的特性,那么就不需要手动导包,只需要在一个类上写@Aspect注解,鼠标放到该注解上按alt+enter就可以自动导包了,但是事与愿违,所以说AOP并不是Spring框架的特性),只是Spring很好的支持了AOP。

使用步骤:
首先定义一个类,将这个类作为切面类
在这个类中定义切面方法(5种:前置,后置,环绕,异常,最终)
将这个切面方法中的业务逻辑对应的代码进行编写和设计
通过连接点来连接目标方法,就是用粗粒度表达式和细粒度表达式来进行连接

(二)切面方法

1.切面方法的访问权限是public。

2.切面方法的返回值类型可以是void或Object,如果该方法被@Around注解修饰,必须使用Object作为返回值类型,并返回连接点方法的返回值;如果使用的注解是@Before或@After等其他注解时,则自行决定。

3.切面方法的名称可以自定义。

4.切面方法可以接收参数,参数是ProccedingJoinPoint接口类型的参数.但是@Around所修饰的方法必须要传递这个参数.其他注解修饰的方法要不要该参数都可以

(三)统计业务方法执行时长

1.因为AOP不是Spring内部封装的技术,所以需要进行导包操作:在pom.xml文件中添加两个关于AOP的依赖aspectjweaver和aspectjtools。

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjtools</artifactId>
</dependency>

2.在com.cy.store.aop包下创建TimerAspect切面类,给类添加两个注解进行修饰:

@Aspect(将当前类标记为切面类)
@Component(将当前类的对象创建使用维护交由Spring容器维护)

@Aspect
@Component
public class TimerAspect {
}

3.在类中添加切面方法,这里使用环绕通知的方式来进行编写

参数ProceedingJoinPoint接口表示连接点,也就是是目标方法的对象

public Object around(ProceedingJoinPoint pjp) throws Throwable {
    //开始时间
    long start = System.currentTimeMillis();
    //调用目标方法,比如login方法,getByUid方法
    Object result = pjp.proceed();
    //结束时间
    long end = System.currentTimeMillis();
    System.out.println("耗时:"+(end-start));
    return result;
}

4.将当前环绕通知映射到某个切面上,也就是指定连接的点.给around方法添加注解@Around

@Around("execution(* com.cy.store.service.impl.*.*(..))")

第一个表示方法返回值是任意的
第二个
表示imp包下的类是任意的
第三个*表示类里面的方法是任意的
(…)表示方法的参数是任意的

后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹




















相关文章
|
28天前
|
XML Java 应用服务中间件
SpringBoot项目打war包流程
本文介绍了将Spring Boot项目改造为WAR包并部署到外部Tomcat服务器的步骤。主要内容包括:1) 修改pom.xml中的打包方式为WAR;2) 排除Spring Boot内置的Tomcat依赖;3) 添加Servlet API依赖;4) 改造启动类以支持WAR部署;5) 打包和部署。通过这些步骤,可以轻松地将Spring Boot应用转换为适合外部Tomcat服务器的WAR包。
132 64
SpringBoot项目打war包流程
|
2月前
|
XML 安全 Java
|
1天前
|
前端开发 Java 数据库连接
Spring框架初识
Spring 是一个分层的轻量级开源框架,核心功能包括控制反转(IOC)和面向切面编程(AOP)。主要模块有核心容器、Spring 上下文、AOP、DAO、ORM、Web 模块和 MVC 框架。它通过 IOC 将配置与代码分离,简化开发;AOP 提供了声明性事务管理等增强功能。
33 21
Spring框架初识
|
3月前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
135 0
|
19天前
|
SQL Java 数据库连接
对Spring、SpringMVC、MyBatis框架的介绍与解释
Spring 框架提供了全面的基础设施支持,Spring MVC 专注于 Web 层的开发,而 MyBatis 则是一个高效的持久层框架。这三个框架结合使用,可以显著提升 Java 企业级应用的开发效率和质量。通过理解它们的核心特性和使用方法,开发者可以更好地构建和维护复杂的应用程序。
110 29
|
1月前
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
136 36
|
8天前
|
XML Java 开发者
通过springboot框架创建对象(一)
在Spring Boot中,对象创建依赖于Spring框架的核心特性——控制反转(IoC)和依赖注入(DI)。IoC将对象的创建和管理交由Spring应用上下文负责,开发者只需定义依赖关系。DI通过构造函数、setter方法或字段注入实现依赖对象的传递。Spring Boot的自动配置机制基于类路径和配置文件,自动为应用程序配置Spring容器,简化开发过程。Bean的生命周期包括定义扫描、实例化、依赖注入、初始化和销毁回调,均由Spring容器管理。这些特性提高了开发效率并简化了代码维护。
|
23天前
|
自然语言处理 IDE Java
SpringBoot start.aliyun.com创建项目,解决properties乱码的问题
通过确保文件和开发环境的编码一致,配置 Maven 编码,设置 Spring Boot 应用和嵌入式服务器的编码,可以有效解决 properties 文件的乱码问题。以上步骤可以帮助开发者确保在 Spring Boot 项目中正确处理和显示多语言字符,避免因编码问题导致的乱码现象。
36 5
|
1月前
|
开发框架 运维 监控
Spring Boot中的日志框架选择
在Spring Boot开发中,日志管理至关重要。常见的日志框架有Logback、Log4j2、Java Util Logging和Slf4j。选择合适的日志框架需考虑性能、灵活性、社区支持及集成配置。本文以Logback为例,演示了如何记录不同级别的日志消息,并强调合理配置日志框架对提升系统可靠性和开发效率的重要性。
|
2月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能