EasyRest-NAS EasyRest 与 Netty, Akka 和 Spring 的整合.快速开始:接口调用示例所有的代码都在 Example 的模块中That’s work! 介绍
EasyRest-NAS
EasyRest 与 Netty, Akka 和 Spring 的整合.
-
不需要 Tomcat,不需要 web.xml 配置,只需一个有 main 函数的 jar 包,你就能拥有一个完美的分布式系统。
-
你可以不知道 Netty,也可以不知道 akka,甚至不熟悉 Spring,但仍然可以使用该框架。
快速开始:
-
REST接口定义
@BindURL(“/rest/{TENANT}/stock”)
public interface StockInfoRest {@Post(“/personal/{USER_ID}/favorite/{CODE}”)
void addFavorite(String TENANT, String USER_ID, String CODE, long time);@Post
ResponseEntity addStocks(int userNumber, String userName, ListstockList); @Get(“/personal/{USER_ID}/favorite/list”)
ListgetStockList(String USER_ID); }
-
使用@Service注解,将该类交给Spring生成bean并管理,该框架可以和spring无缝对接使用。
@Service
public class StockInfoRestController implements StockInfoRest {@Override
public void addFavorite(String TENANT, String USER_ID, String CODE, long time) {
System.out.println(TENANT + ” ” + USER_ID + ” ” + CODE + ” ” + time);
}@Override
@AllDefined
public ResponseEntity addStocks(int userNumber, String userName, ListstockList) {
return ResponseEntity.buildOkResponse(Lists.asList(userNumber, userName, new List[]{stockList}));
}@Override
public ListgetStockList(String USER_ID) {
return Lists.newArrayList(new Stock(100000, “stock1”), new Stock(100001, “stock2”), new Stock(100002, “stock3”));
}
} -
主函数类,用于启动以及配置。
public class Example {
public static void main(String[] args) {
EasyRest easyRest = new EasyRest(“classpath:MyExampleApplicationContext.xml”);
easyRest.startup(“EasyRestServer”);
}}
-
<?xml version=”1.0” encoding=”UTF-8”?>
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
-
@BindURL(“/rest/{TENANT}/stock”) 会绑定该类监听 “/rest/{TENANT}/stock” 路径的请求。
-
@AllDefined 会要求该方法所有的参数在请求中都被赋予非空值,如果检测到有null,框架将会直接拒绝这个请求。可以减少用户的空值判断。
-
@Service 这个是spring的annotation,将交给spring生成bean并管理。
-
ResponseEntity 是一个通用的返回格式,你能将所有格式的数据放进去。(你也可以不使用这个,直接返回任何你想返回的格式)
-
如果你有很多其他的spring配置文件,你可以这样启动EasyRest:
EasyRest easyRest = new EasyRest(“classpath:MyApplicationContext-01.xml”, “classpath:MyApplicationContext-02.xml”…);
-
所有你想暴露的数据接口,EasyRest都会自动检测到,你只需要启动server。
easyRest.startup(“EasyRestServer”);
接口调用示例
-
函数 1
@Post(“/personal/{USER_ID}/favorite/{CODE}”)
void addFavorite(String TENANT, String USER_ID, String CODE, long time);
调用地址:
http://127.0.0.1:8080/rest/100000001/stock/personal/001/favorite/100001
Content-Type is ‘application/json’
请求内容:
{"time":1524827542}
控制台输出:
100000001 001 100001 1524827542
收到的响应内容:
{ "code": "1", "message": "ok" }
-
函数 2
@Post
@AllDefined
ResponseEntity addStocks(int userNumber, String userName, ListstockList);
调用地址:
Content-Type is ‘application/json’
请求内容:
{"userNumber":1, "userName":"Louie", "stockList":[{"code":100001, "name":"stock1"}, {"code":100002, "name":"stock2"}]}
响应内容:
{ "code": "1", "data": [ 1, "Louie", [ { "code": 100001, "name": "stock1" }, { "code": 100002, "name": "stock2" } ] ] }
这个函数有一个 @AllDefined
的注解,所以如果任何参数的值为null,比如:“UserName”,那么响应结果将会如下:
{ "code": "-1", "message": "Failed", "data": { "errorType": "ParameterNotFoundException", "errorMessage": "userName is not defined." } }
-
函数 3
@Get(“/personal/{USER_ID}/favorite/list”)
ListgetStockList(String USER_ID);
调用地址:
http://127.0.0.1:8080/rest/100000001/stock/personal/001/favorite/list
响应内容:
[ { "code": 100000, "name": "stock1" }, { "code": 100001, "name": "stock2" }, { "code": 100002, "name": "stock3" } ]
分布式服务示例
所有的代码都在 Example 的模块中
- Example-distributed-Service-1 - example-service-1-api - example-service-1-main - Example-distributed-Service-2 - example-service-2-api - example-service-2-main - Example-distributed-Service-Model
Example-distributed-Service-1 会收到请求,然后会调用 Example-distributed-Service-2
的服务去创建一个 People,然后将这个 People 做为响应数据返回出去。
-
People 类
public class People {
private String name;
private int age;
private long birthday;
private Listskills;
private People boss;public People(String name, int age, long birthday, List
skills, People boss) {
this.name = name;
this.age = age;
this.birthday = birthday;
this.skills = skills;
this.boss = boss;
}}
example-service-1-api
-
接口定义
@BindURL(“/service1”)
public interface Service1 {@Post
@AllDefined
ResponseEntity createPeople(String name, int age, long birthday, Listskills, People boss); }
example-service-1-main
-
接口实现
@Service
public class Service1Impl implements Service1 {@Override
public ResponseEntity createPeople(String name, int age, long birthday, Listskills, People boss) {
Service2 service2 = EasyRestServiceLookup.lookup(Service2.class);
return ResponseEntity.buildOkResponse(service2.getPeople(name, age, birthday, skills, boss));
}}
EasyRestServiceLookup 有一个静态方法 lookup. 你能使用这个函数获得任何交给
EasyRest,或者spring 的bean实例,包括在其他服务器上的实例,你都能直接调用。
-
主函数
public class Startup {
private static String systemName = "example-service-1";
public static void main(String[] args) throws IOException {
EasyRestdistributedServiceBind.loadConfiguration(Startup.class.getClassLoader().getResourceAsstream(“services-mapping-01.json”));
EasyRest easyRest = new EasyRest(“classpath:MyExampleApplicationContext-01.xml”);
easyRest.startup(systemName, new NettyInit(8001));
}}
EasyRestdistributedServiceBind.loadConfiguration(Startup.class.getClassLoader().getResourceAsstream(“services-
mapping-01.json”)); 将会为框架载入服务映射的关系配置文件。
-
akka 配置文件: application.conf
akka {
actor {
provider = “akka.remote.RemoteActorRefProvider”
}
remote {
transport = “akka.remote.netty.NettyRemoteTransport”
netty {
tcp {
hostname = “127.0.0.1”
port = 2551
}
}
}
}
Akka 系统会检测到这个配置文件,然后在指定的端口监听远程请求。
-
分布式服务映射关系表:(services-mapping-01.json)
{
“self”: {
“akkaSystemName”: “example-service-1”,
“host”: “127.0.0.1”,
“port”: “2551”
},
“services” : [
{
“akkaSystemName”: “example-service-1”,
“host”: “127.0.0.1”,
“port”: “2551”
},
{
“akkaSystemName”: “example-service-2”,
“host”: “127.0.0.1”,
“port”: “2552”
}
]
}
服务映射关系表只需要2个字段: Self 记录本地的服务器信息. Services 是一个数组,记录所有的服务器信息,包括自己本身.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config/> <context:component-scan base-package="com.example"> </context:component-scan> <context:annotation-config/> </beans>
example-service-2-api
-
接口定义
@BindURL(“/service2”)
public interface Service2 {@Get
People getPeople(String name, int age, long birthday, Listskills, People boss); }
example-service-2-main
-
接口实现
@Service
public class Service2Impl implements Service2 {@Override
public People getPeople(String name, int age, long birthday, Listskills, People boss) {
return new People(name, age, birthday, skills, boss);
}
} -
主函数
public class Startup {
private static String systemName = "example-service-2";
public static void main(String[] args) throws IOException {
EasyRestdistributedServiceBind.loadConfiguration(Startup.class.getClassLoader().getResourceAsstream(“services-mapping-02.json”));
EasyRest easyRest = new EasyRest(“classpath:MyExampleApplicationContext-02.xml”);
easyRest.startup(systemName, new NettyInit(8002));
}}
-
akka 配置文件: application.conf
akka {
actor {
provider = “akka.remote.RemoteActorRefProvider”
}
remote {
transport = “akka.remote.netty.NettyRemoteTransport”
netty {
tcp {
hostname = “127.0.0.1”
port = 2552
}
}
}
} -
分布式服务映射表:(services-mapping-02.json,该service并未依赖其他service,所以其实可以不用加载该配置文件)
{
“self”: {
“akkaSystemName”: “example-service-2”,
“host”: “127.0.0.1”,
“port”: “2552”
},
“services” : [
{
“akkaSystemName”: “example-service-1”,
“host”: “127.0.0.1”,
“port”: “2551”
},
{
“akkaSystemName”: “example-service-2”,
“host”: “127.0.0.1”,
“port”: “2552”
}
]
} -
<?xml version=”1.0” encoding=”UTF-8”?>
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
当你在两边的控制台分别看到如下的日志:
[example-service-1-akka.actor.default-dispatcher-5] INFO com.easyrest.utils.LogUtils - From com.easyrest.actors.remote.RemoteServiceExchangeActor: Service mapping init success. [example-service-1-akka.actor.default-dispatcher-5] INFO com.easyrest.utils.LogUtils - example-service-2 is running on the port 8001. [example-service-2-akka.actor.default-dispatcher-3] INFO com.easyrest.utils.LogUtils - From com.easyrest.actors.remote.RemoteServiceExchangeActor: Service mapping init success. [example-service-2-akka.actor.default-dispatcher-3] INFO com.easyrest.utils.LogUtils - example-service-2 is running on the port 8002.
现在我们将通过rest call调用service1.
http://127.0.0.1:8001/service1/createPeople Content-Type:application/json
Body: {“name”:”Louie”, “age”:18, “birthday”:763401600, “skills”:[“java”,
“netty”, “akka”, “spring”], “boss”:{“name”:”Louie_B”, “age”:18,
“birthday”:763401600}}
收到的响应内容:
{ "code": "1", "data": { "name": "Louie", "age": 18, "birthday": 763401600, "skills": [ "java", "netty", "akka", "spring" ], "boss": { "name": "Louie_B", "age": 18, "birthday": 763401600 } } }
That’s work!
持续更新…
EasyRest-NAS EasyRest 与 Netty, Akka 和 Spring 的整合.快速开始:接口调用示例所有的代码都在 Example 的模块中That’s work! 官网
https://github.com/liuhongyuand/EasyRest-NAS
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。