初始化修改代码

This commit is contained in:
2025-07-19 20:22:06 +08:00
parent 06548a4716
commit 4a0cf71e5d
26 changed files with 890 additions and 175 deletions

15
Dockerfile.buildagent Normal file
View File

@ -0,0 +1,15 @@
# 使用 JDK 8 作为构建环境
FROM openjdk:8-jdk
# 使用阿里云的 apt 镜像源Debian 11 bullseye
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list
# 更新包列表并安装 Maven 和 Git
RUN apt update && \
apt install -y maven git && \
mvn --version && \
git --version
# 设置工作目录
WORKDIR /home/jenkins/workspace

31
Jenkinsfile vendored
View File

@ -1,10 +1,10 @@
pipeline { pipeline {
agent any agent any
tools { // tools {
maven 'M3' // 必须在 Jenkins → Manage Jenkins → Global Tool Configuration 中配置过 // maven 'M3' // 必须在 Jenkins → Manage Jenkins → Global Tool Configuration 中配置过
} // }
environment { environment {
APP_NAME = "sczx-app" APP_NAME = "sczx_order"
DOCKER_IMAGE = "${APP_NAME}:latest" DOCKER_IMAGE = "${APP_NAME}:latest"
CONTAINER_NAME = "${APP_NAME}-container" CONTAINER_NAME = "${APP_NAME}-container"
} }
@ -13,11 +13,16 @@ pipeline {
stage('Checkout') { stage('Checkout') {
steps { steps {
echo "📦 正在拉取代码..." echo "📦 正在拉取代码..."
git branch: 'main', url: 'http://115.190.8.52:3000/sczx_group/sczx-app.git' git branch: 'main', url: 'http://115.190.8.52:3000/sczx_group/sczx_order.git'
} }
} }
stage('Build with Maven') { stage('Build with Maven in JDK 8') {
agent {
dockerfile {
filename "Dockerfile.buildagent"
}
}
steps { steps {
echo "🛠️ 正在使用 Maven 构建..." echo "🛠️ 正在使用 Maven 构建..."
sh 'mvn clean package -s settings.xml' sh 'mvn clean package -s settings.xml'
@ -31,32 +36,34 @@ pipeline {
} }
stage('Build Docker Image') { stage('Build Docker Image') {
agent any
steps { steps {
echo "🐋 正在构建 Docker 镜像..." echo "🐋 正在构建 Docker 镜像..."
sh """ sh 'docker build -t "$DOCKER_IMAGE" .'
docker build -t \${DOCKER_IMAGE} .
"""
} }
} }
stage('Stop Old Container') { stage('Stop Old Container') {
agent any
steps { steps {
echo "🛑 正在停止旧的容器(如果存在)..." echo "🛑 正在停止旧的容器(如果存在)..."
sh ''' sh '''
if [ "$(docker ps -f 'name=sczx-app-container' --format '{{.Status}}')" ]; then if [ "$(docker ps -f 'name=sczx_order-container' --format '{{.Status}}')" ]; then
docker stop sczx-app-container docker stop sczx_order-container
docker rm sczx-app-container docker rm sczx_order-container
fi fi
''' '''
} }
} }
stage('Run New Container') { stage('Run New Container') {
agent any
steps { steps {
echo "🟢 正在运行新的容器..." echo "🟢 正在运行新的容器..."
sh """ sh """
docker run -d \ docker run -d \
--name \${CONTAINER_NAME} \ --name \${CONTAINER_NAME} \
--network sczx-net \
-p 8088:8088 \ -p 8088:8088 \
-e JAVA_OPTS="-Xms256m -Xmx512m -Duser.timezone=Asia/Shanghai" \ -e JAVA_OPTS="-Xms256m -Xmx512m -Duser.timezone=Asia/Shanghai" \
--restart always \ --restart always \

View File

@ -1 +1 @@
闪充智行后端 闪充智行订单服务

99
pom.xml
View File

@ -4,12 +4,12 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.sczx</groupId> <groupId>com.sczx</groupId>
<artifactId>sczx-app</artifactId> <artifactId>sczx_order</artifactId>
<version>1.0.0</version> <version>1.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>sczx-app</name> <name>sczx_order</name>
<description>sczx-app service</description> <description>sczx_order service</description>
<properties> <properties>
<java.version>1.8</java.version> <java.version>1.8</java.version>
@ -146,17 +146,46 @@
<version>8.0.33</version> <version>8.0.33</version>
</dependency> </dependency>
<!-- Springdoc OpenAPI UI --> <!-- JWT -->
<dependency> <dependency>
<groupId>org.springdoc</groupId> <groupId>io.jsonwebtoken</groupId>
<artifactId>springdoc-openapi-ui</artifactId> <artifactId>jjwt-api</artifactId>
<version>1.6.14</version> <!-- 支持 Java 8 的最新版本 --> <version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.webjars</groupId> <groupId>org.apache.commons</groupId>
<artifactId>swagger-ui</artifactId> <artifactId>commons-pool2</artifactId>
<version>4.15.5</version> <version>2.11.1</version> <!-- 可根据需要选择版本 -->
</dependency>
<!-- swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency> </dependency>
<!-- JAXB API (Java 8 兼容) --> <!-- JAXB API (Java 8 兼容) -->
@ -171,11 +200,33 @@
<artifactId>reactor-core</artifactId> <artifactId>reactor-core</artifactId>
<version>3.2.2.RELEASE</version> <!-- 支持 Java 8 --> <version>3.2.2.RELEASE</version> <!-- 支持 Java 8 -->
</dependency> </dependency>
<!-- MapStruct 核心库 -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<!-- MapStruct 注解处理器(用于编译期生成实现类) -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
<scope>provided</scope>
</dependency>
<!-- FastJSON -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
</dependencies> </dependencies>
<!-- Build Configuration --> <!-- Build Configuration -->
<build> <build>
<finalName>sczx-app</finalName> <finalName>sczx_order</finalName>
<resources> <resources>
<resource> <resource>
<directory>src/main/resources</directory> <directory>src/main/resources</directory>
@ -214,32 +265,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>unpack</id>
<phase>process-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>4.15.5</version>
<type>jar</type>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<includes>META-INF/resources/**</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <artifactId>maven-source-plugin</artifactId>

View File

@ -1,16 +0,0 @@
package com.sczx.app.config;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
//@Configuration
public class SpringDocConfig {
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group("sczx-service")
.packagesToScan("com.sczx.app.controller")
.build();
}
}

View File

@ -1,44 +0,0 @@
package com.sczx.app.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/swagger-ui/4.15.5/");
registry.addResourceHandler("/swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/swagger-ui.html");
registry.addResourceHandler("/v3/api-docs/**")
.addResourceLocations("classpath:/META-INF/resources/swagger-ui/");
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
// 添加支持 application/json;charset=UTF-8 的 Jackson 转换器
converters.add(new MappingJackson2HttpMessageConverter() {
@Override
public List<MediaType> getSupportedMediaTypes() {
return Collections.singletonList(MediaType.APPLICATION_JSON_UTF8);
}
});
}
}

View File

@ -1,16 +0,0 @@
package com.sczx.app.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Tag(name = "示例接口", description = "用于演示 Springdoc 的接口")
public class DemoController {
@GetMapping("/test")
@Operation(summary = "测试接口", description = "返回一个测试字符串")
public String test() {
return "OK";
}
}

View File

@ -1,7 +1,8 @@
package com.sczx.app; package com.sczx.order;
import com.sczx.app.common.constant.SystemConstants; import com.sczx.order.common.constant.SystemConstants;
import com.sczx.app.utils.ComputerInfo; import com.sczx.order.utils.ComputerInfo;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -15,19 +16,19 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.io.IOException; import java.io.IOException;
@Slf4j
@SpringBootApplication @SpringBootApplication
@EnableDiscoveryClient // 启用服务注册与发现 @EnableDiscoveryClient // 启用服务注册与发现
@EnableRetry @EnableRetry
@EnableFeignClients(basePackages = SystemConstants.FEIGN_CLIENT_BASE_PACKAGE ) @EnableFeignClients(basePackages = SystemConstants.FEIGN_CLIENT_BASE_PACKAGE )
@EnableTransactionManagement @EnableTransactionManagement
@EnableHystrix @EnableHystrix
@MapperScan("com.sczx.app.mapper") // 扫描 Mapper 接口 @MapperScan("com.sczx.order.mapper") // 扫描 Mapper 接口
public class Application { public class Application {
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args); ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
Environment environment = context.getBean(Environment.class); Environment environment = context.getBean(Environment.class);
System.out.println("启动成功后端服务API地址http://" + ComputerInfo.getIpAddr() + ":" log.info("启动成功后端服务API地址http://{}:{}/swagger-ui.html", ComputerInfo.getIpAddr(), environment.getProperty("server.port"));
+ environment.getProperty("server.port") + "/doc.html");
} }
} }

View File

@ -0,0 +1,58 @@
package com.sczx.order.aspect;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* @Author Huang Kai
* @Date 2023/1/18 17:01
* @Version 1.0
*/
@Aspect
@Component
@Slf4j
public class FacadeAspect {
/** 以 controller 包下定义的所有请求为切入点 */
@Pointcut("execution(public * com..facade.*.*(..))")
public void facadeLog() {}
/**
* 在切点之前织入
* @param joinPoint
*/
@Before("facadeLog()")
public void doBefore(JoinPoint joinPoint) {
// 打印请求相关参数
log.info("=========================remote Start =========================");
// 打印 Http method
//log.info("HTTP Method : {}", request.getMethod());
// 打印调用 controller 的全路径以及执行方法
log.info("Class Method:{}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
// 打印请求的 IP
//log.info("IP : {}", request.getRemoteAddr());
// 打印请求入参
log.info("facadeAspect_Request:{}", JSON.toJSONString(joinPoint.getArgs()));
}
@Around("facadeLog()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = proceedingJoinPoint.proceed();
// 打印出参
log.info("facadeAspect_Response:{}", JSON.toJSONString(result));
// 执行耗时
log.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
log.info("=========================remote End =========================");
return result;
}
}

View File

@ -0,0 +1,97 @@
package com.sczx.order.aspect;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* @Author Huang Kai
* @Date 2023/1/18 17:01
* @Version 1.0
*/
@Aspect
@Component
@Slf4j
public class WebLogAspect {
/** 以 controller 包下定义的所有请求为切入点 */
@Pointcut("execution(public * com.sczx.*.controller.*.*(..))")
public void webLog() {}
/**
* 在切点之前织入
* @param joinPoint
*/
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) {
String uid = UUID.randomUUID().toString();
MDC.put("requestId",uid.substring(24,36));
// 开始打印请求日志
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = null;
if (attributes != null) {
request = attributes.getRequest();
}
// 打印请求相关参数
log.info("========================= Start =========================");
// 打印请求入参
try{
Object[] args = joinPoint.getArgs();
List<Object> filteredArgs = new ArrayList<>();
for (Object arg : args) {
//如果是文件类,则只打印文件名称和大小
if (arg instanceof MultipartFile) {
MultipartFile file = (MultipartFile) arg;
JSONObject fileJson = new JSONObject();
fileJson.put("filename", file.getOriginalFilename());
fileJson.put("size", file.getSize());
filteredArgs.add(fileJson);
} else {
filteredArgs.add(arg);
}
}
if (request != null) {
log.info("URL:{} , {}", request.getRequestURL().toString(), JSON.toJSONString(filteredArgs));
}
} catch (Exception e){
log.error("打印WebLogAspect_Request失败args无法被序列化", e);
}
}
/**
* 处理完请求后执行
* @param joinPoint
* @param result
*/
@AfterReturning(pointcut = "webLog()", returning = "result")
public void doAfterReturning(JoinPoint joinPoint, Object result) {
// 打印出参
try {
log.info("WebLogAspect_Response:{}", JSON.toJSON(result));
}catch (Exception e){
log.error("打印WebLogAspect_Response失败result无法被序列化", e);
}
log.info("========================= End =========================");
MDC.clear();
}
@AfterThrowing(throwing="ex",pointcut="webLog()")
public void doRecoveryActions(Throwable ex){
MDC.clear();
}
}

View File

@ -0,0 +1,12 @@
package com.sczx.order.common;
/**
* @Author: 张黎
* @Date: 2025/07/09/20:20
* @Description:
*/
public interface IApiCode {
String getCode();
String getMsg();
}

View File

@ -0,0 +1,123 @@
package com.sczx.order.common;
import com.sczx.order.common.enums.ApiErrorCode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang.StringUtils;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: 张黎
* @Date: 2025/07/09/20:25
* @Description:
*/
@ApiModel(value = "公共返回结果")
@Builder
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1331134667810352183L;
@ApiModelProperty(value = "成功标识")
private boolean success;
@ApiModelProperty(value = "返回编码")
private String code;
@ApiModelProperty(value = "返回信息说明")
private String msg;
private String issue;
@ApiModelProperty(value = "返回数据")
private T data;
public Result(boolean success, String code, String msg, String issue, T data) {
this.success = success;
this.code = code;
this.msg = msg;
this.issue = issue;
this.data = data;
}
public static Result result(IApiCode apiCode) {
return result(apiCode, (Object)null);
}
public static Result result(IApiCode apiCode, Object data) {
return result(apiCode, apiCode.getMsg(), data);
}
public static Result result(IApiCode apiCode, String issue, Object data) {
return result((IApiCode)apiCode, (String)null, issue, data);
}
public static Result result(IApiCode apiCode, String msg, String issue, Object data) {
String message = apiCode.getMsg();
if (StringUtils.isNotBlank(msg)) {
message = msg;
}
return result(apiCode.getCode(), message, issue, data);
}
public static Result result(String code, String msg, String issue, Object data) {
return builder().code(code).success("0".equals(code)).msg(msg).issue(issue).data(data).build();
}
public static Result ok() {
return ok((Object)null);
}
public static Result ok(Object data) {
return result(ApiErrorCode.SUCCESS, data);
}
public static Result ok(String key, Object value) {
Map<String, Object> map = new HashMap(1);
map.put(key, value);
return ok(map);
}
public static Result fail(String msg) {
return result((IApiCode)ApiErrorCode.FAIL, msg, msg, (Object)null);
}
public static Result fail(IApiCode apiCode) {
return result(apiCode, (Object)null);
}
public static Result fail(IApiCode apiCode, String issue) {
return result(apiCode, issue, (Object)null);
}
public static Result fail(String code, String msg) {
return result((String)code, msg, msg, (Object)null);
}
public static Result fail(String code, String msg, String issue) {
return result((String)code, msg, issue, (Object)null);
}
public static Result fail(String code, String msg, String issue, Object data) {
return result(code, msg, issue, data);
}
public static Result fail(IApiCode apiCode, String issue, Object data) {
if (ApiErrorCode.SUCCESS == apiCode) {
throw new RuntimeException("失败结果状态码不能为" + ApiErrorCode.SUCCESS.getCode());
} else {
return result(apiCode, issue, data);
}
}
public static Result fail(String key, Object value) {
Map<String, Object> map = new HashMap();
map.put(key, value);
return result(ApiErrorCode.FAIL, map);
}
public Result() {
}
}

View File

@ -1,4 +1,4 @@
package com.sczx.app.common.constant; package com.sczx.order.common.constant;
/** /**
@ -18,6 +18,6 @@ public interface SystemConstants {
/*** /***
* feign客户端所在包路径 * feign客户端所在包路径
*/ */
String FEIGN_CLIENT_BASE_PACKAGE = "com.sczx.app.thirdpart.facade"; String FEIGN_CLIENT_BASE_PACKAGE = "com.sczx.order.thirdpart.facade";
} }

View File

@ -0,0 +1,55 @@
package com.sczx.order.common.enums;
import com.sczx.order.common.IApiCode;
/**
* @Author: 张黎
* @Date: 2025/07/09/20:22
* @Description:
*/
public enum ApiErrorCode implements IApiCode {
SUCCESS("0", "操作成功"),
ARG_ERROR("401000", "参数错误"),
NOT_PERMISSION("401001", "没有权限"),
HTTP_MEDIA_TYPE_NOT_SUPPORTED_ERROR("401002", "media类型出错"),
HTTP_METHOD_NOT_ALLOW_ERROR("401003", "http请求method错误"),
BODY_NOT_MATCH("401004", "请求的数据格式不符!"),
NOT_FOUND("404000", "你请求的路径不存在"),
UNAUTHORIZED("404001", "非法访问"),
FAIL("500000", "操作失败"),
INNER_ERROR("500001", "服务器内部异常");
private final String code;
private final String msg;
private ApiErrorCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
public static ApiErrorCode getApiCode(String code) {
ApiErrorCode[] ecs = values();
ApiErrorCode[] var2 = ecs;
int var3 = ecs.length;
for(int var4 = 0; var4 < var3; ++var4) {
ApiErrorCode ec = var2[var4];
if (ec.getCode().equals(code)) {
return ec;
}
}
return SUCCESS;
}
@Override
public String getCode() {
return this.code;
}
@Override
public String getMsg() {
return this.msg;
}
}

View File

@ -1,4 +1,4 @@
package com.sczx.app.config; package com.sczx.order.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;

View File

@ -0,0 +1,47 @@
package com.sczx.order.config;
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.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.Arrays;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.sczx.order.controller")) // 修改为你的 controller 包路径
.paths(PathSelectors.any())
.build()
.globalOperationParameters(Arrays.asList(
new ParameterBuilder()
.name("Authorization")
.description("Bearer Token")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(true)
.build()
));
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("订单服务接口文档")
.description("sczx_order订单服务接口文档")
.version("1.0")
.build();
}
}

View File

@ -0,0 +1,14 @@
package com.sczx.order.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@GetMapping("/test")
public String test() {
return "OK";
}
}

View File

@ -0,0 +1,85 @@
package com.sczx.order.exception;
import com.sczx.order.common.IApiCode;
import com.sczx.order.common.enums.ApiErrorCode;
/**
*
* @author zhangli
*/
public class BizException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
protected String errorCode;
/**
* 错误信息
*/
protected String errorMsg;
public BizException() {
super();
}
public BizException(IApiCode apiCode) {
super(apiCode.getCode());
this.errorCode = apiCode.getCode();
this.errorMsg = apiCode.getMsg();
}
public BizException(IApiCode apiCode, Throwable cause) {
super(apiCode.getCode(), cause);
this.errorCode = apiCode.getCode();
this.errorMsg = apiCode.getMsg();
}
public BizException(String errorMsg) {
super(errorMsg);
this.errorCode = ApiErrorCode.FAIL.getCode();
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg, Throwable cause) {
super(errorCode, cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
@Override
public String getMessage() {
return errorMsg;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}

View File

@ -0,0 +1,50 @@
package com.sczx.order.exception;
import com.sczx.order.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
/**
* @author zhangli
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理自定义的业务异常
*
* @param req
* @param e
* @return
*/
@ExceptionHandler(value = BizException.class)
@ResponseBody
public Result bizExceptionHandler(HttpServletRequest req, BizException e) {
log.warn("发生业务异常!原因是:{}", e.getErrorMsg(), e);
return Result.fail(e.getErrorCode(), e.getErrorMsg());
}
@ExceptionHandler(value = InnerException.class)
@ResponseBody
public Result innerExceptionHandler(HttpServletRequest req, InnerException e) {
log.error("发生服务内部异常!原因是:{}", e.getErrorMsg(), e);
return Result.fail(e.getErrorCode(), e.getErrorMsg());
}
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result exceptionHandler(HttpServletRequest req, Exception e) {
log.error("意料外异常!原因是:{}", e.getMessage(), e);
return Result.fail("99999", "系统内部异常");
}
}

View File

@ -0,0 +1,86 @@
package com.sczx.order.exception;
import com.sczx.order.common.IApiCode;
import com.sczx.order.common.enums.ApiErrorCode;
/**
*
* @author zhangli
*/
public class InnerException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
protected String errorCode;
/**
* 错误信息
*/
protected String errorMsg;
public InnerException() {
super();
}
public InnerException(IApiCode apiCode) {
super(apiCode.getCode());
this.errorCode = apiCode.getCode();
this.errorMsg = apiCode.getMsg();
}
public InnerException(IApiCode apiCode, Throwable cause) {
super(apiCode.getCode(), cause);
this.errorCode = apiCode.getCode();
this.errorMsg = apiCode.getMsg();
}
public InnerException(String errorMsg) {
super(errorMsg);
this.errorCode = ApiErrorCode.INNER_ERROR.getCode();
this.errorMsg = errorMsg;
}
public InnerException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public InnerException(String errorCode, String errorMsg, Throwable cause) {
super(errorCode, cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
@Override
public String getMessage() {
return errorMsg;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}

View File

@ -1,4 +1,4 @@
package com.sczx.app.utils; package com.sczx.order.utils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;

View File

@ -0,0 +1,63 @@
package com.sczx.order.utils;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Date;
/**
* @Author: 张黎
* @Date: 2025/07/06/14:00
* @Description:
*/
@Slf4j
@Component
public class JwtUtil {
@Value("${auth.token-expiration}")
private long expiration;
private final SecretKey key;
public JwtUtil(@Value("${auth.secret-key}") String secretKey) {
this.key = Keys.hmacShaKeyFor(secretKey.getBytes());
// this.key = Keys.secretKeyFor(SignatureAlgorithm.HS512);
log.info("JWT 密钥:{}", secretKey);
}
public String generateToken(String username, String role) {
return Jwts.builder()
.setSubject(username)
.claim("role", role)
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.signWith(key, SignatureAlgorithm.HS512)
.compact();
}
public String extractUsername(String token) {
return Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token);
return true;
} catch (JwtException ex) {
return false;
}
}
}

View File

@ -0,0 +1,33 @@
package com.sczx.order.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @Author: 张黎
* @Date: 2025/07/06/14:21
* @Description:
*/
@Component
public class RedisUtil {
@Autowired
private StringRedisTemplate redisTemplate;
public void set(String key, String value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
public void delete(String key) {
redisTemplate.delete(key);
}
}

View File

@ -4,7 +4,7 @@ server:
spring: spring:
application: application:
name: sczx-app # 微服务名称 name: sczx-order # 微服务名称
http: http:
encoding: encoding:
charset: UTF-8 charset: UTF-8
@ -13,7 +13,6 @@ spring:
mvc: mvc:
async: async:
request-timeout: -1 request-timeout: -1
cloud: cloud:
nacos: nacos:
discovery: discovery:
@ -22,7 +21,8 @@ spring:
metadata: metadata:
version: 1.0.0 version: 1.0.0
env: dev env: dev
lifecycle:
timeout-per-shutdown-phase: 30s # 设置优雅停机时间
datasource: datasource:
url: jdbc:mysql://115.190.8.52:3306/sczx?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true url: jdbc:mysql://115.190.8.52:3306/sczx?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: sczx_user username: sczx_user
@ -31,15 +31,16 @@ spring:
hikari: hikari:
maximum-pool-size: 10 maximum-pool-size: 10
auto-commit: true auto-commit: true
redis:
jpa: host: 115.190.8.52
hibernate: port: 6379
ddl-auto: update lettuce:
show-sql: true pool:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect max-active: 8
max-wait: 2000ms
lifecycle: max-idle: 4
timeout-per-shutdown-phase: 30s # 设置优雅停机时间 min-idle: 1
max-life-time: 300000ms
management: management:
endpoints: endpoints:
@ -67,15 +68,14 @@ hystrix:
thread: thread:
timeoutInMilliseconds: 10000 # 默认熔断超时时间 timeoutInMilliseconds: 10000 # 默认熔断超时时间
springdoc:
swagger-ui:
url: /v3/api-docs
path: /doc.html
packages-to-scan: com.sczx.app.controller # 替换为你的 controller 包路径
mybatis-plus: mybatis-plus:
mapper-locations: classpath*:mapper/**/*.xml mapper-locations: classpath*:mapper/**/*.xml
type-aliases-package: com.sczx.app.entity # 实体类包路径 type-aliases-package: com.sczx.order.po # 实体类包路径
configuration: configuration:
mapUnderscoreToCamelCase: true mapUnderscoreToCamelCase: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印 SQL调试用 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印 SQL调试用
auth:
secret-key: his-is-a-very-long-and-secure-secret-key-for-jwt-signing-please-dont-use-short-keys
token-expiration: 86400000 # 24小时

View File

@ -1,21 +0,0 @@
package com.sczx.app.service;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
public class CodeGenerator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://115.190.8.52:3306/sczx", "sczx_user", "Sczx123@")
.globalConfig(builder -> {
builder.author("zhangli")
.outputDir(System.getProperty("user.dir") + "/src/main/java");
})
.packageConfig(builder -> {
builder.parent("com.sczx.app")
.moduleName("user");
})
.strategyConfig(builder -> {
builder.addInclude("user"); // 表名
})
.execute();
}
}

View File

@ -0,0 +1,41 @@
package com.sczx.order.service;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
public class CodeGenerator {
private static final String parentPackage = "com.sczx.order";
private static final String jdbcUrl = "jdbc:mysql://115.190.8.52:3306/sczx?useUnicode=true&characterEncoding=UTF-8&allowPublicKeyRetrieval=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&useSSL=false&serverTimezone=Asia/Shanghai";
private static final String username = "sczx_user";
private static final String password = "Sczx123@";
private static final String author = "zhangli";
public static void main(String[] args) {
DataSourceConfig.Builder DATA_SOURCE_CONFIG = new DataSourceConfig.Builder(jdbcUrl, username, password);
FastAutoGenerator.create(DATA_SOURCE_CONFIG)
// 全局配置
.globalConfig(builder -> builder.outputDir(System.getProperty("user.dir") + "/src/main/java")
.author(author).disableOpenDir().enableSwagger()
.dateType(DateType.TIME_PACK).commentDate("yyyy-MM-dd HH:mm:ss")
.fileOverride())
// 包配置
.packageConfig(builder -> builder.parent(parentPackage).entity("po").service("repository").serviceImpl("repository.impl").xml("")
.mapper("mapper").pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper")))
// 策略配置
.strategyConfig((scanner, builder) -> builder.addInclude(scanner.apply("请输入表名:"))
.addTablePrefix("zc_"/*,"zd_"*/)//可支持多个,按逗号分隔
.entityBuilder().formatFileName("%sPO").enableLombok()
.mapperBuilder().formatMapperFileName("%sMapper").formatXmlFileName("%sMapper")
.controllerBuilder().formatFileName("%sController").enableRestStyle()
.serviceBuilder().formatServiceFileName("%sRepo").formatServiceImplFileName("%sRepoImpl"))
.templateEngine(new FreemarkerTemplateEngine())
.execute();
}
}