Bootstrap

尚硅谷智慧校园 —— 1、简介及环境搭建

目录

1、项目简介

1.1、简介

1.2、项目模块

1.3、使用的技术

2、环境搭建

2.1、使用 IDEA的 SpringBoot 创建一个Maven项目

2.2、在 pom.xml 导入依赖

2.3、准备目录结构

2.4、配置 application.yaml

2.5、准备分页插件的配置类

2.6、准备 swagger2 的配置类

2.7、准备 util 下的工具类

2.7.1、验证码图片工具类

2.7.2、token口令生成工具 JwtHelper

2.7.3、解析request请求中的 token口令的工具AuthContextHolder

2.7.4、MD5加密工具类

2.7.5、响应结果类型码枚举

2.7.6、JSON响应结果格式封装类

2.7.7、文件上传工具类

2.8、创建数据表及数据

2.9、根据数据表准备pojo、mapper、controller、service及其实现类


学习尚硅谷智慧校园项目,视频地址:尚大毕设项目,轻松搞定计算机毕业设计_哔哩哔哩_bilibili 

在评论区中看到该项目较为简单,适合新手练手 

1、项目简介

1.1、简介

智慧校园管理系统:主要是以年级、班级为单位,进行老师和学生信息记录和统计功能。项目采用前后端分离架构思想,前端采用 HTML+CSS+VUE来实现页面效果展示,后端采用 SpringBoot+MybatisPlus 框架实现数据存储等服务。存储层使用高性能的 MySQL,服务器使用 SpringBoot 内置的Tomcat9.x,项目构建工具使用Maven来管理jar包和项目构建。

1.2、项目模块

1.3、使用的技术

2、环境搭建

2.1、使用 IDEA的 SpringBoot 创建一个Maven项目

设置好包名及存放位置即可,无需添加其他功能,后面会对 pom.xml 大改,其他功能通过 maven 添加即可

2.2、在 pom.xml 导入依赖

为了避免影响其他插件的使用,需要使用较低的 SpringBoot 的版本

由于我的数据库是 mysql5,导入的依赖也应该是 5.x 版本的 

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!-- 继承方式使用SpringBoot -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/>
    </parent>

    <groupId>com.zyj</groupId>
    <artifactId>myzhxy</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

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

        <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>

        <!-- thymeleaf支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--  mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1</version>
        </dependency>

        <!-- 简化POJO实体类开发 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--mysql-->
        <!--<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>

        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>

        <!--swagger ui-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>

        <!--swagger2  增强版接口文档-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.4</version>
        </dependency>


        <!--开发者工具-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.29</version>
        </dependency>

        <!-- JWT生成Token-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.4</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <!--spring boot maven插件 , 可以将项目运行依赖的jar包打到我们的项目中-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.3、准备目录结构

  1. java目录下

    1. config : 项目的配置类

    2. controller: 控制层

    3. mapper : 持久层接口

    4. pojo : 实体类

    5. service: 服务层

    6. util: 工具类包

  2. resources目录下

    1. mapper :持久层映射文件

    2. public/upload:文件上传目录

    3. static: 静态资源目录

    4. application.yml :SpringBoot核心配置文件

 2.4、配置 application.yaml

server:
  port: 8080  #指定当前项目启动的端口号
spring:
  #解决SpringBoot2.6.0与swagger冲突问题【原因是在springboot2.6.0中将SpringMVC 默认路径匹配策略从AntPathMatcher 更改为PathPatternParser,导致出错,解决办法是切换回原先的AntPathMatcher】
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
  #配置数据源
  datasource:
    #配置数据源类型
    type: com.zaxxer.hikari.HikariDataSource
    #配置数据库连接属性
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/zhxy_db?characterEncoding=utf-8&useSSL=false   #&serverTimezone=GMT%2B8
    username: root
    password: zyj123
    hikari:
      connection-test-query: SELECT 1
      connection-timeout: 60000
      idle-timeout: 500000
      max-lifetime: 540000
      maximum-pool-size: 12
      minimum-idle: 10
      pool-name: GuliHikariPool
  thymeleaf:
    #模板的模式,支持 HTML, XML TEXT JAVASCRIPT
    mode: HTML5
    #编码 可不用配置
    encoding: UTF-8
    #开发配置为false,避免修改模板还要重启服务器
    cache: false
    #配置模板路径,默认是templates,可以不用配置
    prefix: classpath:/static/
  jackson:
    # 时间格式
    date-format: yyyy-MM-dd HH:mm:ss
    # 时区
    time-zone: GMT+8
  servlet:
    #设置文件上传上限
    multipart:
      # 单个文件最大大小
      max-file-size: 10MB
      # 多个文件总共最大大小
      max-request-size: 100MB
mybatis-plus:
  configuration:
    #添加日志支持
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath*:/mapper/**/*.xml

2.5、准备分页插件的配置类

@Configuration
@MapperScan("com.zyj.myzhxy.mapper")
public class MyConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor(){
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        return paginationInterceptor;
    }

}

2.6、准备 swagger2 的配置类

若想查看,需访问 localhost:端口号/swagger-ui.html

只有有  Api 相关的注解才会生成

@Api 标注在类上,示例:@Api(tags = "年级控制器")

@ApiOperation 标注在方法上,示例:@ApiOperation("(批量)删除年级信息")

@ApiParam 标注在方法参数上,示例:@ApiParam("要删除的年级信息的id的JSON集合") @RequestBody List<Integer> ids

import com.google.common.base.Predicates;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

/**
 * Swagger2配置信息
 */
@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Bean
    public Docket webApiConfig(){

        //添加head参数start
        List<Parameter> pars = new ArrayList<>();
        ParameterBuilder tokenPar = new ParameterBuilder();
        tokenPar.name("userId")
                .description("用户ID")
                .defaultValue("1")
                .modelRef(new ModelRef("string"))
                .parameterType("header")
                .required(false)
                .build();
        pars.add(tokenPar.build());

        ParameterBuilder tmpPar = new ParameterBuilder();
        tmpPar.name("userTempId")
                .description("临时用户ID")
                .defaultValue("1")
                .modelRef(new ModelRef("string"))
                .parameterType("header")
                .required(false)
                .build();
        pars.add(tmpPar.build());
        //添加head参数end

        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("webApi")
                .apiInfo(webApiInfo())
                .select()
                //可以测试请求头中:输入token
                // 有 ApiOperation 注解才生成
                //.apis(RequestHandlerSelectors.withClassAnnotation(ApiOperation.class))
                // 扫描的基础包
                .apis(RequestHandlerSelectors.basePackage("com.zyj.myzhxy.controller"))
                //过滤掉admin路径下的所有页面
                //.paths(Predicates.and(PathSelectors.regex("/sms/.*")))
                //过滤掉所有error或error.*页面
                //.paths(Predicates.not(PathSelectors.regex("/error.*")))
                .build()
                .globalOperationParameters(pars);

    }



    private ApiInfo webApiInfo(){

        return new ApiInfoBuilder()
                .title("网站-API文档")
                .description("本文档描述了网站微服务接口定义")
                .version("1.0")
                .contact(new Contact("atguigu", "http://atguigu.com", "[email protected]"))
                .build();
    }

    private ApiInfo adminApiInfo(){

        return new ApiInfoBuilder()
                .title("后台管理系统-API文档")
                .description("本文档描述了后台管理系统微服务接口定义")
                .version("1.0")
                .contact(new Contact("atguigu", "http://atguigu.com", "[email protected]"))
                .build();
    }

}

2.7、准备 util 下的工具类

2.7.1、验证码图片工具类

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * @project: ssm_sms
 * @description: 绘制验证码图片
 */
public class CreateVerifiCodeImage {

    private static int WIDTH = 90;
    private static int HEIGHT = 35;
    private static int FONT_SIZE = 20; //字符大小
    private static char[] verifiCode; //验证码
    private static BufferedImage verifiCodeImage; //验证码图片

    /**
     * @description: 获取验证码图片
     * @param: no
     * @return: java.awt.image.BufferedImage
     */
    public static BufferedImage getVerifiCodeImage() {
        verifiCodeImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_BGR);// create a image
        Graphics graphics = verifiCodeImage.getGraphics();

        verifiCode = generateCheckCode();
        drawBackground(graphics);
        drawRands(graphics, verifiCode);

        graphics.dispose();

        return verifiCodeImage;
    }

    /**
     * @description: 获取验证码
     * @param: no
     * @return: char[]
     */
    public static char[] getVerifiCode() {
        return verifiCode;
    }

    /**
     * @description: 随机生成验证码
     * @param: no
     * @return: char[]
     */
    private static char[] generateCheckCode() {
        String chars = "0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        char[] rands = new char[4];
        for (int i = 0; i < 4; i++) {
            int rand = (int) (Math.random() * (10 + 26 * 2));
            rands[i] = chars.charAt(rand);
        }
        return rands;
    }

    /**
     * @description: 绘制验证码
     * @param: g
     * @param: rands
     * @return: void
     */
    private static void drawRands(Graphics g, char[] rands) {
        g.setFont(new Font("Console", Font.BOLD, FONT_SIZE));

        for (int i = 0; i < rands.length; i++) {

            g.setColor(getRandomColor());
            g.drawString("" + rands[i], i * FONT_SIZE + 10, 25);
        }
    }

    /**
     * @description: 绘制验证码图片背景
     * @param: g
     * @return: void
     */
    private static void drawBackground(Graphics g) {

        g.setColor(Color.white);
        g.fillRect(0, 0, WIDTH, HEIGHT);

        // 绘制验证码干扰点
        for (int i = 0; i < 200; i++) {
            int x = (int) (Math.random() * WIDTH);
            int y = (int) (Math.random() * HEIGHT);
            g.setColor(getRandomColor());
            g.drawOval(x, y, 1, 1);

        }
    }


    /**
     * @description: 获取随机颜色
     * @param: no
     * @return: java.awt.Color
     */
    private static Color getRandomColor() {
        Random ran = new Random();
        return new Color(ran.nextInt(220), ran.nextInt(220), ran.nextInt(220));
    }
}

2.7.2、token口令生成工具 JwtHelper

package com.zyj.myzhxy.util;

/**
 * @Author zhang
 * @Date 2022/4/17 - 23:18
 * @Version 1.0
 */
import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;

import java.util.Date;

public class JwtHelper {
    // 一天的毫秒数
    private static long tokenExpiration = 24*60*60*1000;
    // 后缀信息,用于增加保密性
    private static String tokenSignKey = "123456";

    //生成token字符串(根据tokenExpiration和tokenSignKey)
    public static String createToken(Long userId, Integer userType) {
        String token = Jwts.builder()

                .setSubject("YYGH-USER")

                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))

                .claim("userId", userId)
//                .claim("userName", userName)
                .claim("userType", userType)

                .signWith(SignatureAlgorithm.HS512, tokenSignKey)
                .compressWith(CompressionCodecs.GZIP)
                .compact();
        return token;
    }

    //从token字符串获取userid
    public static Long getUserId(String token) {
        if(StringUtils.isEmpty(token)) return null;
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        Integer userId = (Integer)claims.get("userId");
        return userId.longValue();
    }

    //从token字符串获取userType
    public static Integer getUserType(String token) {
        if(StringUtils.isEmpty(token)) return null;
        Jws<Claims> claimsJws
                = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        return (Integer)(claims.get("userType"));
    }

    //从token字符串获取userName
    public static String getUserName(String token) {
        if(StringUtils.isEmpty(token)) return "";
        Jws<Claims> claimsJws
                = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("userName");
    }

    //判断token是否有效
    public static boolean isExpiration(String token){
        try {
            boolean isExpire = Jwts.parser()
                    .setSigningKey(tokenSignKey)
                    .parseClaimsJws(token)
                    .getBody()
                    .getExpiration().before(new Date());
            //没有过期,有效,返回false
            return isExpire;
        }catch(Exception e) {
            //过期出现异常,返回true
            return true;
        }
    }


    /**
     * 刷新Token
     * @param token
     * @return
     */
    public String refreshToken(String token) {
        String refreshedToken;
        try {
            final Claims claims = Jwts.parser()
                    .setSigningKey(tokenSignKey)
                    .parseClaimsJws(token)
                    .getBody();
            refreshedToken = JwtHelper.createToken(getUserId(token), getUserType(token));
        } catch (Exception e) {
            refreshedToken = null;
        }
        return refreshedToken;
    }

    public static void main(String[] args) {
//        String token = JwtHelper.createToken(1L, "lucy");
//        System.out.println(token);
//        System.out.println(JwtHelper.getUserId(token));
//        System.out.println(JwtHelper.getUserName(token));
    }
}

2.7.3、解析request请求中的 token口令的工具AuthContextHolder

import javax.servlet.http.HttpServletRequest;

public class AuthContextHolder {

    //从请求头token获取userid
    public static Long getUserIdToken(HttpServletRequest request) {
        //从请求头token
        String token = request.getHeader("token");
        //调用工具类
        Long userId = JwtHelper.getUserId(token);
        return userId;
    }

    //从请求头token获取name
    public static String getUserName(HttpServletRequest request) {
        //从header获取token
        String token = request.getHeader("token");
        //jwt从token获取username
        String userName = JwtHelper.getUserName(token);
        return userName;
    }
}

2.7.4、MD5加密工具类

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;


public final class MD5 {

    /**
     * 将明文转为密文
     * @param strSrc 明文
     * @return 密文
     */
    public static String encrypt(String strSrc) {
        try {
            char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
                    '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            byte[] bytes = strSrc.getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(bytes);
            bytes = md.digest();
            int j = bytes.length;
            char[] chars = new char[j * 2];
            int k = 0;
            for (int i = 0; i < bytes.length; i++) {
                byte b = bytes[i];
                chars[k++] = hexChars[b >>> 4 & 0xf];
                chars[k++] = hexChars[b & 0xf];
            }
            return new String(chars);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("MD5加密出错!!+" + e);
        }
    }
    
}

2.7.5、响应结果类型码枚举

import lombok.Getter;

/**
 * 统一返回结果状态信息类
 *
 */
@Getter
public enum ResultCodeEnum {

    SUCCESS(200,"成功"),
    FAIL(201, "失败"),
    SERVICE_ERROR(2012, "服务异常"),
    ILLEGAL_REQUEST( 204, "非法请求"),
    PAY_RUN(205, "支付中"),
    ARGUMENT_VALID_ERROR(206, "参数校验错误"),

    LOGIN_ERROR(207, "用户名或密码错误"),
    LOGIN_AUTH(208, "未登陆"),
    PERMISSION(209, "没有权限"),
    SECKILL_NO_START(210, "秒杀还没开始"),
    SECKILL_RUN(211, "正在排队中"),
    SECKILL_NO_PAY_ORDER(212, "您有未支付的订单"),
    SECKILL_FINISH(213, "已售罄"),
    SECKILL_END(214, "秒杀已结束"),
    SECKILL_SUCCESS(215, "抢单成功"),
    SECKILL_FAIL(216, "抢单失败"),
    SECKILL_ILLEGAL(217, "请求不合法"),
    SECKILL_ORDER_SUCCESS(218, "下单成功"),
    COUPON_GET(220, "优惠券已经领取"),
    COUPON_LIMIT_GET(221, "优惠券已发放完毕"),
    //2022-02-22
    LOGIN_CODE(222,"长时间未操作,会话已失效,请刷新页面后重试!"),
    CODE_ERROR(223,"验证码错误!"),
    TOKEN_ERROR(224,"Token无效!")
    ;

    private Integer code;

    private String message;

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

2.7.6、JSON响应结果格式封装类

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
 * 全局统一返回结果类
 *
 */
@Data
@ApiModel(value = "全局统一返回结果")
public class Result<T> {

    @ApiModelProperty(value = "返回码")
    private Integer code;

    @ApiModelProperty(value = "返回消息")
    private String message;

    @ApiModelProperty(value = "返回数据")
    private T data;

    public Result(){}

    // 返回数据
    protected static <T> Result<T> build(T data) {
        Result<T> result = new Result<T>();
        if (data != null)
            result.setData(data);
        return result;
    }

    public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
        Result<T> result = build(body);
        result.setCode(resultCodeEnum.getCode());
        result.setMessage(resultCodeEnum.getMessage());
        return result;
    }

    public static<T> Result<T> ok(){
        return Result.ok(null);
    }

    /**
     * 操作成功
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> ok(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.SUCCESS);
    }

    public static<T> Result<T> fail(){
        return Result.fail(null);
    }

    /**
     * 操作失败
     * @param data
     * @param <T>
     * @return
     */
    public static<T> Result<T> fail(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.FAIL);
    }

    public Result<T> message(String msg){
        this.setMessage(msg);
        return this;
    }

    public Result<T> code(Integer code){
        this.setCode(code);
        return this;
    }

    public boolean isOk() {
        if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
            return true;
        }
        return false;
    }
}

2.7.7、文件上传工具类

import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @project: zhxy
 * @description: 上传文件的工具类
 */
public class UploadFile {

    //存储文件上传失败的错误信息
    private static Map<String, Object> error_result = new HashMap<>();
    //存储头像的上传结果信息
    private static Map<String, Object> upload_result = new HashMap<>();

    /**
     * @description: 效验所上传图片的大小及格式等信息...
     * @param: photo
     * @param: path
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    private static Map<String, Object> uploadPhoto(MultipartFile photo, String path) {
        //限制头像大小(20M)
        int MAX_SIZE = 20971520;
        //获取图片的原始名称
        String orginalName = photo.getOriginalFilename();
        //如果保存文件的路径不存在,则创建该目录
        File filePath = new File(path);
        if (!filePath.exists()) {
            filePath.mkdirs();
        }
        //限制上传文件的大小
        if (photo.getSize() > MAX_SIZE) {
            error_result.put("success", false);
            error_result.put("msg", "上传的图片大小不能超过20M哟!");
            return error_result;
        }
        // 限制上传的文件类型
        String[] suffixs = new String[]{".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".gif", ".GIF", ".bmp", ".BMP"};
        SuffixFileFilter suffixFileFilter = new SuffixFileFilter(suffixs);
        if (!suffixFileFilter.accept(new File(path + orginalName))) {
            error_result.put("success", false);
            error_result.put("msg", "禁止上传此类型文件! 请上传图片哟!");
            return error_result;
        }

        return null;
    }

    /**
     * @description: (提取公共代码 : 提高代码的可重用性)获取头像的上传结果信息
     * @param: photo
     * @param: dirPaht
     * @param: portraitPath
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    public static Map<String, Object> getUploadResult(MultipartFile photo, String dirPaht, String portraitPath) {

        if (!photo.isEmpty() && photo.getSize() > 0) {
            //获取图片的原始名称
            String orginalName = photo.getOriginalFilename();
            //上传图片,error_result:存储头像上传失败的错误信息
            Map<String, Object> error_result = UploadFile.uploadPhoto(photo, dirPaht);
            if (error_result != null) {
                return error_result;
            }
            //使用UUID重命名图片名称(uuid__原始图片名称)
            String newPhotoName = UUID.randomUUID() + "__" + orginalName;
            //将上传的文件保存到目标目录下
            try {
                photo.transferTo(new File(dirPaht + newPhotoName));
                upload_result.put("success", true);
                upload_result.put("portrait_path", portraitPath + newPhotoName);//将存储头像的项目路径返回给页面
            } catch (IOException e) {
                e.printStackTrace();
                upload_result.put("success", false);
                upload_result.put("msg", "上传文件失败! 服务器端发生异常!");
                return upload_result;
            }

        } else {
            upload_result.put("success", false);
            upload_result.put("msg", "头像上传失败! 未找到指定图片!");
        }
        return upload_result;
    }
}

2.8、创建数据表及数据

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_admin
-- ----------------------------
DROP TABLE IF EXISTS `tb_admin`;
CREATE TABLE `tb_admin`  (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gender` CHAR(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `telephone` VARCHAR(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `address` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `portrait_path` VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 157 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of tb_admin
-- ----------------------------
INSERT INTO `tb_admin` VALUES (101, 'admin', '女', '21232f297a57a5a743894a0e4a801fc3', '[email protected]', '13260161111', '昌平', 'upload/default.jpg');
INSERT INTO `tb_admin` VALUES (102, 'admin1', '男', '21232f297a57a5a743894a0e4a801fc3', '[email protected]', '13260166090', '北京', 'upload/default.jpg');
INSERT INTO `tb_admin` VALUES (103, 'admin2', '男', '21232f297a57a5a743894a0e4a801fc3', '[email protected]', '13260166090', '北京', 'upload/default.jpg');
INSERT INTO `tb_admin` VALUES (104, 'admin3', '男', '21232f297a57a5a743894a0e4a801fc3', '[email protected]', '13666666666', '宏福苑', 'upload/default.jpg');

-- ----------------------------
-- Table structure for tb_clazz
-- ----------------------------
DROP TABLE IF EXISTS `tb_clazz`;
CREATE TABLE `tb_clazz`  (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `number` INT(3) NULL DEFAULT NULL,
  `introducation` VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `headmaster` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `telephone` VARCHAR(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `grade_name` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of tb_clazz
-- ----------------------------
INSERT INTO `tb_clazz` VALUES (1, '一年一班', 30, '大圣的一年一班好', '大圣', '[email protected]', '13260166090', '一年级');
INSERT INTO `tb_clazz` VALUES (2, '一年二班', 28, '小张的一年二班好', '小张', '[email protected]', '13260166090', '一年级');
INSERT INTO `tb_clazz` VALUES (3, '二年一班', 35, '小韩的二年一班好', '小韩', '[email protected]', '13260166090', '二年级');
INSERT INTO `tb_clazz` VALUES (4, '二年二班', 30, '小强的二年二班好', '小强', '[email protected]', '13260166090', '二年级');
INSERT INTO `tb_clazz` VALUES (5, '三年一班', 30, '小花的三年一班好', '小花', '[email protected]', '13260166090', '三年级');
INSERT INTO `tb_clazz` VALUES (6, '三年二班', 30, '小赵的三年二班好', '小赵', '[email protected]', '13260166090', '三年级');
INSERT INTO `tb_clazz` VALUES (7, '四年一班', 30, '小赵的三年二班好', '小飞', '[email protected]', '13260166090', '四年级');

-- ----------------------------
-- Table structure for tb_grade
-- ----------------------------
DROP TABLE IF EXISTS `tb_grade`;
CREATE TABLE `tb_grade`  (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  `manager` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `telephone` VARCHAR(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `introducation` VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`, `name`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of tb_grade
-- ----------------------------
INSERT INTO `tb_grade` VALUES (1, '一年级', '大圣', '[email protected]', '13260166090', '大学一年级');
INSERT INTO `tb_grade` VALUES (2, '二年级', '小魏', '[email protected]', '13260166090', '大学二年级');
INSERT INTO `tb_grade` VALUES (3, '三年级', '小李', '[email protected]', '13666666666', '三年级,这个班级的孩子们很有才艺');
INSERT INTO `tb_grade` VALUES (4, '五年级', '小丽', '[email protected]', '13666666666', '这个年级的同学多才多活力');
INSERT INTO `tb_grade` VALUES (5, '六年级', '小明', '[email protected]', '13666666666', '这个年级的主任是小明');

-- ----------------------------
-- Table structure for tb_student
-- ----------------------------
DROP TABLE IF EXISTS `tb_student`;
CREATE TABLE `tb_student`  (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `sno` VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `name` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gender` CHAR(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `telephone` VARCHAR(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `address` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `introducation` VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `portrait_path` VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `clazz_name` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of tb_student
-- ----------------------------
INSERT INTO `tb_student` VALUES (1, '1001', '张小明', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京天通苑', '这个学生学习好', 'upload/default.jpg', '一年一班');
INSERT INTO `tb_student` VALUES (2, '1002', '郭建超', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京昌平', '这个学生会功夫', 'upload/default.jpg', '一年一班');
INSERT INTO `tb_student` VALUES (3, '1003', '史汶鑫', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京昌平', '这个学生酒量好', 'upload/default.jpg', '二年一班');
INSERT INTO `tb_student` VALUES (4, '1004', '高建军', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京昌平', '这个学生会做饭', 'upload/default.jpg', '二年一班');
INSERT INTO `tb_student` VALUES (5, '1005', '邹伟斌', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京昌平', '这个学生能吃辣', 'upload/default.jpg', '三年一班');
INSERT INTO `tb_student` VALUES (6, '1006', '刘路', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京昌平', '这个学生是学霸', 'upload/default.jpg', '三年二班');
INSERT INTO `tb_student` VALUES (7, '1007', '庞家仨', '女', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京昌平', '这个学生海拔高', 'upload/default.jpg', '三年二班');
INSERT INTO `tb_student` VALUES (8, '1008', '谭帅', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京昌平', '这个学生想考研', 'upload/default.jpg', '四年一班');

-- ----------------------------
-- Table structure for tb_teacher
-- ----------------------------
DROP TABLE IF EXISTS `tb_teacher`;
CREATE TABLE `tb_teacher`  (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `tno` VARCHAR(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `name` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `gender` CHAR(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `telephone` VARCHAR(12) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `address` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `portrait_path` VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `clazz_name` VARCHAR(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = INNODB AUTO_INCREMENT = 9 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;

-- ----------------------------
-- Records of tb_teacher
-- ----------------------------
INSERT INTO `tb_teacher` VALUES (1, '101', '大圣', '女', '123456', '[email protected]', '13260166090', '北京昌平', 'upload/default.jpg', '一年一班');
INSERT INTO `tb_teacher` VALUES (2, '102', '小张', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京海淀', 'upload/default.jpg', '一年二班');
INSERT INTO `tb_teacher` VALUES (3, '103', '小韩', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京朝阳', 'upload/default.jpg', '二年一班');
INSERT INTO `tb_teacher` VALUES (4, '104', '小强', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京通州', 'upload/default.jpg', '二年二班');
INSERT INTO `tb_teacher` VALUES (5, '105', '小花', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京顺义', 'upload/default.jpg', '三年一班');
INSERT INTO `tb_teacher` VALUES (6, '106', '小赵', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京东城', 'upload/default.jpg', '三年二班');
INSERT INTO `tb_teacher` VALUES (7, '107', '小飞', '男', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13260166090', '北京西城', 'upload/default.jpg', '四年一班');
INSERT INTO `tb_teacher` VALUES (8, '108', '秀秀', '女', 'e10adc3949ba59abbe56e057f20f883e', '[email protected]', '13855555555', '海淀', 'upload/12fe07bf8b6d493b96294f1ef0552339default.jpg', '一年一班');

SET FOREIGN_KEY_CHECKS = 1;

2.9、根据数据表准备pojo、mapper、controller、service及其实现类

这里只写 admin,其他类似

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_admin")
public class Admin {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String name;
    private Character gender;
    private String password;
    private String email;
    private String telephone;
    private String address;
    private String portraitPath;  // 头像图片路径
}
@Mapper
public interface AdminMapper extends BaseMapper<Admin> {
}
public interface AdminService extends IService<Admin> {
}
@Service("adminServiceImpl")
@Transactional
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {
}
@RestController
@RequestMapping("/sms/adminController")
public class AdminController {
}

3、测试访问首页的问题:数据库版本不一致

完成以上搭建后,应该可以实现对首页的访问,但我这里失败了。后来发现是因为数据库版本的不一致的问题。

由于我的 MySQL 版本为 5.7,这里需要在 pom.xml 中更改导入的数据库驱动版本

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

application.yaml 中数据库的配置也要与 5.7 版本的格式对应

    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/zhxy_db?characterEncoding=utf-8&useSSL=false   #&serverTimezone=GMT%2B8
    username: root
    password: zyj123

;