SpringBoot电脑商城-创建订单以及统计方法耗时(AOP)

创建订单

  • 1. 订单
    • 1.1 创建数据库表
    • 1.2 创建实体类
    • 1.3 持久层
    • 1.4 业务层
    • 1.5 控制层
    • 1.6 前端页面
  • 2. 统计业务方法耗时功能
    • 2.1 AOP
    • 2.2 切面方法
    • 2.3 统计业务方法执行时长

1. 订单

SpringBoot电脑商城-创建订单以及统计方法耗时(AOP)_第1张图片
点击在线支付,可以将该订单添加到数据库中。

1.1 创建数据库表

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;

1.2 创建实体类

1.订单实体类

/* 订单数据实体类 */
public class Order extends BaseEntity implements Serializable {
    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;

2.订单项实体类

/* 订单中的商品数据 */
public class OrderItem extends BaseEntity implements Serializable {
    private Integer id;
    private Integer oid;
    private Integer pid;
    private String title;
    private String image;
    private Long price;
    private Integer num;

1.3 持久层

  • 规划SQL语句
    1.将数据插入到订单表中
    insert into t_order (oid除外所有的字段) values (字段的值)
    
    2.将数据插入到订单项的表中
    insert into t_order_item (id除外所有的字段) values (字段的值)
    
  • 设计接口和抽象方法
    创建一个OrderMapper接口,接口中添加以上两个SQL对象的抽象方法。
    public interface OrderMapper {
       
       //插入订单数据
       Integer insertOrder(Order order);
       
       //插入订单项的数据
       Integer insertOrderItem(OrderItem orderItem);
    }
    

1.4 业务层

1.在IAddressService接口中定义根据收货地址的id获取收货地址数据。

Address getByAid(Integer aid, Integer uid);

2.在子类中实现该抽象方法

@Override
public Address getByAid(Integer aid, Integer uid) {
    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;
}

3.在service包下创建IOrderService接口,添加抽象方法用于创建订单。

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

4.创建实现类OrderServiceImpl类

@Service
public class OrderServiceImpl implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private IAddressService addressService;
    @Autowired
    private ICartService cartService;

    @Override
    public Order create(Integer aid, Integer uid, String username, Integer[] cids) {
        //即将要下单的列表
        List<CartVO> list = cartService.getVOByCid(uid, cids);
        //计算总价
        Long totalPrice = 0L;
        //创建订单详细项的信息
        for (CartVO cartVO : list) {
            totalPrice += cartVO.getRealprice();
        }
        Address address = addressService.getByAid(aid,uid);
        Order order = new Order();
        order.setUid(uid);
        //收货地址数据
        order.setRecvName(address.getName());
        order.setRecvPhone(address.getPhone());
        order.setRecvProvince(address.getProvinceName());
        order.setRecvCity(address.getCityName());
        order.setRecvArea(address.getAreaName());
        order.setRecvAddress(address.getAddress());
        //支付、总价
        order.setStatus(0);
        order.setTotalPrice(totalPrice);
        order.setOrderTime(new Date());
        //日志
        order.setCreatedTime(new Date());
        order.setCreatedUser(username);
        order.setModifiedTime(new Date());
        order.setModifiedUser(username);

        //查询数据
        Integer rows = orderMapper.insertOrder(order);
        if(rows != 1) {
            throw new InsertException("插入时异常");
        }

        //创建订单详细项的信息
        for (CartVO cartVO : list) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOid(order.getOid());
            orderItem.setPid(cartVO.getPid());
            orderItem.setTitle(cartVO.getTitle());
            orderItem.setImage(cartVO.getImage());
            orderItem.setPrice(cartVO.getRealprice());
            orderItem.setNum(cartVO.getNum());
            //日志字段
            orderItem.setCreatedUser(username);
            orderItem.setCreatedTime(new Date());
            orderItem.setModifiedUser(username);
            orderItem.setModifiedTime(new Date());
            //插入数据
            rows = orderMapper.insertOrderItem(orderItem);
            if(rows != 1) {
                throw new InsertException("插入时异常");
            }
        }

        return order;
    }
}

5.测试

@Autowired
private IOrderService orderService;

@Test
public void create() {
    Integer[] cids = {3,4}; //假设勾选的订单cid是3和4
    Order order = orderService.create(9, 22, "洪工",cids);
    System.out.println(order);
}

1.5 控制层

1.设计请求

/orders/create
aid, session, cids
post
JsonResult

2.创建OrderController类,并编写请求处理方法

@RestController
@RequestMapping("orders")
public class OrderController extends BaseController{
    @Autowired
    private IOrderService orderService;

    @RequestMapping("create")
    public JsonResult<Order> create(Integer aid, Integer[] cids, HttpSession session) {
        Integer uid = getuidFromSession(session);
        String username = getUsernameFromSession(session);
        Order data = orderService.create(aid, uid, username, cids);
        return new JsonResult<>(OK, data);
    }
}

1.6 前端页面

在订单确定页面中添加发送请求的处理方法

$("#btn-create-order").click(function () {
	let aid = $("#address-list").val();
	let cids = location.search.substr(1); //cid=1&cid=2
	$.ajax({
		url: "/orders/create",
		type: "get",
		data: "aid="+aid+"&"+cids,
		dataType: "JSON",
		success: function (json) {
			if(json.state == 200) {
				location.href = "payment.html";
				alert("订单创建成功");
			}
		},
		error: function (xhr) {
			alert("订单加载产生未知的异常" + xhr.status);
		}
	});
});

2. 统计业务方法耗时功能

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

2.1 AOP

面向切面编程。它并不是Spring框架的特性,只是Spring很好的支持AOP编程。
如果我们相对业务某一些方法同时添加相同的功能需求,并且在不改变原有的业务功能逻辑的基础之上进行完成,可以使用AOP的切面编程进行开发。

首先定义一个类,将这个类作为切面类。
在这个类中定义切面方法(5类)。
将这个切面方法中的业务逻辑要执行的代码进行编写和设计。
通过连接点来连接目标方法,就是用粗粒度表达式和细粒度表达式进行连接。

2.2 切面方法

  1. 切面方法修饰符必须是public
  2. 切面方法的返回值可以是void和Object。如果这个方法被@Around注解修饰,此方法必须声明为Object类型,反之随意。
  3. 切面方法的方法名称可以自定义。
  4. 切面方法可以接收参数,参数是ProceedingJoinPoint接口类型的参数。如果是被@Around所修饰的方法必须要传递这个参数,其他随意。

2.3 统计业务方法执行时长

1.AOP不是Spring的内部封装技术,所以要先导包

<dependency>
    <groupId>org.aspectjgroupId>
    <artifactId>aspectjweaverartifactId>
dependency>
<dependency>
    <groupId>org.aspectjgroupId>
    <artifactId>aspectjtoolsartifactId>
dependency>

2.定义一个切面类

@Component //将当前类的对象创建使用维护交给Spring容器维护
@Aspect //将当前类标记为切面类
public class TimerAspect {

}

3.定义切面方法,我们使用环绕通知的方式来进行编写。ProceedingJoinPoint接口表示连接点,目标方法的对象。

public Object around(ProceedingJoinPoint pjp) throws Throwable {
    //先记录当前时间
    long start = System.currentTimeMillis();
    Object result = pjp.proceed();
    //后记录当前时间
    long end = System.currentTimeMillis();
    System.out.println("耗时:" + (end-start));
    return result;
}

4.将当前环绕通知映射到某个 切面上(指定连接点)

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

5.启动项目,随机去访问任意功能模块

你可能感兴趣的:(项目,java,spring,intellij-idea,mysql)