Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ protected RestOperationMeta findRestOperation(RestServerRequestInternal restRequ
throw new InvocationException(Status.NOT_FOUND, Status.NOT_FOUND.getReasonPhrase());
}

OperationLocator locator = servicePathManager.locateOperation(restRequest.getPath(), restRequest.getMethod());
OperationLocator locator =
servicePathManager.producerLocateOperation(restRequest.getPath(), restRequest.getMethod());
restRequest.setPathParamMap(locator.getPathVarMap());

return locator.getOperation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,40 @@
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;

import org.springframework.stereotype.Component;

import io.servicecomb.common.rest.definition.RestOperationMeta;
import io.servicecomb.common.rest.locator.ServicePathManager;
import io.servicecomb.core.BootListener;
import io.servicecomb.core.definition.MicroserviceMeta;
import io.servicecomb.core.definition.OperationMeta;
import io.servicecomb.core.definition.MicroserviceMetaManager;
import io.servicecomb.core.definition.SchemaMeta;
import io.servicecomb.core.definition.loader.SchemaListener;
import io.servicecomb.serviceregistry.RegistryUtils;

@Component
public class RestEngineSchemaListener implements SchemaListener {
private static final Logger LOGGER = LoggerFactory.getLogger(RestEngineSchemaListener.class);
public class RestEngineSchemaListener implements SchemaListener, BootListener {
private MicroserviceMetaManager microserviceMetaManager;

@Inject
public void setMicroserviceMetaManager(MicroserviceMetaManager microserviceMetaManager) {
this.microserviceMetaManager = microserviceMetaManager;
}

@Override
public void onBootEvent(BootEvent event) {
if (!event.getEventType().equals(EventType.BEFORE_REGISTRY)) {
return;
}

MicroserviceMeta microserviceMeta =
microserviceMetaManager.getOrCreateMicroserviceMeta(RegistryUtils.getMicroservice());
ServicePathManager servicePathManager = ServicePathManager.getServicePathManager(microserviceMeta);
if (servicePathManager != null) {
servicePathManager.buildProducerPaths();
}
}

@Override
public void onSchemaLoaded(SchemaMeta... schemaMetas) {
Expand All @@ -41,30 +61,12 @@ public void onSchemaLoaded(SchemaMeta... schemaMetas) {
for (SchemaMeta schemaMeta : schemaMetas) {
MicroserviceMeta microserviceMeta = schemaMeta.getMicroserviceMeta();
ServicePathManager mgr = findPathManager(mgrMap, microserviceMeta);

if (mgr.isSchemaExists(schemaMeta.getSchemaId())) {
LOGGER.info("on schema loaded, exists schema. {}:{}",
schemaMeta.getMicroserviceName(),
schemaMeta.getSchemaId());
continue;
}
LOGGER.info("on schema loaded, new schema. {}:{}",
schemaMeta.getMicroserviceName(),
schemaMeta.getSchemaId());
mgr.addSchema(schemaMeta.getSchemaId());

for (OperationMeta operationMeta : schemaMeta.getOperations()) {
RestOperationMeta restOperationMeta = new RestOperationMeta();
restOperationMeta.init(operationMeta);
operationMeta.putExtData(RestConst.SWAGGER_REST_OPERATION, restOperationMeta);
mgr.addResource(restOperationMeta);
}
mgr.addSchema(schemaMeta);
}

for (ServicePathManager mgr : mgrMap.values()) {
// 对具有动态path operation进行排序
mgr.sortPath();
mgr.printService();

mgr.saveToMicroserviceMeta();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import javax.ws.rs.core.MediaType;

import com.fasterxml.jackson.databind.JavaType;

import io.servicecomb.common.rest.codec.RestObjectMapper;

public class ProduceJsonProcessor extends AbstractProduceProcessor {
Expand All @@ -32,12 +33,12 @@ public String getName() {
}

@Override
public void encodeResponse(OutputStream output, Object result) throws Exception {
public void doEncodeResponse(OutputStream output, Object result) throws Exception {
RestObjectMapper.INSTANCE.writeValue(output, result);
}

@Override
public Object decodeResponse(InputStream input, JavaType type) throws Exception {
public Object doDecodeResponse(InputStream input, JavaType type) throws Exception {
return RestObjectMapper.INSTANCE.readValue(input, type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,52 @@
import java.io.OutputStream;

import com.fasterxml.jackson.databind.JavaType;

import io.servicecomb.foundation.vertx.stream.BufferInputStream;
import io.servicecomb.foundation.vertx.stream.BufferOutputStream;

import io.vertx.core.buffer.Buffer;

public interface ProduceProcessor {
String getName();

void encodeResponse(OutputStream output, Object result) throws Exception;
default void encodeResponse(OutputStream output, Object result) throws Exception {
if (result == null) {
return;
}

doEncodeResponse(output, result);
}

void doEncodeResponse(OutputStream output, Object result) throws Exception;

default Buffer encodeResponse(Object result) throws Exception {
if (null == result) {
return null;
}

try (BufferOutputStream output = new BufferOutputStream()) {
encodeResponse(output, result);
doEncodeResponse(output, result);
return output.getBuffer();
}
}

Object decodeResponse(InputStream input, JavaType type) throws Exception;
default Object decodeResponse(InputStream input, JavaType type) throws Exception {
if (input.available() == 0) {
return null;
}

return doDecodeResponse(input, type);
}

Object doDecodeResponse(InputStream input, JavaType type) throws Exception;

default Object decodeResponse(Buffer buffer, JavaType type) throws Exception {
if (buffer.length() == 0) {
return null;
}

try (BufferInputStream input = new BufferInputStream(buffer.getByteBuf())) {
return decodeResponse(input, type);
return doDecodeResponse(input, type);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ public String getName() {
}

@Override
public void encodeResponse(OutputStream output, Object result) throws Exception {
public void doEncodeResponse(OutputStream output, Object result) throws Exception {
output.write(String.valueOf(result).getBytes(StandardCharsets.UTF_8));
}

@Override
public Object decodeResponse(InputStream input, JavaType type) throws Exception {
public Object doDecodeResponse(InputStream input, JavaType type) throws Exception {
// plainText类型,肯定是返回string的,想不出有其他类型的场景
return IOUtils.toString(input, StandardCharsets.UTF_8);
// TODO: 该方法尚需进一步修改
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,29 @@

package io.servicecomb.common.rest.definition;

import io.servicecomb.common.rest.codec.produce.ProduceProcessor;
import io.servicecomb.common.rest.codec.produce.ProduceProcessorManager;
import io.servicecomb.common.rest.definition.path.PathRegExp;
import io.servicecomb.common.rest.definition.path.URLPathBuilder;
import io.servicecomb.core.definition.OperationMeta;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
import io.swagger.models.parameters.Parameter;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.MediaType;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.servicecomb.common.rest.codec.produce.ProduceProcessor;
import io.servicecomb.common.rest.codec.produce.ProduceProcessorManager;
import io.servicecomb.common.rest.definition.path.PathRegExp;
import io.servicecomb.common.rest.definition.path.URLPathBuilder;
import io.servicecomb.core.definition.OperationMeta;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
import io.swagger.models.parameters.Parameter;

public class RestOperationMeta {
private static final Logger LOGGER = LoggerFactory.getLogger(RestOperationMeta.class);

Expand Down Expand Up @@ -77,8 +80,6 @@ public void init(OperationMeta operationMeta) {
this.produces = swagger.getProduces();
}

setAbsolutePath(concatPath(swagger.getBasePath(), operationMeta.getOperationPath()));

this.createProduceProcessors();

Method method = operationMeta.getMethod();
Expand All @@ -96,7 +97,7 @@ public void init(OperationMeta operationMeta) {
addParam(param);
}

this.pathBuilder = new URLPathBuilder(absolutePath, paramMap);
setAbsolutePath(concatPath(swagger.getBasePath(), operationMeta.getOperationPath()));
}

public void setOperationMeta(OperationMeta operationMeta) {
Expand All @@ -105,21 +106,22 @@ public void setOperationMeta(OperationMeta operationMeta) {

// 输出b/c/形式的url
private String concatPath(String basePath, String operationPath) {
return ("/" + nonNullify(basePath) + "/" + nonNullify(operationPath) + "/")
.replaceAll("/{2,}", "/");
return ("/" + nonNullify(basePath) + "/" + nonNullify(operationPath) + "/")
.replaceAll("/{2,}", "/");
}

private String nonNullify(String path) {
private String nonNullify(String path) {
return path == null ? "" : path;
}

public String getAbsolutePath() {
public String getAbsolutePath() {
return this.absolutePath;
}

public void setAbsolutePath(String absolutePath) {
this.absolutePath = absolutePath;
this.absolutePathRegExp = createPathRegExp(absolutePath);
this.pathBuilder = new URLPathBuilder(absolutePath, paramMap);
}

public PathRegExp getAbsolutePathRegExp() {
Expand Down Expand Up @@ -262,4 +264,8 @@ private ProduceProcessor getDefaultOrFirstProcessor() {
public String getHttpMethod() {
return operationMeta.getHttpMethod();
}

public List<String> getProduces() {
return produces;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2017 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.servicecomb.common.rest.locator;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.servicecomb.common.rest.definition.RestOperationComparator;
import io.servicecomb.common.rest.definition.RestOperationMeta;
import io.servicecomb.foundation.common.exceptions.ServiceCombException;

public class MicroservicePaths {
private static final Logger LOGGER = LoggerFactory.getLogger(MicroservicePaths.class);

// 运行阶段,静态path,一次直接查找到目标,不必遍历查找
// 以path为key
protected Map<String, OperationGroup> staticPathOperations = new HashMap<>();

// 运行阶段,以path优先级,从高到低排列的operation列表
protected List<RestOperationMeta> dynamicPathOperationsList = new ArrayList<>();

public void cloneTo(MicroservicePaths other) {
other.staticPathOperations.putAll(staticPathOperations);
other.dynamicPathOperationsList.addAll(dynamicPathOperationsList);
}

public void sortPath() {
RestOperationComparator comparator = new RestOperationComparator();
Collections.sort(this.dynamicPathOperationsList, comparator);
}

public void addResource(RestOperationMeta swaggerRestOperation) {
if (swaggerRestOperation.isAbsoluteStaticPath()) {
// 静态path
addStaticPathResource(swaggerRestOperation);
return;
}

dynamicPathOperationsList.add(swaggerRestOperation);
}

protected void addStaticPathResource(RestOperationMeta operation) {
String httpMethod = operation.getHttpMethod();
String path = operation.getAbsolutePath();
OperationGroup group = staticPathOperations.get(path);
if (group == null) {
group = new OperationGroup();
group.register(httpMethod, operation);
staticPathOperations.put(path, group);
return;
}

if (group.findValue(httpMethod) == null) {
group.register(httpMethod, operation);
return;
}

throw new ServiceCombException(
String.format("operation with url %s, method %s is duplicated.", path, httpMethod));
}

public Map<String, OperationGroup> getStaticPathOperationMap() {
return staticPathOperations;
}

public List<RestOperationMeta> getDynamicPathOperationList() {
return dynamicPathOperationsList;
}

public void printPaths() {
for (Entry<String, OperationGroup> entry : staticPathOperations.entrySet()) {
OperationGroup operationGroup = entry.getValue();
printPath(operationGroup.values());
}

printPath(getDynamicPathOperationList());
}

protected void printPath(Collection<RestOperationMeta> operations) {
for (RestOperationMeta operation : operations) {
LOGGER.info("Swagger mapped \"{[{}], method=[{}], produces={}}\" onto {}",
operation.getAbsolutePath(),
operation.getHttpMethod(),
operation.getProduces(),
operation.getOperationMeta().getMethod());
}
}
}
Loading