dashan
12 months ago
4 changed files with 295 additions and 0 deletions
@ -0,0 +1,168 @@ |
|||||||
|
package com.ds.commons.utils.json; |
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude; |
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException; |
||||||
|
import com.fasterxml.jackson.core.type.TypeReference; |
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature; |
||||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper; |
||||||
|
import com.fasterxml.jackson.databind.SerializationFeature; |
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode; |
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
|
||||||
|
/** |
||||||
|
* JSON 工具类 |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
public class JsonUtil { |
||||||
|
|
||||||
|
private static final ObjectMapper objectMapper = new ObjectMapper(); |
||||||
|
|
||||||
|
// 时间日期格式
|
||||||
|
private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss"; |
||||||
|
|
||||||
|
//以静态代码块初始化
|
||||||
|
static { |
||||||
|
//对象的所有字段全部列入序列化
|
||||||
|
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS); |
||||||
|
//取消默认转换timestamps形式
|
||||||
|
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); |
||||||
|
//忽略空Bean转json的错误
|
||||||
|
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); |
||||||
|
//所有的日期格式都统一为以下的格式,即yyyy-MM-dd HH:mm:ss
|
||||||
|
objectMapper.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT)); |
||||||
|
//忽略 在json字符串中存在,但在java对象中不存在对应属性的情况。防止错误
|
||||||
|
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**===========================以下是从JSON中获取对象====================================*/ |
||||||
|
public static <T> T parseObject(String jsonString, Class<T> object) { |
||||||
|
T t = null; |
||||||
|
try { |
||||||
|
t = objectMapper.readValue(jsonString, object); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
log.error("JsonString转为自定义对象失败:{}", e.getMessage()); |
||||||
|
} |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
public static <T> T parseObject(File file, Class<T> object) { |
||||||
|
T t = null; |
||||||
|
try { |
||||||
|
t = objectMapper.readValue(file, object); |
||||||
|
} catch (IOException e) { |
||||||
|
log.error("从文件中读取json字符串转为自定义对象失败:{}", e.getMessage()); |
||||||
|
} |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
//将json数组字符串转为指定对象List列表或者Map集合
|
||||||
|
public static <T> T parseJSONArray(String jsonArray, TypeReference<T> reference) { |
||||||
|
T t = null; |
||||||
|
try { |
||||||
|
t = objectMapper.readValue(jsonArray, reference); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
log.error("JSONArray转为List列表或者Map集合失败:{}", e.getMessage()); |
||||||
|
} |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**=================================以下是将对象转为JSON=====================================*/ |
||||||
|
public static String toJSONString(Object object) { |
||||||
|
String jsonString = null; |
||||||
|
try { |
||||||
|
jsonString = objectMapper.writeValueAsString(object); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
log.error("Object转JSONString失败:{}", e.getMessage()); |
||||||
|
} |
||||||
|
return jsonString; |
||||||
|
} |
||||||
|
|
||||||
|
public static byte[] toByteArray(Object object) { |
||||||
|
byte[] bytes = null; |
||||||
|
try { |
||||||
|
bytes = objectMapper.writeValueAsBytes(object); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
log.error("Object转ByteArray失败:{}", e.getMessage()); |
||||||
|
} |
||||||
|
return bytes; |
||||||
|
} |
||||||
|
|
||||||
|
public static void objectToFile(File file, Object object) { |
||||||
|
try { |
||||||
|
objectMapper.writeValue(file, object); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
log.error("Object写入文件失败:{}", e.getMessage()); |
||||||
|
} catch (IOException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**=============================以下是与JsonNode相关的=======================================*/ |
||||||
|
//JsonNode和JSONObject一样,都是JSON树形模型,只不过在jackson中,存在的是JsonNode
|
||||||
|
public static JsonNode parseJSONObject(String jsonString) { |
||||||
|
JsonNode jsonNode = null; |
||||||
|
try { |
||||||
|
jsonNode = objectMapper.readTree(jsonString); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
log.error("JSONString转为JsonNode失败:{}", e.getMessage()); |
||||||
|
} |
||||||
|
return jsonNode; |
||||||
|
} |
||||||
|
|
||||||
|
public static JsonNode parseJSONObject(Object object) { |
||||||
|
JsonNode jsonNode = objectMapper.valueToTree(object); |
||||||
|
return jsonNode; |
||||||
|
} |
||||||
|
|
||||||
|
public static String toJSONString(JsonNode jsonNode) { |
||||||
|
String jsonString = null; |
||||||
|
try { |
||||||
|
jsonString = objectMapper.writeValueAsString(jsonNode); |
||||||
|
} catch (JsonProcessingException e) { |
||||||
|
log.error("JsonNode转JSONString失败:{}", e.getMessage()); |
||||||
|
} |
||||||
|
return jsonString; |
||||||
|
} |
||||||
|
|
||||||
|
//JsonNode是一个抽象类,不能实例化,创建JSON树形模型,得用JsonNode的子类ObjectNode,用法和JSONObject大同小异
|
||||||
|
public static ObjectNode newJSONObject() { |
||||||
|
return objectMapper.createObjectNode(); |
||||||
|
} |
||||||
|
|
||||||
|
//创建JSON数组对象,就像JSONArray一样用
|
||||||
|
public static ArrayNode newJSONArray() { |
||||||
|
return objectMapper.createArrayNode(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/**===========以下是从JsonNode对象中获取key值的方法,个人觉得有点多余,直接用JsonNode自带的取值方法会好点,出于纠结症,还是补充进来了*/ |
||||||
|
public static String getString(JsonNode jsonObject, String key) { |
||||||
|
String s = jsonObject.get(key).asText(); |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
public static Integer getInteger(JsonNode jsonObject, String key) { |
||||||
|
Integer i = jsonObject.get(key).asInt(); |
||||||
|
return i; |
||||||
|
} |
||||||
|
|
||||||
|
public static Boolean getBoolean(JsonNode jsonObject, String key) { |
||||||
|
Boolean bool = jsonObject.get(key).asBoolean(); |
||||||
|
return bool; |
||||||
|
} |
||||||
|
|
||||||
|
public static JsonNode getJSONObject(JsonNode jsonObject, String key) { |
||||||
|
JsonNode json = jsonObject.get(key); |
||||||
|
return json; |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,106 @@ |
|||||||
|
package com.ds.gateway.filter; |
||||||
|
|
||||||
|
import com.ds.commons.utils.json.JsonUtil; |
||||||
|
import com.fasterxml.jackson.databind.JsonNode; |
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.reactivestreams.Publisher; |
||||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
||||||
|
import org.springframework.cloud.gateway.filter.GlobalFilter; |
||||||
|
import org.springframework.core.Ordered; |
||||||
|
import org.springframework.core.io.buffer.DataBuffer; |
||||||
|
import org.springframework.core.io.buffer.DataBufferUtils; |
||||||
|
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.http.server.reactive.ServerHttpResponseDecorator; |
||||||
|
import org.springframework.lang.NonNull; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
import org.springframework.web.server.ServerWebExchange; |
||||||
|
import reactor.core.publisher.Flux; |
||||||
|
import reactor.core.publisher.Mono; |
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* 因为swagger配置在业务服务中,默认的url会比网关少一层; |
||||||
|
* 这个过滤器主要给url添加上此网关这一层,并且设置到swagger的basePath中,使其可以正常通过swagger调用接口 |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
@Component |
||||||
|
public class SwaggerGlobalFilter implements GlobalFilter, Ordered { |
||||||
|
|
||||||
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { |
||||||
|
ServerHttpRequest request = exchange.getRequest(); |
||||||
|
String path = request.getPath().toString(); |
||||||
|
if (!path.endsWith("/v3/api-docs/swagger-config")) { |
||||||
|
return chain.filter(exchange); |
||||||
|
} |
||||||
|
String[] pathArray = path.split("/"); |
||||||
|
String basePath = pathArray[1]; |
||||||
|
ServerHttpResponse originalResponse = exchange.getResponse(); |
||||||
|
// 定义新的消息头
|
||||||
|
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) { |
||||||
|
@Override |
||||||
|
@NonNull |
||||||
|
public Mono<Void> writeWith(@NonNull Publisher<? extends DataBuffer> body) { |
||||||
|
if (HttpStatus.OK.equals(super.getStatusCode()) && body instanceof Flux) { |
||||||
|
Flux<? extends DataBuffer> fluxBody = Flux.from(body); |
||||||
|
return super.writeWith(fluxBody.buffer().map(dataBuffers -> { |
||||||
|
List<String> list = new ArrayList<>(); |
||||||
|
dataBuffers.forEach(dataBuffer -> { |
||||||
|
byte[] content = new byte[dataBuffer.readableByteCount()]; |
||||||
|
dataBuffer.read(content); |
||||||
|
DataBufferUtils.release(dataBuffer); |
||||||
|
list.add(new String(content, StandardCharsets.UTF_8)); |
||||||
|
}); |
||||||
|
String s = this.listToString(list); |
||||||
|
//获取到/v3/api-docs/swagger-config返回的json串 给文档url添加上网关层url
|
||||||
|
ObjectNode jsonNodes = JsonUtil.parseObject(s,ObjectNode.class); |
||||||
|
JsonNode urls = jsonNodes.get("urls"); |
||||||
|
urls.elements().forEachRemaining(item-> ((ObjectNode)item).put("url","/"+basePath+item.get("url").asText())); |
||||||
|
|
||||||
|
//设置basePath
|
||||||
|
jsonNodes.put("basePath", basePath); |
||||||
|
s = jsonNodes.toString(); |
||||||
|
// 设置更新后的header请求头长度
|
||||||
|
int length = s.getBytes().length; |
||||||
|
HttpHeaders headers = originalResponse.getHeaders(); |
||||||
|
headers.setContentLength(length); |
||||||
|
return bufferFactory().wrap(s.getBytes(StandardCharsets.UTF_8)); |
||||||
|
})); |
||||||
|
} |
||||||
|
return super.writeWith(body); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
@NonNull |
||||||
|
public HttpHeaders getHeaders() { |
||||||
|
// 获取父类原始ServerHttpResponse的header请求头信息,这是代理Delegate类型
|
||||||
|
HttpHeaders httpHeaders = super.getHeaders(); |
||||||
|
httpHeaders.set(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8"); |
||||||
|
return httpHeaders; |
||||||
|
} |
||||||
|
|
||||||
|
private String listToString(List<String> list) { |
||||||
|
StringBuilder stringBuilder = new StringBuilder(); |
||||||
|
for (String s : list) { |
||||||
|
stringBuilder.append(s); |
||||||
|
} |
||||||
|
return stringBuilder.toString(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
// replace response with decorator
|
||||||
|
return chain.filter(exchange.mutate().response(decoratedResponse).build()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getOrder() { |
||||||
|
return -2; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue