Spring5 函数式编程实践

或许大家都已经习惯了SpringMVC的配置一个servlet,然后映射到Controller的web编程模式,现在Spring5出来之后, 为大家提供了一个新的web编程体验。下文所用到的代码,可以在github上下载
https://github.com/weixiaodexiaoxiaodao/nongjihongshu

函数式编程结构简介

Spring5 函数式编程实践_第1张图片

Controller

以前写的Controller,老的SpringMVC,现废弃不用。

dao

映射成/resources/mapper下面的mybatis的mapper文件。

handler

提供处理器方法,供绑定在MainServer里面使用

netty

提供netty运行的主函数,也是整个项目的入口

service

调用dao,并给handler提供数据

mapper

mybatis的数据库sql文件

applicationContext

Spring的bean配置文件

log4j2

log4j2的配置文件

mabatis-config

mybatis的配置文件,因为和Spring集成, 所以里面只配置了Logger,这样可以打印出sql语句

代码概览

  • pom.xml 这里只列出大概,具体代码请移步github
    
    <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-web-reactiveartifactId>
            <version>${SpringVersion}version>
        dependency>
    
        <dependency>
            <groupId>io.projectreactor.ipcgroupId>
            <artifactId>reactor-nettyartifactId>
            <version>0.6.0.RELEASEversion>
        dependency>

        <dependency>
            <groupId>org.reactivestreamsgroupId>
            <artifactId>reactive-streamsartifactId>
            <version>1.0.0version>
        dependency>

        <dependency>
            <groupId>io.projectreactorgroupId>
            <artifactId>reactor-coreartifactId>
            <version>3.0.4.RELEASEversion>
        dependency>
    
        <dependency>
            <groupId>com.fasterxml.jackson.coregroupId>
            <artifactId>jackson-databindartifactId>
            <version>2.8.2version>
        dependency>
  • mainServer.java
package com.nongji.netty;

import com.nongji.handler.CustomerHandler;
import com.nongji.handler.PersonHandler;
import com.nongji.service.DummyPersonRepository;
import com.nongji.service.PersonRepository;
import com.nongji.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import reactor.ipc.netty.http.server.HttpServer;


import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.*;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;

/**
 * Created by lixiang on 2017/1/11.
 */
public class MainServer {

    //netty服务起来后的地址
    public static final String HOST = "localhost";

    public static final int PORT = 8080;

    //加载Spring的bean
    public static  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/applicationContext.xml");

    public static void main(String[] args) throws Exception {

        MainServer server = new MainServer();
        server.startReactorServer();

        System.out.println("Press ENTER to exit.");
        System.in.read();


    }

    public RouterFunction routingFunction() {

        //官网示例
        PersonRepository repository = new DummyPersonRepository();
        PersonHandler handler = new PersonHandler(repository);

        //自己从SpringContext中取出的Bean
        UserService userService = applicationContext.getBean(UserService.class);
        CustomerHandler customerHandler = new CustomerHandler(userService);

        //注册路由方法,相当于MVC中把RequestMapping上的value绑定到handle
        //这里的handler::getCustomer就是处理逻辑的地方
        return route(GET("/person/{id}").and(accept(APPLICATION_JSON)), handler::getPerson)
                .andRoute(GET("/person").and(accept(APPLICATION_JSON)), handler::listPeople)
                .andRoute(POST("/person").and(contentType(APPLICATION_JSON)), handler::createPerson)
                .andRoute(GET("/customer/{uid}").and(accept(APPLICATION_JSON)),customerHandler::getCustomer);
    }

    //开启本地的web服务
    public void startReactorServer() throws InterruptedException {
        RouterFunction route = routingFunction();
        HttpHandler httpHandler = toHttpHandler(route);

        ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
        HttpServer server = HttpServer.create(HOST, PORT);
        server.newHandler(adapter).block();
    }


}
  • CustomerHandler.java
package com.nongji.handler;

import com.nongji.model.Customer;
import com.nongji.service.UserService;
import org.reactivestreams.Publisher;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;


/**
 * Created by lixiang on 11/01/2017.
 */
public class CustomerHandler {

    private final UserService userService;
//现在是构造传值,也可以在这一步用context.getBean
    public CustomerHandler(UserService userDao) {
        this.userService = userDao;
    }

    public Mono getCustomer (ServerRequest request) {

        String personId = request.pathVariable("uid");
        Mono notFound = ServerResponse.notFound().build();
        //调用service方法,去查数据库
        return this.userService.selectAll(personId)
                .then(person -> {
                    Publisher personPublisher = null;
                    personPublisher = Mono.just(person);
                    return ServerResponse.ok().body(personPublisher, Customer.class);
                })
                .otherwiseIfEmpty(notFound);
    }

}

小结

学习Spring5 的前置技能
java 8 函数式编程
reactive 中 Flux , Mono等概念的了解
java8

以下属于个人理解,仅供参考
本质还是传一个object到方法里面,但java8里面不是一个String,或者是Int
而java8传的是一个函数,这个函数运行完的返回值(String或者是别的)再传入进去。这样就和以前的对应起来了。

附:本篇文章不适合Spring初学者,下载源代码后若阅读吃力,可先学习Spring相关基本知识,这个项目是为老家农产品做的一个推广网站,会持续更新,有新技术方案时,也会和大家及时分享,谢谢

你可能感兴趣的:(Spring学习,java)