> 文档中心 > 电商生鲜网站开发(一)——Spring Boot项目开发准备

电商生鲜网站开发(一)——Spring Boot项目开发准备

本系列内容完成Spring Boot框架的电商生鲜网站开发的完整案例,前后端分离开发的案例,先开发后端接口后开发前端,最后部署等待。

Spring Boot项目开发准备

文章目录

  • Spring Boot项目开发准备
    • IDEA web开发必备插件
    • Postman安装——接口自测
    • MySQL可视化工具——mac平台
    • 数据库设计
    • 项目初始化--依赖引入pom
    • 自动创建实体类和mapper
    • 配置项目的数据库连接
    • log4j2日志的引入
    • AOP统一处理Web请求日志

IDEA web开发必备插件

Maven Helper 与Maven一起工作的必备插件

Free Mybatis Tool 帮助我们跳转和识别Mapper中的一些语法错误

Postman安装——接口自测

帮助我们开发时接口自测的调试工具,免费
电商生鲜网站开发(一)——Spring Boot项目开发准备

MySQL可视化工具——mac平台

Sequel pro for mac是Mac os平台上的一款帮助用户快速连接SQL数据库的开源免费Mac软件

http://sequelpro.com/test-builds

在连接MySQL时可能会出现问题:MySQL said: Authentication plugin ‘caching_sha2_password’ cannot be loaded

这会初始化数据库,数据库有数据的话请一定备份😭

打开系偏好设置-MySQL-Initialize Database-输入设置的密码-勾选Use Legacy Password Encryption-启动MySQL

数据库设计

案例:

/* Source Server  : localhost Source Server Type    : MySQL Source Server Version : 80026 Source Host    : localhost:3306 Source Schema  : fresh_mall Target Server Type    : MySQL Target Server Version : 80026 File Encoding  : 65001*/SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for mall_cart-- ----------------------------DROP TABLE IF EXISTS `mall_cart`;CREATE TABLE `mall_cart` (  `id` int NOT NULL AUTO_INCREMENT COMMENT '购物车id',  `product_id` int NOT NULL COMMENT '商品id',  `user_id` int NOT NULL COMMENT '用户id',  `quantity` int NOT NULL DEFAULT '1' COMMENT '商品数量',  `selected` int NOT NULL DEFAULT '1' COMMENT '是否已勾选:0代表未勾选,1代表已勾选',  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='购物车';-- ------------------------------ Table structure for mall_category-- ----------------------------DROP TABLE IF EXISTS `mall_category`;CREATE TABLE `mall_category` (  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',  `name` varchar(32) NOT NULL DEFAULT '' COMMENT '分类目录名称',  `type` int NOT NULL COMMENT '分类目录级别,例如1代表一级,2代表二级,3代表三级',  `parent_id` int NOT NULL COMMENT '父id,也就是上一级目录的id,如果是一级目录,那么父id为0',  `order_num` 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 (`id`)) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品分类 ';-- ------------------------------ Table structure for mall_order-- ----------------------------DROP TABLE IF EXISTS `mall_order`;CREATE TABLE `mall_order` (  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',  `order_no` varchar(128) NOT NULL DEFAULT '' COMMENT '订单号(非主键id)',  `user_id` int NOT NULL COMMENT '用户id',  `total_price` int NOT NULL COMMENT '订单总价格',  `receiver_name` varchar(32) NOT NULL COMMENT '收货人姓名快照',  `receiver_mobile` varchar(32) NOT NULL COMMENT '收货人手机号快照',  `receiver_address` varchar(128) NOT NULL DEFAULT '' COMMENT '收货地址快照',  `order_status` int NOT NULL DEFAULT '10' COMMENT '订单状态: 0用户已取消,10未付款(初始状态),20已付款,30已发货,40交易完成',  `postage` int DEFAULT '0' COMMENT '运费,默认为0',  `payment_type` int NOT NULL DEFAULT '1' COMMENT '支付类型,1-在线支付',  `delivery_time` timestamp NULL DEFAULT NULL COMMENT '发货时间',  `pay_time` timestamp NULL DEFAULT NULL COMMENT '支付时间',  `end_time` timestamp NULL DEFAULT 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 (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单表;';-- ------------------------------ Table structure for mall_order_item-- ----------------------------DROP TABLE IF EXISTS `mall_order_item`;CREATE TABLE `mall_order_item` (  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',  `order_no` varchar(128) NOT NULL DEFAULT '' COMMENT '归属订单id',  `product_id` int NOT NULL COMMENT '商品id',  `product_name` varchar(100) NOT NULL DEFAULT '' COMMENT '商品名称',  `product_img` varchar(128) NOT NULL DEFAULT '' COMMENT '商品图片',  `unit_price` int NOT NULL COMMENT '单价(下单时的快照)',  `quantity` int NOT NULL DEFAULT '1' COMMENT '商品数量',  `total_price` int NOT NULL DEFAULT '0' 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 (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单的商品表 ';-- ------------------------------ Table structure for mall_product-- ----------------------------DROP TABLE IF EXISTS `mall_product`;CREATE TABLE `mall_product` (  `id` int NOT NULL AUTO_INCREMENT COMMENT '商品主键id',  `name` varchar(100) NOT NULL COMMENT '商品名称',  `image` varchar(500) NOT NULL DEFAULT '' COMMENT '产品图片,相对路径地址',  `detail` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '商品详情',  `category_id` int NOT NULL COMMENT '分类id',  `price` int NOT NULL COMMENT '价格,单位-分',  `stock` int NOT NULL COMMENT '库存数量',  `status` int NOT NULL DEFAULT '1' COMMENT '商品上架状态:0-下架,1-上架',  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='商品表';-- ------------------------------ Table structure for mall_user-- ----------------------------DROP TABLE IF EXISTS `mall_user`;CREATE TABLE `mall_user` (  `id` int NOT NULL AUTO_INCREMENT COMMENT '用户id',  `username` varchar(32) NOT NULL DEFAULT '' COMMENT '用户名',  `password` varchar(50) NOT NULL COMMENT '用户密码,MD5加密',  `personalized_signature` varchar(50) NOT NULL DEFAULT '' COMMENT '个性签名',  `role` int NOT NULL DEFAULT '1' COMMENT '角色,1-普通用户,2-管理员',  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表 ';SET FOREIGN_KEY_CHECKS = 1;

项目初始化–依赖引入pom

pom.xml sprintboot版本2.2.1.RELEASE

<dependency>  <groupId>org.mybatis.spring.boot</groupId>  <artifactId>mybatis-spring-boot-starter</artifactId>  <version>1.3.2</version></dependency><dependency>  <groupId>mysql</groupId>  <artifactId>mysql-connector-java</artifactId></dependency><--插件配置-->  <plugin>    <groupId>org.mybatis.generator</groupId>    <artifactId>mybatis-generator-maven-plugin</artifactId>    <version>1.3.7</version>    <configuration>      <verbose>true</verbose>      <overwrite>true</overwrite>    </configuration>  </plugin>

自动创建实体类和mapper

利用mybatis-generator自动创建实体类和mapper

resources下创建generatorConfig.xml

配置mysql-connector-java-8.0.18.jar在你电脑存放的路径,我这里都放入resources

配置数据库连接

配置生成Model类存放位置

配置生成mapper映射文件存放位置

配置生成Dao类存放位置

配置生成对应表及类名

<generatorConfiguration>      <classPathEntry    location="/Users/cat/Documents/fresh-mall/src/main/resources/mysql-connector-java-8.0.18.jar"/>  <context id="MysqlTables" targetRuntime="MyBatis3">    <property name="autoDelimitKeywords" value="true"/>        <property name="beginningDelimiter" value="`"/>    <property name="endingDelimiter" value="`"/>        <commentGenerator>      <property name="suppressDate" value="true"/>      <property name="suppressAllComments" value="true"/>    </commentGenerator>        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"      connectionURL="jdbc:mysql://127.0.0.1:3306/fresh_mall?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull"      userId="root"      password="root1024">      <property name="nullCatalogMeansCurrent" value="true"/>    </jdbcConnection>        <javaTypeResolver>      <property name="forceBigDecimals" value="false"/>    </javaTypeResolver>        <javaModelGenerator targetPackage="com.learn2333.freshmall.model.pojo"      targetProject="src/main/java">            <property name="enableSubPackages" value="true"/>            <property name="trimStrings" value="true"/>            <property name="immutable" value="false"/>    </javaModelGenerator>        <sqlMapGenerator targetPackage="mappers" targetProject="src/main/resources">      <property name="enableSubPackages" value="true"/>    </sqlMapGenerator>        <javaClientGenerator type="XMLMAPPER" targetPackage="com.learn2333.freshmall.model.dao"      targetProject="src/main/java">      <property name="enableSubPackages" value="true"/>    </javaClientGenerator>        <table schema="root" tableName="mall_cart" domainObjectName="Cart"      enableCountByExample="false"      enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"      selectByExampleQueryId="false">    </table>    <table tableName="mall_category" domainObjectName="Category" enableCountByExample="false"      enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"      selectByExampleQueryId="false">    </table>    <table tableName="mall_order" domainObjectName="Order" enableCountByExample="false"      enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"      selectByExampleQueryId="false">    </table>    <table tableName="mall_order_item" domainObjectName="OrderItem"      enableCountByExample="false"      enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"      selectByExampleQueryId="false">    </table>    <table tableName="mall_product" domainObjectName="Product" enableCountByExample="false"      enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"      selectByExampleQueryId="false">    </table>    <table tableName="mall_user" domainObjectName="User" enableCountByExample="false"      enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"      selectByExampleQueryId="false">    </table>  </context></generatorConfiguration>

点击右侧mavan中的插件–这个插件是因为上面pom中配置的才生效的

会自动生成mapper和实体类
电商生鲜网站开发(一)——Spring Boot项目开发准备

在生成的mapper接口和mapper.xml文件中左侧行号右边会有互相跳转的箭头,这是配置的IDEA插件Free Mybatis Tool 生效了

电商生鲜网站开发(一)——Spring Boot项目开发准备

配置项目的数据库连接

application.properties

server.port=8080spring.datasource.name=fresh_mallspring.datasource.url=jdbc:mysql://127.0.0.1:3306/fresh_mall?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghaispring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.username=rootspring.datasource.password=root1024#mapper的位置mybatis.mapper-locations=classpath:mappers/*.xml

Application启动类配置dao mapper接口的注解路径

@MapperScan(basePackages = "com.learn2333.freshmall.model.dao")

创建测试类

controller.UserController

package com.learn2333.freshmall.controller;import com.learn2333.freshmall.model.pojo.User;import com.learn2333.freshmall.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.ResponseBody;/** * 用户控制器 */@Controllerpublic class UserController {    @Autowired    UserService userService;    @GetMapping("/test")    @ResponseBody    public User personalPage() { return userService.getUser();    }}

service.UserService接口

package com.learn2333.freshmall.service;import com.learn2333.freshmall.model.pojo.User;public interface UserService {    User getUser();}

service.impl.UserServiceImpl实现类

package com.learn2333.freshmall.service.impl;import com.learn2333.freshmall.model.dao.UserMapper;import com.learn2333.freshmall.model.pojo.User;import com.learn2333.freshmall.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class UserServiceImpl implements UserService {    @Autowired    UserMapper userMapper;    @Override    public User getUser() { return userMapper.selectByPrimaryKey(1);    }}

运行后访问test即可获得数据,连接成功

但是此时在代码中:引入的mapper会被标红,但仍可正常运行

    @Autowired    UserMapper userMapper;

这是因为编译器无法自动识别mapper,因为mapper是在springboot入口@MapperScan(basePackages = "com.learn2333.freshmall.model.dao")配置的,这是为了给mybatis识别用的,而编译器无法识别,解决方案可以在dao下的mapper接口上增加注解@Repositor,这样IDEA就会认为@Autowired进来的mapper是一个资源。

log4j2日志的引入

日志级别:error, warn,info,debug,trace(依次向下级别递减)

排除之前的日志组件Logback依赖

pom.xml

<dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-web</artifactId>  <exclusions>    <exclusion>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-logging</artifactId>    </exclusion>  </exclusions></dependency>  <dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-log4j2</artifactId></dependency>

配置日志组件

log4j2.xml

配置日志文件保存的位置

<Configuration status="fatal">  <Properties>        <Property name="baseDir" value="${sys:user.home}/logs"/>  </Properties>  <Appenders>    <Console name="Console" target="SYSTEM_OUT">            <ThresholdFilter level="info" onMatch="ACCEPT"  onMismatch="DENY"/>      <PatternLayoutpattern="[%d{MM:dd HH:mm:ss.SSS}] [%level] [%logger{36}] - %msg%n"/>    </Console>        <RollingFile name="debug_appender" fileName="${baseDir}/debug.log"   filePattern="${baseDir}/debug_%i.log.%d{yyyy-MM-dd}">            <Filters>  <ThresholdFilter level="debug"/> <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/>      </Filters>            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>            <Policies>  <TimeBasedTriggeringPolicy interval="1" modulate="true"/>  <SizeBasedTriggeringPolicy size="100 MB"/>      </Policies>    </RollingFile>        <RollingFile name="info_appender" fileName="${baseDir}/info.log"   filePattern="${baseDir}/info_%i.log.%d{yyyy-MM-dd}">            <Filters>  <ThresholdFilter level="info"/> <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>      </Filters>            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>            <Policies>  <TimeBasedTriggeringPolicy interval="1" modulate="true"/>  <SizeBasedTriggeringPolicy size="100 MB"/>      </Policies>    </RollingFile>        <RollingFile name="error_appender" fileName="${baseDir}/error.log"   filePattern="${baseDir}/error_%i.log.%d{yyyy-MM-dd}">            <Filters>  <ThresholdFilter level="error"/>      </Filters>            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>      <Policies>  <TimeBasedTriggeringPolicy interval="1" modulate="true"/>  <SizeBasedTriggeringPolicy size="100 MB"/>      </Policies>    </RollingFile>  </Appenders>  <Loggers>    <logger name="org.springframework" level="info"     additivity="true">      <AppenderRef ref="Console" />      <AppenderRef ref="MyFile" />    </logger>        <Root level="debug">      <AppenderRef ref="Console"/>      <AppenderRef ref="debug_appender"/>      <AppenderRef ref="info_appender"/>      <AppenderRef ref="error_appender"/>    </Root>  </Loggers></Configuration>

运行项目,可以看到在配置好的文件路径下生成了日志
电商生鲜网站开发(一)——Spring Boot项目开发准备

打开控制台使用tail -f 文件名可以打印出文件新增加的内容

电商生鲜网站开发(一)——Spring Boot项目开发准备

访问一个请求,内容也会相应变化,可以用这个方法调试程序。

AOP统一处理Web请求日志

是对系统健壮性的一个保护,利用fitter把每一个请求打印出来,提高开发和调试的效率

目的:创建fitter,把请求和响应信息打印出来

pom引入aop

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

fitter.WebLogAspect.java 直接创建fitter类,利用注解配合方法实现自定义请求和响应日志的输出

package com.learn2333.freshmall.fitter;import com.fasterxml.jackson.core.JsonProcessingException;import com.fasterxml.jackson.databind.ObjectMapper;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.util.Arrays;/** * 打印请求和响应信息 */@Aspect@Componentpublic class WebLogAspect {    private final Logger log = LoggerFactory.getLogger(WebLogAspect.class);    //指定拦截点    @Pointcut("execution(public * com.learn2333.freshmall.controller.*.*(..))")    public void webLog() {    }    @Before("webLog()")    public void doBefore(JoinPoint joinPoint) { //收到请求,记录请求内容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //记录日志 //url log.info("URL : " + request.getRequestURI().toString()); //请求类型 log.info("HTTP_METHOD : " + request.getMethod()); //ip log.info("IP : " + request.getRemoteAddr()); //类的方法 log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); //参数 log.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));    }    @AfterReturning(returning = "res", pointcut = "webLog()")    public void doAfterReturn(Object res) throws JsonProcessingException { //处理完请求,返回内容 //writeValueAsString是fastjson提供的一个将对象转成json格式的工具 log.info("RESPONSE : " + new ObjectMapper().writeValueAsString(res));    }}