Web服务器经过之前压力测试过5000并发请求4核8G服务器也是一点问题都没有
那这次设计理念就用一个Web服务器来处理N个终端请求并处理数据
数据库用目前最先进的:PostgreSQL,Web框架用比较流行的springboot
其他Web框架,我也用过,最顺手还是springboot
目录
[1. Maven配置](#1. Maven配置)
[2. 创建springboot项目](#2. 创建springboot项目)
[3. 安装PostgreSQL数据库](#3. 安装PostgreSQL数据库)
[4. 项目目录讲解](#4. 项目目录讲解)
[5. 创建多个数据库源(重点)](#5. 创建多个数据库源(重点))
步骤一:在application.properties文件下写两个配置源
[6. 好用的Java工具类在maven安装](#6. 好用的Java工具类在maven安装)
[7. 工程目录讲解](#7. 工程目录讲解)
[8. 新嘉丽用户登录功能目录讲解](#8. 新嘉丽用户登录功能目录讲解)
1. Maven配置
java要安装第三方库有几个工具,这里推荐使用maven
这里我们给maven做两个配置:1. 换仓库地址,2. 换国内阿里云下载源
因为Gradle实在是不好配置国内镜像源,安装速度有点慢,即不推荐了
Maven官网:https://maven.apache.org/download.cgi
下载这个zip(应该是这个zip,太久远有点忘了,不是的话自己翻译看看,比较简单的)

解压到自己的文件夹里,并且进来目录

这里有一个目录叫:mvn_resp,是我自己创建的,大家先创建这个目录
然后打开/conf/settings.xml的文件
然后修改仓库地址(就是刚刚新建的文件夹)
这样做有两个好处
-
每次刷机重置电脑后都不需要重新下载
-
不占用C盘空间,毕竟这玩意大起来也能高达几个G

然后来到以下位置,替换下载源,我们这里用阿里云

XML
<mirror>
<id>nexus-aliyun</id> <!--此镜像唯一标识符,区分不同mirror元素-->
<mirrorOf>central</mirrorOf> <!--对哪种仓库进行镜像-->
<name>Nexus aliyun</name> <!--镜像名称-->
<url>http://maven.aliyun.com/nexus/content/groups/public</url><!--镜像url-->
</mirror>
2. 创建springboot项目


然后把这三个依赖加上

3. 安装PostgreSQL数据库
官网下载链接:https://www.enterprisedb.com/downloads/postgres-postgresql-downloads
选最新版本直接下载就行

正常默认安装就行,他会自己开机自启动,所以就不需要管了
然后用Navicat17新建连个数据库,一个是store,一个是xinjiali
Navicat17的安装和破解在B站有,帮你找好了:https://www.bilibili.com/video/BV1TL7GzkE59/?spm_id_from=333.337.search-card.all.click&vd_source=2bcfc110b7fc9b7d7735e4aae40837b2
为啥要用PostgreSQL?
因为他有三层结构:数据库->模式->表
表里的字段可以是数组,这就很方便了,不需要开一个新表来存**(MySQL是做不到的)**

4. 项目目录讲解
关注以下即可,其他文件都不重要

5. 创建多个数据库源(重点)
这里我是做到了一部分项目才想起要写文章,所以左边目录还挺多东西的
外面的课程都没有教多个数据库源的配置,所以这里要认真学清楚了
步骤一:在application.properties文件下写两个配置源

配置文件照抄复制就行,redis暂时虽然用不上,配置先写着先
bash
spring.application.name=Derion_Web
# PostgreSQL的配置
# 第一个数据库源配置
#spring.datasource.url=jdbc:postgresql://8.138.103.111:5432/????
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/store
spring.datasource.username=postgres
spring.datasource.password=填自己的密码
spring.datasource.driver-class-name=org.postgresql.Driver
# 第二个数据库源配置
spring.datasource.second.url=jdbc:postgresql://127.0.0.1:5432/xinjiali
spring.datasource.second.username=postgres
spring.datasource.second.password=填自己的密码
spring.datasource.second.driver-class-name=org.postgresql.Driver
# MyBatis??
#mybatis.mapper-locations=classpath:mappers/**/*.xml
mybatis.type-aliases-package=com.example.derion_web.????.Object
# ?????????????
logging.level.org.mybatis=DEBUG
logging.level.com.example.derion_web=INFO
# Redis的配置
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=test
spring.data.redis.database=0
spring.data.redis.timeout=60000
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=PT-1S
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.min-idle=0
步骤二:创建一个包:config
等下把代码粘贴进去就行,他会自动生成类,不需要手动创建

步骤三:在config包下,复制四个类进去
全选代码复制就行,点击config包,粘贴,就会自动生成java类并有代码了,IDEA的好用之处
java
package com.example.derion_web.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Value("${spring.datasource.url}")
private String primaryUrl;
@Value("${spring.datasource.username}")
private String primaryUsername;
@Value("${spring.datasource.password}")
private String primaryPassword;
@Value("${spring.datasource.driver-class-name}")
private String primaryDriverClassName;
@Value("${spring.datasource.second.url}")
private String secondUrl;
@Value("${spring.datasource.second.username}")
private String secondUsername;
@Value("${spring.datasource.second.password}")
private String secondPassword;
@Value("${spring.datasource.second.driver-class-name}")
private String secondDriverClassName;
// 主数据源配置
@Primary
@Bean(name = "primaryDataSource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create()
.url(primaryUrl)
.username(primaryUsername)
.password(primaryPassword)
.driverClassName(primaryDriverClassName)
.build();
}
// 第二个数据源配置
@Bean(name = "secondDataSource")
public DataSource secondDataSource() {
return DataSourceBuilder.create()
.url(secondUrl)
.username(secondUsername)
.password(secondPassword)
.driverClassName(secondDriverClassName)
.build();
}
}
下方高能:basePackages = {"com.example.derion_web.智慧门店"},
这里设置数据库源是在哪个包下使用
java
package com.example.derion_web.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
@Primary
@MapperScan(
basePackages = {"com.example.derion_web.智慧门店"},
sqlSessionTemplateRef = "primarySqlSessionTemplate"
)
public class PrimaryMapperConfig {
}
java
package com.example.derion_web.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan(
basePackages = {"com.example.derion_web.新嘉丽服务器"},
sqlSessionTemplateRef = "secondSqlSessionTemplate"
)
public class SecondMapperConfig {
}
java
package com.example.derion_web.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
@Configuration
public class TransactionManagerConfig {
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Autowired
@Qualifier("secondDataSource")
private DataSource secondDataSource;
// 主数据源的事务管理器
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager() {
return new DataSourceTransactionManager(primaryDataSource);
}
// 第二个数据源的事务管理器
@Bean(name = "secondTransactionManager")
public PlatformTransactionManager secondTransactionManager() {
return new DataSourceTransactionManager(secondDataSource);
}
}
6. 好用的Java工具类在maven安装

XML
<!-- 下面是自己的 -->
<!-- 很好用的工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.17</version>
</dependency>
<!-- SSL证书依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--json格式转换-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<!--JWT令牌-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--JWT令牌依赖,JDK1.8版本需要加上-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
<!-- 阿里云OSS:如果是java9以上就需要额外加下面的-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<!-- 微信支付相关 -->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.12</version>
</dependency>
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.4.9</version>
</dependency>
<!-- @Builder 和 @Data 需要的 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 创建excel需要的 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version> <!-- 使用适合你项目的版本 -->
</dependency>
<!-- Redis依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Redis连接池依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
7. 工程目录讲解
这种就是创建的工程目录

这里目录的分类是经过多次项目经验后,才这样分的
首先看一级目录:新嘉丽服务器,智慧门店
这两个一级目录是用来区分我们要做的项目
上方配置的PGSQL数据源也是通过这个不同的包来区分,就是说
新嘉丽服务器包下的所有数据库查询的源
和
智慧门店包下所有数据库查询的源
是不一样的
展开新嘉丽这个项目可以看到:Object,用户管理,质保管理
Object就是整个项目都用上的对象类
用户管理和质保管理都是功能模块,里面都有各自的SQL,测试接口,API接口,工具类,Object
就是每一个模块的功能代码都是互相独立

这是我经验得出来的项目整理思路
以前刚开始开发的时候,都是全部API堆在一起,SQL和Object都是另外堆在一起
这就导致找API很方便,但是要找SQL尝尝都是很头晕,Object也是头晕,分不清楚有没有重复写
现在就按模块区分,当前模块有没有写重复的SQL,这就很清晰了
而且Object中也能更好兼容当前模块功能,不至于一个Object硬是不断增加内容来兼容多个业务模块
8. 新嘉丽用户登录功能目录讲解
接下来要做的就是很普通的用户能

现在开始,先跟着我的项目结构来创建包和文件吧
普通的java类这样新建


SQL包下的sql也是java类,不过是一个接口,要选择这个

测试接口是一个.http文件,在springboot可以用来发送网络请求
我用了他之后,我都不用接口测试工具了,这玩意更方便
ok,创建好了包,java类,.http之后,下一章我们就来写代码
9. 自定义通用工具类
通用工具类层级如下

目前只有两个,Jwt令牌的解析和时间工具类
后续没记错的话还会有阿里云OSS的相关工具类,那是后话了
java
package com.example.derion_web.通用工具类;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
public class JwtUtils {
private static String signKey = "这里填自己的密码,不要外漏,不然jwt令牌是可以被破解的,尽量长一点好"; // 签名
private static Long expire = System.currentTimeMillis() + 3600 * 1000 * 24 * 30 * 12 * 100; // 过期时间为100年
/**
* 生成JWT令牌
* @param claims JWT第二部分负载 payload 中存储的内容
* @return
*/
public static String create_JWT(HashMap<String, Object> claims){
String jwt = Jwts.builder()
.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, signKey)
.setExpiration(new Date(System.currentTimeMillis() + expire))
.compact();
return jwt;
}
/**
* 解析JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims Analysis_JWT(String jwt){
Claims claims = Jwts.parser()
.setSigningKey(signKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
public static String get_openid(String jwt){
Claims claims = Analysis_JWT(jwt);
String openid = claims.get("openid", String.class);
return openid;
}
}
java
package com.example.derion_web.通用工具类;
import java.time.Instant;
import cn.hutool.crypto.digest.DigestUtil;
public class 时间工具类 {
/**
* 函数:切割date字符串,返回日期部分
* @param date 日期字符串,格式为yyyy-MM-dd HH:mm:ss
* @return 日期部分,格式为yyyy-MM-dd
*/
public static String 切割日期(String date){
return date.split(" ")[0];
}
public static String 时间戳(){
long timestamp = Instant.now().toEpochMilli();
return String.valueOf(timestamp);
}
public static String MD5时间戳(){
String timestamp = 时间戳();
return DigestUtil.md5Hex(timestamp);
}
}
配置好这两个就要开工了
10. 全局返回类
是每一个项目都默认返回类,虽然都是同一个类,我这里还是区分开了

代码如下,复制粘贴就行
java
package com.example.derion_web.新嘉丽服务器.Object;
public class Result {
private Integer code;
private String msg;
private Object data;
public Result(){}
public Result(Integer code, String msg, Object data){
this.code = code;
this.msg = msg;
this.data = data;
}
// 成功返回,有内容
public static Result success(Object data){
Result success = new Result(1, "success", data);
return success;
}
// 成功返回,内容
public static Result success(){
Result success = new Result(1, "success",null);
return success;
}
// 错误消息
public static Result error(String msg){
return new Result(0,msg,null);
}
@Override
public String toString() {
return "Result{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}