├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── io
│ │ └── vertx
│ │ └── ext
│ │ └── spring
│ │ ├── ContextFactory.java
│ │ ├── VertxSpring.java
│ │ ├── annotation
│ │ ├── RouterHandler.java
│ │ └── VertxRouter.java
│ │ └── impl
│ │ ├── NamespaceHandler.java
│ │ ├── SpringHttpVerticle.java
│ │ ├── VertxHolder.java
│ │ ├── factory
│ │ ├── HttpClientFactory.java
│ │ ├── JdbcClientFactory.java
│ │ ├── RedisClientFactory.java
│ │ ├── RouterFactory.java
│ │ └── VertxFactory.java
│ │ └── parser
│ │ ├── HttpClientParser.java
│ │ ├── JdbcParser.java
│ │ ├── RedisClientParser.java
│ │ ├── RouterParser.java
│ │ └── VertxParser.java
└── resources
│ ├── META-INF
│ ├── spring.handlers
│ └── spring.schemas
│ └── vertx-spring-web.xsd
└── test
├── java
└── io
│ └── vertx
│ └── ext
│ └── spring
│ ├── InMemoryCache.java
│ ├── MultiVerticleServer.java
│ ├── SimpleTest.java
│ └── TestRouter.java
└── resources
└── test-context.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | /*
2 | !/src
3 | !.gitignore
4 | !pom.xml
5 | !README.md
6 | /target/**/*.*
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vertx-spring-web
2 |
3 | ## Overview
4 |
5 | `vertx-spring-web` is a vertx module. The goal of `vertx-spring-web` is to integrate vertx-web and spring framework together.
6 |
7 | ### Features
8 |
9 | 1. Annotation-driven web router handlers
10 | 1. Full support for non-blocking I/O model with vertx
11 | 1. Full support for spring IOC
12 | 1. Auto inject frequently-used vertx components (Vertx instance, RedisClient, JDBCClient etc) with spring beanFactory
13 |
14 | ## Documentation
15 |
16 | English | [中文](https://github.com/guoyu511/vertx-spring-web/wiki/%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C)
17 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 |
6 | io.vertx
7 | vertx-parent
8 | 5
9 |
10 |
11 | vertx-spring-web
12 | jar
13 | 0.0.1
14 | Spring integrate with vertx-web
15 |
16 |
17 | 3.4.2
18 | 4.11
19 | 4.1.0.RELEASE
20 |
21 |
22 |
23 |
24 |
25 | io.vertx
26 | vertx-dependencies
27 | ${stack.version}
28 | pom
29 | import
30 |
31 |
32 |
33 |
34 |
35 |
36 | io.vertx
37 | vertx-core
38 |
39 |
40 | io.vertx
41 | vertx-web
42 |
43 |
44 | io.vertx
45 | vertx-jdbc-client
46 | provided
47 |
48 |
49 | io.vertx
50 | vertx-redis-client
51 | provided
52 |
53 |
54 | org.springframework
55 | spring-core
56 | ${spring.version}
57 |
58 |
59 | org.springframework
60 | spring-context
61 | ${spring.version}
62 |
63 |
64 | io.vertx
65 | vertx-core
66 | test-jar
67 | test
68 |
69 |
70 | junit
71 | junit
72 | ${junit.version}
73 | test
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/ContextFactory.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring;
2 |
3 | import org.springframework.context.ApplicationContext;
4 |
5 | /**
6 | * Created by guoyu on 16/6/27.
7 | */
8 | public interface ContextFactory {
9 |
10 | ApplicationContext create();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/VertxSpring.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring;
2 |
3 | import org.springframework.context.support.ClassPathXmlApplicationContext;
4 |
5 | import io.vertx.core.AsyncResult;
6 | import io.vertx.core.Handler;
7 | import io.vertx.core.Vertx;
8 | import io.vertx.core.http.HttpServerOptions;
9 | import io.vertx.ext.spring.impl.SpringHttpVerticle;
10 |
11 |
12 | public interface VertxSpring {
13 |
14 | static void deploy(Vertx vertx, String configurationFile, HttpServerOptions options) {
15 | deploy(vertx, () -> new ClassPathXmlApplicationContext(configurationFile), options);
16 | }
17 |
18 | static void deploy(Vertx vertx, String configurationFile, HttpServerOptions options, Handler> handler) {
19 | deploy(vertx, () -> new ClassPathXmlApplicationContext(configurationFile), options, handler);
20 | }
21 |
22 | static void deploy(Vertx vertx, ContextFactory factory, HttpServerOptions options) {
23 | deploy(vertx, factory, options, (ar) -> {
24 | });
25 | }
26 |
27 | static void deploy(Vertx vertx, ContextFactory factory, HttpServerOptions options, Handler> handler) {
28 | vertx.deployVerticle(new SpringHttpVerticle(factory, options), handler);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/annotation/RouterHandler.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.annotation;
2 |
3 |
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | import io.vertx.core.http.HttpMethod;
10 |
11 | @Target(ElementType.METHOD)
12 | @Retention(RetentionPolicy.RUNTIME)
13 | public @interface RouterHandler {
14 |
15 | HttpMethod method() default HttpMethod.GET;
16 |
17 | String value();
18 |
19 | boolean worker() default false;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/annotation/VertxRouter.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.annotation;
2 |
3 |
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Target(ElementType.TYPE)
10 | @Retention(RetentionPolicy.RUNTIME)
11 | public @interface VertxRouter {
12 |
13 | String value() default "";
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/NamespaceHandler.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl;
2 |
3 | import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
4 |
5 | import io.vertx.ext.spring.impl.parser.HttpClientParser;
6 | import io.vertx.ext.spring.impl.parser.JdbcParser;
7 | import io.vertx.ext.spring.impl.parser.RedisClientParser;
8 | import io.vertx.ext.spring.impl.parser.RouterParser;
9 | import io.vertx.ext.spring.impl.parser.VertxParser;
10 |
11 | public class NamespaceHandler extends NamespaceHandlerSupport {
12 |
13 | @Override
14 | public void init() {
15 | registerBeanDefinitionParser("vertx", new VertxParser());
16 | registerBeanDefinitionParser("router", new RouterParser());
17 | registerBeanDefinitionParser("http-client", new HttpClientParser());
18 | registerBeanDefinitionParser("jdbc", new JdbcParser());
19 | registerBeanDefinitionParser("redis", new RedisClientParser());
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/SpringHttpVerticle.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl;
2 |
3 | import org.springframework.context.ApplicationContext;
4 |
5 | import io.vertx.core.AbstractVerticle;
6 | import io.vertx.core.Future;
7 | import io.vertx.core.http.HttpServerOptions;
8 | import io.vertx.ext.spring.ContextFactory;
9 | import io.vertx.ext.web.Router;
10 |
11 | /**
12 | * Created by guoyu on 16/6/23.
13 | */
14 | public class SpringHttpVerticle extends AbstractVerticle {
15 |
16 | private ContextFactory factory;
17 |
18 | private ApplicationContext applicationContext;
19 |
20 | private HttpServerOptions options;
21 |
22 | public SpringHttpVerticle(ContextFactory factory, HttpServerOptions options) {
23 | this.factory = factory;
24 | this.options = options;
25 | }
26 |
27 | @Override
28 | public void start(Future startFuture) throws Exception {
29 | vertx.executeBlocking((f) -> {
30 | try {
31 | VertxHolder.set(getVertx());
32 | applicationContext = factory.create();
33 | f.complete(applicationContext);
34 | } catch (Exception e) {
35 | f.fail(e);
36 | }
37 | }, (ar) -> {
38 | if (ar.failed()) {
39 | startFuture.fail(ar.cause());
40 | } else {
41 | Router router = applicationContext.getBean(Router.class);
42 | vertx.createHttpServer(options)
43 | .requestHandler(router::accept)
44 | .listen();
45 | startFuture.complete(null);
46 | }
47 | });
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/VertxHolder.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl;
2 |
3 | import io.vertx.core.Vertx;
4 |
5 |
6 | public class VertxHolder {
7 |
8 | private static ThreadLocal threadLocal = new ThreadLocal<>();
9 |
10 | public static Vertx get() {
11 | return threadLocal.get();
12 | }
13 |
14 | public static void set(Vertx vertx) {
15 | threadLocal.set(vertx);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/factory/HttpClientFactory.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.factory;
2 |
3 | import org.springframework.beans.factory.FactoryBean;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 |
6 | import io.vertx.core.Vertx;
7 | import io.vertx.core.http.HttpClient;
8 | import io.vertx.core.http.HttpClientOptions;
9 |
10 | public class HttpClientFactory implements FactoryBean {
11 |
12 | @Autowired
13 | Vertx vertx;
14 |
15 | private boolean keepAlive;
16 |
17 | private int maxPoolSize;
18 |
19 | private boolean pipelining;
20 |
21 | public void setKeepAlive(boolean keepAlive) {
22 | this.keepAlive = keepAlive;
23 | }
24 |
25 | public void setMaxPoolSize(int maxPoolSize) {
26 | this.maxPoolSize = maxPoolSize;
27 | }
28 |
29 | public void setPipelining(boolean pipelining) {
30 | this.pipelining = pipelining;
31 | }
32 |
33 | @Override
34 | public HttpClient getObject() throws Exception {
35 |
36 | return vertx.createHttpClient(new HttpClientOptions()
37 | .setUsePooledBuffers(true)
38 | .setKeepAlive(keepAlive)
39 | .setMaxPoolSize(maxPoolSize)
40 | .setPipelining(pipelining));
41 | }
42 |
43 | @Override
44 | public Class> getObjectType() {
45 | return HttpClient.class;
46 | }
47 |
48 | @Override
49 | public boolean isSingleton() {
50 | return true;
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/factory/JdbcClientFactory.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.factory;
2 |
3 | import org.springframework.beans.BeansException;
4 | import org.springframework.beans.InvalidPropertyException;
5 | import org.springframework.beans.factory.FactoryBean;
6 | import org.springframework.beans.factory.InitializingBean;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.context.ApplicationContext;
9 | import org.springframework.context.ApplicationContextAware;
10 |
11 | import javax.sql.DataSource;
12 |
13 | import io.vertx.core.Vertx;
14 | import io.vertx.ext.jdbc.JDBCClient;
15 |
16 | public class JdbcClientFactory implements InitializingBean, ApplicationContextAware, FactoryBean {
17 |
18 | @Autowired
19 | Vertx vertx;
20 |
21 | private String dataSourceRef;
22 |
23 | private DataSource dataSource;
24 |
25 | private ApplicationContext applicationContext;
26 |
27 | public void setDataSourceRef(String dataSourceRef) {
28 | this.dataSourceRef = dataSourceRef;
29 | }
30 |
31 | @Override
32 | public JDBCClient getObject() throws Exception {
33 | return JDBCClient.create(vertx, dataSource);
34 | }
35 |
36 | @Override
37 | public Class> getObjectType() {
38 | return JDBCClient.class;
39 | }
40 |
41 | @Override
42 | public boolean isSingleton() {
43 | return true;
44 | }
45 |
46 | @Override
47 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
48 | this.applicationContext = applicationContext;
49 | }
50 |
51 | @Override
52 | public void afterPropertiesSet() throws Exception {
53 | Object bean = applicationContext.getBean(dataSourceRef);
54 | if (!DataSource.class.isInstance(bean)) {
55 | throw new InvalidPropertyException(DataSource.class, "data-source-ref", "Invalid DataSource");
56 | }
57 | dataSource = (DataSource) bean;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/factory/RedisClientFactory.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.factory;
2 |
3 | import org.springframework.beans.factory.FactoryBean;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 |
6 | import io.vertx.core.Vertx;
7 | import io.vertx.redis.RedisClient;
8 | import io.vertx.redis.RedisOptions;
9 |
10 | public class RedisClientFactory implements FactoryBean {
11 |
12 | @Autowired
13 | Vertx vertx;
14 |
15 | private String host;
16 |
17 | private int port;
18 |
19 | public void setHost(String host) {
20 | this.host = host;
21 | }
22 |
23 | public void setPort(int port) {
24 | this.port = port;
25 | }
26 |
27 | @Override
28 | public RedisClient getObject() throws Exception {
29 | return RedisClient.create(vertx, new RedisOptions()
30 | .setHost(host)
31 | .setPort(port)
32 | .setTcpKeepAlive(true)
33 | .setTcpNoDelay(true));
34 | }
35 |
36 | @Override
37 | public Class> getObjectType() {
38 | return RedisClient.class;
39 | }
40 |
41 | @Override
42 | public boolean isSingleton() {
43 | return true;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/factory/RouterFactory.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.factory;
2 |
3 | import org.springframework.beans.BeansException;
4 | import org.springframework.beans.factory.FactoryBean;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.context.ApplicationContext;
7 | import org.springframework.context.ApplicationContextAware;
8 |
9 | import java.lang.reflect.Method;
10 | import java.util.Map;
11 |
12 | import io.vertx.core.Handler;
13 | import io.vertx.core.Vertx;
14 | import io.vertx.core.http.HttpMethod;
15 | import io.vertx.core.logging.Logger;
16 | import io.vertx.core.logging.LoggerFactory;
17 | import io.vertx.ext.spring.annotation.RouterHandler;
18 | import io.vertx.ext.spring.annotation.VertxRouter;
19 | import io.vertx.ext.web.Router;
20 | import io.vertx.ext.web.RoutingContext;
21 | import io.vertx.ext.web.handler.BodyHandler;
22 |
23 | public class RouterFactory implements ApplicationContextAware, FactoryBean {
24 |
25 | private static Logger logger = LoggerFactory.getLogger(RouterFactory.class);
26 |
27 | @Autowired
28 | Vertx vertx;
29 |
30 | private ApplicationContext applicationContext;
31 |
32 | @Override
33 | public Router getObject() throws Exception {
34 | Router router = Router.router(vertx);
35 | Map handlers = applicationContext.getBeansWithAnnotation(
36 | VertxRouter.class);
37 | handlers.values().forEach((handler) -> registerHandlers(router, handler));
38 | return router;
39 | }
40 |
41 | @Override
42 | public Class> getObjectType() {
43 | return Router.class;
44 | }
45 |
46 | @Override
47 | public boolean isSingleton() {
48 | return true;
49 | }
50 |
51 | @Override
52 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
53 | this.applicationContext = applicationContext;
54 | }
55 |
56 | private static void registerHandlers(Router router, Object handler) {
57 | VertxRouter controller = handler.getClass().getAnnotation(VertxRouter.class);
58 | for (Method method : handler.getClass().getMethods()) {
59 | RouterHandler mapping = method.getAnnotation(RouterHandler.class);
60 | if (mapping != null) {
61 | if (method.getParameterTypes().length == 1 &&
62 | method.getParameterTypes()[0].equals(RoutingContext.class)) {
63 | registerMethod(router, handler, method, controller, mapping);
64 | } else {
65 | throw new UnsupportedOperationException(
66 | "Handler method " +
67 | handler.getClass().getSimpleName() + "." + method.getName() +
68 | "should only be declared with 1 parameter " +
69 | RoutingContext.class);
70 | }
71 | }
72 | }
73 | }
74 |
75 | private static void registerMethod(Router router,
76 | Object handler, Method method,
77 | VertxRouter controller, RouterHandler mapping) {
78 | if (mapping.method() == HttpMethod.POST || mapping.method() == HttpMethod.PUT) {
79 | router.route(mapping.method(), controller.value() + mapping.value())
80 | .handler(BodyHandler.create());
81 | }
82 | if (mapping.worker()) {
83 | router.route(mapping.method(), controller.value() + mapping.value())
84 | .blockingHandler(new RouterHandlerImpl(handler, method, mapping.method()))
85 | .failureHandler((ctx) -> {
86 | logger.error(ctx.failure());
87 | ctx.response()
88 | .setStatusCode(500)
89 | .setStatusMessage(ctx.failure().getMessage());
90 | });
91 | } else {
92 | router.route(mapping.method(), controller.value() + mapping.value())
93 | .handler(new RouterHandlerImpl(handler, method, mapping.method()))
94 | .failureHandler((ctx) -> {
95 | logger.error(ctx.failure());
96 | ctx.response()
97 | .setStatusCode(500)
98 | .setStatusMessage(ctx.failure().getMessage());
99 | });
100 | }
101 | logger.info("Register handler " +
102 | mapping.method() + " " +
103 | controller.value() + mapping.value() +
104 | " on " +
105 | handler.getClass().getSimpleName() +
106 | "." +
107 | method.getName());
108 | }
109 |
110 | private static class RouterHandlerImpl implements Handler {
111 |
112 | Object handler;
113 |
114 | Method method;
115 |
116 | HttpMethod httpMethod;
117 |
118 | RouterHandlerImpl(Object handler, Method method, HttpMethod httpMethod) {
119 | this.handler = handler;
120 | this.method = method;
121 | this.httpMethod = httpMethod;
122 | }
123 |
124 | @Override
125 | public void handle(RoutingContext context) {
126 | logger.debug(context.request().method().toString() + " " + context.request().uri());
127 | try {
128 | method.invoke(handler, context);
129 | } catch (Throwable e) {
130 | context.fail(e);
131 | }
132 | }
133 | }
134 |
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/factory/VertxFactory.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.factory;
2 |
3 | import org.springframework.beans.factory.FactoryBean;
4 |
5 | import io.vertx.core.Vertx;
6 | import io.vertx.ext.spring.impl.VertxHolder;
7 |
8 | /**
9 | * Created by guoyu on 16/6/28.
10 | */
11 | public class VertxFactory implements FactoryBean {
12 |
13 | @Override
14 | public Vertx getObject() throws Exception {
15 | return VertxHolder.get();
16 | }
17 |
18 | @Override
19 | public Class> getObjectType() {
20 | return Vertx.class;
21 | }
22 |
23 | @Override
24 | public boolean isSingleton() {
25 | return true;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/parser/HttpClientParser.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.parser;
2 |
3 | import org.springframework.beans.MutablePropertyValues;
4 | import org.springframework.beans.factory.config.BeanDefinition;
5 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
6 | import org.springframework.beans.factory.support.GenericBeanDefinition;
7 | import org.springframework.beans.factory.xml.BeanDefinitionParser;
8 | import org.springframework.beans.factory.xml.ParserContext;
9 | import org.w3c.dom.Element;
10 |
11 | import io.vertx.ext.spring.impl.factory.HttpClientFactory;
12 |
13 | /**
14 | * Created by guoyu on 16/3/14.
15 | */
16 | public class HttpClientParser implements BeanDefinitionParser {
17 |
18 | @Override
19 | public BeanDefinition parse(Element element, ParserContext parserContext) {
20 | BeanDefinitionRegistry registry = parserContext.getRegistry();
21 | GenericBeanDefinition def = new GenericBeanDefinition();
22 | MutablePropertyValues prop = new MutablePropertyValues();
23 | def.setBeanClass(HttpClientFactory.class);
24 | prop.addPropertyValue("keepAlive", element.getAttribute("keep-alive"));
25 | prop.addPropertyValue("maxPoolSize", element.getAttribute("max-pool-size"));
26 | prop.addPropertyValue("pipelining", element.getAttribute("pipelining"));
27 | def.setPropertyValues(prop);
28 | registry.registerBeanDefinition("httpClient", def);
29 | return def;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/parser/JdbcParser.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.parser;
2 |
3 | import org.springframework.beans.MutablePropertyValues;
4 | import org.springframework.beans.factory.config.BeanDefinition;
5 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
6 | import org.springframework.beans.factory.support.GenericBeanDefinition;
7 | import org.springframework.beans.factory.xml.BeanDefinitionParser;
8 | import org.springframework.beans.factory.xml.ParserContext;
9 | import org.w3c.dom.Element;
10 |
11 | import io.vertx.ext.spring.impl.factory.JdbcClientFactory;
12 |
13 | /**
14 | * Created by guoyu on 16/3/14.
15 | */
16 | public class JdbcParser implements BeanDefinitionParser {
17 |
18 | @Override
19 | public BeanDefinition parse(Element element, ParserContext parserContext) {
20 | BeanDefinitionRegistry registry = parserContext.getRegistry();
21 | GenericBeanDefinition def = new GenericBeanDefinition();
22 | MutablePropertyValues prop = new MutablePropertyValues();
23 | def.setBeanClass(JdbcClientFactory.class);
24 | String id = element.getAttribute("id");
25 | prop.addPropertyValue("dataSourceRef", element.getAttribute("data-source-ref"));
26 | def.setPropertyValues(prop);
27 | registry.registerBeanDefinition(id, def);
28 | return def;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/parser/RedisClientParser.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.parser;
2 |
3 | import org.springframework.beans.MutablePropertyValues;
4 | import org.springframework.beans.factory.config.BeanDefinition;
5 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
6 | import org.springframework.beans.factory.support.GenericBeanDefinition;
7 | import org.springframework.beans.factory.xml.BeanDefinitionParser;
8 | import org.springframework.beans.factory.xml.ParserContext;
9 | import org.w3c.dom.Element;
10 |
11 | import io.vertx.ext.spring.impl.factory.RedisClientFactory;
12 |
13 | /**
14 | * Created by guoyu on 16/3/14.
15 | */
16 | public class RedisClientParser implements BeanDefinitionParser {
17 |
18 | @Override
19 | public BeanDefinition parse(Element element, ParserContext parserContext) {
20 | BeanDefinitionRegistry registry = parserContext.getRegistry();
21 | GenericBeanDefinition def = new GenericBeanDefinition();
22 | MutablePropertyValues prop = new MutablePropertyValues();
23 | def.setBeanClass(RedisClientFactory.class);
24 | String id = element.getAttribute("id");
25 | prop.addPropertyValue("host", element.getAttribute("host"));
26 | prop.addPropertyValue("port", element.getAttribute("port"));
27 | def.setPropertyValues(prop);
28 | registry.registerBeanDefinition(id, def);
29 | return def;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/parser/RouterParser.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.parser;
2 |
3 | import org.springframework.beans.factory.config.BeanDefinition;
4 | import org.springframework.beans.factory.support.BeanDefinitionDefaults;
5 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
6 | import org.springframework.beans.factory.support.GenericBeanDefinition;
7 | import org.springframework.beans.factory.xml.BeanDefinitionParser;
8 | import org.springframework.beans.factory.xml.ParserContext;
9 | import org.springframework.context.ConfigurableApplicationContext;
10 | import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
11 | import org.springframework.core.type.filter.AnnotationTypeFilter;
12 | import org.springframework.util.StringUtils;
13 | import org.w3c.dom.Element;
14 |
15 | import io.vertx.ext.spring.annotation.VertxRouter;
16 | import io.vertx.ext.spring.impl.factory.RouterFactory;
17 |
18 | /**
19 | * Created by guoyu on 16/3/14.
20 | */
21 | public class RouterParser implements BeanDefinitionParser {
22 |
23 | @Override
24 | public BeanDefinition parse(Element element, ParserContext parserContext) {
25 | BeanDefinitionRegistry registry = parserContext.getRegistry();
26 | ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(parserContext.getRegistry(), false);
27 | BeanDefinitionDefaults defaults = new BeanDefinitionDefaults();
28 | defaults.setLazyInit(true);
29 | scanner.setBeanDefinitionDefaults(defaults);
30 | String basePackage = element.getAttribute("base-package");
31 | scanner.addIncludeFilter(new AnnotationTypeFilter(VertxRouter.class));
32 | scanner.scan(StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
33 | GenericBeanDefinition def = new GenericBeanDefinition();
34 | def.setBeanClass(RouterFactory.class);
35 | registry.registerBeanDefinition("vertx-spring-web-router", def);
36 | return def;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/io/vertx/ext/spring/impl/parser/VertxParser.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring.impl.parser;
2 |
3 | import org.springframework.beans.factory.config.BeanDefinition;
4 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
5 | import org.springframework.beans.factory.support.GenericBeanDefinition;
6 | import org.springframework.beans.factory.xml.BeanDefinitionParser;
7 | import org.springframework.beans.factory.xml.ParserContext;
8 | import org.w3c.dom.Element;
9 |
10 | import io.vertx.ext.spring.impl.factory.VertxFactory;
11 |
12 | /**
13 | * Created by guoyu on 16/6/28.
14 | */
15 | public class VertxParser implements BeanDefinitionParser {
16 |
17 | @Override
18 | public BeanDefinition parse(Element element, ParserContext parserContext) {
19 | BeanDefinitionRegistry registry = parserContext.getRegistry();
20 | GenericBeanDefinition def = new GenericBeanDefinition();
21 | def.setBeanClass(VertxFactory.class);
22 | registry.registerBeanDefinition("vertx", def);
23 | return def;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/spring.handlers:
--------------------------------------------------------------------------------
1 | http\://www.vertx.io/schema/vertx-spring-web=io.vertx.ext.spring.impl.NamespaceHandler
--------------------------------------------------------------------------------
/src/main/resources/META-INF/spring.schemas:
--------------------------------------------------------------------------------
1 | http\://www.vertx.io/schema/vertx-spring-web.xsd=vertx-spring-web.xsd
--------------------------------------------------------------------------------
/src/main/resources/vertx-spring-web.xsd:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/test/java/io/vertx/ext/spring/InMemoryCache.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | import java.util.HashMap;
6 |
7 | @Component
8 | public class InMemoryCache {
9 |
10 | // shared by verticles
11 | private static HashMap testMap = new HashMap<>();
12 |
13 | String get(String key) {
14 | return testMap.getOrDefault(key, "");
15 | }
16 |
17 | String set(String key, String value) {
18 | testMap.put(key, value);
19 | return value;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/test/java/io/vertx/ext/spring/MultiVerticleServer.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring;
2 |
3 | import java.util.Arrays;
4 |
5 | import io.vertx.core.CompositeFuture;
6 | import io.vertx.core.Future;
7 | import io.vertx.core.Vertx;
8 | import io.vertx.core.http.HttpServerOptions;
9 |
10 | /**
11 | * Created by guoyu on 16/6/23.
12 | */
13 | public class MultiVerticleServer {
14 |
15 | public static void main(String[] args) {
16 | Vertx vertx = Vertx.vertx();
17 | CompositeFuture.all(
18 | Arrays.asList(
19 | deploy(vertx),
20 | deploy(vertx),
21 | deploy(vertx),
22 | deploy(vertx))
23 | ).setHandler((res) -> {
24 | if (res.failed()) {
25 | res.cause().printStackTrace();
26 | }
27 | });
28 | }
29 |
30 | private static Future deploy(Vertx vertx) {
31 | Future future = Future.future();
32 | VertxSpring.deploy(vertx,
33 | "test-context.xml",
34 | new HttpServerOptions()
35 | .setPort(8080),
36 | future.completer());
37 | return future;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/test/java/io/vertx/ext/spring/SimpleTest.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring;
2 |
3 | import org.junit.Test;
4 |
5 | import io.vertx.core.AsyncResult;
6 | import io.vertx.core.Future;
7 | import io.vertx.core.Handler;
8 | import io.vertx.core.Vertx;
9 | import io.vertx.core.http.HttpClient;
10 | import io.vertx.core.http.HttpServerOptions;
11 | import io.vertx.test.core.AsyncTestBase;
12 |
13 | public class SimpleTest extends AsyncTestBase {
14 |
15 | private Vertx vertx = Vertx.vertx();
16 |
17 | private HttpClient client;
18 |
19 | @Test
20 | public void testServer() {
21 | vertx = Vertx.vertx();
22 | client = vertx.createHttpClient();
23 | VertxSpring.deploy(vertx,
24 | "test-context.xml",
25 | new HttpServerOptions()
26 | .setPort(8080),
27 | (deployRes) -> {
28 | if (deployRes.failed()) {
29 | deployRes.cause().printStackTrace();
30 | assertTrue(deployRes.succeeded());
31 | return;
32 | }
33 | testAll((testRes) ->
34 | vertx.undeploy(deployRes.result(), (undeployRes) -> {
35 | testComplete();
36 | })
37 | );
38 | });
39 | await();
40 | }
41 |
42 | private void testAll(Handler> handler) {
43 | testPut("a", "1", (ar) ->
44 | testGet("a", "1", handler)
45 |
46 | );
47 | }
48 |
49 | private void testPut(String key, String value, Handler> handler) {
50 | client.put(8080, "127.0.0.1", "/test?key=" + key + "&value=" + value, (response) -> {
51 | if (response.statusCode() != 200) {
52 | handler.handle(Future.failedFuture(response.statusMessage()));
53 | return;
54 | }
55 | response
56 | .exceptionHandler((e) ->
57 | handler.handle(Future.failedFuture(e))
58 | )
59 | .bodyHandler((buff) ->
60 | handler.handle(Future.succeededFuture())
61 | );
62 | }).end();
63 | }
64 |
65 | private void testGet(String key, String value, Handler> handler) {
66 | client.getNow(8080, "127.0.0.1", "/test?key=" + key, (response) -> {
67 | if (response.statusCode() != 200) {
68 | handler.handle(Future.failedFuture(response.statusMessage()));
69 | return;
70 | }
71 | response
72 | .exceptionHandler((e) ->
73 | handler.handle(Future.failedFuture(e))
74 | )
75 | .bodyHandler((buff) -> {
76 | assertEquals(value, buff.toString());
77 | handler.handle(Future.succeededFuture());
78 | });
79 | });
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/test/java/io/vertx/ext/spring/TestRouter.java:
--------------------------------------------------------------------------------
1 | package io.vertx.ext.spring;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.beans.factory.annotation.Qualifier;
5 |
6 | import java.util.HashMap;
7 | import java.util.Optional;
8 |
9 | import io.vertx.core.http.HttpMethod;
10 | import io.vertx.ext.spring.annotation.RouterHandler;
11 | import io.vertx.ext.spring.annotation.VertxRouter;
12 | import io.vertx.ext.web.RoutingContext;
13 | import io.vertx.redis.RedisClient;
14 |
15 | @VertxRouter
16 | public class TestRouter {
17 |
18 | @Autowired
19 | @Qualifier("testRedis")
20 | RedisClient redis;
21 |
22 | @Autowired InMemoryCache testCache;
23 |
24 | @RouterHandler(method = HttpMethod.GET, value = "/test")
25 | public void testGet(RoutingContext context) {
26 | String key = context.request().params().get("key");
27 | context.response()
28 | .end(testCache.get(key));
29 | }
30 |
31 | @RouterHandler(method = HttpMethod.PUT, value = "/test")
32 | public void testSet(RoutingContext context) {
33 | String key = context.request().params().get("key");
34 | String value = context.request().params().get("value");
35 | testCache.set(key, value);
36 | context.response().end(value);
37 | }
38 |
39 | @RouterHandler(method = HttpMethod.GET, value = "/redis")
40 | public void testRedisGet(RoutingContext context) {
41 | String key = context.request().params().get("key");
42 | redis.get(key, (res) -> {
43 | if (res.failed()) {
44 | context.response()
45 | .setStatusCode(500)
46 | .end(res.cause().getMessage());
47 | return;
48 | }
49 | context.response()
50 | .end(Optional.ofNullable(res.result()).orElse(""));
51 | });
52 | }
53 |
54 | @RouterHandler(method = HttpMethod.PUT, value = "/redis")
55 | public void testRedisSet(RoutingContext context) {
56 | String key = context.request().params().get("key");
57 | String value = context.request().params().get("value");
58 | redis.set(key, value, (res) -> {
59 | if (res.failed()) {
60 | context.response()
61 | .setStatusCode(500)
62 | .end(res.cause().getMessage());
63 | return;
64 | }
65 | context.response().end(value);
66 | });
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/test/resources/test-context.xml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
23 |
--------------------------------------------------------------------------------