1.初始化版本,2.引入thirdpart模块,引入canteen模块,初始化菜品分类,spu
This commit is contained in:
commit
aff77150d6
1595 files changed
+168833
No files matched your search
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2018-2025, pjcloud All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: pjcloud
|
||||
*
|
||||
*/
|
||||
|
||||
package com.bsd.pjcloud.gateway;
|
||||
|
||||
import com.bsd.pjcloud.common.gateway.annotation.EnablePjcloudDynamicRoute;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2018年06月21日 网关应用
|
||||
*/
|
||||
@EnablePjcloudDynamicRoute
|
||||
@EnableDiscoveryClient
|
||||
@SpringBootApplication
|
||||
public class PjcloudGatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(PjcloudGatewayApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2018-2025, pjcloud All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: pjcloud
|
||||
*
|
||||
*/
|
||||
|
||||
package com.bsd.pjcloud.gateway.config;
|
||||
|
||||
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2018/7/1 路由限流配置
|
||||
*/
|
||||
@Configuration
|
||||
public class RateLimiterConfiguration {
|
||||
|
||||
@Bean(value = "remoteAddrKeyResolver")
|
||||
public KeyResolver remoteAddrKeyResolver() {
|
||||
return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
|
||||
}
|
||||
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package com.bsd.pjcloud.gateway.config;
|
||||
|
||||
import com.alibaba.nacos.client.naming.event.InstancesChangeEvent;
|
||||
import com.alibaba.nacos.common.notify.Event;
|
||||
import com.alibaba.nacos.common.notify.NotifyCenter;
|
||||
import com.alibaba.nacos.common.notify.listener.Subscriber;
|
||||
import com.alibaba.nacos.common.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springdoc.core.properties.AbstractSwaggerUiConfigProperties;
|
||||
import org.springdoc.core.properties.SwaggerUiConfigProperties;
|
||||
import org.springdoc.webflux.ui.SwaggerResourceResolver;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.web.reactive.resource.ResourceResolverChain;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2022/3/26
|
||||
* <p>
|
||||
* swagger 3.0 展示
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnProperty(value = "springdoc.api-docs.enabled", matchIfMissing = true)
|
||||
public class SpringDocConfiguration implements InitializingBean {
|
||||
|
||||
private final SwaggerUiConfigProperties swaggerUiConfigProperties;
|
||||
|
||||
private final DiscoveryClient discoveryClient;
|
||||
|
||||
/**
|
||||
* 在初始化后调用的方法,用于注册SwaggerDocRegister订阅器
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
SwaggerDocRegister swaggerDocRegister = new SwaggerDocRegister(swaggerUiConfigProperties, discoveryClient);
|
||||
// 手动调用一次,避免监听事件掉线问题
|
||||
swaggerDocRegister.onEvent(null);
|
||||
NotifyCenter.registerSubscriber(swaggerDocRegister);
|
||||
}
|
||||
|
||||
/**
|
||||
* Swagger resource resolver swagger resource resolver.
|
||||
* @param swaggerUiConfigProperties the swagger ui config properties
|
||||
* @return the swagger resource resolver
|
||||
*/
|
||||
@Bean
|
||||
@Lazy(false)
|
||||
SwaggerResourceResolver swaggerResourceResolver(SwaggerUiConfigProperties swaggerUiConfigProperties) {
|
||||
return new SwaggerResourceResolverPlus(swaggerUiConfigProperties);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 扩展的 SwaggerResourceResolver 类
|
||||
*/
|
||||
class SwaggerResourceResolverPlus extends SwaggerResourceResolver {
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* @param swaggerUiConfigProperties Swagger UI 配置属性
|
||||
*/
|
||||
public SwaggerResourceResolverPlus(SwaggerUiConfigProperties swaggerUiConfigProperties) {
|
||||
super(swaggerUiConfigProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析资源
|
||||
* @param exchange ServerWebExchange 对象
|
||||
* @param requestPath 请求路径
|
||||
* @param locations 资源位置列表
|
||||
* @param chain ResourceResolverChain 对象
|
||||
* @return 解析后的 Mono<Resource> 对象
|
||||
*/
|
||||
@Override
|
||||
public Mono<Resource> resolveResource(ServerWebExchange exchange, String requestPath,
|
||||
List<? extends Resource> locations, ResourceResolverChain chain) {
|
||||
Mono<Resource> resolved = chain.resolveResource(exchange, requestPath, locations);
|
||||
if (!Mono.empty().equals(resolved) && requestPath.startsWith("swagger-ui")) {
|
||||
String webJarResourcePath = findWebJarResourcePath(requestPath);
|
||||
if (webJarResourcePath != null)
|
||||
return chain.resolveResource(exchange, webJarResourcePath, locations);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Swagger文档注册器,继承自Subscriber<InstancesChangeEvent>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
class SwaggerDocRegister extends Subscriber<InstancesChangeEvent> {
|
||||
|
||||
private final SwaggerUiConfigProperties swaggerUiConfigProperties;
|
||||
|
||||
private final DiscoveryClient discoveryClient;
|
||||
|
||||
/**
|
||||
* 事件回调方法,处理InstancesChangeEvent事件
|
||||
* @param event 事件对象
|
||||
*/
|
||||
@Override
|
||||
public void onEvent(InstancesChangeEvent event) {
|
||||
Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> swaggerUrlSet = discoveryClient.getServices()
|
||||
.stream()
|
||||
.flatMap(serviceId -> discoveryClient.getInstances(serviceId).stream())
|
||||
.filter(instance -> StringUtils.isNotBlank(instance.getMetadata().get("spring-doc")))
|
||||
.map(instance -> {
|
||||
AbstractSwaggerUiConfigProperties.SwaggerUrl swaggerUrl = new AbstractSwaggerUiConfigProperties.SwaggerUrl();
|
||||
swaggerUrl.setName(instance.getServiceId());
|
||||
swaggerUrl.setUrl(String.format("/%s/v3/api-docs", instance.getMetadata().get("spring-doc")));
|
||||
return swaggerUrl;
|
||||
})
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
swaggerUiConfigProperties.setUrls(swaggerUrlSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅类型方法,返回订阅的事件类型
|
||||
* @return 订阅的事件类型
|
||||
*/
|
||||
@Override
|
||||
public Class<? extends Event> subscribeType() {
|
||||
return InstancesChangeEvent.class;
|
||||
}
|
||||
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, pjcloud All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: pjcloud
|
||||
*/
|
||||
|
||||
package com.bsd.pjcloud.gateway.filter;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2018/10/30
|
||||
* <p>
|
||||
* 自定义basic认证,针对特殊场景使用
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class HttpBasicGatewayFilter extends AbstractGatewayFilterFactory {
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Object config) {
|
||||
return (exchange, chain) -> {
|
||||
if (hasAuth(exchange)) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
else {
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
response.getHeaders().add(HttpHeaders.WWW_AUTHENTICATE, "Basic Realm=\"pjcloud\"");
|
||||
return response.setComplete();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单的basic认证
|
||||
* @param exchange 上下文
|
||||
* @return 是否有权限
|
||||
*/
|
||||
private boolean hasAuth(ServerWebExchange exchange) {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
String auth = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
|
||||
log.info("Basic认证信息为:{}", auth);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, pjcloud All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: pjcloud
|
||||
*/
|
||||
|
||||
package com.bsd.pjcloud.gateway.filter;
|
||||
|
||||
import com.bsd.pjcloud.common.core.constant.CommonConstants;
|
||||
import com.bsd.pjcloud.common.core.constant.SecurityConstants;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
|
||||
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2018/10/8
|
||||
* <p>
|
||||
* 全局拦截器,作用所有的微服务
|
||||
* <p>
|
||||
* 1. 对请求头中参数进行处理 from 参数进行清洗 2. 重写StripPrefix = 1,支持全局
|
||||
* <p>
|
||||
* 支持swagger添加X-Forwarded-Prefix header (F SR2 已经支持,不需要自己维护)
|
||||
*/
|
||||
@Component
|
||||
public class PjcloudRequestGlobalFilter implements GlobalFilter, Ordered {
|
||||
|
||||
/**
|
||||
* Process the Web request and (optionally) delegate to the next {@code WebFilter}
|
||||
* through the given {@link GatewayFilterChain}.
|
||||
* @param exchange the current server exchange
|
||||
* @param chain provides a way to delegate to the next filter
|
||||
* @return {@code Mono<Void>} to indicate when request processing is complete
|
||||
*/
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
// 1. 清洗请求头中from 参数
|
||||
ServerHttpRequest request = exchange.getRequest().mutate().headers(httpHeaders -> {
|
||||
httpHeaders.remove(SecurityConstants.FROM);
|
||||
// 设置请求时间
|
||||
httpHeaders.put(CommonConstants.REQUEST_START_TIME,
|
||||
Collections.singletonList(String.valueOf(System.currentTimeMillis())));
|
||||
}).build();
|
||||
|
||||
// 2. 重写StripPrefix
|
||||
addOriginalRequestUrl(exchange, request.getURI());
|
||||
String rawPath = request.getURI().getRawPath();
|
||||
String newPath = "/" + Arrays.stream(StringUtils.tokenizeToStringArray(rawPath, "/"))
|
||||
.skip(1L)
|
||||
.collect(Collectors.joining("/"));
|
||||
ServerHttpRequest newRequest = request.mutate().path(newPath).build();
|
||||
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());
|
||||
|
||||
return chain.filter(exchange.mutate().request(newRequest.mutate().build()).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2025, pjcloud All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* Author: pjcloud
|
||||
*/
|
||||
|
||||
package com.bsd.pjcloud.gateway.filter;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilter;
|
||||
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2018/8/21 演示环境过滤处理
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class PreviewGatewayFilter extends AbstractGatewayFilterFactory {
|
||||
|
||||
private static final String TOKEN = "token";
|
||||
|
||||
@Override
|
||||
public GatewayFilter apply(Object config) {
|
||||
return (exchange, chain) -> {
|
||||
ServerHttpRequest request = exchange.getRequest();
|
||||
|
||||
// GET,直接向下执行
|
||||
if (StrUtil.equalsIgnoreCase(request.getMethod().name(), HttpMethod.GET.name())
|
||||
|| StrUtil.containsIgnoreCase(request.getURI().getPath(), TOKEN)) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
log.warn("演示环境不能操作-> {},{}", request.getMethod().name(), request.getURI().getPath());
|
||||
ServerHttpResponse response = exchange.getResponse();
|
||||
response.setStatusCode(HttpStatus.LOCKED);
|
||||
return response.setComplete();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user