10天手敲一个SpringBoot网上商城项目(九)—— 确认订单、创建订单功能的实现及AOP

静态资源及sql文件分享
链接:https://pan.baidu.com/s/1X-yjmQcPD3PqS21x0HplNA?pwd=23gr
提取码:23gr

确认订单

1.确认订单-持久层

1.1规划需要执行的SQL语句

用户在购物车列表页中通过随机勾选相关的商品,在点击"结算"按钮后跳转到"确认订单页",在这个页面中需要展示用户在上个页面所勾选的"购物车列表页"中对应的数据.说白了也就是列表展示,且展示的内容还是来自于购物车表.但是用户勾选了哪些商品呢,所以"购物车列表页"需要将用户勾选的商品id传递给"确认订单页"

所以在持久层需要完成“根据若干个不确定的id值,查询购物车数据表,显示购物车中的数据信息”。则需要执行的SQL语句大致是。

select
    cid,
    uid,
    pid,
    t_cart.price,
    t_cart.num,
    title,
    t_product.price as realPrice,
    image
from t_cart
left join t_product on t_cart.pid = t_product.id
where
	cid in (?,?,?)
order by
	t_cart.created_time desc

注意where cid in (?,?,?),这里是需要传入cid的集合

1.2设计接口和抽象方法

在CartMapper接口中添加findVOByCids抽象方法

List<CartVO> findVOByCids(Integer[] cids);
1.3配置映射

1.在CartMapper.xml文件中添加SQL语句的映射配置

<select id="findVOByCids" resultType="com.cy.store.vo.CartVO">
    select
        cid,
        uid,
        pid,
        t_cart.price,
        t_cart.num,
        title,
        t_product.price as realPrice,
        image
    from t_cart
    left join t_product on t_cart.pid = t_product.id
    where
        cid in (
            <foreach collection="array" item="cid" separator=",">
                #{cid}
            </foreach>
            )
    order by
    	t_cart.created_time desc
</select>

foreach循环就是一个for循环

  • collection标识循环的是list集合还是数组,如果是list集合就用collection=“list”
  • item用来接收每次循环获取的值
  • separator标识循环出来的值中间用什么隔开,且最后循环出来的值后面不加
1.4单元测试

在CartMapperTests测试类中添加findVOByCids方法进行测试

@Test
public void findVOByCids() {
    Integer[] cids = {1, 2, 6, 8, 100};//可以写表中不存在的,无非就是查不到数据,并不会报错
    List<CartVO> list = cartMapper.findVOByCids(cids);
    for (CartVO item : list) {
        System.out.println(item);
    }
}

2.确认订单-业务层

2.1规划异常

查询语句,没有需要规划的异常,在业务层判断这几条购物车商品的数据归属是否正确,如果不正确也不需要抛出异常,直接从查询到的数据中移除该商品就行了

2.2设计接口和抽象方法及实现

1.在ICartService接口中添加getVOByCids()抽象方法

List<CartVO> getVOByCids(Integer uid, Integer[] cids);//uid是为了判断数据归属是否正确

2.在CartServiceImpl类中重写业务接口中的抽象方法

@Override
public List<CartVO> getVOByCids(Integer uid, Integer[] cids) {
    List<CartVO> list = cartMapper.findVOByCids(cids);

    //可以使用for遍历,这里玩个新的,用迭代器遍历
    Iterator<CartVO> it = list.iterator();
    while (it.hasNext()) {

        //指向的是该元素之前,所以需要next得到该元素
        CartVO cart = it.next();

        if (!cart.getUid().equals(uid)) {
            /**
             * 不能用list.remove(cart)
             * 在迭代器进行遍历的时候不能使用集合的移除
             * 方法,需要用迭代器特有的移除方法
             */
            it.remove();
        }
    }
    return list;
}
2.3单元测试

业务层只是调用持久层获取数据并判断归属是否正确,这里不再测试

3.确认订单-控制层

3.1处理异常

业务层没有抛出异常,所以不需要处理异常

3.2设计请求
  • /carts/list
  • GET
  • Integer[] cids, HttpSession session
  • JsonResult<List<CartVO>>
3.3处理请求

1.在CartController类中添加处理请求的getVOByCids()方法。

@RequestMapping("list")
public JsonResult<List<CartVO>> findVOByCids(Integer[] cids, HttpSession session) {
    List<CartVO> data = cartService.getVOByCids(getUidFromSession(session), cids);
    return new JsonResult<>(OK, data);
}

启动服务,登录后在地址栏输入http://localhost:8080/carts/list?cids=1&cids=5&cids=7进行测试

4.确认订单-前端页面

4.1显示勾选的购物车数据

1.检查cart.html页面,里面form标签的action="orderConfirm.html"属性(规定表单数据提交到哪里)和结算按钮的类型"type=submit"是必不可少的,这样点击"结算"时才能将数据传给"确认订单页"并在"确认订单页"展示选中的商品数据

2.在orderConfirm.html页面中实现自动加载从cart.html页面中传递过来的cids数据,再去请求ajax,然后将后端返回的数据填充在页面的某个区域中

3.orderConfirm.js文件中

  • $(“.link-pay”).click(……)作用:点击"在线支付"后跳转到支付页面,这个其实就是下个模块要做的"创建订单"功能,该功能需要和数据库交互,所以不是在前端实现的,所以这行代码无用

  • $(“.link-success”).click(…):在orderConfirm.html页面没有class为link-success的标签,所以这行代码不会被执行

    综上两条,orderConfirm.js文件在orderConfirm.html页面中无用,但存在可能会和下个模块"创建订单"功能冲突(下个模块会实现点击"创建订单"后页面跳转),所以注释掉


下面在orderConfirm.html页面编写js代码

<script type="text/javascript">
    $(document).ready(function() {
    showCartList();
	});

    function showCartList() {
        $("#cart-list").empty();
        $.ajax({
            url: "/carts/list",
            type: "GET",
            data: location.search.substr(1),
            dataType: "JSON",
            success: function(json) {
                if (json.state == 200) {
                    var list = json.data;
                    console.log(location.search.substr(1));//调试用

                    //声明两个变量用于更新"确认订单"页的总件数和总价
                    var allCount = 0;
                    var allPrice = 0;

                    for (var i = 0; i < list.length; i++) {
                        var tr = '<tr>\n' +
                            '<td><img src="..#{image}collect.png" class="img-responsive" /></td>\n' +
                            '<td>#{title}</td>\n' +
                            '<td>¥<span>#{price}</span></td>\n' +
                            '<td>#{num}</td>\n' +
                            '<td><span>#{totalPrice}</span></td>\n' +
                            '</tr>';
                        tr = tr.replace("#{image}",list[i].image);
                        tr = tr.replace("#{title}",list[i].title);
                        tr = tr.replace("#{price}",list[i].realPrice);
                        tr = tr.replace("#{num}",list[i].num);
                        tr = tr.replace("#{totalPrice}",list[i].realPrice*list[i].num);
                        $("#cart-list").append(tr);

                        //更新"确认订单"页的总件数和总价
                        allCount += list[i].num;
                        allPrice += list[i].realPrice*list[i].num;
                    }
                    $("#all-count").html(allCount);
                    $("#all-price").html(allPrice);
                }
            },
            error: function (xhr) {
                alert("在确认订单页加载勾选的购物车数据时发生未知的异常"+xhr.status);
            }
        });
    }
</script>

1.为什么点击购物车列表页面的"结算"按钮后地址栏中会请求http://localhost:8080/web/orderConfirm.html?cids=6&cids=5呢,因为该按钮有一个type=submit属性,且表单有一个action="orderConfirm.html"属性,所以点击该按钮后会携带表单中参数自动跳转

会携带哪些参数呢:把表单中有name属性的标签的value值传递出去,针对这个请求传递的是name"cids",其value值根据勾选的商品而定,可以是1或3或10

2.data: location.search.substr(1)这个API的参数为0表示截取地址栏中?后面的数据,即参数

如果这个API的参数为0则表示截取地址栏中?前面的数据,即请求地址

4.2显示选择收货地址

收货地址存放在前端的一个select下拉列表中,我们需要将查询到的当前登录用户的收货地址动态的加载到这个下拉列表中.从数据库的角度看,是一个select查询语句,在"收货地址列表展示"模块已经编写了该持久层,业务层,控制层,所以这里只需要编写对应的前端页面就可以了

1.在orderConfirm.html页面中的ready函数中添加showAddressList方法的调用,使确认订单页加载时能够自动从后端获取该用户地址填充到select控件中并将第一个地址显示出来

$(document).ready(function() {
    showCartList();
    showAddressList();
});

2.在orderConfirm.html页面中编写showAddressList方法

function showAddressList() {
    $("#address-list").empty();
    $.ajax({
        url: "/addresses",
        type: "GET",
        dataType: "JSON",
        success: function(json) {
            if (json.state == 200) {
                var list = json.data;
                for (var i = 0; i < list.length; i++) {

                    /*
                                value="#{aid}"在该模块没有用,但是扔写上,只要是从数据库查到到的数据,都要让前端页
                                面的该条数据和id绑定(因为可能干别的什么时需要用到,就比如说下一个"创建订单"模块
                                就需要根据前端传给后端的aid查询用户选中的是哪一个地址然后将其加入订单表)
                     * */
                    var opt = '<option value="#{aid}">#{name}&nbsp;&nbsp;&nbsp;#{tag}&nbsp;&nbsp;&nbsp;#{provinceName}#{cityName}#{areaName}#{address}&nbsp;&nbsp;&nbsp;#{tel}</option>';
                    opt = opt.replace("#{aid}",list[i].aid);
                    opt = opt.replace("#{name}",list[i].name);
                    opt = opt.replace("#{tag}",list[i].tag);
                    opt = opt.replace("#{provinceName}",list[i].provinceName);
                    opt = opt.replace("#{cityName}",list[i].cityName);
                    opt = opt.replace("#{areaName}",list[i].areaName);
                    opt = opt.replace("#{address}",list[i].address);
                    opt = opt.replace("#{tel}",list[i].tel);

                    $("#address-list").append(opt);
                }
            }
        },
        error: function (xhr) {
            alert("在确认订单页加载用户地址时发生未知的异常"+xhr.status);
        }
    });
}

创建订单

1.创建数据表

1.使用use命令先选中store数据库。

USE store;

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

针对该模块可以将t_order_item表和t_order表合并,但是以后可能开发某个模块可能单独用到t_order_item(比如用户查看订单时只需要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;

2.创建用户的实体类

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

/** 订单数据的实体类 */
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;
    /**
     * get,set
     * equals和hashCode
     * toString
     */
}    

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

/** 订单中的商品数据 */
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;
    /**
     * get,set
     * equals和hashCode
     * toString
     */
}    

3.创建订单-持久层

3.1规划需要执行的SQL语句

1.插入订单数据的SQL语句

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

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

inert into t_order (id除外的所有字段) values (字段的值)
3.2实现接口和抽象方法

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

public interface OrderMapper {
    /**
     * 插入订单数据
     * @param order 订单数据
     * @return 受影响的行数
     */
    Integer insertOrder(Order order);

    /**
     * 插入某一个订单中商品数据
     * @param orderItem 订单中商品数据
     * @return 受影响的行数
     */
    Integer insertOrderItem(OrderItem orderItem);
}
3.3编写映射

创建OrderMapper.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.cy.store.mapper.OrderMapper">

    <!-- 插入订单数据 -->
    <insert id="insertOrder" useGeneratedKeys="true" keyProperty="oid">
        insert into t_order (
        uid, recv_name, recv_phone, recv_province, recv_city, recv_area, recv_address,
        total_price,status, order_time, pay_time, created_user, created_time, modified_user,
        modified_time
        ) values (
        #{uid}, #{recvName}, #{recvPhone}, #{recvProvince}, #{recvCity}, #{recvArea},
        #{recvAddress}, #{totalPrice}, #{status}, #{orderTime}, #{payTime}, #{createdUser},
        #{createdTime}, #{modifiedUser}, #{modifiedTime}
        )
    </insert>

    <!-- 插入订单商品数据 -->
    <insert id="insertOrderItem" useGeneratedKeys="true" keyProperty="id">
        insert into t_order_item (
        oid, pid, title, image, price, num, created_user,
        created_time, modified_user, modified_time
        ) values (
        #{oid}, #{pid}, #{title}, #{image}, #{price}, #{num}, #{createdUser},
        #{createdTime}, #{modifiedUser}, #{modifiedTime}
        )
    </insert>
</mapper>
3.4单元测试

创建OrderMapperTests测试类并添加测试方法

@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderMapperTests {
    @Autowired
    private OrderMapper orderMapper;

    @Test
    public void insertOrder() {
        Order order = new Order();
        order.setUid(31);
        order.setRecvName("小王");
        order.setRecvPhone("133333");
        orderMapper.insertOrder(order);
    }

    @Test
    public void insertOrderItem() {
        OrderItem orderItem = new OrderItem();
        orderItem.setOid(1);
        orderItem.setPid(10000001);
        orderItem.setTitle("高档铅笔");
        orderMapper.insertOrderItem(orderItem);
    }
}

4.创建订单-业务层

4.1规划异常

无异常

4.2实现接口和抽象方法及实现

查看订单表的字段从而分析业务层方法需要哪些参数:

oid:主键自增,所以不需要该参数

uid:由控制层获取session中uid传给业务层,所以需要该参数
recv_name:通过"确认订单页"传递选中的地址aid,根据aid在在业务层调用已经声明的findByAid方法(该方法是在做"设置默认地址"模块时创建的,只在持久层创建了,并没有在业务层继续实现),所以需要参数aid
recv_phone:同上
recv_province:同上
recv_city:同上
recv_area:同上
recv_address:同上
total_price:根据前端传来的cids查询出每类商品数量和单价,然后相乘后求和,所以需要参数Integer[] cids
status:默认是0,所以不需要该参数
order_time:业务层实现方法内部可以声明,所以不需要该参数
pay_time:"创建订单"模块不需要此参数
created_user:由控制层获取session中username传给业务层,所以需要该参数
created_time:业务层实现方法内部可以声明,所以不需要该参数
modified_user:由控制层获取session中username传给业务层,所以需要该参数
modified_time:业务层实现方法内部可以声明,所以不需要该参数

综上分析,需要的参数是uid和aid,且需要在IAddressService接口添加getByAid()方法来获取选中的收货地址的详细数据:

1.在IAddressService接口中添加getByAid()方法

Address getByAid(Integer aid, Integer uid);

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

@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 {
    Order create(Integer aid, Integer[] cids, Integer uid, String username);
}

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

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

@Service
public class OrderServiceImpl implements IOrderService {

    @Autowired
    private OrderMapper orderMapper;

    //需要调用业务层的getByAid方法
    @Autowired
    private IAddressService addressService;

    //需要调用业务层的getVOByCids方法
    @Autowired
    private ICartService cartService;

    //需要调用业务层的getByUid方法
    private IUserService userService;

    @Override
    public Order create(Integer aid, Integer[] cids, Integer uid, String username) {

        //返回的列表中的对象都是即将下单的
        List<CartVO> list = cartService.getVOByCids(uid, cids);

        long totalPrice = 0L;
        for (CartVO cartVO : list) {
            totalPrice += cartVO.getRealPrice()*cartVO.getNum();

        }
        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.setOrderTime(new Date());
        order.setStatus(0);
        order.setTotalPrice(totalPrice);

        //封装四个日志
        order.setCreatedUser(username);
        order.setCreatedTime(new Date());
        order.setModifiedUser(username);
        order.setModifiedTime(new Date());
        Integer rows = orderMapper.insertOrder(order);
        if (rows != 1) {
            throw new InsertException("插入数据时产生未知的异常");
        }

        //插入数据——将某条订单的所有商品的详细数据插入
        for (CartVO cartVO : list) {
            OrderItem orderItem = new OrderItem();

            /**
             * 此时获取的oid不为空,因为在配置文件里面开启了oid主
             * 键自增,所以上面的代码执行插入时就自动将oid赋值了
             */
            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;
    }
}
4.3单元测试

创建OrderServiceTests测试类并添加create()方法进行功能测试

@SpringBootTest
@RunWith(SpringRunner.class)
public class OrderServiceTests {
    @Autowired
    private IOrderService orderService;

    @Autowired
    IUserService userService;

    @Test
    public void create() {
        Integer[] cids = {2,4,6};
        Order order = orderService.create(13, cids, 11, "小红");
        System.out.println(order);
    }
}

5.创建订单-控制层

5.1处理异常

没有异常需要处理

5.2设计请求
  • /orders/create
  • GET
  • Integer aid, Integer[] cids, HttpSession session
  • JsonResult<Order>
5.3处理请求

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

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

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

6.创建订单-前端页面

在"确认订单页"添加发送请求的处理方法使点击"在线支付"按钮可以创建订单并跳转到"支付信息页"(支付页显示详细商品信息这个功能这里不做了)

请求参数是通过字符串拼接得到的,那么就必须用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的切面编程进行开发

1.Spring AOP

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

使用步骤:

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

2.切面方法

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

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

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

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

3 统计业务方法执行时长

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包下的类是任意的
  • 第三个*表示类里面的方法是任意的
  • (…)表示方法的参数是任意的

5.启动项目,在前端浏览器访问任意一个功能模块进行功能的测试

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: 好的,下面是创建一个简单的 Spring Boot 项目的步骤: 1. 打开 IntelliJ IDEA 或 Eclipse 等 Java IDE 工具; 2. 选择创建项目,选择 Spring Initializr; 3. 配置项目的基本信息,包括项目名称、groupId、artifactId、版本号等; 4. 选择 Spring Boot 版本; 5. 添加项目的依赖,可以根据项目需要选择添加不同的依赖,例如 web、JPA、Thymeleaf 等; 6. 点击完成创建项目创建完成后,可以在 IDE 工具中打开创建项目,编辑代码并运行。可以使用 Spring Boot 的自带服务器来运行项目,也可以打包成 jar 或 war 文件进行部署。 下面是一个示例项目的 pom.xml 文件,其中添加了 web 和 Thymeleaf 依赖: ``` <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies> ``` 另外,还需要在项目中添加一个启动类,如下所示: ``` @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } ``` 这个启动类标注了 `@SpringBootApplication` 注解,告诉 Spring Boot 这是一个 Spring Boot 应用程序的入口类。其中,`main()` 方法启动了 Spring Boot 应用程序。 ### 回答2: 创建一个Spring Boot项目的步骤如下: 1. 安装Java开发工具包(JDK)并配置环境变量。确保您已经安装了适当版本的JDK,并将其路径添加到系统的环境变量中。 2. 下载并安装一个集成开发环境(IDE),如IntelliJ IDEA或Eclipse。这些IDE可以帮助简化项目创建和管理过程。 3. 启动IDE并创建一个新的项目。在IDE的界面中,选择创建一个项目的选项。根据IDE的提示,在合适的位置选择项目的名称、类型和模板。 4. 配置项目的依赖项。使用Maven或Gradle等构建工具,配置项目所需的依赖项。Spring Boot提供了许多常用的依赖项,例如Spring MVC和Spring Data JPA。 5. 创建一个主应用程序类。在项目的源代码目录中创建一个新的Java类,并使用`@SpringBootApplication`注解标记它。这个类将是应用程序的入口点,并且会自动配置Spring Boot项目。 6. 添加所需的业务逻辑和功能。根据项目的需求,在主应用程序类中创建其他类和方法,以实现所需的业务逻辑。您可以使用Spring框架的各种功能,如依赖注入和AOP等。 7. 运行和测试应用程序。在IDE中通过点击运行按钮或使用命令行界面运行应用程序。在应用程序启动后,可以使用浏览器或API测试工具来测试应用程序的功能。 8. 打包和部署应用程序。使用构建工具将代码打包成可执行的jar或war文件。然后,将生成的文件部署到适当的服务器上,以供其他用户或系统使用。 以上是创建一个Spring Boot项目的基本步骤。当然,具体的细节和配置可能会根据您的实际需求和偏好而有所不同。可以通过查阅Spring Boot官方文档和其他参考资料来获得更多详细的指导和帮助。 ### 回答3: 创建一个SpringBoot项目的步骤如下: 1. 首先,确保已经安装好Java开发环境和Maven构建工具。 2. 打开IDE(如IntelliJ IDEA)并创建一个新的Maven项目。 3. 在项目的POM文件中,添加SpringBoot的相关依赖。可以通过在Maven仓库中搜索“SpringBoot starter”来找到所需的依赖,并将其添加到POM文件中。 4. 创建一个主启动类,这个类将作为项目的入口。在类上加上`@SpringBootApplication`注解,该注解包含了`@Configuration`、`@EnableAutoConfiguration`和`@ComponentScan`三个注解,可以帮助自动配置和启动SpringBoot应用。 5. 定义其他的业务类和功能类,并在需要的地方使用注解进行配置。例如,使用`@RestController`注解定义一个RESTful接口,使用`@Repository`注解定义一个数据访问接口,使用`@Service`注解定义一个业务逻辑类等。 6. 在主启动类中使用`SpringApplication.run()`方法来启动SpringBoot应用。这个方法会根据项目的配置自动执行一系列的初始化操作,包括加载依赖、自动配置等。 7. 运行项目,并访问定义的接口或功能,验证是否正常工作。可以通过浏览器、Postman等工具进行访问。 8. 根据需要,可以在POM文件中添加其他的依赖,或者在配置文件中进行配置修改。 9. 最后,可以使用Maven进行打包和发布,以便在其他环境中进行部署和运行。 以上就是创建一个SpringBoot项目的基本步骤,根据项目的需求和功能可以进行相应的扩展和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

认真生活的灰太狼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值