Feat: init project

This commit is contained in:
xinsin 2023-04-10 22:02:00 +08:00
parent 238b411ed3
commit 89ff44cfcf
12 changed files with 452 additions and 2 deletions

3
.gitignore vendored
View File

@ -42,4 +42,5 @@ buildNumber.properties
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
.idea
target

View File

@ -1,3 +1,3 @@
# Commerce-System-Backend
🚧 Fix, Feat,🔨 Refactor,📝 Docs,✨ Style,🍱 Perf,🔧 Test,⚡️ Chore,🐛 Bug
Commerce System

110
pom.xml Normal file
View File

@ -0,0 +1,110 @@
<?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>top.xinsin</groupId>
<artifactId>Commerce-System-Backend</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.5</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.26</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.20.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 模板引擎依赖-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package top.xinsin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("top.xinsin.mapper")
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class,args);
}
}

View File

@ -0,0 +1,23 @@
package top.xinsin.config;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author xinsin
* Created On 2023/4/3 15:55
* @version 1.0
*/
@SpringBootConfiguration
public class GlobalWebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "DELETE", "PUT", "HEAD")
.allowedHeaders("*")
.exposedHeaders("*");
}
}

View File

@ -0,0 +1,24 @@
package top.xinsin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import top.xinsin.interceptor.AuthenticationInterceptor;
/**
* @author xinsin
* Created On 2023/4/3 15:54
* @version 1.0
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthenticationInterceptor()).
//拦截
addPathPatterns("/**").
//放行登录接口
excludePathPatterns("/user/login").
excludePathPatterns("/user/register");
}
}

View File

@ -0,0 +1,25 @@
package top.xinsin.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig{
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setOptimizeJoin(true);
paginationInnerInterceptor.setDbType(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();
interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);
return interceptor;
}
}

View File

@ -0,0 +1,56 @@
package top.xinsin.interceptor;
import com.alibaba.fastjson2.JSONObject;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import top.xinsin.util.HttpCodes;
import top.xinsin.util.JWTUtils;
import top.xinsin.util.R;
/**
* @author xinsin
* Created On 2023/4/3 15:49
* @version 1.0
*/
@Slf4j
public class AuthenticationInterceptor implements HandlerInterceptor {
public static final String OPTIONS = "OPTIONS";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (OPTIONS.equals(request.getMethod())) {
return true;
}
// 从http请求头中取出token
final String token = request.getHeader("Access-Token");
//解决跨域问题
response.setHeader("Access-Control-Allow-Origin","*");
//解决跨域问题
response.setHeader("Access-Control-Allow-Headers","*");
R responseData;
try {
JWTUtils.verify(token);
return true;
} catch (SignatureVerificationException e) {
log.info("用户验证了无效签名");
responseData = R.failed(HttpCodes.ACCESS_DENIED,"无效签名");
}catch (TokenExpiredException e){
log.info("用户验证的签名已过期");
responseData = R.failed(HttpCodes.INVALID_TOKEN,"签名已过期");
}catch (AlgorithmMismatchException e){
log.info("用户验证的token算法不一致");
responseData = R.failed(HttpCodes.INVALID_TOKEN,"token算法不一致");
}catch (Exception e){
log.info("token无效或者是空的");
responseData = R.failed(HttpCodes.INVALID_TOKEN,"token无效");
}
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JSONObject.toJSONString(responseData));
return false;
}
}

View File

@ -0,0 +1,56 @@
package top.xinsin.util;
/**
* @author xinsin
* Created On 2023/4/3 15:47
* @version 1.0
*/
public enum HttpCodes {
/**
* 200
* 成功执行
*/
HTTP_CODES200(200,"接口一不小心执行成功啦!"),
/**
* 500
* 服务器错误
*/
HTTP_CODES500(500,"哎呀,错误了请节哀!"),
/**
* 401
* 数据错误
*/
HTTP_CODES401(401,"你这请求是坏的,你不会写吗?"),
/**
* 501
* 账号密码错误
*/
HTTP_CODES501(501,"帐号或密码错误!"),
/**
* 250
* token验证错误
*/
INVALID_TOKEN(250,"令牌验证错误"),
/**
* 251
* 无权限访问
*/
ACCESS_DENIED( 251,"你没有权限访问");
private final int code;
private final String message;
HttpCodes(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}

View File

@ -0,0 +1,72 @@
package top.xinsin.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
import java.util.Map;
/**
* @author xinsin
* Created On 2023/4/3 15:47
* @version 1.0
*/
public class JWTUtils {
private static final String KEY = "a3Q%b5R@j7kP*9d-v'Y|h-%i(h9J0sU1/o";
/**
* 创建token
* @param map 字段
* @return token
*/
public static String getToken(Map<String,String> map){
Calendar instance = Calendar.getInstance();
//默认两个小时过期
instance.add(Calendar.HOUR,2);
//创建jwt builder
JWTCreator.Builder builder = JWT.create();
//payload
map.forEach(builder::withClaim);
//指定令牌过期时间
return builder.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC512(KEY));
}
/**
* 验证token是否合法
* @param token token
*/
public static void verify(String token){
JWT.require(Algorithm.HMAC512(KEY)).build().verify(token);
}
/**
* 从token中提取信息
*
* @param token token
* @return token中包含的信息
*/
public static DecodedJWT getTokenInfo(String token) {
return JWT.require(Algorithm.HMAC512(KEY)).build().verify(token);
}
/**
* 判断token与用户名是否对应
*
* @param token token
* @param username 用户名
* @return 是否对应
*/
public static boolean isUser(String token, String username) {
String tokenUsername = getTokenInfo(token).getClaim("username").asString();
return tokenUsername.equals(username);
}
public static Integer getId(String token){
return Integer.valueOf(getTokenInfo(token).getClaim("id").asString());
}
public static Integer getAuth(String token) {
return getTokenInfo(token).getClaim("auth").asInt();
}
}

View File

@ -0,0 +1,34 @@
package top.xinsin.util;
import lombok.Data;
/**
* @author xinsin
* Created On 2023/4/3 15:45
* @version 1.0
*/
@Data
public class R<T> {
private int status;
private String message;
private T data;
private long timestamp;
public R() {
this.timestamp = System.currentTimeMillis();
}
public static<T> R<T> success(T data){
R<T> rData = new R<>();
rData.setStatus(HttpCodes.HTTP_CODES200.getCode());
rData.setMessage(HttpCodes.HTTP_CODES200.getMessage());
rData.setData(data);
return rData;
}
public static<T> R<T> failed(HttpCodes httpCodes, T data){
R<T> rData = new R<>();
rData.setStatus(httpCodes.getCode());
rData.setMessage(httpCodes.getMessage());
rData.setData(data);
return rData;
}
}

View File

@ -0,0 +1,36 @@
server:
port: 8001
spring:
datasource:
username: commerce_system
password: Jix656dzD6St4YCn
url: jdbc:mysql://wzpmc.cn:3306/commerce_system?serverTimezone=UTC-8
driver-class-name: com.mysql.cj.jdbc.Driver
# druid配置
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
# 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mvc:
static-path-pattern: /static/**
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-field: del # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)