Skip to content

Commit

Permalink
[SCB-989]scan RestController to to make springmvc controller publish …
Browse files Browse the repository at this point in the history
…as ServiceComb Rest easier
  • Loading branch information
liubao68 committed Oct 29, 2018
1 parent e35600f commit 0daff2e
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 6 deletions.
Expand Up @@ -70,4 +70,6 @@ private RestConst() {
// the size threshold after which files will be written to disk
// only available for servlet rest transport
public static final String UPLOAD_FILE_SIZE_THRESHOLD = "servicecomb.uploads.fileSizeThreshold";

public static final String PROVIDER_SCAN_REST_CONTROLLER = "servicecomb.provider.rest.scanRestController";
}
Expand Up @@ -32,6 +32,7 @@
import org.apache.servicecomb.it.testcase.TestParamCodec;
import org.apache.servicecomb.it.testcase.TestParamCodecEdge;
import org.apache.servicecomb.it.testcase.TestRequestBodySpringMvcSchema;
import org.apache.servicecomb.it.testcase.TestRestController;
import org.apache.servicecomb.it.testcase.TestRestServerConfig;
import org.apache.servicecomb.it.testcase.TestRestServerConfigEdge;
import org.apache.servicecomb.it.testcase.TestTrace;
Expand Down Expand Up @@ -132,6 +133,7 @@ private static void runShareTestCases() throws Throwable {

ITJUnitUtils.run(TestRequestBodySpringMvcSchema.class);
ITJUnitUtils.run(TestDefaultJsonValueJaxrsSchema.class);
ITJUnitUtils.run(TestRestController.class);
}

private static void testStandalone() throws Throwable {
Expand Down
Expand Up @@ -29,6 +29,8 @@ public class ITSCBRestTemplate extends CseRestTemplate {

private String schemaId;

private String basePath;

public ITSCBRestTemplate(String schemaId) {
this.schemaId = schemaId;
}
Expand All @@ -40,14 +42,19 @@ public ITSCBRestTemplate init() {
DefinitionConst.VERSION_RULE_ALL);
MicroserviceVersionMeta microserviceVersionMeta = microserviceVersionRule.getLatestMicroserviceVersion();
SchemaMeta schemaMeta = microserviceVersionMeta.getMicroserviceMeta().ensureFindSchemaMeta(schemaId);
urlPrefix = String.format("cse://%s/%s", producerName, schemaMeta.getSwagger().getBasePath());
basePath = schemaMeta.getSwagger().getBasePath();
urlPrefix = String.format("cse://%s%s", producerName, basePath);

setUriTemplateHandler(new ITUriTemplateHandler(urlPrefix));
setRequestFactory(new ITClientHttpRequestFactory());

return this;
}

public String getBasePath() {
return basePath;
}

public String getUrlPrefix() {
return urlPrefix;
}
Expand Down
@@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.servicecomb.it.testcase;

import org.apache.servicecomb.it.extend.engine.ITSCBRestTemplate;
import org.junit.Assert;
import org.junit.Test;

public class TestRestController {
private static ITSCBRestTemplate restControllerSchemaClient = new ITSCBRestTemplate
("org.apache.servicecomb.it.schema.RestControllerSchema");

private static ITSCBRestTemplate restControllerEmptyMappingSchemaClient = new ITSCBRestTemplate
("org.apache.servicecomb.it.schema.RestControllerEmptyMappingSchema");

private static ITSCBRestTemplate restControllerWithRequestMappingSchemaClient = new ITSCBRestTemplate
("org.apache.servicecomb.it.schema.RestControllerWithRequestMappingSchema");

private static ITSCBRestTemplate restControllerWithRestSchemaSchemaClient = new ITSCBRestTemplate
("RestControllerWithRestSchemaSchema");

@Test
public void restControllerSchemaClient() {
Assert.assertEquals("/", restControllerSchemaClient.getBasePath());
int result = restControllerSchemaClient.getForObject("/restControllerSchemaQuery?input=2", int.class);
Assert.assertEquals(2, result);
}

@Test
public void restControllerEmptyMappingSchemaClient() {
// empty path default to class name(@RequestMapping(path = "")). Shall we change this behavior in future?
Assert.assertEquals("/RestControllerEmptyMappingSchema", restControllerEmptyMappingSchemaClient.getBasePath());
int result = restControllerEmptyMappingSchemaClient
.getForObject("/restControllerEmptyMappingSchemaQuery?input=2", int.class);
Assert.assertEquals(2, result);
}

@Test
public void restControllerWithRequestMappingSchemaClient() {
Assert.assertEquals("/restControllerWithRequest", restControllerWithRequestMappingSchemaClient.getBasePath());
int result = restControllerWithRequestMappingSchemaClient
.getForObject("/restControllerWithRequestMappingSchemaQuery?input=2", int.class);
Assert.assertEquals(2, result);
}

@Test
public void restControllerWithRestSchemaSchemaClient() {
Assert.assertEquals("/restControllerWithRestSchemaSchema", restControllerWithRestSchemaSchemaClient.getBasePath());
int result = restControllerWithRestSchemaSchemaClient
.getForObject("/restControllerWithRestSchemaSchemaQuery?input=2", int.class);
Assert.assertEquals(2, result);
}
}
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.servicecomb.it.schema;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(path = "")
public class RestControllerEmptyMappingSchema {
@GetMapping(path = "restControllerEmptyMappingSchemaQuery")
public int intQuery(@RequestParam(name = "input", required = false, defaultValue = "13") int input) {
return input;
}
}
@@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.servicecomb.it.schema;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RestControllerSchema {
@GetMapping(path = "restControllerSchemaQuery")
public int intQuery(@RequestParam(name = "input", required = false, defaultValue = "13") int input) {
return input;
}
}
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.servicecomb.it.schema;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(path = "/restControllerWithRequest")
public class RestControllerWithRequestMappingSchema {
@GetMapping(path = "restControllerWithRequestMappingSchemaQuery")
public int intQuery(@RequestParam(name = "input", required = false, defaultValue = "13") int input) {
return input;
}
}
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.servicecomb.it.schema;

import org.apache.servicecomb.provider.rest.common.RestSchema;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RestSchema(schemaId = "RestControllerWithRestSchemaSchema")
@RequestMapping(path = "/restControllerWithRestSchemaSchema")
public class RestControllerWithRestSchemaSchema {
@GetMapping(path = "restControllerWithRestSchemaSchemaQuery")
public int intQuery(@RequestParam(name = "input", required = false, defaultValue = "13") int input) {
return input;
}
}
Expand Up @@ -19,16 +19,23 @@
import java.util.ArrayList;
import java.util.List;

import org.apache.servicecomb.common.rest.RestConst;
import org.apache.servicecomb.core.provider.producer.ProducerMeta;
import org.apache.servicecomb.foundation.common.utils.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.config.DynamicPropertyFactory;

@Component
public class RestProducers implements BeanPostProcessor {
private List<ProducerMeta> producerMetaList = new ArrayList<>();

private boolean scanRestController = DynamicPropertyFactory.getInstance()
.getBooleanProperty(RestConst.PROVIDER_SCAN_REST_CONTROLLER, true).get();

public List<ProducerMeta> getProducerMetaList() {
return producerMetaList;
}
Expand All @@ -49,15 +56,24 @@ protected void processProvider(String beanName, Object bean) {
// aop后,新的实例的父类可能是原class,也可能只是个proxy,父类不是原class
// 所以,需要先取出原class,再取标注
Class<?> beanCls = BeanUtils.getImplClassFromBean(bean);
if(beanCls == null) {
return;
if (beanCls == null) {
return;
}
RestSchema restSchema = beanCls.getAnnotation(RestSchema.class);
ProducerMeta producerMeta;
if (restSchema == null) {
return;
if (!scanRestController) {
return;
}
RestController controller = beanCls.getAnnotation(RestController.class);
if (controller == null) {
return;
}
producerMeta = new ProducerMeta(beanCls.getName(), bean, beanCls);
} else {
producerMeta = new ProducerMeta(restSchema.schemaId(), bean, beanCls);
}

ProducerMeta producerMeta = new ProducerMeta(restSchema.schemaId(), bean, beanCls);
producerMetaList.add(producerMeta);
}
}
Expand Up @@ -35,6 +35,7 @@
import org.apache.servicecomb.swagger.generator.springmvc.processor.annotation.RequestMappingMethodAnnotationProcessor;
import org.apache.servicecomb.swagger.generator.springmvc.processor.annotation.RequestParamAnnotationProcessor;
import org.apache.servicecomb.swagger.generator.springmvc.processor.annotation.RequestPartAnnotationProcessor;
import org.apache.servicecomb.swagger.generator.springmvc.processor.annotation.RestControllerClassAnnotationProcessor;
import org.apache.servicecomb.swagger.generator.springmvc.processor.parameter.SpringmvcDefaultParameterProcessor;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.DeleteMapping;
Expand All @@ -49,6 +50,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;

public class SpringmvcSwaggerGeneratorContext extends RestSwaggerGeneratorContext {
private static final int ORDER = 1000;
Expand All @@ -60,7 +62,7 @@ public int getOrder() {

@Override
public boolean canProcess(Class<?> cls) {
return ClassUtils.hasAnnotation(cls, RequestMapping.class);
return ClassUtils.hasAnnotation(cls, RequestMapping.class) || ClassUtils.hasAnnotation(cls, RestController.class);
}

@Override
Expand All @@ -78,6 +80,7 @@ protected void initClassAnnotationMgr() {
super.initClassAnnotationMgr();

classAnnotationMgr.register(RequestMapping.class, new RequestMappingClassAnnotationProcessor());
classAnnotationMgr.register(RestController.class, new RestControllerClassAnnotationProcessor());
}

@Override
Expand Down
@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.servicecomb.swagger.generator.springmvc.processor.annotation;

import org.apache.commons.lang3.StringUtils;
import org.apache.servicecomb.swagger.generator.core.ClassAnnotationProcessor;
import org.apache.servicecomb.swagger.generator.core.SwaggerGenerator;

import io.swagger.models.Swagger;

public class RestControllerClassAnnotationProcessor implements ClassAnnotationProcessor {

@Override
public void process(Object annotation, SwaggerGenerator swaggerGenerator) {
Swagger swagger = swaggerGenerator.getSwagger();
if (StringUtils.isEmpty(swagger.getBasePath())) {
swagger.setBasePath("/");
}
}
}

0 comments on commit 0daff2e

Please sign in to comment.