一.项目设计
1.角色划分
- 买家(手机端)
- 卖家(PC端)
2.功能分析
- 买家
- 查看商品列表
- 订单创建
- 订单查询
- 订单取消
- …
- 卖家
- 订单管理
- 商品管理
- 类目管理
- …
3.数据库设计
-
数据库表之间的关系说明
- 类目表product_category
- 商品表product_info
- 订单详情表order_detail
- 订单主表order_master
- 卖家信息表seller_info
-
设计数据库表
#创建数据库 create database WechatOrder; #切换数据库 use WechatOrder; #商品表 create table `product_info`( `product_id` varchar(32) not null, `product_name` varchar(64) not null comment '商品名称', `product_price` decimal(8,2) not null comment '单价', `product_stock` int not null comment '库存', `product_description` varchar(64) comment '描述', `product_icon` varchar(512) comment '小图', `category_type` int not null comment '类目编号', `create_time` timestamp not null default current_timestamp comment '创建时间',#timestamp是时间戳 `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',#设置当修改的时候自动记录时间 primary key(`product_id`) )comment '商品表'; #类目表 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 '创建时间',#timestamp是时间戳 `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 '类目表'; #订单主表 create table `order_master`( `order_id` varchar(32) not null, `buyer_name` varchar(32) not null comment '买家名字', `buyer_phone` varchar(32) not null comment '买家电话', `buyer_address` varchar(128) not null comment '买家地址', `buyer_openid` varchar(64) not null comment '买家微信openid', `order_amount` decimal(8,2) not null comment '订单总金额', `order_status` tinyint(3) not null default '0' comment '订单状态,默认0新下单', `pay_status` tinyint(3) not null default '0' comment '支付状态,默认0未支付', `create_time` timestamp not null default current_timestamp comment '创建时间',#timestamp是时间戳 `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',#设置当修改的时候自动记录时间 primary key(`order_id`), key `idx_buyer_openid`(`buyer_openid`) )comment '订单主表'; #订单详情表 create table `order_detail`( `detail_id` varchar(32) not null, `order_id` varchar(32) not null, `product_id` varchar(32) not null, `product_name` varchar(64) not null comment '商品名称', `product_price` decimal(8,2) not null comment '商品价格', `product_quantity` int not null comment '商品数量', `product_icon` varchar(512) comment '商品小图', `create_time` timestamp not null default current_timestamp comment '创建时间',#timestamp是时间戳 `update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',#设置当修改的时候自动记录时间 primary key(`detail_id`), key `idx_order_id` (`order_id`) )comment '订单详情表';
4.开发环境搭建
- 虚拟机操作系统centos7.3
- JDK
- Maven
- Idea编辑器
5.日志
-
什么是日志框架?
- 是一套能实现日志输出的工具包
- 能够描述系统运行状态的所有时间都可以算作日志
- 什么算作日志:用户下线,接口超时,数据库崩溃,Helloworld
-
日志框架的能力
- 定制输出目标(
System.out
只能将日志输出到控制台) - 定制输出格式(通过配置文件修改日志文件的具体内容,在不修改的情况下任意修改日志格式)
- 携带上下文信息
- 运行时选择性输出(根据需要输出对应模块的日志信息)
- 灵活的配置
- 优异的性能
- 定制输出目标(
-
常见的日志框架
- JDK自带的
log.in
,简称JUL - Apache自带的
common log in
,简称JCL - Log4j
- Log4j2
- Logback
- SLF4j
- Jboss-logging
- 分类
日志门面 日志实现 JCL Log4j SLF4j Log4j2 Jboss-logging Logback JUL - JDK自带的
-
使用SLF4j实例代码
package com.wechatorder.sell.service; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class LoggerTest { private final Logger logger = LoggerFactory.getLogger(LoggerTest.class);//参数是当前类,表示记录日志的类。可以在类上使用@Slf4j注解替代。 @Test public void test1(){ logger.debug("debug...");//没有输出内容,因为系统默认的日志级别是info,在info之上的可以输出出来 logger.info("info...");//2018-09-27 20:09:57.730 INFO 1519 --- [ main] com.wechatorder.sell.service.LoggerTest : info... logger.error("error...");//2018-09-27 20:09:57.730 ERROR 1519 --- [ main] com.wechatorder.sell.service.LoggerTest : error... } }
-
org.slf4j.event.Level
中的等级分布等级 级别(越大级别越高) ERROR 40 WARN 30 INFO 20 DEBUG 10 TRACE 0 -
在类上使用@Slf4j注解替代
LoggerFactory.getLogger(LoggerTest.class)
-
需引入maven依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
-
logger可以使用log替换
-
替换后的代码
package com.wechatorder.sell.service; import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest @Slf4j public class LoggerTest { @Test public void test1(){ log.debug("debug...");//没有输出内容,因为系统默认的日志级别是info,在info之上的可以输出出来 log.info("info...");//2018-09-27 20:34:14.844 INFO 1661 --- [ main] com.wechatorder.sell.service.LoggerTest : info... log.error("error...");//2018-09-27 20:34:14.844 ERROR 1661 --- [ main] com.wechatorder.sell.service.LoggerTest : error... } }
-
-
打印日志中使用变量,实例代码(
{}
表示占位符)package com.wechatorder.sell.service; import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest @Slf4j public class LoggerTest { @Test public void test1(){ String username = "Jack"; String perference = "smart"; log.debug("debug...");//没有输出内容,因为系统默认的日志级别是info,在info之上的可以输出出来 log.info("info...");//2018-09-27 20:09:57.730 INFO 1519 --- [ main] com.wechatorder.sell.service.LoggerTest : info... log.error("error...");//2018-09-27 20:09:57.730 ERROR 1519 --- [ main] com.wechatorder.sell.service.LoggerTest : error... log.info("Your name is {}, your perference is {}",username,perference);//2018-09-27 20:38:51.486 INFO 1683 --- [ main] com.wechatorder.sell.service.LoggerTest : Your name is Jack, your perference is smart } }
-
-
Logback的使用与配置
-
application.yml
中配置 -
logback-spring.xml
中配置 -
Logback的配置需求:
-
区分info和error日志
-
每天产生一个日志文件(便于日后定位问题,查找方便)
-
配置
application.yml
的logging:pattern:console
实现按照指定格式输出日志【演示功能,实际实现上述需求请参见下方对logback-spring.xml
的配置】#%d日期 %msg日志信息 %n换行 logging: pattern: console: "%d - %msg%n" #path:/var/log/tomcat #会输出spring.log日志文件到此路径(文件中记录日志) file:/var/log/tomcat/sell.log #会输出指定日志文件名sell.log的文件到此路径(文件中记录日志) level:debug
- 上述代码输出结果
2018-09-27 20:45:49,760 - info... 2018-09-27 20:45:49,760 - error... 2018-09-27 20:45:49,760 - Your name is Jack, your perference is smart
logging:path:/var/log/tomcat
会输出spring.log日志文件到此路径(文件中记录日志信息)logging:file:/var/log/tomcat/sell.log
会输出指定日志文件名sell.log的文件到此路径(文件中记录日志信息)【通常我们会采用file,因为可以自定义文件名。且file和path二选一即可】logging:level:debug
将默认的日志级别从info变成debug(也可以指定文件的日志级别:logging:level:com.wechatorder.sell.service.LoggerTest:debug
)
-
配置
logback-spring.xml
实现按照指定格式输出日志(如resources文件夹下没有则自行创建)<?xml version="1.0" encoding="UTF-8" ?> <configuration> <appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender"><!-- appender为配置项,含义为此配置项需要用到ConsoleAppender类去处理 --> <layout class="ch.qos.logback.classic.PatternLayout"><!-- layout为一个展示的形式 --> <pattern><!-- 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><!-- 只输出INFO级别的日志 --> <onMatch>DENY</onMatch><!-- 如果匹配则禁止 --> <onMismatch>ACCEPT</onMismatch><!-- 如果没有匹配则使用 --> </filter> <encoder> <pattern><!-- 设置展示形式 --> %msg%n </pattern> </encoder> <!-- 滚动策略 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按照时间滚动 --> <!-- 输出路径,可以利用%d在输出文件中加上时间 --> <fileNamePattern>/Users/wangzhe/Desktop/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><!-- 只输出ERROR级别的日志 --> </filter> <encoder> <pattern><!-- 设置展示形式 --> %msg%n </pattern> </encoder> <!-- 滚动策略 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按照时间滚动 --> <!-- 输出路径,可以利用%d在输出文件中加上时间 --> <fileNamePattern>/Users/wangzhe/Desktop/error.%d.log</fileNamePattern> </rollingPolicy> </appender> <root level="info"><!-- root表示整个项目都适用,level级别为info --> <appender-ref ref="consoleLog"></appender-ref><!-- 关联上方设置的appender --> <appender-ref ref="fileInfoLog"></appender-ref><!-- 关联上方设置的appender --> <appender-ref ref="fileErrorLog"></appender-ref><!-- 关联上方设置的appender --> </root> </configuration>
-
info.2018-09-27.log
Starting LoggerTest on Jack.local with PID 1936 (started by wangzhe in /Users/wangzhe/Practice/微信点餐系统) No active profile set, falling back to default profiles: default Refreshing org.springframework.web.context.support.GenericWebApplicationContext@13d73f29: startup date [Thu Sep 27 21:32:09 CST 2018]; root of context hierarchy Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] Looking for @ControllerAdvice: org.springframework.web.context.support.GenericWebApplicationContext@13d73f29: startup date [Thu Sep 27 21:32:09 CST 2018]; root of context hierarchy Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest) Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] Started LoggerTest in 4.076 seconds (JVM running for 5.469) info... Your name is Jack, your perference is smart Closing org.springframework.web.context.support.GenericWebApplicationContext@13d73f29: startup date [Thu Sep 27 21:32:09 CST 2018]; root of context hierarchy
-
error.2018-09-27.log
error...
-
-
-