这是一个为快速开发而设计的高性能RESTful框架,极易搭建集群和使用分布式。你可以完全专注在你的业务逻辑上。
不需要 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, List<Stock> stockList); @Get("/personal/{USER_ID}/favorite/list") List<Stock> getStockList(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, List<Stock> stockList) { return ResponseEntity.buildOkResponse(Lists.asList(userNumber, userName, new List[]{stockList})); } @Override public List<Stock> getStockList(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"); } }
一个基础的spring配置文件
<?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>
@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, List<Stock> stockList);
调用地址:
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") List<Stock> getStockList(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" } ]
对于 content type, 'multipart/form-data' 也是支持的.
框架支持分布式服务,并且十分容易搭建.
- 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 List<String> skills; private People boss; public People(String name, int age, long birthday, List<String> 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, List<String> skills, People boss); }
example-service-1-main
接口实现
@Service public class Service1Impl implements Service1 { @Override public ResponseEntity createPeople(String name, int age, long birthday, List<String> skills, 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 是一个数组,记录所有的服务器信息,包括自己本身.
字段 akkaSystemName 的值必须和主函数中 systemName 的值一致!!!
*一个基本的spring配置文件:
<?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, List<String> skills, People boss); }
example-service-2-main
接口实现
@Service public class Service2Impl implements Service2 { @Override public People getPeople(String name, int age, long birthday, List<String> skills, 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" } ] }
一个基本的spring配置文件:
<?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-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 } } }
持续更新...
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
Uragano 旨在提供一个搭建和使用简单的高性能 RPC 框架。Uragano 是基于 netstandard2.0 开发的。Uragano 默认采用 DotNetty 实现远程通信,使用 MessagePack 进行编解码。
我正在用docx4j做一些测试。我需要做的是将复杂的Word文档(2-3页的文本、表格、项目符号列表、图像)转换成XHTML。
我在我的应用程序中创建了第二个DataSource。 我用HikariDataSource创建了它,因为它断开了连接,所以出现了问题。 现在它没有断开,但是很慢 我的配置如下: 爪哇: 有人能告诉我如何提高绩效吗。 它们是表的小查询,分页约为25条记录,需要4秒钟。 我观察到,查询一个select的200条记录需要46秒,而查询只需要2秒。 以前,它们是千分之一秒。 非常感谢。
本文向大家介绍推荐 21 款优秀的高性能 Node.js 开发框架,包括了推荐 21 款优秀的高性能 Node.js 开发框架的使用技巧和注意事项,需要的朋友参考一下 Node.js 框架可以帮助你开发出更友好的 web 应用。Node.js 框架的许多特性和功能也能开发出大型的 web 应用。下面我们来介绍 21 款最好的 Node.js 框架,帮助开发者快速开发 web 应用。 Express
我有一个cron作业方法,它根据用户的特色故事构建用户的故事提要,跟踪类别并跟踪用户。 最终提要按正确顺序添加到以下数据库表中: 用户提要表: Uid 方法如下,包含注释<代码: 对于30名用户,上述方法需要约35秒才能完成<问:我如何改进代码和性能?
imi v1.0.13 版本新增了一个 Swoole\Coroutine\Http\Server 实现的协程服务器。需要 Swoole 4.4+ 才可使用该特性。 该特性是可选的,不影响以前使用的服务器模式。 使用协程服务器特性,依靠 Linux 系统的端口重用机制,系统级的负载均衡,可以让你的多进程 Http 服务处理请求的能力得到提升。 使用 ab,本机->虚拟机(双核+2进程)压测Hello