diff --git a/mall-common/pom.xml b/mall-common/pom.xml index 1e6424b..ba550d8 100644 --- a/mall-common/pom.xml +++ b/mall-common/pom.xml @@ -24,23 +24,15 @@ lombok + + com.github.ben-manes.caffeine + caffeine + org.springframework.boot spring-boot-starter-thymeleaf - - - org.springframework.boot - spring-boot-starter-test - test - - - junit - junit - test - - com.alibaba.cloud @@ -54,10 +46,10 @@ - - - - + + org.springframework.cloud + spring-cloud-starter-loadbalancer + diff --git a/mall-gateway/pom.xml b/mall-gateway/pom.xml index 51075b7..17fd885 100644 --- a/mall-gateway/pom.xml +++ b/mall-gateway/pom.xml @@ -36,9 +36,5 @@ org.springframework.cloud spring-cloud-starter-gateway - - - - diff --git a/mall-gateway/src/main/java/com/mall/gateway/MallGatewayApplication.java b/mall-gateway/src/main/java/com/mall/gateway/MallGatewayApplication.java index 7220dfe..10e06c0 100644 --- a/mall-gateway/src/main/java/com/mall/gateway/MallGatewayApplication.java +++ b/mall-gateway/src/main/java/com/mall/gateway/MallGatewayApplication.java @@ -3,8 +3,10 @@ package com.mall.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +@EnableDiscoveryClient public class MallGatewayApplication { public static void main(String[] args) { SpringApplication.run(MallGatewayApplication.class, args); diff --git a/mall-gateway/src/main/resources/application-routes.yaml b/mall-gateway/src/main/resources/application-routes.yaml index da5ca6d..6b79c5c 100644 --- a/mall-gateway/src/main/resources/application-routes.yaml +++ b/mall-gateway/src/main/resources/application-routes.yaml @@ -11,9 +11,8 @@ spring: - "*" allowed-methods: - "*" - allowed-origins: - - "*" allow-credentials: true + routes: - id: route-product uri: lb://service-product @@ -32,4 +31,8 @@ spring: - id: route-coupon uri: lb://service-coupon predicates: - - Path=/api/coupon/** \ No newline at end of file + - Path=/api/coupon/** + - id: route-third-party + uri: lb://service-third-party + predicates: + - Path=/api/third-party/** \ No newline at end of file diff --git a/mall-gateway/src/main/resources/application.yaml b/mall-gateway/src/main/resources/application.yaml index b950296..02d80ab 100644 --- a/mall-gateway/src/main/resources/application.yaml +++ b/mall-gateway/src/main/resources/application.yaml @@ -7,12 +7,16 @@ spring: - routes application: name: service-gateway + devtools: + livereload: + port: 0 cloud: nacos: server-addr: bunny-web.site:8848 - username: admin - password: admin123 + config: + import-check: + enabled: false jackson: date-format: yyyy-MM-dd HH:mm:ss diff --git a/mall-product/pom.xml b/mall-product/pom.xml index cd770ee..86c8b8e 100644 --- a/mall-product/pom.xml +++ b/mall-product/pom.xml @@ -31,6 +31,17 @@ runtime true + + + org.springframework.boot + spring-boot-starter-test + test + + + junit + junit + test + org.springframework.boot diff --git a/mall-product/src/main/resources/application.yaml b/mall-product/src/main/resources/application.yaml index a5a84b0..3721ea7 100644 --- a/mall-product/src/main/resources/application.yaml +++ b/mall-product/src/main/resources/application.yaml @@ -17,6 +17,9 @@ spring: maximum-pool-size: 20 connection-timeout: 30000 + jackson: + date-format: yyyy-MM-dd HH:mm:ss + mybatis-plus: mapper-locations: classpath:/mapper/*.xml global-config: @@ -25,5 +28,5 @@ mybatis-plus: logic-delete-value: 1 logic-not-delete-value: 0 - jackson: - date-format: yyyy-MM-dd HH:mm:ss \ No newline at end of file +# LTAI5tMynexvsUvznfXXL6x4 +# 8H3EwbyvCKQ9FiTpnRzOojmHg1NKpg \ No newline at end of file diff --git a/mall-third-party/pom.xml b/mall-third-party/pom.xml index c8a4486..6aae891 100644 --- a/mall-third-party/pom.xml +++ b/mall-third-party/pom.xml @@ -18,6 +18,75 @@ + + com.mall + mall-common + 1.0-SNAPSHOT + + + com.baomidou + mybatis-plus-boot-starter + + + com.mysql + mysql-connector-j + + + com.zaxxer + HikariCP + + + + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + junit + junit + test + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + + com.aliyun.oss + aliyun-sdk-oss + 3.18.2 + + + com.aliyun + alibabacloud-secretsmanager-client + 1.3.7 + + + com.aliyun + aliyun-java-sdk-core + 4.7.0 + + + com.aliyun + sts20150401 + 1.1.6 + diff --git a/mall-third-party/src/main/java/com/mall/App.java b/mall-third-party/src/main/java/com/mall/App.java deleted file mode 100644 index 38d1876..0000000 --- a/mall-third-party/src/main/java/com/mall/App.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.mall; - -/** - * Hello world! - * - */ -public class App -{ - public static void main( String[] args ) - { - System.out.println( "Hello World!" ); - } -} diff --git a/mall-third-party/src/main/java/com/mall/thirdParty/MallThirdPartyApplication.java b/mall-third-party/src/main/java/com/mall/thirdParty/MallThirdPartyApplication.java new file mode 100644 index 0000000..5f08255 --- /dev/null +++ b/mall-third-party/src/main/java/com/mall/thirdParty/MallThirdPartyApplication.java @@ -0,0 +1,15 @@ +package com.mall.thirdParty; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.context.config.annotation.RefreshScope; + +@EnableDiscoveryClient +@RefreshScope +@SpringBootApplication() +public class MallThirdPartyApplication { + public static void main(String[] args) { + SpringApplication.run(MallThirdPartyApplication.class, args); + } +} diff --git a/mall-third-party/src/main/java/com/mall/thirdParty/client/AliOssClient.java b/mall-third-party/src/main/java/com/mall/thirdParty/client/AliOssClient.java new file mode 100644 index 0000000..fba39cb --- /dev/null +++ b/mall-third-party/src/main/java/com/mall/thirdParty/client/AliOssClient.java @@ -0,0 +1,66 @@ +package com.mall.thirdParty.client; + +import com.aliyun.oss.ClientBuilderConfiguration; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.common.auth.Credentials; +import com.aliyun.oss.common.auth.CredentialsProvider; +import com.aliyun.oss.common.auth.DefaultCredentials; +import com.aliyun.oss.common.comm.SignVersion; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "aliyun.oss") +@Data +@Slf4j +public class AliOssClient { + + @Value("${aliyun.oss.endpoint}") + String endpoint; + + @Value("${aliyun.oss.accessKeyId}") + String accessKeyId; + + @Value("${aliyun.oss.accessKeySecrect}") + String accessKeySecrect; + + @Value("${aliyun.oss.bucketName}") + String bucketName; + + @Value("${aliyun.oss.region}") + String region; + + @Bean("AliOssClient") + public OSS aliOssClient() { + CredentialsProvider credentialsProvider = new CredentialsProvider() { + @Override + public Credentials getCredentials() { + return new DefaultCredentials(accessKeyId, accessKeySecrect); + } + + @Override + public void setCredentials(Credentials credentials) { + } + }; + + try { + ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); + clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); + return OSSClientBuilder.create() + .endpoint(endpoint) + .credentialsProvider(credentialsProvider) + .clientConfiguration(clientBuilderConfiguration) + .region(region) + .build(); + } catch (Exception exception) { + log.error(exception.getMessage(), exception); + } + + return null; + } +} diff --git a/mall-third-party/src/main/java/com/mall/thirdParty/config/Knife4jConfig.java b/mall-third-party/src/main/java/com/mall/thirdParty/config/Knife4jConfig.java new file mode 100644 index 0000000..c65719a --- /dev/null +++ b/mall-third-party/src/main/java/com/mall/thirdParty/config/Knife4jConfig.java @@ -0,0 +1,54 @@ +package com.mall.thirdParty.config; + +import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import lombok.extern.slf4j.Slf4j; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableKnife4j +@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.ANY) +@Slf4j +public class Knife4jConfig { + + @Value("${server.port}") + private String port; + + @Bean + public OpenAPI openAPI() { + String url = "http://localhost:" + port; + + // 作者等信息 + Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url(url); + // 使用协议 + License license = new License().name("MIT").url("https://mit-license.org"); + // 相关信息 + Info info = new Info().title("Bunny-Admin") + .contact(contact).license(license) + .description("BunnyMall商城") + .summary("Bunny商城") + .termsOfService(url) + .version("v0.0.1"); + + return new OpenAPI().info(info).externalDocs(new ExternalDocumentation()); + } + + @Bean + public GroupedOpenApi all() { + return GroupedOpenApi.builder().group("全部请求接口").pathsToMatch("/api/**").build(); + } + + @Bean + public GroupedOpenApi product() { + return GroupedOpenApi.builder().group("第三方请求接口").pathsToMatch("/api/third-party/**").build(); + } + +} diff --git a/mall-third-party/src/main/java/com/mall/thirdParty/controller/AliOssController.java b/mall-third-party/src/main/java/com/mall/thirdParty/controller/AliOssController.java new file mode 100644 index 0000000..eed48c9 --- /dev/null +++ b/mall-third-party/src/main/java/com/mall/thirdParty/controller/AliOssController.java @@ -0,0 +1,29 @@ +package com.mall.thirdParty.controller; + +import com.mall.common.domain.vo.result.Result; +import com.mall.thirdParty.service.AliOssService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@Tag(name = "阿里云上传文件", description = "阿里云上传文件相关接口") +@RestController +@RequestMapping("/api/third-party") +@RequiredArgsConstructor +public class AliOssController { + + private final AliOssService aliOssService; + + @GetMapping("/oss/policy") + @Operation(summary = "oss请求Token", description = "oss请求Token") + public Result> getPostSignatureForOssUpload() { + Map vo = aliOssService.getPostSignatureForOssUpload(); + return Result.success(vo); + } + +} \ No newline at end of file diff --git a/mall-third-party/src/main/java/com/mall/thirdParty/service/AliOssService.java b/mall-third-party/src/main/java/com/mall/thirdParty/service/AliOssService.java new file mode 100644 index 0000000..5d9c3ee --- /dev/null +++ b/mall-third-party/src/main/java/com/mall/thirdParty/service/AliOssService.java @@ -0,0 +1,12 @@ +package com.mall.thirdParty.service; + +import java.util.Map; + +public interface AliOssService { + /** + * OSS获取服务端签名 + * + * @return OSS服务端签名 + */ + Map getPostSignatureForOssUpload(); +} diff --git a/mall-third-party/src/main/java/com/mall/thirdParty/service/ext/AliOssServiceImplExt.java b/mall-third-party/src/main/java/com/mall/thirdParty/service/ext/AliOssServiceImplExt.java new file mode 100644 index 0000000..c02607d --- /dev/null +++ b/mall-third-party/src/main/java/com/mall/thirdParty/service/ext/AliOssServiceImplExt.java @@ -0,0 +1,61 @@ +package com.mall.thirdParty.service.ext; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +public class AliOssServiceImplExt { + + /** + * 通过指定有效的时长(秒)生成过期时间。 + * + * @param seconds 有效时长(秒)。 + * @return ISO8601 时间字符串,如:"2014-12-01T12:00:00.000Z"。 + */ + public static String generateExpiration(long seconds) { + // 获取当前时间戳(以秒为单位) + long now = Instant.now().getEpochSecond(); + // 计算过期时间的时间戳 + long expirationTime = now + seconds; + // 将时间戳转换为Instant对象,并格式化为ISO8601格式 + Instant instant = Instant.ofEpochSecond(expirationTime); + // 定义时区为UTC + ZoneId zone = ZoneOffset.UTC; + // 将 Instant 转换为 ZonedDateTime + ZonedDateTime zonedDateTime = instant.atZone(zone); + // 定义日期时间格式,例如2023-12-03T13:00:00.000Z + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + // 格式化日期时间 + // 输出结果 + return zonedDateTime.format(formatter); + } + + public static byte[] hmacsha256(byte[] key, String data) { + try { + // 初始化HMAC密钥规格,指定算法为HMAC-SHA256并使用提供的密钥。 + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256"); + + // 获取Mac实例,并通过getInstance方法指定使用HMAC-SHA256算法。 + Mac mac = Mac.getInstance("HmacSHA256"); + // 使用密钥初始化Mac对象。 + mac.init(secretKeySpec); + + // 执行HMAC计算,通过doFinal方法接收需要计算的数据并返回计算结果的数组。 + return mac.doFinal(data.getBytes()); + } catch (Exception e) { + throw new RuntimeException("Failed to calculate HMAC-SHA256", e); + } + } + + public static byte[] calculateSigningKey(String accesskeysecret, String date, String region) { + byte[] dateKey = hmacsha256(("aliyun_v4" + accesskeysecret).getBytes(), date); + byte[] dateRegionKey = hmacsha256(dateKey, region); + byte[] dateRegionServiceKey = hmacsha256(dateRegionKey, "oss"); + return hmacsha256(dateRegionServiceKey, "aliyun_v4_request"); + } + +} diff --git a/mall-third-party/src/main/java/com/mall/thirdParty/service/impl/AliOssServiceImpl.java b/mall-third-party/src/main/java/com/mall/thirdParty/service/impl/AliOssServiceImpl.java new file mode 100644 index 0000000..3529409 --- /dev/null +++ b/mall-third-party/src/main/java/com/mall/thirdParty/service/impl/AliOssServiceImpl.java @@ -0,0 +1,84 @@ +package com.mall.thirdParty.service.impl; + +import com.aliyun.oss.common.utils.BinaryUtil; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.mall.thirdParty.client.AliOssClient; +import com.mall.thirdParty.service.AliOssService; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.apache.commons.codec.binary.Base64; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.mall.thirdParty.service.ext.AliOssServiceImplExt.*; + +@Service +@RequiredArgsConstructor +public class AliOssServiceImpl implements AliOssService { + + private final AliOssClient aliOssClient; + + /** + * OSS获取服务端签名 + * + * @return OSS服务端签名 + */ + @SneakyThrows + public Map getPostSignatureForOssUpload() { + // 基础信息获取 + String accesskeyid = aliOssClient.getAccessKeyId(); + String accesskeysecret = aliOssClient.getAccessKeySecrect(); + String uploadDir = "images/" + LocalDate.now().format(DateTimeFormatter.ISO_DATE); + String region = aliOssClient.getRegion(); + String bucket = aliOssClient.getBucketName(); + + // 时间格式化 + ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC); + String date = now.format(DateTimeFormatter.BASIC_ISO_DATE); + String xOssDate = now.format(DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'")); + String xOssCredential = String.format("%s/%s/%s/oss/aliyun_v4_request", accesskeyid, date, region); + + // 创建policy + Map policy = new HashMap<>(); + policy.put("expiration", generateExpiration(3600L)); + + List conditions = Arrays.asList( + Map.of("bucket", bucket), + Map.of("x-oss-signature-version", "OSS4-HMAC-SHA256"), + Map.of("x-oss-credential", xOssCredential), + Map.of("x-oss-date", xOssDate), + Arrays.asList("content-length-range", 1, 10240000), + Arrays.asList("eq", "$success_action_status", "200"), + Arrays.asList("starts-with", "$key", uploadDir) + ); + policy.put("conditions", conditions); + + // 签名计算 + String jsonPolicy = new ObjectMapper().writeValueAsString(policy); + String stringToSign = Base64.encodeBase64String(jsonPolicy.getBytes()); + + byte[] signingKey = calculateSigningKey(accesskeysecret, date, region); + String signature = BinaryUtil.toHex(hmacsha256(signingKey, stringToSign)); + + // 构建返回结果 + return Map.of( + "version", "OSS4-HMAC-SHA256", + "policy", stringToSign, + "x_oss_credential", xOssCredential, + "x_oss_date", xOssDate, + "signature", signature, + "dir", uploadDir, + "accessId", aliOssClient.getAccessKeyId(), + "host", aliOssClient.getEndpoint() + ); + } + +} diff --git a/mall-third-party/src/main/resources/application-dev.yml b/mall-third-party/src/main/resources/application-dev.yml new file mode 100644 index 0000000..0cd1aae --- /dev/null +++ b/mall-third-party/src/main/resources/application-dev.yml @@ -0,0 +1,22 @@ +spring: + cloud: + nacos: + server-addr: bunny-web.site:8848 + config: + import-check: + enabled: true + server-addr: bunny-web.site:8848 + namespace: 9e2b0e65-7823-4897-97bb-7095a3e4f74f + group: DEFAULT_GROUP + refresh-enabled: true + + config: + import: + - nacos:oss.yml + +logging: + file: + path: "logs/${spring.application.name}" + level: + com.mall.product: debug + root: info diff --git a/mall-third-party/src/main/resources/application.yaml b/mall-third-party/src/main/resources/application.yaml new file mode 100644 index 0000000..ee4c504 --- /dev/null +++ b/mall-third-party/src/main/resources/application.yaml @@ -0,0 +1,27 @@ +server: + port: 8081 + +spring: + profiles: + active: dev + application: + name: service-third-party + main: + allow-bean-definition-overriding: true + devtools: + livereload: + port: 0 + + jackson: + date-format: yyyy-MM-dd HH:mm:ss + +aliyun: + oss: + endpoint: "https://oss-cn-shanghai.aliyuncs.com" + accessKeyId: LTAI5tMynexvsUvznfXXL6x4 + accessKeySecrect: 8H3EwbyvCKQ9FiTpnRzOojmHg1NKpg + bucketName: bunny-mall-cloud + region: cn-shanghai + +# LTAI5tMynexvsUvznfXXL6x4 +# 8H3EwbyvCKQ9FiTpnRzOojmHg1NKpg \ No newline at end of file diff --git a/mall-third-party/src/main/resources/banner.txt b/mall-third-party/src/main/resources/banner.txt new file mode 100644 index 0000000..89b2c00 --- /dev/null +++ b/mall-third-party/src/main/resources/banner.txt @@ -0,0 +1,13 @@ + + +,-----. ,--. ,--. ,--.,--. +| |) /_ ,--.,--.,--,--, ,--,--, ,--. ,--. | `.' | ,--,--.| || | +| .-. \| || || \| \ \ ' / | |'.'| |' ,-. || || | +| '--' /' '' '| || || || | \ ' | | | |\ '-' || || | +`------' `----' `--''--'`--''--'.-' / `--' `--' `--`--'`--'`--' + `---' + + +Service Name${spring.application.name} +SpringBoot Version: ${spring-boot.version}${spring-boot.formatted-version} +Spring Active:${spring.profiles.active} diff --git a/mall-third-party/src/main/resources/logback.xml b/mall-third-party/src/main/resources/logback.xml new file mode 100644 index 0000000..02b7abe --- /dev/null +++ b/mall-third-party/src/main/resources/logback.xml @@ -0,0 +1,72 @@ + + + logback + + + + + + + + + + + + + + DEBUG + + + + %cyan([%thread %d{yyyy-MM-dd HH:mm:ss}]) %yellow(%-5level) %green(%logger{100}).%boldRed(%method)-%boldMagenta(%line)-%blue(%msg%n) + + ${ENCODING} + + + + + + logs/${APP_NAME}/${datetime}.log + true + + %date{yyyy-MM-dd HH:mm:ss} [%-5level] %thread %file:%line %logger %msg%n + ${ENCODING} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/400.html b/mall-third-party/src/main/resources/static/error/400.html new file mode 100644 index 0000000..fc1e212 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/400.html @@ -0,0 +1,69 @@ + + + + + 400 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 400 - Bad Request + + 错误说明:因为错误的语法导致服务器无法理解请求信息。 + 原因1:客户端发起的请求不符合服务器对请求的某些限制,或者请求本身存在一定的错误。 + 解决办法: + 链接中有特殊字符或者链接长度过长导致,请对应修改. + 原因2:request header 或者 cookie 过大所引起 + 解决办法: + crtl+shift+delete 快捷键清除cookie. + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/403.html b/mall-third-party/src/main/resources/static/error/403.html new file mode 100644 index 0000000..6c281b0 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/403.html @@ -0,0 +1,69 @@ + + + + + 403 错误 - phpstudy + + + + + + + + + + + + + + + + + + 403 - Forbidden 禁止访问: 访问被拒绝 + + 错误说明:禁止访问,服务器拒绝访问 + 原因1:未找到默认的索引文件 + 解决办法: + IIS中【启用默认内容文档】选项中将默认打开文档修改为程序首页文件格式,如:index.html或者index.php + 原因2:文件夹安全权限导致 + 解决办法: + 程序文件-右击-属性-安全-Users-修改为读取和执行权限 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/404.html b/mall-third-party/src/main/resources/static/error/404.html new file mode 100644 index 0000000..6cc5d1e --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/404.html @@ -0,0 +1,78 @@ + + + + + 404 错误 - phpstudy + + + + + + + + + + + + + + + + + + 404 - Page Not Found 未找到 + + 错误说明:请求的页面不存在 + 原因1:访问的文档权限不够 + 解决办法: + 修改文件权限为755,windos系统修改目录权限为可写可读。 + 原因2:防火墙的原因 + 解决办法: + 先关闭让防火墙通过WWW服务。 + 原因3:站点根目录无默认访问文件 + 解决办法: + 在根目录中创建index.html或者创建index.php。 + 原因4:站点配置目录不正确 + 解决办法: + 将网站应用程序复制到站点目录中,或者修改站点配置目录指定到应用程序目录中。 + 原因5:站点使用了伪静态 + 解决办法: + 将伪静态规则删除,或者重新编写正确的伪静态规则,或关闭伪静态配置。 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/500.html b/mall-third-party/src/main/resources/static/error/500.html new file mode 100644 index 0000000..6071bf4 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/500.html @@ -0,0 +1,64 @@ + + + + + 500 - 服务器错误 + + + + + + :'( + 服务器开小差啦!管理员正在修理中... + 还请阁下静候站点恢复~ + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/501.html b/mall-third-party/src/main/resources/static/error/501.html new file mode 100644 index 0000000..48ac544 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/501.html @@ -0,0 +1,66 @@ + + + + + 501 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 501 - Not Implemented + + 错误说明:服务器没有相应的执行动作来完成当前请求。 + 原因1:Web 服务器不支持实现此请求所需的功能 + 解决办法: + 可以用来HttpWebRequest指定一个UserAgent来试试的,有时候你可以换电脑来测试一下的。 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/502.html b/mall-third-party/src/main/resources/static/error/502.html new file mode 100644 index 0000000..ea44be2 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/502.html @@ -0,0 +1,80 @@ + + + + + 502 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 502 - Bad Gateway 没有响应 + + 错误说明:坏的网关,http向后端节点请求,没有响应 + 原因1:DNS 缓冲 + 解决办法: + 在dos窗口运行 ipconfig /flushdns,该命令会刷新DNS缓冲。 + 原因2:浏览器代理 + 解决办法: + 关掉代理。 + 原因3:dns 被劫持了,即使使用国外的dns,也会被劫持 + 解决办法: + + 去掉VPN服务器的DNS。切换另外的dns。在windows系统中,可以在本地网络连接的属性中,去掉默认的dns,选用国外的dns,比如google的或opendns。 + + 原因4:php执行超时 + 解决办法: + 修改/usr/local/php/etc/php.ini 将max_execution_time 改为300。 + 原因5:nginx等待时间超时 + 解决办法: + 适当增加nginx.conf配置文件中FastCGI的timeout时间。 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/503.html b/mall-third-party/src/main/resources/static/error/503.html new file mode 100644 index 0000000..c6fec86 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/503.html @@ -0,0 +1,69 @@ + + + + + 503 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 503 - Service Unavailable 服务不可用 + + 错误说明:服务当前不可用 + 原因1:服务不可用状态 + 解决办法: + 服务器或许就是正在维护或者暂停了,你可以联系一下服务器空间商。 + 原因2:程序占用资源太多 + 解决办法: + 通过设置应用程序池把账户改为NetworkService即可解决。 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/504.html b/mall-third-party/src/main/resources/static/error/504.html new file mode 100644 index 0000000..2980dd0 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/504.html @@ -0,0 +1,81 @@ + + + + + 504 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 504 - Gateway Timeout 网关超时 + + 错误说明:网关超时,服务器响应时间,达到超出设定的范围 + 原因1:后端电脑之间 IP 通讯缓慢而产生 + 解决办法: + 如果您的 Web 服务器由某一网站托管, 只有负责那个网站设置的人员才能解决这个问题。 + 原因2:由于nginx默认的fastcgi进程响应的缓冲区太小造成的错误 + 解决办法: + 一般默认的fastcgi进程响应的缓冲区是8K,这时可以设置大一点,在nginx.conf里,加入:fastcgi_buffers 8 + 128k这表示设置fastcgi缓冲区为8块128k大小的空间。当然如果在进行某一项即时的操作, 可能需要nginx的超时参数调大点, + 例如设置成60秒:send_timeout 60;经过这两个参数的调整,一般不会再提示“504 Gateway Time-out”错误,问题基本解决。 + + 原因3:PHP环境的配置问题 + 解决办法: + 更改php-fpm的几处配置: 把max_children由之前的10改为现在的30,这样就可以保证有充足的php-cgi进程可以被使用; + 把request_terminate_timeout由之前的0s改为60s,这样php-cgi进程 处理脚本的超时时间就是60秒,可以防止进程都被挂起,提高利用效率。 + 接着再更改nginx的几个配置项,减少FastCGI的请求次数,尽量维持buffers不变: fastcgi_buffers由 4 64k 改为 2 + 256k; fastcgi_buffer_size 由 64k 改为 128K; fastcgi_busy_buffers_size 由 128K 改为 256K; + fastcgi_temp_file_write_size 由 128K 改为 256K。 重新加载php-fpm和nginx的配置,再次测试,如果没有出现“504 + Gateway Time-out”错误,问题解决。 + + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/505.html b/mall-third-party/src/main/resources/static/error/505.html new file mode 100644 index 0000000..1cd5dd5 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/505.html @@ -0,0 +1,72 @@ + + + + + 505 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 505 - HTTP Version Not Supported + + 错误说明:HTTP 版本不受支持。 + 原因1:您的 Web 服务器不支持,或拒绝支持客户端(如您的浏览器)在发送给服务器的 HTTP 请求数据流中指定的 HTTP + 协议版本 + + 解决办法: + 升级您的 Web 服务器软件。 + 原因2:http请求格式的错误 + 解决办法: + 对照一下自己的代码,从打印的信息中终于找到问题所在。可能在请求后面多加了一个空格。http协议真是很严格了。 + + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/506.html b/mall-third-party/src/main/resources/static/error/506.html new file mode 100644 index 0000000..8160abd --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/506.html @@ -0,0 +1,66 @@ + + + + + 506 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 506 - Variant Also Negotiates + + 错误说明: + 原因1:服务器存在内部配置错误 + 解决办法: + 被请求的协商变元资源被配置为在透明内容协商中使用自己,因此在一个协商处理中不是一个合适的重点。 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/507.html b/mall-third-party/src/main/resources/static/error/507.html new file mode 100644 index 0000000..fb6c7e7 --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/507.html @@ -0,0 +1,66 @@ + + + + + 507 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 507 - Insufficient Storage + + 错误说明: + 原因1:服务器无法存储完成请求所必须的内容 + 解决办法: + 这个状况被认为是临时的。WebDAV (RFC 4918)。 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/509.html b/mall-third-party/src/main/resources/static/error/509.html new file mode 100644 index 0000000..520abbd --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/509.html @@ -0,0 +1,66 @@ + + + + + 509 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 509 - Bandwidth Limit Exceeded + + 错误说明: + 原因1:网站流量已经超出您所购买的方案限制即服务器达到带宽限制 + 解决办法: + 1.升级方案 2.等到下个月后流量重新计算,网站即可正常浏览。 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/error/510.html b/mall-third-party/src/main/resources/static/error/510.html new file mode 100644 index 0000000..95b2f9f --- /dev/null +++ b/mall-third-party/src/main/resources/static/error/510.html @@ -0,0 +1,66 @@ + + + + + 510 错误 - phpstudy + + + + + + + + + + + + + + + + + + HTTP 510 - Not Extended + + 错误说明: + 原因1:获取资源所需要的策略并没有被满足 + 解决办法: + 需要请求有额外的扩展内容,服务器才能处理请求。 + + + + + \ No newline at end of file diff --git a/mall-third-party/src/main/resources/static/favicon.ico b/mall-third-party/src/main/resources/static/favicon.ico new file mode 100644 index 0000000..385f8a6 Binary files /dev/null and b/mall-third-party/src/main/resources/static/favicon.ico differ diff --git a/mall-third-party/src/main/resources/static/images/architecture-diagram.jpg b/mall-third-party/src/main/resources/static/images/architecture-diagram.jpg new file mode 100644 index 0000000..76719fa Binary files /dev/null and b/mall-third-party/src/main/resources/static/images/architecture-diagram.jpg differ diff --git a/mall-third-party/src/main/resources/templates/index.html b/mall-third-party/src/main/resources/templates/index.html new file mode 100644 index 0000000..5a86bcc --- /dev/null +++ b/mall-third-party/src/main/resources/templates/index.html @@ -0,0 +1,266 @@ + + + + + + 谷粒商城 - 第三方插件模块 + + + + + + + + + + + + + + 谷粒商城 + + + + + + + + 第三方插件模块 + + + Swagger API文档 + + + + + + + + + + 谷粒商城第三方插件模块 + 基于Java 17和Spring Boot 3.x的全新版本 + + + 查看API文档 + + + GitHub仓库 + + + + + + + + + + 核心特性 + 第三方插件模块提供丰富的扩展功能和集成能力 + + + + + + + + + + 插件扩展 + 支持热插拔式插件扩展,动态加载和卸载功能模块。 + + + + + + + + + 第三方集成 + 预集成支付、物流、短信等常用第三方服务接口。 + + + + + + + + + 配置管理 + 统一管理插件配置,支持运行时动态调整参数。 + + + + + + + + + + + 安全沙箱 + 插件运行在安全沙箱中,隔离系统核心功能。 + + + + + + + + + 快速接入 + 标准化接入流程,快速对接新第三方服务。 + + + + + + + + + 性能监控 + 实时监控插件性能,保障系统稳定运行。 + + + + + + + + + + + 现代化技术栈 + + + + Java 17 - 使用最新的LTS版本 + + + + Spring Boot 3.x - 企业级开发框架 + + + + Knife4j - 强大的API文档工具 + + + + Thymeleaf - 现代化模板引擎 + + + + + + + + + + + + + + + 快速开始 + + + + # 克隆项目 + git clone https://gitee.com/BunnyBoss/mall-cloud.git + + # 启动第三方插件模块 + cd mall-cloud + mvn spring-boot:run + + + + + 立即体验API + + + + + + + + + + + + + \ No newline at end of file diff --git a/mall-third-party/src/test/java/Demo.java b/mall-third-party/src/test/java/Demo.java new file mode 100644 index 0000000..ae04c6a --- /dev/null +++ b/mall-third-party/src/test/java/Demo.java @@ -0,0 +1,82 @@ +import com.aliyun.oss.*; +import com.aliyun.oss.common.auth.Credentials; +import com.aliyun.oss.common.auth.CredentialsProvider; +import com.aliyun.oss.common.auth.DefaultCredentials; +import com.aliyun.oss.common.comm.SignVersion; +import com.aliyun.oss.model.PutObjectRequest; +import com.aliyun.oss.model.PutObjectResult; + +import java.io.File; + +public class Demo { + + public static void main(String[] args) throws Exception { + + CredentialsProvider credentialsProvider = new CredentialsProvider() { + // 初始化变量 + final String accessKeyId = "LTAI5tMynexvsUvznfXXL6x4"; + // 初始化变量 + final String accessKeySecrect = "8H3EwbyvCKQ9FiTpnRzOojmHg1NKpg"; + // 初始化变量 + // String token = null; + + @Override + public Credentials getCredentials() { + // 返回长期凭证 access_key_id, access_key_secrect + return new DefaultCredentials(accessKeyId, accessKeySecrect); + // 返回 临时凭证 access_key_id, access_key_secrect, token + // 对于临时凭证,需要根据过期时间,刷新凭证。 + // return new DefaultCredentials(accessKeyId, accessKeySecrect, token); + } + + @Override + public void setCredentials(Credentials credentials) { + } + }; + // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。 + String endpoint = "https://oss-cn-shanghai.aliyuncs.com"; + // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 + // EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); + // 填写Bucket名称,例如examplebucket。 + String bucketName = "bunny-mall-cloud"; + // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。 + String objectName = "images/5b5e74d0978360a1.jpg"; + // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。 + String filePath = "F:\\文档&学习\\学习\\谷粒商城\\基础篇\\资料\\pics\\5b5e74d0978360a1.jpg"; + // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。 + String region = "cn-shanghai"; + + // 创建OSSClient实例。 + // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。 + ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); + clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); + OSS ossClient = OSSClientBuilder.create() + .endpoint(endpoint) + .credentialsProvider(credentialsProvider) + .clientConfiguration(clientBuilderConfiguration) + .region(region) + .build(); + + try { + // 创建PutObjectRequest对象。 + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath)); + + // 上传文件。 + PutObjectResult result = ossClient.putObject(putObjectRequest); + } catch (OSSException oe) { + System.out.println("Caught an OSSException, which means your request made it to OSS, " + + "but was rejected with an error response for some reason."); + System.out.println("Error Message:" + oe.getErrorMessage()); + System.out.println("Error Code:" + oe.getErrorCode()); + System.out.println("Request ID:" + oe.getRequestId()); + System.out.println("Host ID:" + oe.getHostId()); + } catch (ClientException ce) { + System.out.println("Caught an ClientException, which means the client encountered " + + "a serious internal problem while trying to communicate with OSS, " + + "such as not being able to access the network."); + System.out.println("Error Message:" + ce.getMessage()); + } finally { + ossClient.shutdown(); + } + } +} \ No newline at end of file diff --git a/mall-third-party/src/test/java/com/mall/thirdParty/config/AliOssClientTest.java b/mall-third-party/src/test/java/com/mall/thirdParty/config/AliOssClientTest.java new file mode 100644 index 0000000..51d2012 --- /dev/null +++ b/mall-third-party/src/test/java/com/mall/thirdParty/config/AliOssClientTest.java @@ -0,0 +1,54 @@ +package com.mall.thirdParty.config; + +import com.aliyun.oss.ClientException; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSException; +import com.aliyun.oss.model.PutObjectRequest; +import com.aliyun.oss.model.PutObjectResult; +import com.mall.thirdParty.client.AliOssClient; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.io.File; + +@SpringBootTest +class AliOssClientTest { + + @Autowired + private OSS ossClient; + + @Autowired + private AliOssClient aliOssClient; + + @Test + public void test() { + // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。 + String objectName = "images/73ab4d2e818d2211.jpg"; + // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。 + String filePath = "F:\\文档&学习\\学习\\谷粒商城\\基础篇\\资料\\pics\\73ab4d2e818d2211.jpg"; + + try { + // 创建PutObjectRequest对象。 + String bucketName = aliOssClient.getBucketName(); + PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath)); + + // 上传文件。 + PutObjectResult result = ossClient.putObject(putObjectRequest); + } catch (OSSException oe) { + System.out.println("Caught an OSSException, which means your request made it to OSS, " + + "but was rejected with an error response for some reason."); + System.out.println("Error Message:" + oe.getErrorMessage()); + System.out.println("Error Code:" + oe.getErrorCode()); + System.out.println("Request ID:" + oe.getRequestId()); + System.out.println("Host ID:" + oe.getHostId()); + } catch (ClientException ce) { + System.out.println("Caught an ClientException, which means the client encountered " + + "a serious internal problem while trying to communicate with OSS, " + + "such as not being able to access the network."); + System.out.println("Error Message:" + ce.getMessage()); + } finally { + ossClient.shutdown(); + } + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index d0d3177..c400dd3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.2 + 3.3.13 @@ -70,7 +70,7 @@ org.springframework.cloud spring-cloud-dependencies - 2023.0.3 + 2023.0.6 pom import
服务器开小差啦!管理员正在修理中...
还请阁下静候站点恢复~
基于Java 17和Spring Boot 3.x的全新版本
第三方插件模块提供丰富的扩展功能和集成能力
支持热插拔式插件扩展,动态加载和卸载功能模块。
预集成支付、物流、短信等常用第三方服务接口。
统一管理插件配置,支持运行时动态调整参数。
插件运行在安全沙箱中,隔离系统核心功能。
标准化接入流程,快速对接新第三方服务。
实时监控插件性能,保障系统稳定运行。
+ # 克隆项目 + git clone https://gitee.com/BunnyBoss/mall-cloud.git + + # 启动第三方插件模块 + cd mall-cloud + mvn spring-boot:run +