以下内容,都很重要
以下内容,都很重要
以下内容,都很重要
请勿忽略
一, 配置文件
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); } }