SpringBoot 企业微信点餐系统实战二:日志配置、商品类目开发

这是【SpringBoot企业微信点餐系统实战】系列第二篇
源码地址:https://github.com/cachecats/sell

文章列表:

SpringBoot 企业微信点餐系统实战一:环境搭建和数据库设计

SpringBoot 企业微信点餐系统实战二:日志配置、商品类目开发

SpringBoot 企业微信点餐系统实战三:商品信息及买家商品api开发


一、依赖引入和数据库配置

编辑 pom.xml 引入 mysqljpalombok 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.solo</groupId>
    <artifactId>sell</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>sell</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

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

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.properties 改名为 application.yml ,不改也行但 yml 文件写起来更爽。配置数据库连接和 jpa

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: root
    url: jdbc:mysql://127.0.0.1/sell?characterEncoding=utf-8&useSSL=false
  jpa:
    show-sql: true

二、项目日志配置

最终选择了 LogBack 作为日志工具,配置如下:

项目目录/src/main/resources 目录下新建 logback 配置文件 logback-spring.xml

<?xml version="1.0" encoding="UTF-8" ?>

<configuration>

    <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>
                %d - %msg%n
            </pattern>
        </layout>
    </appender>

    <appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <encoder>
            <pattern>
                %msg%n
            </pattern>
        </encoder>
        <!--滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--路径-->
            <fileNamePattern>/Users/solo/Documents/project/springboot/log/info.%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>


    <appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>
                %msg%n
            </pattern>
        </encoder>
        <!--滚动策略-->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--路径-->
            <fileNamePattern>/Users/solo/Documents/project/springboot/log/error.%d.log</fileNamePattern>
        </rollingPolicy>
    </appender>

    <root level="info">
        <appender-ref ref="consoleLog" />
        <appender-ref ref="fileInfoLog" />
        <appender-ref ref="fileErrorLog" />
    </root>

</configuration>

这里配置了日志格式、每天生成日志文件到指定目录、error 和其他级别日志分开、滚动策略等,就不一一介绍了,把这个文件粘到项目中就可以。

三、商品类目dao、service层开发

上篇文章介绍了数据库的设计,今天就来开发具体业务吧。
开发顺序基本是每个表先写 dto类,再写 dao 层,再写 service 层,每步开发完都进行单元测试。

3.1 类目 dto

这个没什么难度,照着数据库表每个字段写下来就好,采用驼峰式命名规则。
为方便比较,先给出上篇的商品类目 product_category sql创建语句

create table `product_category`(
    `category_id` int not null auto_increment,
    `category_name` varchar(64) not null comment '类目名字',
    `category_type` int not null comment '类目编号',
    `create_time` timestamp not null default current_timestamp comment '创建时间',
    `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',
    primary key (`category_id`),
    unique key `uqe_category_type` (`category_type`)
) comment '类目表';

新建 dto 包,在该包下新建 javaProductCategory

package com.solo.sell.dto;

import lombok.Data;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 * 商品分类
 */

@Entity
@DynamicUpdate
@Data
public class ProductCategory {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer categoryId;

    /** 种类名称 */
    private String categoryName;

    /** 种类类型 */
    private Integer categoryType;

    public ProductCategory() {
    }

    public ProductCategory(String categoryName, Integer categoryType) {
        this.categoryName = categoryName;
        this.categoryType = categoryType;
    }
}

说一下类名上面的三个注解:
@Entity:表示这是一个entity实体类
@DynamicUpdate:因为数据库中updateTime字段设置了自动更新,如果不加这个注解,自动更新将不会生效
@Datalombok 的辅助方法,可以自动生成 Get、Set、toString方法,官方文档介绍:

@Data
All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields, and @RequiredArgsConstructor!

注意:如果重写了构造方法,一定要加一个无参构造,否则后面会报错。

3.2 商品类目 repository

新建 repository 包,用来存放数据库操作的仓库。
数据库操作用 JPA ,新建接口ProductCategoryRepository 继承自 JpaRepository.

public interface ProductCategoryRepository extends JpaRepository<ProductCategory, Integer>{

    /**
     * 传入类型列表,查询包含列表中类型的所有数据
     */
    List<ProductCategory> findByCategoryTypeIn(List<Integer> types);
}

JpaRepository<ProductCategory, Integer>里面有两个参数,第一个是数据表对应的实体类名,第二个是主键类型。
这里添加一个方法 findByCategoryTypeIn(List<Integer> types),传入商品类目的类型列表,返回包含这些类目的所有数据。

3.3 商品类目 service

新建 service 包,创建接口 ProductCategoryService

package com.solo.sell.service;

import com.solo.sell.dto.ProductCategory;
import java.util.List;

public interface ProductCategoryService {

    ProductCategory findOne(Integer id);

    List<ProductCategory> findAll();

    ProductCategory save(ProductCategory productCategory);

    List<ProductCategory> findByCategoryTypeIn(List<Integer> types);
}

service 包下新建 impl 存放 service 的实现类,并创建 ProductCategoryService 的实现类 ProductCategoryServiceImpl

package com.solo.sell.service.impl;

import com.solo.sell.dto.ProductCategory;
import com.solo.sell.repository.ProductCategoryRepository;
import com.solo.sell.service.ProductCategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 类目服务实现
 */
@Service
public class ProductCategoryServiceImpl implements ProductCategoryService {

    @Autowired
    ProductCategoryRepository repository;

    @Override
    public ProductCategory findOne(Integer id) {
        return repository.findById(id).get();
    }

    @Override
    public List<ProductCategory> findAll() {
        return repository.findAll();
    }

    @Override
    public ProductCategory save(ProductCategory productCategory) {
        return repository.save(productCategory);
    }

    @Override
    public List<ProductCategory> findByCategoryTypeIn(List<Integer> types) {
        return repository.findByCategoryTypeIn(types);
    }
}

四、单元测试

ProductCategoryRepositoryProductCategoryServiceImpl 都编写单元测试。

ProductCategoryRepository 的单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductCategoryRepositoryTest {

    @Autowired
    private ProductCategoryRepository repository;

    @Test
    @Transactional
    public void add() {
        ProductCategory category = new ProductCategory("女生最爱", 1);
        ProductCategory save = repository.save(category);
        Assert.assertNotNull(save);
    }

    @Test
    public void findOne() {
        ProductCategory productCategory = repository.findById(1).get();
        Assert.assertNotNull(productCategory);
    }

    @Test
    @Transactional
    public void update() {
        ProductCategory category = repository.findById(1).get();
        category.setCategoryType(4);
        ProductCategory save = repository.save(category);
        Assert.assertNotNull(save);
    }

    /**
     * 传入类型列表,查询包含列表中类型的所有数据
     */
    @Test
    public void findByCategoryType() {
        List<Integer> types = Arrays.asList(2, 3, 4);
        List<ProductCategory> list = repository.findByCategoryTypeIn(types);
        Assert.assertNotEquals(0, list.size());
    }
}

ProductCategoryServiceImpl 的单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductCategoryServiceImplTest {

    @Autowired
    ProductCategoryServiceImpl service;

    @Test
    public void findOne() {
        ProductCategory one = service.findOne(1);
        Assert.assertEquals(new Integer(1), one.getCategoryId());
    }

    @Test
    public void findAll() {
        List<ProductCategory> list = service.findAll();
        Assert.assertNotEquals(0, list.size());
    }

    @Test
    public void save() {
        ProductCategory cate = service.save(new ProductCategory("热销榜", 5));
        Assert.assertNotNull(cate);
    }

    @Test
    public void findByCategoryTypeIn() {
        List<ProductCategory> list = service.findByCategoryTypeIn(Arrays.asList(3, 4, 5, 6));
        Assert.assertNotEquals(0, list.size());
    }
}

注意:在测试方法上加注解 @Transactional ,会在测试之后把测试中操作的数据库全部回滚,不会因为测试污染数据库。

今天就到这,下次见~

源码地址:https://github.com/cachecats/sell

文章列表:

SpringBoot 企业微信点餐系统实战一:环境搭建和数据库设计

SpringBoot 企业微信点餐系统实战二:日志配置、商品类目开发

SpringBoot 企业微信点餐系统实战三:商品信息及买家商品api开发

猜你喜欢

转载自blog.csdn.net/solocoder/article/details/81670079