ActiveJ - это современная платформа Java, построенная с нуля. Он предназначен для того, чтобы быть самодостаточным (без сторонних зависимостей), простых, легких и обеспечивает конкурентоспособную производительность. ActiveJ состоит из ряда ортогональных библиотек, от инъекции зависимостей и высокопроизводительных асинхронных ввода/вывода (вдохновленный Node.js), до серверов приложений и решений для больших данных.
Эти библиотеки имеют как можно меньше зависимостей по отношению друг к другу и могут использоваться вместе или отдельно. ActiveJ не в другой структуре, которая заставляет пользователя использовать его на основе все или ничего, но вместо этого он дает пользователю как можно больше свободы с точки зрения выбора компонентов библиотеки для определенных задач.
ActiveJ состоит из нескольких модулей, которые могут быть логически сгруппированы в следующие категории:
Async.io - высокопроизводительный асинхронный IO с эффективной петлей события, Nio, обещания, потоковая передача и CSP. Альтернатива Нетти, Ркьяву, Акка и другим. (Обещание, Eventloop, Net, CSP, DataStream)
// Basic eventloop usage
public static void main ( String [] args ) {
Eventloop eventloop = Eventloop . create ();
eventloop . post (() -> System . out . println ( "Hello, world!" ));
eventloop . run ();
} // Promise chaining
public static void main ( String [] args ) {
Eventloop eventloop = Eventloop . builder ()
. withCurrentThread ()
. build ();
Promises . delay ( Duration . ofSeconds ( 1 ), "world" )
. map ( string -> string . toUpperCase ())
. then ( string -> Promises . delay ( Duration . ofSeconds ( 3 ))
. map ( $ -> "HELLO " + string ))
. whenResult ( string -> System . out . println ( string ));
eventloop . run ();
} // CSP workflow example
ChannelSuppliers . ofValues ( 1 , 2 , 3 , 4 , 5 , 6 )
. filter ( x -> x % 2 == 0 )
. map ( x -> 2 * x )
. streamTo ( ChannelConsumers . ofConsumer ( System . out :: println )); // Datastream workflow example
StreamSuppliers . ofValues ( 1 , 2 , 3 , 4 , 5 , 6 )
. transformWith ( StreamTransformers . filter ( x -> x % 2 == 0 ))
. transformWith ( StreamTransformers . mapper ( x -> 2 * x ))
. streamTo ( StreamConsumers . ofConsumer ( System . out :: println ));HTTP - высокопроизводительный HTTP -сервер и клиент с поддержкой WebSocket. Его можно использовать в качестве простого веб -сервера или в качестве сервера приложений. Альтернатива другим обычным клиентам и серверам HTTP. (Http)
// Server
public static void main ( String [] args ) throws IOException {
Eventloop eventloop = Eventloop . create ();
AsyncServlet servlet = request -> HttpResponse . ok200 ()
. withPlainText ( "Hello world" )
. toPromise ();
HttpServer server = HttpServer . builder ( eventloop , servlet )
. withListenPort ( 8080 )
. build ();
server . listen ();
eventloop . run ();
} // Client
public static void main ( String [] args ) {
Eventloop eventloop = Eventloop . create ();
HttpClient client = HttpClient . create ( eventloop );
HttpRequest request = HttpRequest . get ( "http://localhost:8080" ). build ();
client . request ( request )
. then ( response -> response . loadBody ())
. map ( body -> body . getString ( StandardCharsets . UTF_8 ))
. whenResult ( bodyString -> System . out . println ( bodyString ));
eventloop . run ();
}ActiveJ Inject - легкая библиотека для инъекции зависимости. Оптимизирован для быстрого запуска приложения и производительности во время выполнения. Поддерживает проводку компонентов на основе аннотаций, а также проводку без отражения. (ActiveJ Inject)
// Manual binding
public static void main ( String [] args ) {
Module module = ModuleBuilder . create ()
. bind ( int . class ). toInstance ( 101 )
. bind ( String . class ). to ( number -> "Hello #" + number , int . class )
. build ();
Injector injector = Injector . of ( module );
String string = injector . getInstance ( String . class );
System . out . println ( string ); // "Hello #101"
} // Binding via annotations
public static class MyModule extends AbstractModule {
@ Provides
int number () {
return 101 ;
}
@ Provides
String string ( int number ) {
return "Hello #" + number ;
}
}
public static void main ( String [] args ) {
Injector injector = Injector . of ( new MyModule ());
String string = injector . getInstance ( String . class );
System . out . println ( string ); // "Hello #101"
}Boot - готовые к производству инструменты для запуска и мониторинга приложения ActiveJ. Одновременный контроль жизненного цикла услуг на основе их зависимостей. Различные утилиты мониторинга обслуживания с поддержкой JMX и Zabbix. (Пускор, график сервиса, JMX, триггеры)
public class MyLauncher extends Launcher {
@ Inject
String message ;
@ Provides
String message () {
return "Hello, world!" ;
}
@ Override
protected void run () {
System . out . println ( message );
}
public static void main ( String [] args ) throws Exception {
Launcher launcher = new MyLauncher ();
launcher . launch ( args );
}
}Манипуляция с байт -кодом
ActiveJ CodeGen - Динамический генератор байт -кодов для классов и методов поверх объекта Wheat ASM Библиотеки. Отражает сложность прямых манипуляций с байт-кодом и позволяет создавать пользовательские классы на лету, используя LISP-подобные выражения AST. (ActiveJ Codegen)
// Manually implemented method
public class MyCounter implements Counter {
@ Override
public int countSum () {
int sum = 0 ;
for ( int i = 0 ; i < 100 ; i ++) {
sum += i ;
}
return sum ;
}
} // The same method generated via ActiveJ Codegen
public static void main ( String [] args ) {
DefiningClassLoader classLoader = DefiningClassLoader . create ();
Counter counter = ClassGenerator . builder ( Counter . class )
. withMethod ( "countSum" ,
let ( value ( 0 ), sum ->
sequence (
iterate (
value ( 0 ),
value ( 100 ),
i -> set ( sum , add ( sum , i ))),
sum
)))
. build ()
. generateClassAndCreateInstance ( classLoader );
System . out . println ( counter . countSum ()); // 4950
}ActiveJ Serializer - быстрые и космические сериализаторы, созданные с помощью инженерии Bytecode. Представляет подход без схемы для лучшей производительности. (ActiveJ Serializer)
// A class to be serialized
public class User {
private final int id ;
private final String name ;
public User ( @ Deserialize ( "id" ) int id , @ Deserialize ( "name" ) String name ) {
this . id = id ;
this . name = name ;
}
@ Serialize
public int getId () {
return id ;
}
@ Serialize
public String getName () {
return name ;
}
} // Serialization and deserialization
public static void main ( String [] args ) {
BinarySerializer < User > userSerializer = SerializerFactory . defaultInstance ()
. create ( User . class );
User john = new User ( 1 , "John" );
byte [] buffer = new byte [ 100 ];
userSerializer . encode ( buffer , 0 , john );
User decoded = userSerializer . decode ( buffer , 0 );
System . out . println ( decoded . id ); // 1
System . out . println ( decoded . name ); // John
} // Serialization of Java records
@ SerializeRecord
public record User ( int id , String name ) {
} // StreamCodec usage example
public static void main ( String [] args ) throws IOException {
StreamCodec < User > userStreamCodec = StreamCodec . create ( User :: new ,
User :: getId , StreamCodecs . ofVarInt (),
User :: getName , StreamCodecs . ofString ()
);
List < User > users = List . of (
new User ( 1 , "John" ),
new User ( 2 , "Sarah" ),
new User ( 3 , "Ben" )
);
ByteArrayOutputStream baos = new ByteArrayOutputStream ();
try ( StreamOutput streamOutput = StreamOutput . create ( baos )) {
for ( User user : users ) {
userStreamCodec . encode ( streamOutput , user );
}
}
ByteArrayInputStream bais = new ByteArrayInputStream ( baos . toByteArray ());
try ( StreamInput streamInput = StreamInput . create ( bais )) {
while (! streamInput . isEndOfStream ()) {
User decoded = userStreamCodec . decode ( streamInput );
System . out . println ( decoded . getId () + " " + decoded . getName ());
}
}
}ActiveJ Specializer - Инновационная технология для повышения производительности класса во время выполнения путем автоматического преобразования экземпляров классов в специализированные статические классы и поля экземпляра класса в запеченные статические поля. Обеспечивает широкий спектр оптимизации JVM для статических классов, которые невозможны в противном случае: Устранение мертвого кода, агрессивное внедрение методов и статические константы. (ActiveJ Specializer)
// Operators
public record IdentityOperator () implements IntUnaryOperator {
@ Override
public int applyAsInt ( int operand ) {
return operand ;
}
}
public record ConstOperator ( int value ) implements IntUnaryOperator {
@ Override
public int applyAsInt ( int operand ) {
return value ;
}
}
public record SumOperator ( IntUnaryOperator left , IntUnaryOperator right ) implements IntUnaryOperator {
@ Override
public int applyAsInt ( int operand ) {
return left . applyAsInt ( operand ) + right . applyAsInt ( operand );
}
}
public record ProductOperator ( IntUnaryOperator left , IntUnaryOperator right ) implements IntUnaryOperator {
@ Override
public int applyAsInt ( int operand ) {
return left . applyAsInt ( operand ) * right . applyAsInt ( operand );
}
} // Expression specialization
public static void main ( String [] args ) {
// ((x + 10) * (-5)) + 33
IntUnaryOperator expression = new SumOperator (
new ProductOperator (
new ConstOperator (- 5 ),
new SumOperator (
new ConstOperator ( 10 ),
new IdentityOperator ()
)
),
new ConstOperator ( 33 )
);
Specializer specializer = Specializer . create ();
expression = specializer . specialize ( expression );
System . out . println ( expression . applyAsInt ( 0 )); // -17
}Облачные компоненты
ActiveJ FS - Асинхронная абстракция над файловой системой для создания эффективных, масштабируемых локальных или удаленных файловых фарниров, которые поддерживают избыточность, перебалансирование и переосмысление данных. (ActiveJ FS)
public static void main ( String [] args ) throws IOException {
Eventloop eventloop = Eventloop . builder ()
. withCurrentThread ()
. build ();
HttpClient httpClient = HttpClient . create ( eventloop );
ExecutorService executor = Executors . newCachedThreadPool ();
Path directory = Files . createTempDirectory ( "fs" );
FileSystem fileSystem = FileSystem . create ( eventloop , executor , directory );
String filename = "file.txt" ;
fileSystem . start ()
// Upload
. then (() -> fileSystem . upload ( filename ))
. then ( consumer -> httpClient . request ( HttpRequest . get ( "http://localhost:8080" ). build ())
. then ( response -> response . loadBody ())
. then ( body -> ChannelSuppliers . ofValue ( body ). streamTo ( consumer )))
// Download
. then (() -> fileSystem . download ( filename ))
. then ( supplier -> supplier . streamTo ( ChannelConsumers . ofConsumer ( byteBuf ->
System . out . println ( byteBuf . asString ( StandardCharsets . UTF_8 )))))
// Cleanup
. whenComplete ( executor :: shutdown );
eventloop . run ();
}ActiveJ RPC -Высокопроизводительный двоичный клиентский протокол. Позволяет строительству распределенных, оскорбленных и устойчивых к сбои применения микросервиса. (ActiveJ RPC)
// Server
public static void main ( String [] args ) throws IOException {
Eventloop eventloop = Eventloop . create ();
RpcServer server = RpcServer . builder ( eventloop )
. withMessageTypes ( String . class )
. withHandler ( String . class , name -> Promise . of ( "Hello, " + name ))
. withListenPort ( 9000 )
. build ();
server . listen ();
eventloop . run ();
} // Client
public static void main ( String [] args ) {
Eventloop eventloop = Eventloop . create ();
RpcClient client = RpcClient . builder ( eventloop )
. withStrategy ( RpcStrategies . server ( new InetSocketAddress ( 9000 )))
. withMessageTypes ( String . class )
. build ();
client . start ()
. then (() -> client . sendRequest ( "John" ))
. whenResult ( response -> System . out . println ( response )) // "Hello, John"
. whenComplete ( client :: stop );
eventloop . run ();
}Различные дополнительные услуги: ActiveJ CRDT, Redis Client, Memcache, Olap Cube, Dataflow
Вставьте этот фрагмент в свой терминал ...
mvn archetype:generate -DarchetypeGroupId=io.activej -DarchetypeArtifactId=archetype-http -DarchetypeVersion=6.0-beta2
... и откройте проект в своей любимой IDE. Затем создайте приложение и запустите его. Откройте свой браузер на Localhost: 8080, чтобы увидеть сообщение «Hello World».
public final class HttpHelloWorldExample extends HttpServerLauncher {
@ Provides
AsyncServlet servlet () {
return request -> HttpResponse . ok200 ()
. withPlainText ( "Hello, World!" )
. toPromise ();
}
public static void main ( String [] args ) throws Exception {
Launcher launcher = new HttpHelloWorldExample ();
launcher . launch ( args );
}
}Некоторые технические подробности о примере выше:
Чтобы узнать больше о ActiveJ, пожалуйста, посетите https://activej.io или следуйте нашему 5-минутному руководству.
Примеры использования платформы ActiveJ и всех библиотек ActiveJ можно найти в модуле examples .
Примечания к выпуску для ActiveJ можно найти здесь