A preliminary study of spring Webflux __spring

Source: Internet
Author: User
on the Webflux of spring

Not long ago, spring made a big change, primarily to increase support for responsive programming.

Spring defaults to the support of the reactor project as a responsive programming (reactive programming), which I also use as a basis for discussion.

Reactor Project Address: Https://github.com/reactor/reactor Why should reactor

In general, reactor is also a library for writing asynchronous code, and it is well known that the overhead of IO takes a long time for a synchronization program. So people are constantly advocating the use of asynchronous way to write some code, and Java also provides a way to write asynchronous programs to developers, then why we need reactor. In my short time experience, reactor makes it easier and faster to write asynchronous code, to make a job simpler or more efficient, and I think it's a problem that a library should solve, and obviously reactor did it, after using the reactor, You'll never have to write callback that smelly, long noodle code, and the readability and maintainability of the code is greatly enhanced. Compared to future, reactor provides more full-featured operations, and programming complexity is greatly reduced

Well, we're not here to introduce reactor, more information about reactor, and how it compares to other asynchronous ways of the JVM. Refer to Reactor Documentation: http://projectreactor.io/docs/core/release/ Analogy between Webflux and webmvc of reference Webflux instances

Webmvc Webflux
Controller Handler
Request Mapping Router

* Pom.xml

<?xml version= "1.0" encoding= "UTF-8"?> <project xmlns= "http://maven.apache.org/POM/4.0.0" xmlns:xsi= "http ://www.w3.org/2001/XMLSchema-instance "xsi:schemalocation=" http://maven.apache.org/POM/4.0.0 http:// Maven.apache.org/xsd/maven-4.0.0.xsd "> <modelVersion>4.0.0</modelVersion> &LT;GROUPID&GT;CN.EDU.N Cu</groupid> <artifactId>reactive-demo</artifactId> <version>0.0.1-snapshot</version&
    Gt  <packaging>jar</packaging> <name>reactive-demo</name> <description>demo Project for
        Spring boot</description> <parent> <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.0.M7</version> <relativePath/> <!--lookup parent from repository--> </parent> <properties> &L t;project.build.sourceencoding>utf-8</pRoject.build.sourceencoding> <project.reporting.outputencoding>utf-8</ Project.reporting.outputencoding> <java.version>1.8</java.version> </properties>
            ;d ependencies> <dependency> <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-starter-test</a Rtifactid> <scope>test</scope> </dependency> <!--Https://mvnreposito Ry.com/artifact/org.springframework.boot/spring-boot-starter-webflux--> <dependency> <gro Upid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-webflux</artifactid&
        Gt </dependency> <dependency&Gt <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-starter-data-redis</a
        Rtifactid> </dependency> <!--Https://mvnrepository.com/artifact/redis.clients/jedis--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis< /artifactid> <version>2.9.0</version> </dependency> <!--https://mvnre Pository.com/artifact/org.mindrot/jbcrypt--> <dependency> <groupid>org.mindrot</gro Upid> <artifactId>jbcrypt</artifactId> <version>0.4</version> & lt;/dependency> <!--Https://mvnrepository.com/artifact/com.alibaba/fastjson--> &LT;DEPENDENCY&G
            T <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> &Lt;version>1.2.44</version> </dependency> </dependencies> <build> <p
                Lugins> <plugin> <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins>
            </build> <repositories> <repository> <id>spring-snapshots</id>
            <name>spring snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </ repository> <repository> <id>spring-milestones</id> <name>sprin G milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots&gt
                ; <enabled>false</enabled> </snapshots> </repository> </repositories> & Lt;pluginrepositories> <pluginRepository> <id>spring-snapshots</id> & Lt;name>spring snapshots</name> <url>https://repo.spring.io/snapshot</url> &L t;snapshots> <enabled>true</enabled> </snapshots> </pluginrepo sitory> <pluginRepository> <id>spring-milestones</id> &LT;NAME&GT;SPR ing milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots&
                Gt <enabled>false</enabled> </snapshots> </pluginRepository> </pluginrepos Itories> </project>
Write Handler

First write a Hello World handler practice practicing
Package cn.edu.ncu.reactivedemo.handlers;

@Service public
class HelloWorldHandler {public

    mono<serverresponse> HelloWorld (serverrequest request {return
        Serverresponse.ok ()
                . ContentType (Mediatype.text_plain)
                . Body (Bodyinserters.fromobject (" Hello World "));
    }
Registering routes

Register a written handler on a route
Package Cn.edu.ncu.reactivedemo;

@Configuration public
class Router {
    @Autowired private helloworldhandler HelloWorldHandler;
    @Autowired private Userhandler Userhandler;

    @Bean public
    routerfunction<?> routerfunction () {return
        Routerfunctions.route ( Requestpredicates.get ("/hello"), Helloworldhandler::helloworld);
    }
Start class

The default is to use Netty as the underlying boot of the reactor
Package Cn.edu.ncu.reactivedemo;

@SpringBootApplication public
class Reactivedemoapplication {public

    static void Main (string[] args) {
        Springapplication.run (Reactivedemoapplication.class, args);
    }

Visit Http://127.0.0.1:8080/hello

Return to Hello World for successful database use

Temporary support for reactive programming database only MongoDB, Redis, Cassandra, couchbase
We use the Redis as a test, do a simple registration login interface on the line
* Configure Redis

Package cn.edu.ncu.reactivedemo.config;


@Configuration public
class Redisconfig {
    @Autowired
    private redisconnectionfactory factory;
    @Bean public
    reactiveredistemplate<string, string> reactiveredistemplate (reactiveredisconnectionfactory ConnectionFactory) {return
        to new reactiveredistemplate<string, string> (ConnectionFactory, Redisserializationcontext.string ());
    }
    @Bean Public
    reactiveredisconnection Connection (reactiveredisconnectionfactory connectionfactory) {
        return connectionfactory.getreactiveconnection ();
    }

    Public @PreDestroy void Flushdb () {
        factory.getconnection (). FLUSHDB ();
    }
}
Testing the Redis interface
Package Cn.edu.ncu.reactivedemo;

@RunWith (Springrunner.class)
@SpringBootTest (classes = reactivedemoapplication.class) public
class redistests {
    @Autowired
    private reactiveredisconnection connection;
    @Test public
    void Testredis () {
        connection
                . Stringcommands (). Set (Bytebuffer.wrap ("H". GetBytes ()), Bytebuffer.wrap ("W". GetBytes ()))
                . Subscribe (system.out::p rintln);
    }

Write Userhandler
Package cn.edu.ncu.reactivedemo.handlers;

    @Service public class Userhandler {@Autowired private reactiveredisconnection connection; Public mono<serverresponse> Register (serverrequest request) {mono<map> BODY = Request.bodytomono (Map.
        Class);
            Return Body.flatmap (map-> {string username = (string) map.get ("username");
            String password = (string) map.get ("password");
                String Hashedpassword = BCRYPT.HASHPW (password, bcrypt.gensalt ()); Return Connection.stringcommands (). Set (Bytebuffer.wrap (Username.getbytes ()), Bytebuffer.wrap (HASHEDPA
        Ssword.getbytes ()));
            }). Flatmap (Aboolean-> {map<string, string> result = new hashmap<> ();
            Serverresponse serverresponse = null;
                if (Aboolean) {result.put ("message", "successful"); Return Serverresponse.ok (). ContentType (mediatype.
            Application_json_utf8). Body (Bodyinserters.fromobject);
                }else {result.put ("message", "failed"); 
                        Return Serverresponse.status (httpstatus.bad_request). ContentType (Mediatype.application_json_utf8)
            . Body (Bodyinserters.fromobject (request));
    }
        }); mono<serverresponse> Login (serverrequest request) {mono<map> BODY = Request.bodytomono (M
        Ap.class);
            Return Body.flatmap (map-> {string username = (string) map.get ("username");
            String password = (string) map.get ("password"); Return Connection.stringcommands (). Get (Bytebuffer.wrap (Username.getbytes ())). Flatmap (Bytebuffer-> {by
                te[] bytes = new byte[bytebuffer.remaining ()];
                Bytebuffer.get (bytes, 0, bytes.length);
                String Hashedpassword = null;
         try {           Hashedpassword = new String (bytes, "UTF-8");
                catch (Unsupportedencodingexception e) {e.printstacktrace ();
                } map<string, string> result = new hashmap<> (); if (Hashedpassword = NULL | |!)
                    BCRYPT.CHECKPW (password, hashedpassword)) {result.put ("message", "Account or password error"); Return Serverresponse.status (httpstatus.unauthorized). ContentType (Mediatype.application_json_
                UTF8). Body (Bodyinserters.fromobject);
                    }else {result.put ("token", "false token");
                            Return Serverresponse.ok (). ContentType (Mediatype.application_json_utf8)
                . Body (Bodyinserters.fromobject);
        }
            });
    });
 }
}
Add Router
Package Cn.edu.ncu.reactivedemo;

@Configuration public
class Router {
    @Autowired private helloworldhandler HelloWorldHandler;
    @Autowired private Userhandler Userhandler;

    @Bean public
    routerfunction<?> routerfunction () {return
        Routerfunctions.route (requestpredicates.get ("/hello"), Helloworldhandler::helloworld)
                . Androute (Requestpredicates.post ("/register"), Userhandler:: Register)
                . Androute (Requestpredicates.post ("/login"), Userhandler::login);
    }

Interface is very rough, did not write the model layer, there is no data validation, the test is directly with the HTTP requester test

Reference:

Https://spring.io/blog/2016/11/28/going-reactive-with-spring-data

http://projectreactor.io/docs/core/release/reference/

http://projectreactor.io/docs/core/release/api/

Https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-fn-handler-functions

Demo Address:

Https://github.com/ncuwaln/spring-reactive-demo

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.