springboot项目引入Sentinel熔断

本文是springboot项目+nacos进行引入,sentiel需自行按照部署

1.springboot包要是2.2.5或以上

<dubbo.version>2.7.7</dubbo.version>
        <spring-boot.version>2.2.5.RELEASE</spring-boot.version>
        <chainwork-boot.version>1.0.5-SNAPSHOT</chainwork-boot.version>
        <nacos.version>0.2.7</nacos.version>
        <spring-cloud-nacos-config.version>2.2.5.RELEASE</spring-cloud-nacos-config.version>
        <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
        <spring-cloud-nacos-discovery.version>2.2.5.RELEASE</spring-cloud-nacos-discovery.version>
<!--       
        <arthas.version>3.4.3</arthas.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <nacos-client.version>1.4.1</nacos-client.version>
        <redisson.version>3.13.6</redisson.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>

2.项目后端需依赖包

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
        </dependency>

        <!-- Sentinel数据源之 Nacos -->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-web-servlet</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

<dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.0.1.Final</version>
        </dependency>

3.项目前端需依赖包

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>${spring-cloud-alibaba.version}</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-web-servlet</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
<dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.0.1.Final</version>
        </dependency>

4.后端 bootstrap.yml需配置

#server:
#  port: 8888
spring:
  #  application:
  #    name: test-server
  main:
    allow-bean-definition-overriding: true
  cloud:
    sentinel:
      datasource:
        # 流控规则,名字任意
        ds-flow:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-flow-rules
            ## 配置存储的格式
            data-type: json
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            rule-type: flow
        ## 配置降级规则,名字任意
        ds-degrade:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-degrade-rules
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            ## 配置存储的格式
            data-type: json
            ## rule-type设置对应得规则类型,总共七大类型,在com.alibaba.cloud.sentinel.datasource.RuleType这个枚举类中有体现
            rule-type: degrade
        ## 配置系统规则,名字任意
        ds-system:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-system-rules
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            ## 配置存储的格式
            data-type: json
            rule-type: system
    nacos:
      discovery:
        server-addr: 11.11.11.11:8848
      #        group: lj
      config:
        # 配置中心地址配置
        server-addr: 11.11.11.11:8848
        # 定义配置文件后缀为.properties, dataId=${spring.application.name}-${spring.profiles.active}.properties
        file-extension: properties
        group: prd
        # 定义配置中心分组:
        shared-configs[0]: #多个从0开始递增  扩展的是数字越大的优先级越高
          data-id: global-server-prd.properties #配置文件名
          group: DEFAULT_GROUP #分组名称
        #          refresh: true #配置扩展属性动态刷新
        shared-configs[1]:
          data-id: test-service-prd.properties
          #          data-id: test-service-test-sit.properties
          group: prd
  #          refresh: true
  profiles:
    # 定义环境为dev
    active: prd

5.前端 bootstrap.yml需配置

server:
  #  port: 8888
  servlet:
    context-path: /test-web
spring:
  #  application:
  #    name: test-web
  main:
    allow-bean-definition-overriding: true
  cloud:
    sentinel:
      #      eager: true
      #      filter:
      #        enabled: false
      #      transport:
      #        dashboard: 127.0.0.1:12180
      #      web-context-unify: false
      datasource:
        # 流控规则,名字任意
        ds-flow:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-flow-rules
            ## 配置存储的格式
            data-type: json
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            rule-type: flow
        ## 配置降级规则,名字任意
        ds-degrade:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-degrade-rules
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            ## 配置存储的格式
            data-type: json
            ## rule-type设置对应得规则类型,总共七大类型,在com.alibaba.cloud.sentinel.datasource.RuleType这个枚举类中有体现
            rule-type: degrade
        ## 配置系统规则,名字任意
        ds-system:
          nacos:
            ## nacos的地址
            server-addr: 11.11.11.11:8848
            ## 配置ID
            dataId: ${spring.application.name}-system-rules
            ## 配置分组,默认是DEFAULT_GROUP
            groupId: SENTINEL_GROUP
            ## 配置存储的格式
            data-type: json
            rule-type: system
    nacos:
      discovery:
        server-addr: 11.11.11.11:8848
      config:
        # 配置中心地址配置
        
        server-addr: 11.11.11.11:8848
        # 定义配置文件后缀为.properties, dataId=${spring.application.name}-${spring.profiles.active}.properties
        file-extension: properties
        #        group: sit
        # 定义配置中心分组:
        shared-configs[0]: #多个从0开始递增 扩展的是数字越大的优先级越高
          data-id: global-web-prd.properties #配置文件名
          group: DEFAULT_GROUP #分组名称
          refresh: true #配置扩展属性动态刷新
        shared-configs[1]:
          data-id: test-web-prd.properties
          group: prd
#          refresh: true

6.后端引入异常处理及配置类

import cn.hutool.json.JSONUtil;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.sinoservices.beans.ResultMessage;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * sentinel异常处理程序
 */
@Configuration
public class SentinelCustomBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        ResultMessage resultMessage = new ResultMessage();

        if (e instanceof FlowException) {
            // 限流
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统请求繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统请求繁忙,请稍后请求哦");
        } else if (e instanceof DegradeException) {
            // 熔断
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统请求在排队,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统请求在排队,请稍后请求哦");
        } else if (e instanceof ParamFlowException) {
            // 参数热点
            resultMessage.setSuccess(false);
            resultMessage.setMessage("ParamFlow系统请求繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("ParamFlow系统请求繁忙,请稍后请求哦");
        } else if (e instanceof SystemBlockException) {
            //系统保护
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统资源繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统资源繁忙,请稍后请求哦");
        } else if (e instanceof AuthorityException) {

        }
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.getWriter().write(JSONUtil.toJsonStr(resultMessage));
    }
}

**
 * 常量
 *
 * @description: 全局异常处理
 */
@Slf4j
@ControllerAdvice
public class TestServerGlobalExceptionHandler {

    /**
     * validator 方法参数校验
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public Message handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error("参数校验异常:{},{}", e.getMessage(), e);
        FieldError fieldError = e.getBindingResult().getFieldError();

        Message message = MessageFactory.getMessage();
        message.setSuccess(false);
        message.addMessage(fieldError.getDefaultMessage());
        //message.addMessage(fieldError.getField() + fieldError.getDefaultMessage());
        return message;
    }

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public Message handleFeignException(IllegalArgumentException e) {
        log.error("IllegalArgumentException异常:{},{}", e.getMessage(), e);
        Message message = MessageFactory.getMessage();
        message.setSuccess(false);
        message.addMessage(e.getMessage());
        return message;
    }

    @ExceptionHandler(FeignException.class)
    @ResponseBody
    public ResultMessage handleFeignException(FeignException e) {
        log.error("openFeign异常:{},{}", e.getMessage(), e);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setSuccess(false);
        resultMessage.setMessage(e.getMessage());
        resultMessage.setErrorDetailMessage(e.getMessage());
        return resultMessage;
    }

    

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Message handleException(Exception e) {
        log.error("接口异常:{},{}", e.getMessage(), e);
        Message message = MessageFactory.getMessage();
        message.setSuccess(false);
        message.addMessage(e.getMessage());
        return message;
    }

    @ExceptionHandler(StaleObjectStateException.class)
    @ResponseBody
    public Message versionErrorException(Exception e) {
        log.error("数据库修改版本冲突异常:{},{}", e.getMessage(), e);
        Message message = MessageFactory.getMessage();
        message.setSuccess(false);
        message.addMessage("数据版本冲突,请刷新后再操作");
        return message;
    }

    @ExceptionHandler(BlockException.class)
    @ResponseBody
    public ResultMessage sentinelBlockHandler(BlockException e) {
        log.error("sentinelBlock异常:{},{}", e.getMessage(), e);
        ResultMessage resultMessage = new ResultMessage();
        resultMessage.setSuccess(false);
        resultMessage.setMessage(e.getRule() + "系统繁忙,请稍后处理");
        resultMessage.setErrorDetailMessage(e.getRule() + "系统繁忙,请稍后处理");
        return resultMessage;
    }


}


import com.alibaba.cloud.sentinel.SentinelProperties;
import com.alibaba.cloud.sentinel.SentinelProperties.Filter;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.SentinelWebInterceptor;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.DefaultBlockExceptionHandler;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.config.SentinelWebMvcConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Optional;

@Configuration(
        proxyBeanMethods = false
)
@ConditionalOnClass({SentinelWebInterceptor.class})
@EnableConfigurationProperties({SentinelProperties.class})
public class SentinelWebAutoConfiguration implements WebMvcConfigurer {
    private static final Logger log = LoggerFactory.getLogger(SentinelWebAutoConfiguration.class);
    @Autowired
    private SentinelProperties properties;
    @Autowired
    private Optional<UrlCleaner> urlCleanerOptional;
    @Autowired
    private Optional<BlockExceptionHandler> blockExceptionHandlerOptional;
    @Autowired
    private Optional<RequestOriginParser> requestOriginParserOptional;
    @Autowired
    private Optional<SentinelWebInterceptor> sentinelWebInterceptorOptional;

    public SentinelWebAutoConfiguration() {
    }

    public void addInterceptors(InterceptorRegistry registry) {
        if (this.sentinelWebInterceptorOptional.isPresent()) {
            Filter filterConfig = this.properties.getFilter();
            registry.addInterceptor((HandlerInterceptor) this.sentinelWebInterceptorOptional.get()).order(filterConfig.getOrder()).addPathPatterns(filterConfig.getUrlPatterns());
            log.info("[Sentinel Starter] register SentinelWebInterceptor with urlPatterns: {}.", filterConfig.getUrlPatterns());
        }
    }

    @Bean
    public SentinelWebInterceptor sentinelWebInterceptor(SentinelWebMvcConfig sentinelWebMvcConfig) {
        return new SentinelWebInterceptor(sentinelWebMvcConfig);
    }

    @Bean
    public SentinelWebMvcConfig sentinelWebMvcConfig() {
        SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig();
        sentinelWebMvcConfig.setHttpMethodSpecify(this.properties.getHttpMethodSpecify());
        sentinelWebMvcConfig.setWebContextUnify(this.properties.getWebContextUnify());
        if (this.blockExceptionHandlerOptional.isPresent()) {
            this.blockExceptionHandlerOptional.ifPresent(sentinelWebMvcConfig::setBlockExceptionHandler);
        } else if (StringUtils.hasText(this.properties.getBlockPage())) {
            sentinelWebMvcConfig.setBlockExceptionHandler((request, response, e) -> {
                response.sendRedirect(this.properties.getBlockPage());
            });
        } else {
            sentinelWebMvcConfig.setBlockExceptionHandler(new DefaultBlockExceptionHandler());
        }

        this.urlCleanerOptional.ifPresent(sentinelWebMvcConfig::setUrlCleaner);
        this.requestOriginParserOptional.ifPresent(sentinelWebMvcConfig::setOriginParser);
        return sentinelWebMvcConfig;
    }
}

7.前端引入异常处理及配置类

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

/**
 * @description:
 * @author: John.Zhang
 * @date: 2023年03月02日
 * @version: 1.0.0
 */

@Component
@RefreshScope
@Data
public class FilterAssignUrlConfig {

    /**
     * 忽略静态资源
     */
    @Value("${request.ignore.requestSuffix}")
    public  String ignoreRequestSuffix;


    /**
     * 忽略登录请求
     */
    @Value("${request.ignore.requestUrl}")
    public  String ignoreRequestUrl;

}

import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * @description:
 */
@Configuration
public class FilterContextConfig {

    @Autowired
    private SentinelCustomFilter sentinelCustomFilter;

    @Autowired
    private FilterAssignUrlConfig filterAssignUrlConfig;


    /**
     * https://github.com/alibaba/Sentinel/issues/1213
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean sentinelFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(sentinelCustomFilter);
        registration.addUrlPatterns("/*");
        registration.addInitParameter("excludedUris", filterAssignUrlConfig.getIgnoreRequestUrl());
        registration.addInitParameter("excludedRequestFileExtension", filterAssignUrlConfig.getIgnoreRequestSuffix());
        registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
        registration.setName("sentinelCustomFilter");
        registration.setOrder(1);
        return registration;
    }


}

import com.alibaba.csp.sentinel.*;
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlCleaner;
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import com.alibaba.csp.sentinel.adapter.servlet.config.WebServletConfig;
import com.alibaba.csp.sentinel.adapter.servlet.util.FilterUtil;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSON;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Component
public class SentinelCustomFilter implements Filter {

    /**
     * Specify whether the URL resource name should contain the HTTP method prefix (e.g. {@code POST:}).
     */
    public static final String HTTP_METHOD_SPECIFY = "HTTP_METHOD_SPECIFY";
    /**
     * If enabled, use the default context name, or else use the URL path as the context name,
     * {@link WebServletConfig#WEB_SERVLET_CONTEXT_NAME}. Please pay attention to the number of context (EntranceNode),
     * which may affect the memory footprint.
     *
     * @since 1.7.0
     */
    public static final String WEB_CONTEXT_UNIFY = "WEB_CONTEXT_UNIFY";

    private final static String COLON = ":";

    private boolean httpMethodSpecify = false;
    private boolean webContextUnify = true;
    private String[] excludedUris;
    private String excludedRequestFileExtension;


    @Override
    public void init(FilterConfig filterConfig) {
        String param = filterConfig.getInitParameter("excludedUris");
        if (StringUtils.isNotBlank(param)) {
            this.excludedUris = param.split(",");
        }

        String excludedRequestFileExtension = filterConfig.getInitParameter("excludedRequestFileExtension");
        if (StringUtils.isNotBlank(excludedRequestFileExtension)) {
            this.excludedRequestFileExtension = excludedRequestFileExtension;
        }

        httpMethodSpecify = Boolean.parseBoolean(filterConfig.getInitParameter(HTTP_METHOD_SPECIFY));
        if (filterConfig.getInitParameter(WEB_CONTEXT_UNIFY) != null) {
            webContextUnify = Boolean.parseBoolean(filterConfig.getInitParameter(WEB_CONTEXT_UNIFY));
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest sRequest = (HttpServletRequest) request;
        Entry urlEntry = null;
        String target = null;
        boolean reqFlag = false;
        try {
            target = FilterUtil.filterTarget(sRequest);
            // 定义表示变量 并验证用户请求URI 是否包含不过滤路径
            for (String uri : excludedUris) {
                if (target.equals(uri)) {
                    reqFlag = true;
                }
                if (target.indexOf(".") > -1) {
                    if (excludedRequestFileExtension.contains(target.substring(target.lastIndexOf(".") + 1, target.length()))) {
                        reqFlag = true;
                    }
                }

            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        try {
            if (!reqFlag) {
                // Clean and unify the URL.
                // For REST APIs, you have to clean the URL (e.g. `/foo/1` and `/foo/2` -> `/foo/:id`), or
                // the amount of context and resources will exceed the threshold.
                UrlCleaner urlCleaner = WebCallbackManager.getUrlCleaner();
                if (urlCleaner != null) {
                    target = urlCleaner.clean(target);
                }

                // If you intend to exclude some URLs, you can convert the URLs to the empty string ""
                // in the UrlCleaner implementation.
                if (!StringUtil.isEmpty(target)) {
                    // Parse the request origin using registered origin parser.
                    String origin = parseOrigin(sRequest);
                    String contextName = webContextUnify ? WebServletConfig.WEB_SERVLET_CONTEXT_NAME : target;
                    ContextUtil.enter(contextName, origin);

                    if (httpMethodSpecify) {
                        // Add HTTP method prefix if necessary.
                        String pathWithHttpMethod = sRequest.getMethod().toUpperCase() + COLON + target;
                        urlEntry = SphU.entry(pathWithHttpMethod, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
                    } else {
                        urlEntry = SphU.entry(target, ResourceTypeConstants.COMMON_WEB, EntryType.IN);
                    }
                }
            }
            chain.doFilter(request, response);
        } catch (BlockException e) {
            HttpServletResponse sResponse = (HttpServletResponse) response;
            HttpServletRequest sRequest2 = (HttpServletRequest) request;
            // Return the block page, or redirect to another URL.
            // WebCallbackManager.getUrlBlockHandler().blocked(sRequest, sResponse, e);
            StringBuffer url = sRequest2.getRequestURL();
            if ("GET".equals(sRequest2.getMethod()) && StringUtil.isNotBlank(sRequest2.getQueryString())) {
                url.append("?").append(sRequest2.getQueryString());
            }
            ResultMessage resultMessage = new ResultMessage();

            if (e instanceof FlowException) {
                // 限流
                resultMessage.setSuccess(false);
                resultMessage.setMessage("系统请求繁忙,请稍后请求哦");
                resultMessage.setErrorDetailMessage("系统请求繁忙,请稍后请求哦");
            } else if (e instanceof DegradeException) {
                // 熔断
                resultMessage.setSuccess(false);
                resultMessage.setMessage("系统请求在排队,请稍后请求哦");
                resultMessage.setErrorDetailMessage("系统请求在排队,请稍后请求哦");
            } else if (e instanceof ParamFlowException) {
                // 参数热点
                resultMessage.setSuccess(false);
                resultMessage.setMessage("ParamFlow系统请求繁忙,请稍后请求哦");
                resultMessage.setErrorDetailMessage("ParamFlow系统请求繁忙,请稍后请求哦");
            } else if (e instanceof SystemBlockException) {
                //系统保护
                resultMessage.setSuccess(false);
                resultMessage.setMessage("系统资源繁忙,请稍后请求哦");
                resultMessage.setErrorDetailMessage("系统资源繁忙,请稍后请求哦");
            }

            if (StringUtil.isBlank(WebServletConfig.getBlockPage())) {
                sResponse.setStatus(WebServletConfig.getBlockPageHttpStatus());
                sResponse.setCharacterEncoding("utf-8");
                sResponse.setHeader("Content-Type", "application/json;charset=utf-8");
                PrintWriter out = sResponse.getWriter();
                String blockMsg = JSON.toJSONString(resultMessage);
                out.print(blockMsg);
                out.flush();
                out.close();
            } else {
                String redirectUrl = WebServletConfig.getBlockPage() + "?http_referer=" + url.toString();
                sResponse.sendRedirect(redirectUrl);
            }
        } catch (IOException | ServletException | RuntimeException e2) {
            Tracer.traceEntry(e2, urlEntry);
            throw e2;
        } finally {
            if (urlEntry != null) {
                urlEntry.exit();
            }
            ContextUtil.exit();
        }
    }

    private String parseOrigin(HttpServletRequest request) {
        RequestOriginParser originParser = WebCallbackManager.getRequestOriginParser();
        String origin = EMPTY_ORIGIN;
        if (originParser != null) {
            origin = originParser.parseOrigin(request);
            if (StringUtil.isEmpty(origin)) {
                return EMPTY_ORIGIN;
            }
        }
        return origin;
    }

    @Override
    public void destroy() {

    }

    private static final String EMPTY_ORIGIN = "";

}



import cn.hutool.json.JSONUtil;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * sentinel异常处理程序
 */
@Configuration
public class SentinelCustomBlockExceptionHandler implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
        ResultMessage resultMessage = new ResultMessage();

        if (e instanceof FlowException) {
            // 限流
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统请求繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统请求繁忙,请稍后请求哦");
        } else if (e instanceof DegradeException) {
            // 熔断
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统请求在排队,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统请求在排队,请稍后请求哦");
        } else if (e instanceof ParamFlowException) {
            // 参数热点
            resultMessage.setSuccess(false);
            resultMessage.setMessage("ParamFlow系统请求繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("ParamFlow系统请求繁忙,请稍后请求哦");
        } else if (e instanceof SystemBlockException) {
            //系统保护
            resultMessage.setSuccess(false);
            resultMessage.setMessage("系统资源繁忙,请稍后请求哦");
            resultMessage.setErrorDetailMessage("系统资源繁忙,请稍后请求哦");
        } else if (e instanceof AuthorityException) {

        }
        response.setCharacterEncoding("utf-8");
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.getWriter().write(JSONUtil.toJsonStr(resultMessage));
    }
}

8.nacos需增加对应配置

spring.cloud.sentinel.transport.dashboard=11.111.1.112:11180
spring.cloud.sentinel.web-context-unify=false
spring.cloud.sentinel.eager=true
spring.cloud.sentinel.filter.enabled=false
feign.sentinel.enabled=true

9.启动项目后就可在sentiel中进行规则配置

相关推荐
拾木20022 分钟前
常见的限流算法
java·开发语言
处处清欢27 分钟前
MaintenanceController
java·开发语言
飞翔的佩奇39 分钟前
Java项目: 基于SpringBoot+mybatis+maven校园资料分享平台(含源码+数据库+答辩PPT+毕业论文)
java·spring boot·spring·毕业设计·maven·mybatis·校园资料分享平台
不平衡的叉叉树42 分钟前
Java对象列表属性映射工具类
java
缘友一世1 小时前
mac系统安装最新(截止2024.9.13)Oracle JDK操作记录
java·macos·oracle
跃ZHD1 小时前
BolckingQueue
java
西岭千秋雪_1 小时前
谷粒商城のElasticsearch
java·大数据·服务器·spring boot·elasticsearch·搜索引擎
yueqingll2 小时前
020、二级Java选择题综合知识点(持续更新版)
java·开发语言
许野平2 小时前
Rust:深入浅出说一说 Error 类型
java·开发语言·rust·error
jingling5552 小时前
后端开发刷题 | 数字字符串转化成IP地址
java·开发语言·javascript·算法