diff --git a/doc/architecture.jpg b/doc/architecture.jpg
deleted file mode 100644
index e85c8a5..0000000
Binary files a/doc/architecture.jpg and /dev/null differ
diff --git a/doc/lifecycle.jpg b/doc/lifecycle.jpg
deleted file mode 100644
index df0cc10..0000000
Binary files a/doc/lifecycle.jpg and /dev/null differ
diff --git a/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/HelloServiceApp.java b/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/HelloServiceApp.java
index 9379168..9c835f0 100644
--- a/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/HelloServiceApp.java
+++ b/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/HelloServiceApp.java
@@ -4,12 +4,15 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
+import io.springside.springtime.springboot.EnableSpringTime;
import io.springside.springtime.springboot.SpringTimeConfiguration;
+import springfox.documentation.swagger.web.InMemorySwaggerResourcesProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@SpringBootApplication
@Import(SpringTimeConfiguration.class)
@EnableSwagger2
+@EnableSpringTime
public class HelloServiceApp {
public static void main(String[] args) throws Exception {
SpringApplication.run(HelloServiceApp.class, args);
diff --git a/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/idl/GreetingService.java b/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/idl/GreetingService.java
index c6d114b..8c5f986 100644
--- a/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/idl/GreetingService.java
+++ b/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/idl/GreetingService.java
@@ -1,7 +1,12 @@
package io.springside.springtime.examples.helloservice.idl;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@Api("Greeting Service")
public interface GreetingService {
+
public static class HelloRequest {
public String name;
}
@@ -18,8 +23,10 @@ public static class WeatherResponse {
public String weather;
}
+ @ApiOperation(value = "hello")
public HelloResponse hello(HelloRequest helloRequest);
+ @ApiOperation(value = "weather")
public WeatherResponse weather(WeatherRequest weatherRequest);
}
diff --git a/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/service/GreetingServiceImpl.java b/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/service/GreetingServiceImpl.java
index c7417dd..9b5c03f 100644
--- a/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/service/GreetingServiceImpl.java
+++ b/examples/hello-service/src/main/java/io/springside/springtime/examples/helloservice/service/GreetingServiceImpl.java
@@ -1,13 +1,12 @@
package io.springside.springtime.examples.helloservice.service;
-import org.springframework.stereotype.Controller;
-
import io.springside.springtime.examples.helloservice.idl.GreetingService;
+import io.springside.springtime.springboot.SpringTimeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Api("greeting")
-@Controller("greeting")
+@SpringTimeService("greeting")
public class GreetingServiceImpl implements GreetingService {
@Override
diff --git a/springtime/pom.xml b/springtime/pom.xml
index b4fad97..7767ffc 100644
--- a/springtime/pom.xml
+++ b/springtime/pom.xml
@@ -48,9 +48,15 @@
io.swagger
- swagger-annotations
+ swagger-core
${swagger.version}
+
+ io.swagger
+ swagger-jaxrs
+ ${swagger.version}
+
+
io.springfox
springfox-swagger2
diff --git a/springtime/src/main/java/io/springside/springtime/jetty/SpringTimeHandler.java b/springtime/src/main/java/io/springside/springtime/jetty/SpringTimeHandler.java
index 8e4e0ab..15b3c4a 100644
--- a/springtime/src/main/java/io/springside/springtime/jetty/SpringTimeHandler.java
+++ b/springtime/src/main/java/io/springside/springtime/jetty/SpringTimeHandler.java
@@ -14,9 +14,9 @@
import io.springside.springtime.serializer.JsonSerializer;
import io.springside.springtime.serializer.Serializer;
+import io.springside.springtime.service.ServiceBeanFactory;
import io.springside.springtime.service.ServiceDispatcher;
-import io.springside.springtime.service.ServiceBeanRegistry;
-import io.swagger.annotations.Api;
+import io.springside.springtime.springboot.SpringTimeService;
/**
* Jetty的Handler.
@@ -32,13 +32,14 @@ public class SpringTimeHandler extends AbstractHandler {
private Serializer serializer = new JsonSerializer();
public SpringTimeHandler(ApplicationContext applicationContext) {
- ServiceBeanRegistry serviceRegistry = new ServiceBeanRegistry();
- Map beans = applicationContext.getBeansWithAnnotation(Api.class);
+ ServiceBeanFactory serviceBeanFactory = new ServiceBeanFactory();
+ //TODO: 检查名称重复的方法
+ Map beans = applicationContext.getBeansWithAnnotation(SpringTimeService.class);
for (Entry entry : beans.entrySet()) {
- serviceRegistry.add(RPC_PREFIX, entry.getKey(), entry.getValue());
+ serviceBeanFactory.add(RPC_PREFIX, entry.getKey(), entry.getValue());
}
- dispatcher = new ServiceDispatcher(serviceRegistry);
+ dispatcher = new ServiceDispatcher(serviceBeanFactory);
}
@Override
diff --git a/springtime/src/main/java/io/springside/springtime/service/ServiceBeanRegistry.java b/springtime/src/main/java/io/springside/springtime/service/ServiceBeanFactory.java
similarity index 98%
rename from springtime/src/main/java/io/springside/springtime/service/ServiceBeanRegistry.java
rename to springtime/src/main/java/io/springside/springtime/service/ServiceBeanFactory.java
index fcecb0d..4035945 100644
--- a/springtime/src/main/java/io/springside/springtime/service/ServiceBeanRegistry.java
+++ b/springtime/src/main/java/io/springside/springtime/service/ServiceBeanFactory.java
@@ -11,7 +11,7 @@
/**
* 保存通过cglib快速执行服务方法的MethodInvoker
*/
-public class ServiceBeanRegistry {
+public class ServiceBeanFactory {
//key: path
public Map methodInvokerMap = new HashMap();
diff --git a/springtime/src/main/java/io/springside/springtime/service/ServiceDispatcher.java b/springtime/src/main/java/io/springside/springtime/service/ServiceDispatcher.java
index 33d2204..983ba99 100644
--- a/springtime/src/main/java/io/springside/springtime/service/ServiceDispatcher.java
+++ b/springtime/src/main/java/io/springside/springtime/service/ServiceDispatcher.java
@@ -5,13 +5,13 @@
import java.io.OutputStream;
import io.springside.springtime.serializer.Serializer;
-import io.springside.springtime.service.ServiceBeanRegistry.MethodInvoker;
+import io.springside.springtime.service.ServiceBeanFactory.MethodInvoker;
public class ServiceDispatcher {
- private ServiceBeanRegistry registry;
+ private ServiceBeanFactory registry;
- public ServiceDispatcher(ServiceBeanRegistry registry) {
+ public ServiceDispatcher(ServiceBeanFactory registry) {
this.registry = registry;
}
diff --git a/springtime/src/main/java/io/springside/springtime/springboot/EnableSpringTime.java b/springtime/src/main/java/io/springside/springtime/springboot/EnableSpringTime.java
new file mode 100644
index 0000000..2e89357
--- /dev/null
+++ b/springtime/src/main/java/io/springside/springtime/springboot/EnableSpringTime.java
@@ -0,0 +1,15 @@
+package io.springside.springtime.springboot;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import org.springframework.context.annotation.Import;
+
+@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
+@Target(value = { java.lang.annotation.ElementType.TYPE })
+@Documented
+@Import({SpringTimeConfiguration.class})
+public @interface EnableSpringTime {
+
+}
diff --git a/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeConfiguration.java b/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeConfiguration.java
index b205d5c..6997f23 100644
--- a/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeConfiguration.java
+++ b/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeConfiguration.java
@@ -1,24 +1,15 @@
package io.springside.springtime.springboot;
-import static springfox.documentation.builders.PathSelectors.*;
-
-import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
-import com.google.common.base.Predicates;
-
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
+import io.springside.springtime.swagger.SpringFoxConfiguration;
@ComponentScan
@Configuration
+@Import(SpringFoxConfiguration.class)
public class SpringTimeConfiguration {
- @Bean
- public Docket swaggerSpringMvcPlugin() {
- return new Docket(DocumentationType.SWAGGER_2).groupName("business-api").select().paths(Predicates.not(regex("/manage.*"))) // and by paths
- .build();
- }
}
diff --git a/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeJettyCustomizer.java b/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeJettyCustomizer.java
index 1e58754..5d8b883 100644
--- a/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeJettyCustomizer.java
+++ b/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeJettyCustomizer.java
@@ -8,6 +8,7 @@
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.web.ServerProperties;
@@ -23,7 +24,7 @@
import io.springside.springtime.jetty.SpringTimeHandler;
/**
- * 定制化Jetty,加入Http/Http2支持,指定专门的
+ * 定制化Jetty,加入Http/Http2支持,指定专门的Handler
*/
@Component
@ConfigurationProperties(prefix = "server.jetty", ignoreUnknownFields = true)
@@ -31,7 +32,9 @@ public class SpringTimeJettyCustomizer implements EmbeddedServletContainerCustom
private ApplicationContext applicationContext;
- private Integer maxThreads = Runtime.getRuntime().availableProcessors() * 20;
+ private Integer minThreads = Math.max(8, Runtime.getRuntime().availableProcessors());
+
+ private Integer maxThreads = Math.max(200, Runtime.getRuntime().availableProcessors() * 20);
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
@@ -77,34 +80,31 @@ private void customizeHttp2Connector(Server server) {
}
private void customizeSpringTimeHanlder(Server server) {
- // add SpringTimeHandler at the beginning
+ // add SpringTimeHandler as first handler
Handler[] oldHandlers = server.getHandlers();
SpringTimeHandler springTimeHandler = new SpringTimeHandler(applicationContext);
+
HandlerList handlerList = new HandlerList();
- handlerList.addHandler(springTimeHandler);
- for (Handler handler : oldHandlers) {
- handlerList.addHandler(handler);
- }
+ handlerList.setHandlers(ArrayUtil.prependToArray(springTimeHandler, oldHandlers, Handler.class));
+
server.setHandler(handlerList);
}
-
});
}
private void customizeThreadPool(JettyEmbeddedServletContainerFactory jettyFactory) {
- QueuedThreadPool threadPool = (QueuedThreadPool) jettyFactory.getThreadPool();
- if (threadPool == null) {
- threadPool = new QueuedThreadPool();
- jettyFactory.setThreadPool(threadPool);
- }
- threadPool.setMaxThreads(maxThreads);
- threadPool.setIdleTimeout(10000);
+ QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads, minThreads, 10000);
+ jettyFactory.setThreadPool(threadPool);
}
public void setMaxThreads(Integer maxThreads) {
this.maxThreads = maxThreads;
}
+ public void setMinThreads(Integer minThreads) {
+ this.minThreads = minThreads;
+ }
+
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
diff --git a/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeService.java b/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeService.java
new file mode 100644
index 0000000..43fe6cb
--- /dev/null
+++ b/springtime/src/main/java/io/springside/springtime/springboot/SpringTimeService.java
@@ -0,0 +1,23 @@
+package io.springside.springtime.springboot;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.stereotype.Component;
+
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Component
+public @interface SpringTimeService {
+ /**
+ * The value may indicate a suggestion for a logical component name,
+ * to be turned into a Spring bean in case of an autodetected component.
+ * @return the suggested component name, if any
+ */
+ String value() default "";
+
+}
diff --git a/springtime/src/main/java/io/springside/springtime/swagger/SpringFoxConfiguration.java b/springtime/src/main/java/io/springside/springtime/swagger/SpringFoxConfiguration.java
new file mode 100644
index 0000000..e6b301e
--- /dev/null
+++ b/springtime/src/main/java/io/springside/springtime/swagger/SpringFoxConfiguration.java
@@ -0,0 +1,24 @@
+package io.springside.springtime.swagger;
+
+import static springfox.documentation.builders.PathSelectors.*;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+import com.google.common.base.Predicates;
+
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+
+@ComponentScan
+@Configuration
+public class SpringFoxConfiguration {
+
+ //TODO: manage路径从Spring里读
+ @Bean
+ public Docket swaggerSpringMvcPlugin() {
+ return new Docket(DocumentationType.SWAGGER_2).groupName("restful-api").select()
+ .paths(Predicates.not(regex("/manage.*"))).build();
+ }
+}
diff --git a/springtime/src/main/java/io/springside/springtime/swagger/SpringTimeSwaggerDocsController.java b/springtime/src/main/java/io/springside/springtime/swagger/SpringTimeSwaggerDocsController.java
new file mode 100644
index 0000000..f1cd243
--- /dev/null
+++ b/springtime/src/main/java/io/springside/springtime/swagger/SpringTimeSwaggerDocsController.java
@@ -0,0 +1,62 @@
+package io.springside.springtime.swagger;
+
+import static org.springframework.http.MediaType.*;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.springside.springtime.springboot.SpringTimeService;
+import io.swagger.jaxrs.Reader;
+import io.swagger.jaxrs.config.ReaderConfigUtils;
+import io.swagger.models.Info;
+import io.swagger.models.Swagger;
+import springfox.documentation.annotations.ApiIgnore;
+
+@RestController
+@ApiIgnore
+public class SpringTimeSwaggerDocsController implements InitializingBean, ApplicationContextAware {
+ private Swagger swagger;
+
+ private ApplicationContext applicationContext;
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ swagger = new Swagger();
+ Info info = new Info();
+ info.setTitle("GreetingService");
+ swagger.setInfo(info);
+
+ Map beans = applicationContext.getBeansWithAnnotation(SpringTimeService.class);
+ Set> classes = new HashSet>();
+ for (Object bean : beans.values()) {
+ classes.add(bean.getClass());
+ }
+
+ Reader reader = new Reader(swagger, ReaderConfigUtils.getReaderConfig(null));
+ swagger = reader.read(classes);
+ }
+
+ @RequestMapping(value = "/v2/rfc-api-docs", method = RequestMethod.GET, produces = { APPLICATION_JSON_VALUE })
+ public @ResponseBody Swagger getDocumentation(HttpServletRequest servletRequest) {
+ return swagger;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+
+ }
+
+}
diff --git a/springtime/src/main/java/io/springside/springtime/swagger/SpringTimeSwaggerProvider.java b/springtime/src/main/java/io/springside/springtime/swagger/SpringTimeSwaggerProvider.java
new file mode 100644
index 0000000..2d63313
--- /dev/null
+++ b/springtime/src/main/java/io/springside/springtime/swagger/SpringTimeSwaggerProvider.java
@@ -0,0 +1,30 @@
+package io.springside.springtime.swagger;
+
+import java.util.List;
+
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+import springfox.documentation.spring.web.DocumentationCache;
+import springfox.documentation.swagger.web.InMemorySwaggerResourcesProvider;
+import springfox.documentation.swagger.web.SwaggerResource;
+
+@Component
+@Primary
+public class SpringTimeSwaggerProvider extends InMemorySwaggerResourcesProvider {
+
+ public SpringTimeSwaggerProvider(DocumentationCache documentationCache) {
+ super(documentationCache);
+ }
+
+ @Override
+ public List get() {
+ List resources = super.get();
+ SwaggerResource springTimeResource = new SwaggerResource();
+ springTimeResource.setName("SpringTime");
+ springTimeResource.setLocation("/v2/rfc-api-docs");
+ resources.add(0, springTimeResource);
+ return resources;
+ }
+
+}