Java 之 Spring Boot + Vue + Element UI 前后端分离项目(上-项目搭建) 【博客论坛项目高仿CSDN】(一篇文章精通系列)

x33g5p2x  于2022-02-16 转载在 Vue.js  
字(31.3k)|赞(0)|评价(0)|浏览(784)

一、项目简介

1、JDK1.8``SpringBoot 2.6.2``mybatis2.2.0
2. Vue3
3. 使用工具 后端IDEA 和 前端HBuilderX
4、数据库使用mysql5.5 SQL文件

SQL文件下载
https://download.csdn.net/download/qq_44757034/80926009

二、后端SpringBoot项目搭建

1、项目搭建

(1)创建工程

(2)引入依赖

<?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>cn.itbluebox</groupId>
    <artifactId>springboot_csdn</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>springboot_csdn</name>
    <description>Demo project for Spring Boot</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>
        <!--分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.1</version>
        </dependency>
        <!-- 通用Mapper启动器 -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.3</version>
        </dependency>
        <!-- mysql驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.32</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.3</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-core</artifactId>
            <version>1.0.4</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-extra</artifactId>
            <version>1.0.4</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-base</artifactId>
            <version>1.0.4</version>
        </dependency>
        <!-- web启动器 -->
        <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>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>

        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.26.1-RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.0</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.9.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <!--注册Dao包目录下Mybatis映射文件资源目录-->
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <!--注册webapp目录为资源目录-->
            <resource>
                <directory>src/main/webapp</directory>
                <targetPath>META-INF/resources</targetPath>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
(3)创建其他项目文件以及配置文件
1)启动类

package cn.itbluebox.springbootcsdn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootCSDNApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootCSDNApplication.class, args);
    }
}
2)配置文件

application.yml

server:
  port: 9090
#datasource
spring:
  datasource:
    url: jdbc:mysql:///csdn
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  mvc:
    view:
      prefix: /
      suffix: .jsp
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
sc:
  jwt:
    secret: blueboxai@Login(Auth}*^31)&heiMa% # 登录校验的密钥
    pubKeyPath: C:\\Users\\ZHENG\\Desktop\\leyou_msgrs\\rsa\\rsa.pub # 公钥地址
    priKeyPath: C:\\Users\\ZHENG\\Desktop\\leyou_msgrs\\rsa\\rsa.pri # 私钥地址
    expire: 30 # 过期时间,单位分钟
    cookieName: SC_TOKEN
    cookieMaxAge: 1200
3)webapp

设置文件类型

4)创建完整的目录结构

创建方式都一样省略不写

运行测试

运行成功,工程搭建的没有问题

2、编写数据库对应的实体类

(1)Blog

package cn.itbluebox.springbootcsdn.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Transient;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Blog {
    private Long id;              //文章id
    private String title;         //文章标题
    private String abstract_text;       //文章内容
    private String thumbnail;       //缩略图
    private Date create_time;      //创建时间
    private Long like_count;              //点赞数量
    private Long view_count;     //浏览量
    private Long consumer_id;     //用户ID
    private String type_id;       //类型
    private Long blog_article_id;     //博客文章ID
    @Transient //Transient声明当前字段不是数据对应的字段
    private Long[] typeId;
}
(2)BlogArticle

package cn.itbluebox.springbootcsdn.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Table;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "blog_article")
public class BlogArticle {

    private Long id;
    private String context;
    private Date last_update_time;      //更新时间
    private Character is_original;

}
(2)BlogHeader

package cn.itbluebox.springbootcsdn.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Table;
import javax.persistence.Transient;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "blog_header")
public class BlogHeader {
    private Long id;
    private Long blog_id;
    private String title;
    private String abstract_text;
    private String type;
    @Transient //Transient声明当前字段不是数据对应的字段
    private String thumbnail;
}
(3)BlogType

package cn.itbluebox.springbootcsdn.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Table;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "blog_type")
public class BlogType {
    private Long id;
    private String typename;
}
(4)Consumer

package cn.itbluebox.springbootcsdn.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "consumer")
public class Consumer {
    private Long id;
    private Character sex;
    private String name;
    private String email;
    private String image;
    private String type;
    private Long phone;
    private Date birthday;
    private String password;
    @Transient //Transient声明当前字段不是数据对应的字段
    private String token;
}

3、编写枚举类ExceptionEnum

package cn.itbluebox.springbootcsdn.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum ExceptionEnum {
    UPLOAD_FILE_ERROR(500,"文件上传失败"),
    CONSUMER_FIND_ERROR(500,"用户查询失败"),
    INVALID_FILE_TYPE(400,"无效的文件类型"),
    BLOG_SAVE_ERROR(500,"新增博客失败"),
    CONSUMER_SAVE_ERROR(500,"新增用户失败"),
    CONSUMER_LOGIN_ERROR(500,"用户登录失败"),
    UN_AUTHORIZED(401,"未授权"),
    ;
    private int code;
    private String msg;
}

4、编写异常处理类BlException

package cn.itbluebox.springbootcsdn.exception;

import cn.itbluebox.springbootcsdn.enums.ExceptionEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Getter
public class BlException extends RuntimeException{
    private ExceptionEnum exceptionEnum;
}

5、编写过滤器设置全局配置

package cn.itbluebox.springbootcsdn.filter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //1) 允许的域,不要写*,否则cookie就无法使用了(将来如果有多个域需要夸则添加多个)
        config.addAllowedOrigin("http://localhost:8080");
        config.addAllowedOrigin("http://localhost:9090");
        //2) 是否发送Cookie信息
        config.setAllowCredentials(true);
        //3) 允许的请求方式
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        config.setMaxAge(3600L);
        // 4)允许的头信息
        config.addAllowedHeader("*");
        // 5) 有效时长 1小时
        config.setMaxAge(3600L);
        //2.添加映射路径,我们拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        //3.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}

6、编写实体类对应的mapper接口

  • BlogMapper

package cn.itbluebox.springbootcsdn.mapper;

import cn.itbluebox.springbootcsdn.domain.Blog;
import tk.mybatis.mapper.common.Mapper;

public interface BlogMapper extends Mapper<Blog> {
}

其他的都类似

  • BlogArticleMapper

package cn.itbluebox.springbootcsdn.mapper;
import cn.itbluebox.springbootcsdn.domain.BlogArticle;
import tk.mybatis.mapper.common.Mapper;

public interface BlogArticleMapper extends Mapper<BlogArticle> {
}
  • BlogHeaderMapper

package cn.itbluebox.springbootcsdn.mapper;

import cn.itbluebox.springbootcsdn.domain.BlogHeader;
import tk.mybatis.mapper.common.Mapper;

public interface BlogHeaderMapper extends Mapper<BlogHeader> {
}
  • BlogHeaderMapper

package cn.itbluebox.springbootcsdn.mapper;

import cn.itbluebox.springbootcsdn.domain.BlogHeader;
import tk.mybatis.mapper.common.Mapper;

public interface BlogHeaderMapper extends Mapper<BlogHeader> {
}
  • BlogTypeMapper

package cn.itbluebox.springbootcsdn.mapper;

import cn.itbluebox.springbootcsdn.domain.BlogType;
import tk.mybatis.mapper.common.Mapper;

public interface BlogTypeMapper extends Mapper<BlogType> {
}
  • ConsumerMapper

package cn.itbluebox.springbootcsdn.mapper;

import cn.itbluebox.springbootcsdn.domain.Consumer;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.Mapper;

public interface ConsumerMapper extends Mapper<Consumer> {

    @Select("select * from consumer where email = #{email} and password = #{password}")
    Consumer selectConsumerOne(String email, String password);
}

7、编写对应工具类

  • CookieUtils

package cn.itbluebox.springboottest22.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * Cookie 工具类
 */
public final class CookieUtils {

    protected static final Logger logger = LoggerFactory.getLogger(CookieUtils.class);

    /**
     * 得到Cookie的值, 不编码
     *
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName) {
        return getCookieValue(request, cookieName, false);
    }

    /**
     * 得到Cookie的值,
     *
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
        Cookie[] cookieList = request.getCookies();
        if (cookieList == null || cookieName == null) {
            return null;
        }
        String retValue = null;
        try {
            for (int i = 0; i < cookieList.length; i++) {
                if (cookieList[i].getName().equals(cookieName)) {
                    if (isDecoder) {
                        retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
                    } else {
                        retValue = cookieList[i].getValue();
                    }
                    break;
                }
            }
        } catch (UnsupportedEncodingException e) {
            logger.error("Cookie Decode Error.", e);
        }
        return retValue;
    }

    /**
     * 得到Cookie的值,
     *
     * @param request
     * @param cookieName
     * @return
     */
    public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
        Cookie[] cookieList = request.getCookies();
        if (cookieList == null || cookieName == null) {
            return null;
        }
        String retValue = null;
        try {
            for (int i = 0; i < cookieList.length; i++) {
                if (cookieList[i].getName().equals(cookieName)) {
                    retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
                    break;
                }
            }
        } catch (UnsupportedEncodingException e) {
            logger.error("Cookie Decode Error.", e);
        }
        return retValue;
    }

    /**
     * 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue) {
        setCookie(request, response, cookieName, cookieValue, -1);
    }

    /**
     * 设置Cookie的值 在指定时间内生效,但不编码
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage) {
        setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
    }

    /**
     * 设置Cookie的值 不设置生效时间,但编码
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, boolean isEncode) {
        setCookie(request, response, cookieName, cookieValue, -1, isEncode);
    }

    /**
     * 设置Cookie的值 在指定时间内生效, 编码参数
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
        doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
    }

    /**
     * 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
     */
    public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
        doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
    }

    /**
     * 删除Cookie带cookie域名
     */
    public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String cookieName) {
        doSetCookie(request, response, cookieName, "", -1, false);
    }

    /**
     * 设置Cookie的值,并使其在指定时间内生效
     *
     * @param cookieMaxage cookie生效的最大秒数
     */
    private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
        try {
            if (cookieValue == null) {
                cookieValue = "";
            } else if (isEncode) {
                cookieValue = URLEncoder.encode(cookieValue, "utf-8");
            }
            Cookie cookie = new Cookie(cookieName, cookieValue);
            if (cookieMaxage > 0)
                cookie.setMaxAge(cookieMaxage);
            if (null != request)// 设置域名的cookie
                cookie.setDomain(getDomainName(request));
            cookie.setPath("/");
            response.addCookie(cookie);
        } catch (Exception e) {
            logger.error("Cookie Encode Error.", e);
        }
    }

    public static final Cookie setGetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
        Cookie cookie = null;
        try {
            if (cookieValue == null) {
                cookieValue = "";
            } else if (isEncode) {
                cookieValue = URLEncoder.encode(cookieValue, "utf-8");
            }
            cookie = new Cookie(cookieName, cookieValue);
            if (cookieMaxage > 0)
                cookie.setMaxAge(cookieMaxage);
            if (null != request)// 设置域名的cookie
                cookie.setDomain(getDomainName(request));
            cookie.setPath("/");
            response.addCookie(cookie);

        } catch (Exception e) {
            logger.error("Cookie Encode Error.", e);
        }
        return cookie;
    }

    /**
     * 设置Cookie的值,并使其在指定时间内生效
     *
     * @param cookieMaxage cookie生效的最大秒数
     */
    private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
        try {
            if (cookieValue == null) {
                cookieValue = "";
            } else {
                cookieValue = URLEncoder.encode(cookieValue, encodeString);
            }
            Cookie cookie = new Cookie(cookieName, cookieValue);
            if (cookieMaxage > 0)
                cookie.setMaxAge(cookieMaxage);
            if (null != request)// 设置域名的cookie
                cookie.setDomain(getDomainName(request));
            cookie.setPath("/");
            response.addCookie(cookie);
        } catch (Exception e) {
            logger.error("Cookie Encode Error.", e);
        }
    }

    /**
     * 得到cookie的域名
     */
    private static final String getDomainName(HttpServletRequest request) {
        String domainName = null;

        String serverName = request.getRequestURL().toString();
        if (serverName == null || serverName.equals("")) {
            domainName = "";
        } else {
            serverName = serverName.toLowerCase();
            serverName = serverName.substring(7);
            final int end = serverName.indexOf("/");
            serverName = serverName.substring(0, end);
            final String[] domains = serverName.split("\\.");
            int len = domains.length;
            if (len > 3) {
                // www.xxx.com.cn
                domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
            } else if (len <= 3 && len > 1) {
                // xxx.com or xxx.cn
                domainName = domains[len - 2] + "." + domains[len - 1];
            } else {
                domainName = serverName;
            }
        }

        if (domainName != null && domainName.indexOf(":") > 0) {
            String[] ary = domainName.split("\\:");
            domainName = ary[0];
        }
        return domainName;
    }

}
  • IdWorker

package cn.itbluebox.springbootcsdn.utils;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Random;

/**
 * <p>名称:IdWorker.java</p>
 * <p>描述:分布式自增长ID</p>
 * <pre>
 *     Twitter的 Snowflake JAVA实现方案
 * </pre>
 * 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用:
 * 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
 * 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,
 * 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),
 * 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
 * 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),
 * 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
 * <p>
 * 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
 *
 * @author Polim
 */
public class IdWorker {
    // 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
    private final static long twepoch = 1288834974657L;
    // 机器标识位数
    private final static long workerIdBits = 5L;
    // 数据中心标识位数
    private final static long datacenterIdBits = 5L;
    // 机器ID最大值
    private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
    // 数据中心ID最大值
    private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    // 毫秒内自增位
    private final static long sequenceBits = 12L;
    // 机器ID偏左移12位
    private final static long workerIdShift = sequenceBits;
    // 数据中心ID左移17位
    private final static long datacenterIdShift = sequenceBits + workerIdBits;
    // 时间毫秒左移22位
    private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

    private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
    /* 上次生产id时间戳 */
    private static long lastTimestamp = -1L;
    // 0,并发控制
    private long sequence = 0L;

    private final long workerId;
    // 数据标识id部分
    private final long datacenterId;

    public IdWorker() {
        this.datacenterId = getDatacenterId(maxDatacenterId);
        this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
    }

    /**
     * @param workerId     工作机器ID
     * @param datacenterId 序列号
     */
    public IdWorker(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    /**
     * 获取下一个ID
     *
     * @return
     */
    public synchronized long nextId() {
        long timestamp = timeGen();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            // 当前毫秒内,则+1
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                // 当前毫秒内计数满了,则等待下一秒
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        // ID偏移组合生成最终的ID,并返回ID
        long nextId = ((timestamp - twepoch) << timestampLeftShift)
                | (datacenterId << datacenterIdShift)
                | (workerId << workerIdShift) | sequence;

        return nextId;
    }

    private long tilNextMillis(final long lastTimestamp) {
        long timestamp = this.timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = this.timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }

    /**
     * <p>
     * 获取 maxWorkerId
     * </p>
     */
    protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
        StringBuffer mpid = new StringBuffer();
        mpid.append(datacenterId);
        String name = ManagementFactory.getRuntimeMXBean().getName();
        if (!name.isEmpty()) {
            /*
             * GET jvmPid
             */
            mpid.append(name.split("@")[0]);
        }
        /*
         * MAC + PID 的 hashcode 获取16个低位
         */
        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
    }

    /**
     * <p>
     * 数据标识id部分
     * </p>
     */
    protected static long getDatacenterId(long maxDatacenterId) {
        long id = 0L;
        try {
            InetAddress ip = InetAddress.getLocalHost();
            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
            if (network == null) {
                id = 1L;
            } else {
                byte[] mac = network.getHardwareAddress();
                id = ((0x000000FF & (long) mac[mac.length - 1])
                        | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
                id = id % (maxDatacenterId + 1);
            }
        } catch (Exception e) {
            System.out.println(" getDatacenterId: " + e.getMessage());
        }
        return id;
    }

    public static void main(String[] args) {
        IdWorker idWorker = new IdWorker(new Random().nextInt(10), 1);
        long l = idWorker.nextId();
        System.out.println(l);
    }

}
  • JwtConstants

package cn.itbluebox.springbootcsdn.utils;

public class JwtConstants {
    public static final String JWT_KEY_ID = "id";
    public static final String JWT_KEY_EMAIL = "email";
    public static final String JWT_KEY_NAME = "name";
    public static final String JWT_KEY_IMG = "image";
}
  • JwtUtils

package cn.itbluebox.springbootcsdn.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;

import java.security.PrivateKey;
import java.security.PublicKey;

public class JwtUtils {
    /**
     * 生成Token
     * @param userInfo
     * @param privateKey
     * @param expireMinutes
     * @return
     */
    public static String generateToken(UserInfo userInfo, PrivateKey privateKey, int expireMinutes) {
        return Jwts.builder()
                .claim(JwtConstants.JWT_KEY_ID, userInfo.getId())
                .claim(JwtConstants.JWT_KEY_NAME, userInfo.getName())
                .claim(JwtConstants.JWT_KEY_IMG, userInfo.getImage())
                .claim(JwtConstants.JWT_KEY_EMAIL, userInfo.getEmail())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();
    }

    /**
     * 生成Token
     * @param userInfo
     * @param privateKey
     * @param expireMinutes
     * @return
     * @throws Exception
     */
    public static String generateToken(UserInfo userInfo, byte[] privateKey, int expireMinutes) throws Exception {
        return Jwts.builder()
                .claim(JwtConstants.JWT_KEY_ID, userInfo.getId())
                .claim(JwtConstants.JWT_KEY_NAME, userInfo.getName())
                .claim(JwtConstants.JWT_KEY_IMG, userInfo.getImage())
                .claim(JwtConstants.JWT_KEY_EMAIL, userInfo.getEmail())
                .setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate())
                .signWith(SignatureAlgorithm.ES256, RsaUtils.getPrivateKey(privateKey))
                .compact();
    }

    /**
     * 公钥解析Token
     * @param publicKey
     * @param token
     * @return
     */
    public static Jws<Claims> parseToken(PublicKey publicKey, String token) {
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

    /**
     * 公钥解析Token
     * @param publicKey
     * @param token
     * @return
     * @throws Exception
     */
    public static Jws<Claims> parseToken(byte[] publicKey, String token) throws Exception {
        return Jwts.parser().setSigningKey(RsaUtils.getPublicKey(publicKey)).parseClaimsJws(token);
    }

    /**
     * 从Token中获取用户信息(使用公钥解析)
     * @param publicKey
     * @param token
     * @return
     */
    public static UserInfo getUserInfo(PublicKey publicKey, String token) {
        Jws<Claims> claimsJws = parseToken(publicKey, token);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                ObjectUtils.toLong(body.get(JwtConstants.JWT_KEY_ID)),
                ObjectUtils.toString(body.get(JwtConstants.JWT_KEY_NAME)),
                ObjectUtils.toString(body.get(JwtConstants.JWT_KEY_EMAIL)),
                ObjectUtils.toString(body.get(JwtConstants.JWT_KEY_IMG))
        );
    }

    /**
     * 从Token中获取用户信息(使用公钥解析)
     * @param publicKey
     * @param token
     * @return
     * @throws Exception
     */
    public static UserInfo getUserInfo(byte[] publicKey, String token) throws Exception {
        Jws<Claims> claimsJws = parseToken(publicKey, token);
        Claims body = claimsJws.getBody();
        return new UserInfo(
                ObjectUtils.toLong(body.get(JwtConstants.JWT_KEY_ID)),
                ObjectUtils.toString(body.get(JwtConstants.JWT_KEY_NAME)),
                ObjectUtils.toString(body.get(JwtConstants.JWT_KEY_IMG)),
                ObjectUtils.toString(body.get(JwtConstants.JWT_KEY_EMAIL))
        );
    }
}
  • LongJSONArray

package cn.itbluebox.springbootcsdn.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;

public class LongJSONArray {

    public static String LongToJSON(Long l[]) {
        StringBuilder sb = new StringBuilder(JSONArray.toJSONString(l));
        sb.replace(0, 1, "");
        sb.replace(sb.length() - 1, sb.length(), "");
        return sb.toString();
    }

    public static Long[] JSONToLong(String l) {
        l = "[" + l + "]";
        Long[] longs = JSON.parseObject(l, Long[].class);
        return longs;
    }
}
  • ObjectUtils

package cn.itbluebox.springbootcsdn.utils;

import org.apache.commons.lang3.StringUtils;

public class ObjectUtils {

    public static String toString(Object obj) {
        if (obj == null) {
            return null;
        }
        return obj.toString();
    }

    public static Long toLong(Object obj) {
        if (obj == null) {
            return 0L;
        }
        if (obj instanceof Double || obj instanceof Float) {
            return Long.valueOf(StringUtils.substringBefore(obj.toString(), "."));
        }
        if (obj instanceof Number) {
            return Long.valueOf(obj.toString());
        }
        if (obj instanceof String) {
            return Long.valueOf(obj.toString());
        } else {
            return 0L;
        }
    }

    public static Integer toInt(Object obj) {
        return toLong(obj).intValue();
    }
}
  • RandomAdmin
package cn.itbluebox.springbootcsdn.utils;

import java.text.NumberFormat;
import java.util.Random;

public class RandomAdmin {
    public static double RandmoncreateMoney() {
        int max = 100, min = 1;
        int ran1 = (int) (Math.random() * (max - min) + min);
        double max1 = 10, min1 = 1;
        double ran2 = (double) (Math.random() * (max1 - min1) + min1);
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits(2);
        return  Double.parseDouble(nf.format(ran1 + ran2));
    }
    private static final int BASE_RANDOM = 0x9fa5 - 0x4e00 + 1;
    private static Random random = new Random();
    public static char RandomString(){
        return (char) (0x4e00 + random.nextInt(BASE_RANDOM));
    }

    public static String RandomString(int num){
        String str = "";
        for(int i = 0; i < num; i++){
            str += (char) (0x4e00 + random.nextInt(BASE_RANDOM));
        }
        return str;
    }
}
  • RsaUtils
package cn.itbluebox.springbootcsdn.utils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RsaUtils {
    /**
     * 从文件中读取公钥
     *
     * @param filename 公钥保存路径,相对于classpath
     * @return 公钥对象
     * @throws Exception
     */
    public static PublicKey getPublicKey(String filename) throws Exception {
        byte[] bytes = readFile(filename);
        return getPublicKey(bytes);
    }

    /**
     * 从文件中读取密钥
     *
     * @param filename 私钥保存路径,相对于classpath
     * @return 私钥对象
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String filename) throws Exception {
        byte[] bytes = readFile(filename);
        return getPrivateKey(bytes);
    }

    /**
     * 获取公钥
     *
     * @param bytes 公钥的字节形式
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(byte[] bytes) throws Exception {
        X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePublic(spec);
    }

    /**
     * 获取密钥
     *
     * @param bytes 私钥的字节形式
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(byte[] bytes) throws Exception {
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return factory.generatePrivate(spec);
    }

    /**
     * 根据密文,生存rsa公钥和私钥,并写入指定文件
     *
     * @param publicKeyFilename  公钥文件路径
     * @param privateKeyFilename 私钥文件路径
     * @param secret             生成密钥的密文
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(secret.getBytes());
        keyPairGenerator.initialize(1024, secureRandom);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        // 获取公钥并写出
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        writeFile(publicKeyFilename, publicKeyBytes);
        // 获取私钥并写出
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        writeFile(privateKeyFilename, privateKeyBytes);
    }

    private static byte[] readFile(String fileName) throws Exception {
        return Files.readAllBytes(new File(fileName).toPath());
    }

    private static void writeFile(String destPath, byte[] bytes) throws IOException {
        File dest = new File(destPath);
        if (!dest.exists()) {
            dest.createNewFile();
        }
        Files.write(dest.toPath(), bytes);
    }
}
  • StringPaseDate
package cn.itbluebox.springbootcsdn.utils;

import java.util.Calendar;
import java.util.Date;

public class StringPaseDate {

    public static Date getDate(String str_date){
        String[] split = str_date.split("-");
        Calendar calendar=Calendar.getInstance();
        calendar.set(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));

        return calendar.getTime();
    }

}
  • TimeForMate
package cn.itbluebox.springbootcsdn.utils;

import java.text.SimpleDateFormat;
import java.util.Date;

public class TimeForMate {

    public static String forMate(String dateStr) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        date.setTime(Long.parseLong(dateStr));
        return dateFormat.format(date);
    }

}
  • UserInfo
package cn.itbluebox.springbootcsdn.utils;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {

    private Long id;
    private String name;
    private String image;
    private String email;

}

8、创建PageResult

package cn.itbluebox.springbootcsdn.vo;

import lombok.Data;

import java.util.List;

@Data
public class PageResult<T>  {

    private Long total;//总条数
    private Integer totalPage;//总页数
    private List<T> items;//当前页数据

    public PageResult() {

    }
    public PageResult(Long total, List<T> items){
        this.total = total;
        this.items = items;
    }

    public PageResult(Long total, Integer totalPage, List<T> items) {
        this.total = total;
        this.totalPage = totalPage;
        this.items = items;
    }

}

三、前端Vue + Element UI项目搭建

1、项目搭建

(1)项目构建

使用 Vue-cli构建 Vue 项目
安装命令:

npm install -g vue-cli

用vue-cli命令,快速搭建一个webpack的项目

一直向下回车。遇到yes或者no 选择y

创建成功

(2)引入Element UI和 Axios

安装 Element UI

npm i element-ui -S

安装axios

npm install axios

将模块安装到目录下

npm install --save default-passive-events

在main.js引入

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import 'default-passive-events'
import axios from 'axios'
Vue.prototype.$axios = axios
Vue.config.productionTip = false
Vue.use(ElementUI)
/* eslint-disable no-new */
axios.defaults.withCredentials = true
new Vue({
  el: '#app',
  router,
  axios,
  components: { App },
  template: '<App/>'
})

2、运行测试

在HelloWord当中引入一些Element UI的组件测试

<el-row>
      <el-button disabled>默认按钮</el-button>
      <el-button type="primary" disabled>主要按钮</el-button>
      <el-button type="success" disabled>成功按钮</el-button>
      <el-button type="info" disabled>信息按钮</el-button>
      <el-button type="warning" disabled>警告按钮</el-button>
      <el-button type="danger" disabled>危险按钮</el-button>
    </el-row>

npm run dev

访问:http://localhost:8080/#/

相关文章