新版本微服务时代Spring Boot企业微信点餐系统-课程笔记

第1章 课程介绍

1-1 课程导学

第2章 项目设计

2-1 课程源码和文档

源码下载
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 切换到对应章节的源码
    在这里插入图片描述
    在这里插入图片描述

2-2 项目设计

2-3 架构和基础框架

2-4 数据库设计

第3章 项目起步

3-1 开发环境搭建

新建数据库

在这里插入图片描述
在这里插入图片描述
在Navicat上执行SQL语句
在这里插入图片描述
在这里插入图片描述

3-2 日志的使用

第4章 买家端类目

4-1 买家类目-dao(上)

数据库修改时间自动跟新

在这里插入图片描述
在这里插入图片描述

通过传入List类型的参数查询

在这里插入图片描述
以上查询方法要求需要实体类中有无参的构造方法
在这里插入图片描述
在这里插入图片描述

4-2 买家类目-dao(下)

避免重复写Get /set/toString方法

包含依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

安装插件
在这里插入图片描述
在类上面添加@Data注解,就不用再写get和set和toString方法了,而且不影响性能,性能和手写一样
在这里插入图片描述

@Test 中的@Transactional

单元测试的@TransActional注解会自动回滚,他会自动带有@Rollback(true),不会修改数据库中的数据,如果需要修改数据库就不要使用@TransActional注解或者添加@Rollback(flase)
在这里插入图片描述

4-3 买家类目-service

在这里插入图片描述
在这里插入图片描述

第5章 买家端商品

5-1 买家商品-dao

5-2 买家商品-service

分页

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

新建枚举类

在这里插入图片描述
在这里插入图片描述
在service中使用
在这里插入图片描述

5-3 买家商品-api(上)

在这里插入图片描述
在这里插入图片描述

  • application.yml 中配置
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
对应代码

@Data
public class ResultVO<T> {

    /** 错误码. */
    private Integer code;

    /** 提示信息. */
    private String msg;

    /** 具体内容. */
    private T data;
}

@Data
public class ProductVO {

    @JsonProperty("name")
    private String categoryName;

    @JsonProperty("type")
    private Integer categoryType;

    @JsonProperty("foods")
    private List<ProductInfoVO> productInfoVOList;
}

@Data
public class ProductInfoVO {

    @JsonProperty("id")
    private String productId;

    @JsonProperty("name")
    private String productName;

    @JsonProperty("price")
    private BigDecimal productPrice;

    @JsonProperty("description")
    private String productDescription;

    @JsonProperty("icon")
    private String productIcon;
}

5-4 买家商品-api(下)

在这里插入图片描述
在这里插入图片描述

第6章 买家端订单

6-1 买家订单-dao(上)

在实体类中设置默认值

在这里插入图片描述

6-2 买家订单-dao(下)

6-3 买家订单-service创建_A

字段忽略

不建议,最好再重新建个类,数据传输对象,在每个层之间传数据用的

在这里插入图片描述

6-4 买家订单-service创建_B

创建异常

异常类

public class SellException extends RuntimeException{

    private Integer code;

    public SellException(ResultEnum resultEnum) {
        super(resultEnum.getMessage());

        this.code = resultEnum.getCode();
    }

    public SellException(Integer code, String message) {
        super(message);
        this.code = code;
    }
}

异常方法参数枚举

@Getter
public enum ResultEnum {

    PARAM_ERROR(1, "参数不正确"),

    PRODUCT_NOT_EXIST(10, "商品不存在"),

    PRODUCT_STOCK_ERROR(11, "商品库存不正确"),
 
    ;

    private Integer code;

    private String message;

    ResultEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}

异常使用
在service使用

//1. 查询商品(数量, 价格)
        for (OrderDetail orderDetail: orderDTO.getOrderDetailList()) {
            ProductInfo productInfo =  productService.findOne(orderDetail.getProductId());
            if (productInfo == null) {
                throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
            }

BigDecimal的乘法加法

初始化

 BigDecimal orderAmount = new BigDecimal(BigInteger.ZERO);

不能直接使用±*/,只能使用BigDecimal的类方法
productInfo.getProductPrice()*orderDetail.getProductQuantity())的BigDecimal的乘法如下:

 productInfo.getProductPrice() .multiply(new BigDecimal(orderDetail.getProductQuantity()))

a+b:

a.add(d);

产生随机数

在这里插入图片描述

public class KeyUtil {

    /**
     * 生成唯一的主键
     * 格式: 时间+随机数
     * @return
     */
    public static synchronized String genUniqueKey() {
        Random random = new Random();
        Integer number = random.nextInt(900000) + 100000;

        return System.currentTimeMillis() + String.valueOf(number);
    }
}

6-5 买家订单-service创建_C

@Transactional 事务注解

在这里插入图片描述

6-6 买家订单-service创建_D

6-7 买家订单-service查询

6-8 买家订单-service取消

6-9 买家订单-service finish和paid

6-10 买家订单-api_A

Json转换工具

<dependency>
	<groupId>com.google.code.gson</groupId>
	<artifactId>gson</artifactId>
</dependency>

例子:
在这里插入图片描述

 List<OrderDetail> orderDetailList = new ArrayList<>();
        try {
            orderDetailList = gson.fromJson(orderForm.getItems(),
                    new TypeToken<List<OrderDetail>>() {
                    }.getType());
        } catch (Exception e) {
            log.error("【对象转换】错误, string={}", orderForm.getItems());
            throw new SellException(ResultEnum.PARAM_ERROR);
        }

6-11 买家订单-api_B

Postman使用技巧

在这里插入图片描述
在这里插入图片描述
转换成功,但会有些发生错乱
在这里插入图片描述
一条键值对不要有回车
在这里插入图片描述
在这里插入图片描述
去掉多余的引号
在这里插入图片描述

6-12 买家订单-api_C

@JsonInclude(JsonInclude.Include.NON_NULL)

对于非必须返回的值,且返回为空时再此属性的类上加上@JsonInclude(JsonInclude.Include.NON_NULL)
在这里插入图片描述
在这里插入图片描述
加上注解后,为null不再返回
在这里插入图片描述

在这里插入图片描述
必须返回的字段,且不能返回为null,需要在类中给定默认初始值

6-13 买家订单-api_D

第9章 卖家端订单

9-1 卖家订单-service

9-2 卖家-订单-controller(上)

分页查询

controller

    /**
     * 订单列表
     * @param page 第几页, 从1页开始
     * @param size 一页有多少条数据
     * @return
     */
    @GetMapping("/list")
    public ModelAndView list(@RequestParam(value = "page", defaultValue = "1") Integer page,
                             @RequestParam(value = "size", defaultValue = "10") Integer size,
                             Map<String, Object> map) {
        PageRequest request = PageRequest.of(page - 1, size);
        Page<OrderDTO> orderDTOPage = orderService.findList(request);
        map.put("orderDTOPage", orderDTOPage);
        map.put("currentPage", page);
        map.put("size", size);
//        orderDTOPage.getTotalPages()
        return new ModelAndView("order/list", map);
    }

service

@Override
    public Page<OrderDTO> findList(Pageable pageable) {
        Page<OrderMaster> orderMasterPage = orderMasterRepository.findAll(pageable);

        List<OrderDTO> orderDTOList = OrderMaster2OrderDTOConverter.convert(orderMasterPage.getContent());

        return new PageImpl<>(orderDTOList, pageable, orderMasterPage.getTotalElements());
    }

ibootstrap前端页面

官网
http://www.ibootstrap.cn/

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
9-3 卖家-订单-controller(下) (15:30)
9-4 卖家订单-controller-翻页 (16:59)
9-5 卖家订单-controller-取消订单 (17:51)
9-6 卖家订单-controller-订单详情 (16:50)
9-7 卖家订单-controller-完结订单 (05:11)
第10章 卖家端通用功能和上下架
10-1 关于模版的小技巧 (02:57)
10-2 实现边栏 (11:08)
10-3 实现商品列表 (16:10)
10-4 商品上下架-service (09:10)
10-5 商品上下架-controller (07:25)
第11章 卖家端新增商品和类目
11-1 卖家商品-新增修改页面 (21:06)
11-2 卖家商品-修改表单提交 (11:16)
11-3 卖家商品-新增功能 (06:49)
11-4 卖家类目功能开发 (18:15)

第12章 买家和卖家端联通

12-1 分布式session理论(上)

在这里插入图片描述
在这里插入图片描述

  • 分布式:不同业务功能的节点,每个节点都可以做成集群
  • 集群:相同业务功能的节点(集群不一定是分布式的)

12-2 分布式session理论(下) (05:47)
12-3 卖家信息表-dao开发 (06:12)
12-4 卖家扫码登录service开发 (03:02)
12-5 卖家扫码登录获取openid (19:15)
12-6 登录成功 (24:16)
12-7 登出成功 (13:17)

12-8 AOP实现身份验证

@Aspect
@Component
@Slf4j
public class SellerAuthorizeAspect {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Pointcut("execution(public * com.imooc.controller.Seller*.*(..))" +
    "&& !execution(public * com.imooc.controller.SellerUserController.*(..))")
    public void verify() {}

    @Before("verify()")
    public void doVerify() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //查询cookie
        Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN);
        if (cookie == null) {
            log.warn("【登录校验】Cookie中查不到token");
            throw new SellerAuthorizeException();
        }

        //去redis里查询
        String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue()));
        if (StringUtils.isEmpty(tokenValue)) {
            log.warn("【登录校验】Redis中查不到token");
            throw new SellerAuthorizeException();
        }
    }
}

12-9 微信模版消息推送 (21:05)
12-10 webSocket消息推送 (26:37)

第13章 项目优化

13-1 异常捕获

在这里插入图片描述

@ControllerAdvice
public class SellExceptionHandler {

    @Autowired
    private ProjectUrlConfig projectUrlConfig;

    //拦截登录异常
    //http://sell.natapp4.cc/sell/wechat/qrAuthorize?returnUrl=http://sell.natapp4.cc/sell/seller/login
    @ExceptionHandler(value = SellerAuthorizeException.class)
//    @ResponseStatus(HttpStatus.FORBIDDEN)
    public ModelAndView handlerAuthorizeException() {
        return new ModelAndView("redirect:"
        .concat(projectUrlConfig.getWechatOpenAuthorize())
        .concat("/sell/wechat/qrAuthorize")
        .concat("?returnUrl=")
        .concat(projectUrlConfig.getSell())
        .concat("/sell/seller/login"));
    }

    @ExceptionHandler(value = SellException.class)
    @ResponseBody
    public ResultVO handlerSellerException(SellException e) {

        return ResultVOUtil.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(value = ResponseBankException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public void handleResponseBankException() {

    }
}

13-2 mybatis注解方式使用_A

	<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.2.0</version>
		</dependency>
public interface ProductCategoryMapper {

    @Insert("insert into product_category(category_name, category_type) values (#{categoryName, jdbcType=VARCHAR}, #{category_type, jdbcType=INTEGER})")
    int insertByMap(Map<String, Object> map);  //写入成功返回1,失败返回0

    @Insert("insert into product_category(category_name, category_type) values (#{categoryName, jdbcType=VARCHAR}, #{categoryType, jdbcType=INTEGER})")
    int insertByObject(ProductCategory productCategory);

    @Select("select * from product_category where category_type = #{categoryType}")
    @Results({
            @Result(column = "category_id", property = "categoryId"),
            @Result(column = "category_name", property = "categoryName"),
            @Result(column = "category_type", property = "categoryType")
    })
    ProductCategory findByCategoryType(Integer categoryType);

    @Select("select * from product_category where category_name = #{categoryName}")
    @Results({
            @Result(column = "category_id", property = "categoryId"),
            @Result(column = "category_name", property = "categoryName"),
            @Result(column = "category_type", property = "categoryType")
    })
    List<ProductCategory> findByCategoryName(String categoryName);

    @Update("update product_category set category_name = #{categoryName} where category_type = #{categoryType}")
    int updateByCategoryType(@Param("categoryName") String categoryName,
                             @Param("categoryType") Integer categoryType);

    @Update("update product_category set category_name = #{categoryName} where category_type = #{categoryType}")
    int updateByObject(ProductCategory productCategory);

    @Delete("delete from product_category where category_type = #{categoryType}")
    int deleteByCategoryType(Integer categoryType);

    ProductCategory selectByCategoryType(Integer categoryType);
}

在这里插入图片描述


@SpringBootApplication
@MapperScan(basePackages = "com.imooc.dataobject.mapper")
@EnableCaching
public class SellApplication {

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

  • 测试
  • 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class ProductCategoryMapperTest {

    @Autowired
    private ProductCategoryMapper mapper;

    @Test
    public void insertByMap() throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("categoryName", "师兄最不爱");
        map.put("category_type", 101);
        int result = mapper.insertByMap(map);
        Assert.assertEquals(1, result);
    }

    @Test
    public void insertByObject() {
        ProductCategory productCategory = new ProductCategory();
        productCategory.setCategoryName("师兄最不爱");
        productCategory.setCategoryType(102);
        int result = mapper.insertByObject(productCategory);
        Assert.assertEquals(1, result);
    }

    @Test
    public void findByCategoryType() {
        ProductCategory result = mapper.findByCategoryType(102);
        Assert.assertNotNull(result);
    }

    @Test
    public void findByCategoryName() {
        List<ProductCategory> result = mapper.findByCategoryName("师兄最不爱");
        Assert.assertNotEquals(0, result.size());
    }

    @Test
    public void updateByCategoryType() {
        int result = mapper.updateByCategoryType("师兄最不爱的分类", 102);
        Assert.assertEquals(1, result);
    }

    @Test
    public void updateByObject() {
        ProductCategory productCategory = new ProductCategory();
        productCategory.setCategoryName("师兄最不爱");
        productCategory.setCategoryType(102);
        int result = mapper.updateByObject(productCategory);
        Assert.assertEquals(1, result);
    }

    @Test
    public void deleteByCategoryType() {
        int result = mapper.deleteByCategoryType(102);
        Assert.assertEquals(1, result);
    }

    @Test
    public void selectByCategoryType() {
        ProductCategory productCategory = mapper.selectByCategoryType(101);
        Assert.assertNotNull(productCategory);
    }

}

在这里插入图片描述
在这里插入图片描述
13-3 mybatis注解方式使用_B
13-4 mybatis xml方式使用 (08:16)

13-5 jpa和mybatis的选择

  • 小型的项目用jpa
    在这里插入图片描述

13-6 ab压测介绍

在这里插入图片描述

13-7 synchronized处理并发

在这里插入图片描述

13-8 redis分布式锁

13-9 redis缓存的使用(上)

13-10 redis缓存的使用(下) (14:14)

第14章 项目部署

pom.xml
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

14-1 项目部署 (17:33)
第15章 课程总结
15-1 13.总结 (04:19)
第16章 SpringBoot2.x版

16-1 抓包

16-2 升级到2.1.1 (21:56)
16-3 支付理论 (06:48)
16-4 授权1 (19:09)
16-5 授权2 (19:58)

16-6 网络不通调试方法

在这里插入图片描述
16-7 支付1 (11:54)
16-8 支付2 (12:44)
第17章 实战-ID-187-SpringCloud体验章
17-1 导学 (11:57)
17-2 微服务和其他常见架构 (11:45)
17-3 从一个极简的微服务架构开始 (09:08)
17-4 Spring Cloud Eureka (01:33)
17-5 Eureka Server (17:17)
17-6 Eureka Client的使用 (16:07)
17-7 Eureka的高可用 (10:32)
17-8 Eureka总结_音频.mp4 (02:31)
17-9 分布式下服务注册的地位和原理 (11:53)

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值