毕设利器,教你从零搭建一个有规范的spring boot项目【二】

接上篇《毕设利器,教你从零搭建一个有规范的spring boot项目【一】》

之前只是做了简单的访问测试,要作为一个完整的web项目,我们需要

  1. 解析用户发出的请求
  2. 拿到数据库中的数据
  3. 进行数据的运算
  4. 将数据呈现在用户面前

之前只是简单地了解了第一步,接下来要连接数据库,通常用的都是MySQL。

引入依赖

首先还是拿别人写好的代码,引入连接数据库所需要的依赖:

<!--整合mybatis-plus-->
<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>3.3.2</version>
</dependency>
<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.11</version>
</dependency>
<!--alibaba的数据连接池-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.21</version>
</dependency>

这里说一下这些依赖的作用,在学习Java Web的时候,我们连接数据库需要做下面几件事:

  1. 建立和数据库的连接
  2. 编写SQL查询我们想要的数据
  3. 关闭和数据库的连接

上面这些依赖的作用就是让你省去1、3两个步骤,专注于SQL的编写。

但还是要写一写配置文件的,声明你要连接哪个数据库,对应的账号密码是多少。

然后那些繁琐的连接操作,框架会帮你解决的。

注意,这里的驱动(即第二个依赖:mysql-connector-java)要看对应的mysql版本,我的mysql是8以上的,所以mysql驱动要用8.0.11的。

如果你的mysql是5.X的,建议去找5.X的mysql驱动。

我之前用的mysql驱动是5.X的,就会报错,因此这块要注意。

至于怎么查看自己的MySQL版本,可以百度一下。

5.X的驱动,也可以百度MySQL5.X的依赖。

编写配置文件

接下来在application.properties文件中编写对应的配置文件,此举在于告诉框架,我们要连接哪个数据库、对应的账号密码是多少,还有一些细小的配置。

有些spring boot项目用的是application.yml文件,但都是一个东西,只是语法不一样而已,这里用的是application.properties,它都会放在如下图的位置:
在这里插入图片描述

在application.properties中配置数据源DataSource,这里的配置根据自己的实际情况写

springboot数据源初始化

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/你的数据库名?serverTimezone=UTC&characterEncoding=utf8&useUnicode=true&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=你的数据库用户名
spring.datasource.password=你的数据库密码

同样的,这里的url(即代码中的第三行)MySQL5.X的写法跟我8.X的写法是不一样的,同样需要你去百度。

只会比我上面这个写法简单。

MySQL建数据库的规范

说到这里顺便说一下MySQL建表的规范好了。

我用的是navicat,都是一样的。

在这里插入图片描述
现在建库的字符集都是用utf8mb4,听说可以存表情图标?

哈哈哈,细节不用管太多,通常都是用这个字符集的,可以解决很多问题。

建一个用户表(user)举个例子。

在这里插入图片描述
一个有规范的表,除了用户信息和主键,还应该有is_delete、create_time、update_time字段,这三个字段的作用分别是:

  • is_delete:1表示删除,0表示还没删除,通常我们很多的删除操作都不是真正的删除,因为如果你数据库学的还不错的话,你就知道如果要建立索引,数据就不能经常删除。此外不真正地删除数据后面说不定也能用上。格式用tinyint就行,横竖只会有1和0两个值。设置默认值为0就行,插入数据的时候可以不用管,MySQL会自动生成的。
    在这里插入图片描述

  • create_time:创建时间,一般默认值设置为now()就行,插入的时候甚至不用管他,MySQL会自动生成的。

  • update_time:更新时间,通常我们也是默认值设置为now(),不过需要再勾选个【根据当前时间戳更新】,同样的,更新跟插入数据的时候也是不用管他,MySQL会自动生成的。
    在这里插入图片描述

最好再给表写个注释,说明这个表是干嘛用的:
在这里插入图片描述

当然这些只是规范,公司不同,具体的字段名也会不同,但这三个字段基本都会有。

甚至于说,你不按我说的来也行。

只是,会看我这篇博客的通常都是刚入门的,还没工作的,我也是在网上看着各种教程自学过来的。

怎么说呢,能提前熟悉一下公司的规范也不是坏事,并且事情做的工整些,也是个好习惯,你说是不是?

而且这些确实有好处,小项目可能体现不出来,但有的时候找bug就是要靠这些字段来判断。

注释写的好,后面回来看也快。

如果你用的不是navicat,不知道上面一些操作在哪设置,你也可以复制我下面的建表SQL:

/*
 Navicat MySQL Data Transfer

 Source Server         : localhost_3306
 Source Server Type    : MySQL
 Source Server Version : 80019
 Source Host           : localhost:3306
 Source Schema         : demo

 Target Server Type    : MySQL
 Target Server Version : 80019
 File Encoding         : 65001

 Date: 06/09/2021 23:27:07
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `uuid` bigint(0) NOT NULL COMMENT '主键',
  `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',
  `is_delete` tinyint(1) NULL DEFAULT NULL COMMENT '1删除',
  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
  `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`uuid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

表建好了,那么让我们回到spring boot,继续我们的工作。

Java是面向对象的,通常我们需要个对象,来装我们从数据库中查出来的对象,这里也是有规范的。

model层

上篇文章已经说明了mvc,大概讲了c即controller,这里讲一下m即model,翻译过来就是模型,其实就是上面说的用来装数据的对象。

这些大体上分为po和vo:

  • po:跟数据库里的字段一摸一样,不能有任何偏差。
  • vo:展现到前端的数据,根据不同的业务展现字段。

以刚刚建的user表为例,我们要把数据放进去,就需要一个和数据库字段一摸一样的UserPO类来装数据。

在controller层的平级建一个model包:
在这里插入图片描述
再在model包下建一个po包:
在这里插入图片描述
然后建一个UserPO类,这个类的字段要求和数据库中的user表一摸一样:

package com.TandK.model.po;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;

/**
 * 用户表
 * @TableName user
 */
@TableName(value ="user")
@Data
public class UserPO implements Serializable {
    /**
     * 主键
     */
    @TableId(value = "uuid")
    private String uuid;

    /**
     * 用户名
     */
    @TableField(value = "name")
    private String name;

    /**
     * 1删除
     */
    @TableField(value = "is_delete")
    private Integer isDelete;

    /**
     * 
     */
    @TableField(value = "create_time")
    private Date createTime;

    /**
     * 
     */
    @TableField(value = "update_time")
    private Date updateTime;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

这里解释一下类上的注解@Data,是lombok的注解,它会生成对应字段的getter/setter方法,这样你就可以不用自己写了。

@TableName(value =“user”)注解是告诉框架,这个类对应的是数据库中的哪个表。

@TableField()注解,可以看到每个字段都有,就是声明这个字段对应数据库中该表的哪个字段,很多情况下,数据库的注解是下划线的,而java通常用的是驼峰,比如上面的创建时间这个字段,在数据库中它是create_time,在java中它就是createTime,写下这个注解能解决很多问题。

如果字段保证一样,这个注解可以不写。

然后可以看到uuid字段,明明数据库里设置的bigint类型,到这里为什么改成了String类型了?

这是因为设置成bigint,19位长度的数字的话,在传送给前端的时候会丢失精度,用String的话的可以解决这个问题。

上面是po的一些规范,接下来说说vo的。

同样是user,需要在model包下建一个vo包,再在vo包下建一个UserVO类,注意和po是同级的:
在这里插入图片描述
为什么要这么麻烦呢?

因为有的时候一些字段是不需要暴露给前端的,我们自己用就行了,比如is_delete、create_time、update_time这些字段,当然具体的业务还会有不同。

那这里的user为例,那么UserVO的字段只需要下面这些:

package com.TandK.model.vo;

import lombok.Data;

/**
 * @author TandK
 * @since 2021/9/6 23:58
 */
@Data
public class UserVO {

    /**
     * 主键
     */
    private String uuid;

    /**
     * 用户名
     */
    private String name;

}

view层

说完了mvc的m和c,顺便说说v好了,v即view层,就是视觉层,早些年项目都是前后端一起写的,现在前后端分离,现在view层不需要我们写了,交给专业的前端。

结合起来理解mvc,其实就是

  1. 用户在浏览器输入了一个链接,你的controller层会解析这个url,决定调用什么方法。
  2. 通常来说会需要去数据库里查数据,这个时候model层就起了作用了,首先用po装你刚查出来的数据,再转成vo,有选择地展现一些数据出去。
  3. 接下来再渲染view层,这样用户就看到了一个完整的网页了。

其实就是这么一个流程。

查询数据

数据库有了、装数据的容器对象也有了,接下来就是把查询到的数据返回给前端了。

我们把从数据库中查询数据的方法都放在mapper层中,也叫dao(Data Access Object,即数据连接对象)层。

这一层只执行数据库的增删改查操作。

新建一个mapper包,如下:
在这里插入图片描述

连接数据库的User表,需要一个UserMapper类:

package com.TandK.mapper;

import com.TandK.model.po.UserPO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * @author TandK
 * @since 2021/9/8 22:05
 */
public interface UserMapper extends BaseMapper<UserPO> {
}

建立完mapper包后,要在Application类中加上一个@MapperScan(“com.TandK.mapper”)注解,声明Mapper层所在的包:

package com.TandK;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.TandK.mapper")
@SpringBootApplication
public class Application {

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

}

然后你的具体业务逻辑需要写在service层,新建一个service包和service.impl包,在service包下建立UserService,在service.impl包下建立UserServiceImpl:
在这里插入图片描述

让UserServiceImpl实现UserService接口:

package com.TandK.service;

/**
 * @author TandK
 * @since 2021/9/8 22:07
 */
public interface UserService {
}

package com.TandK.service.impl;

import com.TandK.service.UserService;
import org.springframework.stereotype.Service;

/**
 * @author TandK
 * @since 2021/9/8 22:07
 */
@Service
public class UserServiceImpl implements UserService {
}

@Service注解会告诉Spring Boot框架,这是真正的Service实现类,深入讲的话会涉及到Spring的依赖注入了,这里先不深入讲,先学会用再去深入理解为什么吧,你可以理解为这里不加这个注解就会报错。

这些准备好了之后,我们做一个查询用户列表的操作:

首先在UserController类下写一个方法:

package com.TandK.controller;

import com.TandK.model.vo.UserVO;
import com.TandK.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author TandK
 * @since 2021/9/3 0:19
 */
@RestController
@RequestMapping("users")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping()
    public List<UserVO> getUsers(){
        return userService.getUsers();
    }
}

仔细看你会发现UserService并没有初始化值。

正常情况下,我们要用UserService这个对象需要这么写:

private UserService userService = new UserServiceImpl();

毕竟UserServiceImpl才是真正的实现对象,UserService只是一个接口而已。

但是我们刚刚已经在UserServiceImpl类上加入了@Service注解,再在这个变量上面加了@Autowired注解。
在这里插入图片描述
在这里插入图片描述
这样框架就会自动给你生成一个实例对象。

这就是Spring之前经常拿出来吹的IoC,关于这点的细节可以看看我的《IoC和AOP》,但我建议等你真正会用SpringBoot之后再看。

Service层的方法如下:

package com.TandK.service;

import com.TandK.model.vo.UserVO;

import java.util.List;

/**
 * @author TandK
 * @since 2021/9/8 22:07
 */
public interface UserService {

    /**
     * 获取用户列表
     * @return
     */
    List<UserVO> getUsers();
}

在实现类中实现上面的方法:

package com.TandK.service.impl;

import com.TandK.mapper.UserMapper;
import com.TandK.model.po.UserPO;
import com.TandK.model.vo.UserVO;
import com.TandK.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author TandK
 * @since 2021/9/8 22:07
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public List<UserVO> getUsers() {
        // 查询
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("is_delete", 0);
        List<UserPO> userPOS = userMapper.selectList(wrapper);
        // 转化成vo
        List<UserVO> userVOS = userPOS.stream().map(userPO -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(userPO, userVO);
            return userVO;
        }).collect(Collectors.toList());
        return userVOS;
    }
}

详细说明下这个方法:
在这里插入图片描述
这用了插件的部分,其实就是拼装、并查询了下面这句SQL

SELECT * FROM user WHERE is_delete = 0

拼装和查询用的MyBatis-plus,它可以让你不用编写简单的sql,只用几个简单的方法就能拼装。

MyBatis-plus的依赖前面已经引入了,你也可以直接用。

但其实除了偷懒没什么叼用,因为还要让它拼装,所以执行效率我觉得还不如你自己手写的快。

美其名曰提高开发效率,其实我用的还是挺爽的,但是稍稍复杂点的SQL,比如连表查询,我觉得还是自己手写SQL吧,不止执行效率高,后面你回去改也不那么难受。

Service层负责查询数据、进行逻辑的编写,最简单的,比如你查出来的UserPO,有些字段比如is_delete、create_time这些,前端是完全不需要知道他们的存在的,那么你就可以转成VO再传出去。

然后启动项目,在数据库里随便插点数据,就可以在浏览器中访问到对应的数据了:

在这里插入图片描述

上面就是完成了一个最简单的查询动作。

我们搭建完项目之后,其实最主要的工作就是:

  1. 编写Controller层的方法,这部分的工作刚刚说过了,就是输入一个url,然后Controller层知道调用哪个方法,一般在Controller层的方法里会调用Service层的方法。
  2. Service层的方法是真正写业务逻辑的地方,它调用mapper层的方法增删改查数据库里的数据,然后做各种运算,返回想要的数据
  3. mapper层的方法很简单,就是简单的执行sql语句。

完成了一个最简单的查询动作之后,我们要做一下操作让这个项目变得规范起来。

上面这样也能用,倒不如说我做毕设的时候就是这样子开始写的,只不过接下来这些,有了规范,会有各个方面的好处,最直接的好处就是能提前熟悉外面公司的做法。

这个就下一篇写了。

有什么问题可以留言,看到了都会尽量帮忙解决。


2021-09-16更新:

下一篇在这里:《毕设利器,教你从零搭建一个有规范的spring boot项目【三】—— 返回结果的处理和统一异常处理》

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

TandK

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

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

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

打赏作者

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

抵扣说明:

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

余额充值