1.初始化版本,2.引入thirdpart模块,引入canteen模块,初始化菜品分类,spu
This commit is contained in:
commit
aff77150d6
1595 files changed
+168833
No files matched your search
+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.common.sentinel;
|
||||
|
||||
import com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.RequestOriginParser;
|
||||
import com.bsd.pjcloud.common.sentinel.feign.PjcloudSentinelFeign;
|
||||
import com.bsd.pjcloud.common.sentinel.handle.GlobalBizExceptionHandler;
|
||||
import com.bsd.pjcloud.common.sentinel.handle.PjcloudUrlBlockHandler;
|
||||
import com.bsd.pjcloud.common.sentinel.parser.PjcloudHeaderRequestOriginParser;
|
||||
import feign.Feign;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2020-02-12
|
||||
* <p>
|
||||
* sentinel 配置
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigureBefore(SentinelFeignAutoConfiguration.class)
|
||||
public class PjcloudSentinelAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@Scope("prototype")
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(name = "spring.cloud.openfeign.sentinel.enabled",matchIfMissing = true)
|
||||
public Feign.Builder feignSentinelBuilder() {
|
||||
return PjcloudSentinelFeign.builder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
/**
|
||||
* 创建一个块异常处理器实例
|
||||
* 如果没有定义块异常处理器,则创建一个PjcloudUrlBlockHandler实例
|
||||
*/
|
||||
public BlockExceptionHandler blockExceptionHandler() {
|
||||
return new PjcloudUrlBlockHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
/**
|
||||
* 创建一个请求源解析器实例
|
||||
* 如果没有定义请求源解析器,则创建一个PjcloudHeaderRequestOriginParser实例
|
||||
*/
|
||||
public RequestOriginParser requestOriginParser() {
|
||||
return new PjcloudHeaderRequestOriginParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个全局业务异常处理器实例
|
||||
* 用于处理全局的业务异常
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
public GlobalBizExceptionHandler globalBizExceptionHandler() {
|
||||
return new GlobalBizExceptionHandler();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
package com.bsd.pjcloud.common.sentinel.feign;
|
||||
|
||||
import com.alibaba.cloud.sentinel.feign.SentinelContractHolder;
|
||||
import feign.Contract;
|
||||
import feign.Feign;
|
||||
import feign.InvocationHandlerFactory;
|
||||
import feign.Target;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cloud.openfeign.FallbackFactory;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.cloud.openfeign.FeignClientFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
/**
|
||||
* 支持自动降级注入 重写 {@link com.alibaba.cloud.sentinel.feign.SentinelFeign}
|
||||
*
|
||||
* @author pjcloud
|
||||
* @date 2020/6/9
|
||||
*/
|
||||
public final class PjcloudSentinelFeign {
|
||||
|
||||
private PjcloudSentinelFeign() {
|
||||
|
||||
}
|
||||
|
||||
public static PjcloudSentinelFeign.Builder builder() {
|
||||
return new PjcloudSentinelFeign.Builder();
|
||||
}
|
||||
|
||||
public static final class Builder extends Feign.Builder implements ApplicationContextAware {
|
||||
|
||||
private Contract contract = new Contract.Default();
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private FeignClientFactory feignClientFactory;
|
||||
|
||||
@Override
|
||||
public Feign.Builder invocationHandlerFactory(InvocationHandlerFactory invocationHandlerFactory) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PjcloudSentinelFeign.Builder contract(Contract contract) {
|
||||
this.contract = contract;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Feign internalBuild() {
|
||||
super.invocationHandlerFactory(new InvocationHandlerFactory() {
|
||||
@Override
|
||||
public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
|
||||
|
||||
// 查找 FeignClient 上的 降级策略
|
||||
FeignClient feignClient = AnnotationUtils.findAnnotation(target.type(), FeignClient.class);
|
||||
Class<?> fallback = feignClient.fallback();
|
||||
Class<?> fallbackFactory = feignClient.fallbackFactory();
|
||||
|
||||
String beanName = feignClient.contextId();
|
||||
if (!StringUtils.hasText(beanName)) {
|
||||
beanName = feignClient.name();
|
||||
}
|
||||
|
||||
Object fallbackInstance;
|
||||
FallbackFactory<?> fallbackFactoryInstance;
|
||||
if (void.class != fallback) {
|
||||
fallbackInstance = getFromContext(beanName, "fallback", fallback, target.type());
|
||||
return new PjcloudSentinelInvocationHandler(target, dispatch,
|
||||
new FallbackFactory.Default(fallbackInstance));
|
||||
}
|
||||
|
||||
if (void.class != fallbackFactory) {
|
||||
fallbackFactoryInstance = (FallbackFactory<?>) getFromContext(beanName, "fallbackFactory",
|
||||
fallbackFactory, FallbackFactory.class);
|
||||
return new PjcloudSentinelInvocationHandler(target, dispatch, fallbackFactoryInstance);
|
||||
}
|
||||
return new PjcloudSentinelInvocationHandler(target, dispatch);
|
||||
}
|
||||
|
||||
private Object getFromContext(String name, String type, Class<?> fallbackType, Class<?> targetType) {
|
||||
Object fallbackInstance = feignClientFactory.getInstance(name, fallbackType);
|
||||
if (fallbackInstance == null) {
|
||||
throw new IllegalStateException(String
|
||||
.format("No %s instance of type %s found for feign client %s", type, fallbackType, name));
|
||||
}
|
||||
|
||||
if (!targetType.isAssignableFrom(fallbackType)) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Incompatible %s instance. Fallback/fallbackFactory of type %s is not assignable to %s for feign client %s",
|
||||
type, fallbackType, targetType, name));
|
||||
}
|
||||
return fallbackInstance;
|
||||
}
|
||||
});
|
||||
|
||||
super.contract(new SentinelContractHolder(contract));
|
||||
return super.internalBuild();
|
||||
}
|
||||
|
||||
private Object getFieldValue(Object instance, String fieldName) {
|
||||
Field field = ReflectionUtils.findField(instance.getClass(), fieldName);
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
return field.get(instance);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
this.feignClientFactory = this.applicationContext.getBean(FeignClientFactory.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
package com.bsd.pjcloud.common.sentinel.feign;
|
||||
|
||||
import com.alibaba.cloud.sentinel.feign.SentinelContractHolder;
|
||||
import com.alibaba.cloud.sentinel.feign.SentinelInvocationHandler;
|
||||
import com.alibaba.csp.sentinel.Entry;
|
||||
import com.alibaba.csp.sentinel.EntryType;
|
||||
import com.alibaba.csp.sentinel.SphU;
|
||||
import com.alibaba.csp.sentinel.Tracer;
|
||||
import com.alibaba.csp.sentinel.context.ContextUtil;
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import feign.Feign;
|
||||
import feign.InvocationHandlerFactory;
|
||||
import feign.MethodMetadata;
|
||||
import feign.Target;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.openfeign.FallbackFactory;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static feign.Util.checkNotNull;
|
||||
|
||||
/**
|
||||
* 重写 {@link com.alibaba.cloud.sentinel.feign.SentinelInvocationHandler} 支持自动降级注入
|
||||
*
|
||||
* @author pjcloud
|
||||
* @date 2020/6/9
|
||||
*/
|
||||
@Slf4j
|
||||
public class PjcloudSentinelInvocationHandler implements InvocationHandler {
|
||||
|
||||
public static final String EQUALS = "equals";
|
||||
|
||||
public static final String HASH_CODE = "hashCode";
|
||||
|
||||
public static final String TO_STRING = "toString";
|
||||
|
||||
private final Target<?> target;
|
||||
|
||||
private final Map<Method, InvocationHandlerFactory.MethodHandler> dispatch;
|
||||
|
||||
private FallbackFactory fallbackFactory;
|
||||
|
||||
private Map<Method, Method> fallbackMethodMap;
|
||||
|
||||
PjcloudSentinelInvocationHandler(Target<?> target, Map<Method, InvocationHandlerFactory.MethodHandler> dispatch,
|
||||
FallbackFactory fallbackFactory) {
|
||||
this.target = checkNotNull(target, "target");
|
||||
this.dispatch = checkNotNull(dispatch, "dispatch");
|
||||
this.fallbackFactory = fallbackFactory;
|
||||
this.fallbackMethodMap = toFallbackMethod(dispatch);
|
||||
}
|
||||
|
||||
PjcloudSentinelInvocationHandler(Target<?> target, Map<Method, InvocationHandlerFactory.MethodHandler> dispatch) {
|
||||
this.target = checkNotNull(target, "target");
|
||||
this.dispatch = checkNotNull(dispatch, "dispatch");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
|
||||
if (EQUALS.equals(method.getName())) {
|
||||
try {
|
||||
Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
|
||||
return equals(otherHandler);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (HASH_CODE.equals(method.getName())) {
|
||||
return hashCode();
|
||||
}
|
||||
else if (TO_STRING.equals(method.getName())) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
Object result;
|
||||
InvocationHandlerFactory.MethodHandler methodHandler = this.dispatch.get(method);
|
||||
// only handle by HardCodedTarget
|
||||
if (target instanceof Target.HardCodedTarget) {
|
||||
Target.HardCodedTarget hardCodedTarget = (Target.HardCodedTarget) target;
|
||||
MethodMetadata methodMetadata = SentinelContractHolder.METADATA_MAP
|
||||
.get(hardCodedTarget.type().getName() + Feign.configKey(hardCodedTarget.type(), method));
|
||||
// resource default is HttpMethod:protocol://url
|
||||
if (methodMetadata == null) {
|
||||
result = methodHandler.invoke(args);
|
||||
}
|
||||
else {
|
||||
String resourceName = methodMetadata.template().method().toUpperCase() + ":" + hardCodedTarget.url()
|
||||
+ methodMetadata.template().path();
|
||||
Entry entry = null;
|
||||
try {
|
||||
ContextUtil.enter(resourceName);
|
||||
entry = SphU.entry(resourceName, EntryType.OUT, 1, args);
|
||||
result = methodHandler.invoke(args);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
// fallback handle
|
||||
if (!BlockException.isBlockException(ex)) {
|
||||
Tracer.trace(ex);
|
||||
}
|
||||
if (fallbackFactory != null) {
|
||||
try {
|
||||
Object fallbackResult = fallbackMethodMap.get(method)
|
||||
.invoke(fallbackFactory.create(ex), args);
|
||||
return fallbackResult;
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// shouldn't happen as method is public due to being an
|
||||
// interface
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new AssertionError(e.getCause());
|
||||
}
|
||||
}
|
||||
else if (R.class == method.getReturnType()) {
|
||||
log.error("feign 服务间调用异常", ex);
|
||||
return R.failed(ex.getLocalizedMessage());
|
||||
}
|
||||
else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (entry != null) {
|
||||
entry.exit(1, args);
|
||||
}
|
||||
ContextUtil.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// other target type using default strategy
|
||||
result = methodHandler.invoke(args);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof SentinelInvocationHandler) {
|
||||
PjcloudSentinelInvocationHandler other = (PjcloudSentinelInvocationHandler) obj;
|
||||
return target.equals(other.target);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return target.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return target.toString();
|
||||
}
|
||||
|
||||
static Map<Method, Method> toFallbackMethod(Map<Method, InvocationHandlerFactory.MethodHandler> dispatch) {
|
||||
Map<Method, Method> result = new LinkedHashMap<>();
|
||||
for (Method method : dispatch.keySet()) {
|
||||
method.setAccessible(true);
|
||||
result.put(method, method);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.common.sentinel.handle;
|
||||
|
||||
import com.alibaba.csp.sentinel.Tracer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import feign.FeignException;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2020-06-29
|
||||
*/
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalBizExceptionHandler {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* 全局异常.
|
||||
*
|
||||
* @param e the e
|
||||
* @return R
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public R handleGlobalException(Exception e) {
|
||||
|
||||
log.error("全局异常信息 ex={}", e.getMessage(), e);
|
||||
|
||||
// 业务异常交由 sentinel 记录
|
||||
Tracer.trace(e);
|
||||
return R.failed(e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* SQLException Exception
|
||||
*
|
||||
* @param exception 数据库调用异常
|
||||
* @return R
|
||||
*/
|
||||
@ExceptionHandler({SQLException.class})
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public R handleSQLException(SQLException exception) {
|
||||
log.error("数据库调用异常 ex={}", exception.getMessage(), exception);
|
||||
return R.failed("数据库调用异常,请联系管理员处理");
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@ExceptionHandler(FeignException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public R handleGlobalException(FeignException e) {
|
||||
log.error("全局异常信息 ex={}", e.getMessage(), e);
|
||||
|
||||
// 业务异常交由 sentinel 记录
|
||||
Tracer.trace(e);
|
||||
|
||||
if (e.responseBody().isPresent()) {
|
||||
return objectMapper.readValue(e.responseBody().get().array(), R.class);
|
||||
}
|
||||
|
||||
return R.failed(e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* AccessDeniedException
|
||||
*
|
||||
* @param e the e
|
||||
* @return R
|
||||
*/
|
||||
@ExceptionHandler(AccessDeniedException.class)
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public R handleAccessDeniedException(AccessDeniedException e) {
|
||||
log.error("拒绝授权异常信息 ex={}", e.getMessage());
|
||||
return R.failed("权限不足,不允许访问");
|
||||
}
|
||||
|
||||
/**
|
||||
* validation Exception
|
||||
*
|
||||
* @param exception
|
||||
* @return R
|
||||
*/
|
||||
@ExceptionHandler({BindException.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public R handleBodyValidException(BindException exception) {
|
||||
List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
|
||||
// 插入log 的逻辑
|
||||
return R.failed(String.format("%s %s", fieldErrors.get(0).getField(), fieldErrors.get(0).getDefaultMessage()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 避免 404 重定向到 /error 导致NPE ,ignore-url 需要配置对应端点
|
||||
*
|
||||
* @return R
|
||||
*/
|
||||
@DeleteMapping("/error")
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public R noHandlerFoundException() {
|
||||
return R.failed(HttpStatus.NOT_FOUND.getReasonPhrase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保持和低版本请求路径不存在的行为一致
|
||||
* <p>
|
||||
* <a href="https://github.com/spring-projects/spring-boot/issues/38733">[Spring Boot
|
||||
* 3.2.0] 404 Not Found behavior #38733</a>
|
||||
*
|
||||
* @param exception
|
||||
* @return R
|
||||
*/
|
||||
@ExceptionHandler({NoResourceFoundException.class})
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public R noResourceFoundException(NoResourceFoundException exception) {
|
||||
log.debug("请求路径 404 {}", exception.getMessage());
|
||||
return R.failed(exception.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.common.sentinel.handle;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.BlockExceptionHandler;
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2019-10-11
|
||||
* <p>
|
||||
* 降级 限流策略
|
||||
*/
|
||||
@Slf4j
|
||||
public class PjcloudUrlBlockHandler implements BlockExceptionHandler {
|
||||
|
||||
/**
|
||||
* Handle the request when blocked.
|
||||
*
|
||||
* @param request Servlet request
|
||||
* @param response Servlet response
|
||||
* @param resourceName resource name
|
||||
* @param e the block exception
|
||||
* @throws Exception users may throw out the BlockException or other error occurs
|
||||
*/
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response, String resourceName, BlockException e) throws Exception {
|
||||
log.error("sentinel 降级 资源名称{}", resourceName, e);
|
||||
response.setContentType("application/json");
|
||||
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
|
||||
response.getWriter().print(JSONUtil.toJsonStr(R.failed(e.getMessage())));
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.common.sentinel.parser;
|
||||
|
||||
|
||||
import com.alibaba.csp.sentinel.adapter.spring.webmvc_v6x.callback.RequestOriginParser;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author pjcloud
|
||||
* @date 2019-10-11
|
||||
* <p>
|
||||
* sentinel 请求头解析判断
|
||||
*/
|
||||
public class PjcloudHeaderRequestOriginParser implements RequestOriginParser {
|
||||
|
||||
/**
|
||||
* 请求头获取allow
|
||||
*/
|
||||
private static final String ALLOW = "Allow";
|
||||
|
||||
/**
|
||||
* Parse the origin from given HTTP request.
|
||||
* @param request HTTP request
|
||||
* @return parsed origin
|
||||
*/
|
||||
@Override
|
||||
public String parseOrigin(HttpServletRequest request) {
|
||||
return request.getHeader(ALLOW);
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
com.bsd.pjcloud.common.sentinel.PjcloudSentinelAutoConfiguration
|
||||
Reference in new issue
Block a user