zoukankan      html  css  js  c++  java
  • Gateway 过滤器,过滤器统一异常处理

    以下内容,都很重要

    以下内容,都很重要

    以下内容,都很重要

    请勿忽略

    一, 配置文件

    spring:
      cloud:
        gateway:
          globalcors:
            cors-configurations:        #cors
              '[/**]':
                allowed-headers: "*"
                allowed-origins: "*"
                allowed-methods: "*"
    #      discovery:
    #        locator:
    #          lower-case-service-id: true
    #          enabled: true
          routes:
            - id: web-mac
              uri: lb://web-mac
              predicates:
                - Path=/web-mac/**
              filters:
                - StripPrefix=1
                - Token_Mac=true

    解释:

    一, cors 不多说了,跨域设置

    二, discovery

    这个当中的 locator.enabled 必须注释掉。

    它会影响到过滤的转发功能。

    三,属性

    id:随便起名字

    uri:lb开头,无需更改。web-mac是注册中心的application name(eruake显示大写,配置里用小写没关系)

    predicates:匹配规则

    filters:过滤器

    在使用过滤器时,StripPrefix=1 必须!

    Token_Mac 是我的过滤器,True是代表Config中是否开启。

    二,过滤器

    package com.tenyears.gateway.filter;
     
    /**
     * @description :
     * @auther Tyler
     * @date 2021/8/12
     */
     
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    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 java.util.Arrays;
    import java.util.List;
     
     
    @Component
    public class Token_MacGatewayFilterFactory extends AbstractGatewayFilterFactory<Token_MacGatewayFilterFactory.Config> {
     
        private static final String TOKEN_HEADER="Authorization";
        private static final String TOKEN_IS_INVALID = "Token is invalid";
     
     
        public Token_MacGatewayFilterFactory() {
            super(Config.class);
        }
     
        @Override
        public List<String> shortcutFieldOrder() {
            return Arrays.asList("enabled");
        }
     
        @Override
        public GatewayFilter apply(Token_MacGatewayFilterFactory.Config config) {
            System.out.println("TokenGatewayFilterFactory begin");
            return (exchange, chain) -> {
     
                if (!config.isEnabled()) {
                    return chain.filter(exchange);
                }
     
                ServerHttpRequest request = exchange.getRequest();
                
                HttpHeaders headers = request.getHeaders();
                String token = headers.getFirst(TOKEN_HEADER);
                System.out.println("token : "+token);
                if (StringUtils.isEmpty(token) ) {
                    throw new RuntimeException(TOKEN_IS_INVALID);
    //                response.setStatusCode(HttpStatus.UNAUTHORIZED);
    //                return response.setComplete();
                }
     
                //验证token,这里举个例子
                if (!token.equals("123") ) {
                    throw new RuntimeException(TOKEN_IS_INVALID);
    //                response.setStatusCode(HttpStatus.UNAUTHORIZED);
    //                return response.setComplete();
                }
                System.out.println("TokenGatewayFilterFactory end");
                return chain.filter(exchange);
            };
        }
     
        public static class Config {
            // 控制是否开启认证
            private boolean enabled;
     
            public Config() {}
     
            public boolean isEnabled() {
                return enabled;
            }
     
            public void setEnabled(boolean enabled) {
                this.enabled = enabled;
            }
        }
     
    }

    一,继承自AbstractGatewayFilterFactory

    二,过滤器名:Token_MacGatewayFilterFactory

    必须 GatewayFilterFactory  结尾!

    三,统一异常处理 

    package com.tenyears.gateway.advice;
     
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.tenyears.model.common.ApiResult;
    import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.annotation.Order;
    import org.springframework.core.io.buffer.DataBufferFactory;
    import org.springframework.http.MediaType;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.web.server.ResponseStatusException;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
     
    /**
     * @description :
     * @auther Tyler
     * @date 2021/8/12
     */
     
    @Order(-1)
    @Configuration
    public class GlobalErrorExceptionHandler implements ErrorWebExceptionHandler {
     
        private final ObjectMapper objectMapper=new ObjectMapper();
     
        @Override
        public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
            ServerHttpResponse response = exchange.getResponse();
            if (response.isCommitted()) {
                return Mono.error(ex);
            }
     
            // 设置返回JSON
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            if (ex instanceof ResponseStatusException) {
                response.setStatusCode(((ResponseStatusException) ex).getStatus());
            }
     
            return response.writeWith(Mono.fromSupplier(() -> {
                DataBufferFactory bufferFactory = response.bufferFactory();
                try {
                    //返回响应结果
                    ApiResult<String> result=new ApiResult<>();
                    result.setCodeToFail(ex.getMessage());
                    return bufferFactory.wrap(objectMapper.writeValueAsBytes(result));
                }
                catch (JsonProcessingException e) {
                    return bufferFactory.wrap(new byte[0]);
                }
            }));
        }
    }

     filter 抛出的异常,会被GlobalErrorExceptionHandler 统一处理

    ApiResult<T> 

    是我自定义的返回结果。 

    package com.tenyears.model.common;
     
    /**
     * Created by Tyler on 2017/6/20.
     */
     
    @Data
    public class ApiResult<T> {
        public static final String FAIL_CODE = "0";        //失败码
        public static final String SUC_CODE = "1";        //成功码
        public static final String ERROR_CODE = "2";    //错误码
        public static final String SUC_MESSAGE = "Operate successfully";    //成功信息
        public static final String FAIL_MESSAGE = "Operation failure";        //失败信息
        public static final String ERROR_MESSAGE = "System Error";            //错误信息
        public static final String NOACCESS_MESSAGE = "No permission to access this page.";        //无权操作
     
        /**
         * 代码
         * 0 失败
         * 1 成功
         * 2 错误
         * @mock 1
         */
        private String code = FAIL_CODE;
        /**
         * 信息(对应code)
         * Operate successfully
         * Operation failure
         * System Error
         * @mock Operate successfully
         */
        private String message = FAIL_MESSAGE;
        /**
         * 模型
         */
        private T data;
     
        /**
         * 当前页(分页时有效)
         */
        private Integer page_index = -1;
        /**
         * 条目(分页时有效)
         */
        private Integer page_size= -1;
     
        /**
         * 总页数(分页时有效)
         */
        private Integer total_pages=-1;
        /**
         * 总条目数(分页时有效)
         */
        private Integer total_elements=-1;
     
     
        public void setCode(String code, String message) {
            this.code = code;
            this.message = message;
        }
     
        public void setCodeToSuccessed() {
            this.code = SUC_CODE;
            this.message = SUC_MESSAGE;
        }
        public void setCodeToSuccessed(T data) {
            this.data = data;
            this.code = SUC_CODE;
            this.message = SUC_MESSAGE;
        }
        
        public void setCodeToError(String message) {
            this.code = ERROR_CODE;
            this.message = message;
        }
        
        public void setCodeToError() {
            this.code = ERROR_CODE;
            this.message = ERROR_MESSAGE;
        }
     
        public void setCodeToFail(String message) {
            this.code = ERROR_CODE;
            this.message = message;
        }
     
        public void setCodeToFail() {
            this.code = FAIL_CODE;
            this.message = FAIL_MESSAGE;
        }
        
        public void setCodeByNoAccess() {
            this.code = FAIL_CODE;
            this.message = NOACCESS_MESSAGE;
        }
     
        public boolean isSuccess() {
            return SUC_CODE.equals(code);
        }
     
    }
  • 相关阅读:
    【MM系列】SAP库龄报表逻辑理解
    【MM系列】SAP技巧之更改布局
    【MM系列】SAP里批量设置采购信息记录删除标记
    《跃迁-从技术到管理的硅谷路径》读书笔记
    Java安全编码标准
    web安全/渗透测试--1--web安全原则
    使用spring validation完成数据后端校验
    9 个Java 异常处理的规则
    程序员必看:给你一份详细的Spring Boot知识清单
    Java架构技术知识点梳理
  • 原文地址:https://www.cnblogs.com/hanjun0612/p/15136471.html
Copyright © 2011-2022 走看看