当前位置: 首页 > 工具软件 > EasyRest-NAS > 使用案例 >

java easyrest_EasyRest 一个为快速开发而设计的高性能RESTful框架

张卓
2023-12-01

EasyRest-NAS

中文文档地址:

EasyRest integration with Netty, Akka and Spring.

This is the high performance RESTful framework, designed for the fast development. Easy to cluster and distributed. You can focus on your business logic.

No tomcat, no web.xml, only need a jar package with 'main' function, you can get a prefect distributed system.

You can don't know Netty, Akka even Spring. You can still using this framework.

Quick start:

The rest definition

@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, List stockList);

@Get("/personal/{USER_ID}/favorite/list")

List getStockList(String USER_ID);

}

The Service is the bean of spring, you can integrate with 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, List stockList) {

return ResponseEntity.buildOkResponse(Lists.asList(userNumber, userName, new List[]{stockList}));

}

@Override

public List getStockList(String USER_ID) {

return Lists.newArrayList(new Stock(100000, "stock1"), new Stock(100001, "stock2"), new Stock(100002, "stock3"));

}

}

The main class.

public class Example {

public static void main(String[] args) {

EasyRest easyRest = new EasyRest("classpath:MyExampleApplicationContext.xml");

easyRest.startup("EasyRestServer");

}

}

An empty spring config file

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") will bind this endpoint at "/rest/{TENANT}/stock"

@AllDefined will check all parameters not be null, if any parameter is null, the framework will reject the request directly.

@Service is spring annotation, that will create bean by spring.

ResponseEntity is the generic response entity, you can put any thing you want in it.

If you have own spring properties, you can create EasyRest by

EasyRest easyRest = new EasyRest("classpath:MyApplicationContext-01.xml", "classpath:MyApplicationContext-02.xml"...);

All over the rest interface will be detected by EasyRest automatically, you just need start the server.

easyRest.startup("EasyRestServer");

REST CALL EXAMPLE

Methd 1

@Post("/personal/{USER_ID}/favorite/{CODE}")

void addFavorite(String TENANT, String USER_ID, String CODE, long time);

Call it at:

Content-Type is 'application/json'

POST body is:

{"time":1524827542}

The output is:

100000001 001 100001 1524827542

And the response is:

{

"code": "1",

"message": "ok"

}

Methd 2

@Post

@AllDefined

ResponseEntity addStocks(int userNumber, String userName, List stockList);

Call it at:

Content-Type is 'application/json'

POST body is:

{"userNumber":1, "userName":"Louie", "stockList":[{"code":100001, "name":"stock1"}, {"code":100002, "name":"stock2"}]}

And the response is:

{

"code": "1",

"data": [

1,

"Louie",

[

{

"code": 100001,

"name": "stock1"

},

{

"code": 100002,

"name": "stock2"

}

]

]

}

The method has annotation @AllDefined, so if any one of the parameter is missing, e.g. "userName". The response will be:

{

"code": "-1",

"message": "Failed",

"data": {

"errorType": "ParameterNotFoundException",

"errorMessage": "userName is not defined."

}

}

Methd 3

@Get("/personal/{USER_ID}/favorite/list")

List getStockList(String USER_ID);

Call it at:

And the response is:

[

{

"code": 100000,

"name": "stock1"

},

{

"code": 100001,

"name": "stock2"

},

{

"code": 100002,

"name": "stock3"

}

]

For the content type, 'multipart/form-data' is also supported.

Distributed is supported and very easily.

Distribute service example

All of the code are in the Example module.

- 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 will get request from the rest call, then will invoke Example-Distributed-Service-2 to create a People and response the rest call with this People.

Example-Distributed-Service-Model

People class

public class People {

private String name;

private int age;

private long birthday;

private List skills;

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-Distributed-Service-1

example-service-1-api

Interface definition

@BindURL("/service1")

public interface Service1 {

@Post

@AllDefined

ResponseEntity createPeople(String name, int age, long birthday, List skills, People boss);

}

example-service-1-main

Interface Implement

@Service

public class Service1Impl implements Service1 {

@Override

public ResponseEntity createPeople(String name, int age, long birthday, List skills, People boss) {

Service2 service2 = EasyRestServiceLookup.lookup(Service2.class);

return ResponseEntity.buildOkResponse(service2.getPeople(name, age, birthday, skills, boss));

}

}

EasyRestServiceLookup has a static method lookup. You can use this method to get any service instance, even this service on the other server!

The main class

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")); will load the service mapping for the framework.

akka config file: application.conf

akka {

actor {

provider = "akka.remote.RemoteActorRefProvider"

}

remote {

transport = "akka.remote.netty.NettyRemoteTransport"

netty {

tcp {

hostname = "127.0.0.1"

port = 2551

}

}

}

}

Akka system will detect this file, and open the port to listening remote request.

Distributed service mapping file:(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"

}

]

}

Service mapping file only need two fields: Self to record local system info. Services is an array to record all system info, including self.

The akkaSystemName must be the same with systemName in Main class.

An empty spring config file:

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-Distributed-Service-2

example-service-2-api

Interface definition

@BindURL("/service2")

public interface Service2 {

@Get

People getPeople(String name, int age, long birthday, List skills, People boss);

}

example-service-2-main

Interface Implement

@Service

public class Service2Impl implements Service2 {

@Override

public People getPeople(String name, int age, long birthday, List skills, People boss) {

return new People(name, age, birthday, skills, boss);

}

}

The main class

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 config file: application.conf

akka {

actor {

provider = "akka.remote.RemoteActorRefProvider"

}

remote {

transport = "akka.remote.netty.NettyRemoteTransport"

netty {

tcp {

hostname = "127.0.0.1"

port = 2552

}

}

}

}

Distributed service mapping file:(services-mapping-02.json)

{

"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"

}

]

}

An empty spring config file:

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">

Start Service 1 and Service 2.

When you see this log on each console:

[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.

That means services are ready now!

Now, We will invoke the service1 via rest call.

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}}

And then we can get response:

{

"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!

Not the end...

TODO

Support callback

 类似资料: