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

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
<!--Spring的 web reactive包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web-reactive</artifactId>
<version>${SpringVersion}</version>
</dependency>
<!-- 使用的netty , 以及Flux等包 -->
<dependency>
<groupId>io.projectreactor.ipc</groupId>
<artifactId>reactor-netty</artifactId>
<version>0.6.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<!-- 官网demo给的json包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.2</version>
</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<ServerResponse> getCustomer (ServerRequest request) {
String personId = request.pathVariable("uid");
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
//调用service方法,去查数据库
return this.userService.selectAll(personId)
.then(person -> {
Publisher<Customer> 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相关基本知识,这个项目是为老家农产品做的一个推广网站,会持续更新,有新技术方案时,也会和大家及时分享,谢谢
版权声明:本文为weixiaodedao原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。