Spring回顾

目录

Spring是什么

Spring IOC

大致从源码分析而出

bean管理

bean类型

bean的生命周期

bean 的后置处理器BeanPostProcessor

Spring AOP

底层实现

Spring AOP操作术语

切面

织入

Spring JDBC(不再细说)

Spring orm

orm

JPA

Spring Context

大体刷新流程

Spring 事务

主要表现为ACID四种特性

事务的七种传播行为

事务的四种隔离级别

spring web(MVC执行流程在webFLux中)

spring5新功能(WebFlux)

webFlux新特点:

SpringMVC和webflux的区别

Observe和Observeable的理解

使用时,需要添加依赖

三中信号流的特点

just声明

其他方式声明

 操作符

Netty

WebFlux

WebFlux写法

WebFlux函数式编程

spring webflux在流程上和spring MVC的区别


Spring是什么

spring是一个轻量级的JavaEE框架,对原生的JAVA EE进行了一次封装

包含了spring IOC 、spring Aop、sprng Web、 spring Core、spring Context、spring data、spring orm七大模块

Spring IOC

 IOC是一种控制反转的思想、将对象的创建和销毁交由spring IOC容器进行管理,IOC容器就是对象工厂,ioc在进行创建被调用哲实例时候,需要进行依赖注入,而实现依赖注入有三种方法se方法注入、构造器注入、p命名空间注入

Spring IOC 容器的实现是通过两种方式(两个接口)

BeanFactory:IOC的基础实现,是spring内部的使用接口,不提供开发人员的使用,它在加载配置文件的时候,是不会创建对象的,在获取对象的时候才会创建对象

ApplicationContext:是BeanFactory的子接口,提供更多的功能,它在加载配置文件的时候,就会创建对象

ApplicationContext的三个实现类

ClassPathXmlApplicationContext、

它可以加载类路径下的配置文件,要求配置文件必须在类路径下。

AnnotationConfigApplicationContext

它可以加载磁盘任意路径下的配置文件

FileSystemXmlApplicationContext

它是用于读取注解创建容器的

大致从源码分析而出

初始化bean的大概流程就是在初始化bean的实例时候,判断是否写了构造方法,没有的话,是会通过反射调用无参,如果有的会获取所有候选的构造方法,然后返回参数个数,并将参数个数封装成TypeStringValue,且会针对public和参数个数来做一个优先级的排列,遍历候选构造方法并转换参数类型为目的类型,来找到合适的构造方法,最后基于找出的构造方法和参数创建实例,并设置到BeanWrapper中

bean管理

这样管理bean的过程可以细分为两个部分,一个部分是创建bean,另一个部分是对bean的属性进进行一个依赖注入

创建bean可以通过xml文件,中创建bean标签,标签里添加对应属性

依赖注入,通过xml格式的话:

通过set方法注入、

<bean id="类名"  class="类的全路径">
<property  name="" value=""></property>
</bean>

通过有参构造器注入

<bean id="" class="">
<constructor-arg name="" value=""></constructor-arg>
</bean>

通过p命名名称空间注入

<bean id="" class=""  p:bname="" p:bauthor="">
</bean>

如何通过xml注入外部属性

<bean id="userService" class="com.alpaca.service">

<property name="userService" ref="userServiceImpl"></property>

</bean>

<bean  id="userServiceImpl" class="com.alpaca.service.impl"></bean>

如何通过xml注入内部bean

<bean id="userService" class="com.alpaca.service">

<property  name=""  value=""></property>

<property name="userService" >
    <bean id=""  class="">
            <property name="" value=""></property>

     </bean>

</property>

</bean>

通过集合注入,就不再赘述

bean类型

大致分为两种bean,一种是普通的bean,另一种是FactoryBean

普通的bean就是自己创建的bean:而且在配置问价中定义的bean就是他们的返回类型

FactoryBean:在配置文件中定义的bean类型和他们返回的类型是不一致的,它的主要作用就是简化bean的实例过程

bean的作用域

singleton 、prototype、request、session

bean的生命周期

 1.通过构造器创建bean的实例(无参数构造)

 2.为bean的属性设置值和对其他bean引用(调用set方法)

 3. 调用bean的初始化方法(需要进行配置初始化的方法)

 4. bean可以使用了(也就是可以获取到了)

 5.当容器关闭的时候,调用bean的销毁方法(需要配置销毁的方法)

       但是调用bean的销毁方法并不是真正的销毁bean,需要手动对bean进行一个bean的销毁

        ((ClassPathXMLContext)  context).close();

bean 的后置处理器BeanPostProcessor

可以通过实现这个接口,对每一个bean进行初始化之前要做的和初始化之后要做的事,进行一个增强

@Autowire:针对属性类型进行注入

@Qualifier:针对属性名字进行注入,需要搭配@Autowire一起使用

@Resource:可以针对属性名字进行注入,也可以通过属性类型进行注入

@Value:普通属性进行注入

Spring AOP

aop是面向切面编程,aop可以针对业务逻辑的各个部分进行一个隔离,从而使得业务的耦合度降低,从而使得代码的重用性提高

底层实现

第一种,通过JDK动态代理

通过创建接口实现类的代理对象,来对对象进行一个增强

创建接口实现类的代理类

直接创建一个匿名内部类来进行对象的增强

public  class JDKProxy{


  public static void main(String[] args){


        Class[] interface={UserService.class};
           
         
        Proxy.newInstance(JDKProxy.class.getClassLoader,interfaces,new InvocationHandler{
            
           public Object invoke(Object obj,Method method,Object[] args){

            //方法之前要做的事

            //方法的执行
             method.invoke(obj,args);
        

             //方法之后要做的事
    
            } 
        });

    }



}

 通过创建一个实现类来做实际代理

public class ProxyClass implements InvocationHandler{

       private Object obj;
       public ProxyClass(Object obj){
        
         this.obj=obj;
        }
    public Object invoke(Object obj,Method method,Object[] args){

        //方法之前要做的事

        //方法的执行
         method.invoke(obj,args);
        

         //方法之后要做的事
    
    }

}

第二种,通过CGLIB动态代理 

在没有接口的时候,使用cglib动态代理,可以通过创建当前类的子类的代理对象,实现增强

Spring AOP操作术语

连接点

类中的那些方法可以被增强,这些方法被称为连接点

切入点

类中实际被增强的方法,称为切入点

切面

执行的具体业务逻辑

织入

将通知应用到目标对象,来创建新的代理对象的过程

   编译期织入,这要求使用特殊的Java编译器。
   类装载期织入,这要求使用特殊的类装载器。
   动态代理织入,在运行期为目标类添加增强生成子类的方式。
   Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。

通知

实际增强的逻辑部分,被称为通知

通知可以被分为

开启aspect生成代理对象

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

通过注解的方式

@EnableAspectjAutoProxy(proxyTargetClass=true)

 前置通知 

   基于注解实现

public class Sloution{

    
    @Before(value="execution(* com.alpaca.aop.User.add(..))")
    public void  before(){

        System.out.println("before .... ");         
    }

}

基于xml实现

<bean id="userService" class="com.alpaca.aop.UserService"></bean>

<bean id="userServicePorxy" class="com.alpaca.aop.UserServiceProxy"></bean>


<aop:config>
<!-- 切入点-->
<aop:pointcut id="p" expression="* com.alpaca.aop.UserService.buy(..)" />

<!-- 切面-->
<aop:aspect ref="userServiceProxy"> 
     <!-- 具体实现的方法-->
    <aop:before method="before" pointcut-ref="p"></aop:before>
</aop:aspect>

</aop:config>

   后置通知

  基于注解实现

public class Sloution{

    
    @After(value="execution(* com.alpaca.aop.User.add(..))")
    public void  after(){

        System.out.println("after .... ");         
    }

}

   环绕通知

基于注解实现

public class Sloution{

    
    @Around(value="execution(* com.alpaca.aop.User.add(..))")
    public void  around(){

        System.out.println("around.... ");         
    }

}

   异常通知

基于注解实现

public class Sloution{

    
    @AfterThrowing(value="execution(* com.alpaca.aop.User.add(..))")
    public void  afterThrow(){

        System.out.println("throw.... ");         
    }

}

注解中的切入点,可以声明一个公共的切入点 ,也就是抽取公共的切入点

public class slution{

   
  @PoinCut(vlaue="execution(* com.alpaca.aop.User.add)")
  public void  demo(){
      
  }
    
  @Before(value="demo")
  public void  before(){

        System.out.println("before .... ");         
  }


}

如果有多个增强类对同一个方法进行增强,可以设置优先级

通过@Order(1) 数字越小,优先级越高

切面

是动作,将通知应用到切入点中

具体实现

通过AspectJ 和 SpringAOP搭配使用

Spring JDBC(不再细说)

通过jdbcTemplate实现增删改查

配置数据源

创建JDBCTemplate对象

<!-- 设置数据源 -->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">

<property name="username" value="${jdbc-username}"></property>

<property name="password" value="${jdbc-password}"></property>

<property name="driverClassName" value="${jdbc-driverClassName}"></property>

<property name="url" value="${jdbc-url}"></property>

</bean>


<!-- 配置spring事务管理器 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" 
id="DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"></property>

</bean>

Spring orm

orm

对象和数据库之间的映射框架,早期的Hibernate和现在的Mybatis。MybatisPlus,

其实现的规范也就是JPA(sun官方提出的Java持久化规范)

JPA

它本质上也就是一种orm规范(注意:是规范不是框架),他只提供了相应规范的接口,也就是api

Spring Context

Spring容器的上下文,在soring启动时,会加载所有的bean,将其定义和封装

大体刷新流程

首先准备刷新上下文环境,初始化并加载定义信息(初始化BeanFactory、并加载bean  definitions信息)

然后对beanFactory进行系统配置,提交给BeanFactoryPostProcessors,初始化信息资源,也就是MessageSource、事件广播器、注册事件监听器,最后构造加载单例的Bean,通知生命周期处理器,如果刷新错误就销毁并且修改bean

Spring 事务

事务数据库逻辑上的一组操作,要么都执行,要么都不执行

主要表现为ACID四种特性

原子性:这组操作,不可分割,要么都执行,要么都不执行

一致性:数据库数据的完整性,在事务之前和事务之后,都没有被破坏

隔离性:防止事务在数据库并发执行时,由于相互交叉执行,导致数据不一致

持久性:数据库数据在修改后是永久的,即使数据库宕机

事务的七种传播行为

指当前事务被执行时,采用哪种方式

对事务的要求程度从大到小排序:

mandatory / supports / required / requires_new / nested / not supported / never

PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,有的话就加入,是Spring默认的事务传播行为。


PROPAGATION_SUPPORTS:如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。(supports支持,有则加入,没有就不管了,非事务运行)


PROPAGATION_MANDATORY:如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。(mandatory强制性,有则加入,没有异常)


PROPAGATION_REQUIRES_NEW:无论当前存不存在事务,都创建新事务。(requires_new需要新的,不管有没有,直接创建新事务)


PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。(not supported不支持事务,存在就挂起)


PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。(never不支持事务,存在就异常)


PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。(nested存在就在嵌套的执行,没有就找是否存在外面的事务,有则加入,没有则新建)
 

事务的四种隔离级别

读未提交

当前事务在写操作时,不允许其他事务写操作,但允许其他事务读操作,那么就容易出现脏读

提交读

事务在读操作,允许其他事务进行读操作,也就是读完数据后,数据可能已经发生改变,会出现幻读和不可重复读,而写事务不允许其他事务进行读写,可以避免脏读

可重复读

事务在读操作时,允许其他事务读,但不允许写,允许多次读,在写事务时,不允许读写,但偶尔可能会出现幻读

串行化(序列化)

最高级的隔离级别,它要求事务序列化执行,事务只能一个一个执行,无法并发执行

编程式事务

 xml配置方式

<!-- 配置spring事务管理器 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="DataSourceTransactionManager">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>

</bean>
<tx:advice id="txadvice" transaction-manager="DataSourceTransactionManager">

<tx:attributes>

<tx:method name="*" propagation="REQUIRED"/>

</tx:attributes>

</tx:advice>
<!-- 如何配置事务管理器的工作 -->
<aop:config proxy-target-class="true">

<aop:pointcut expression="execution(* com.hx.service.*.*(..))" id="txcut"/>

<aop:advisor advice-ref="txadvice"   pointcut-ref="txcut"/>

</aop:config>

代码方式

public void testTransaction() {

        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {

                try {

                    // ....  业务代码
                } catch (Exception e){
                    //回滚
                    transactionStatus.setRollbackOnly();
                }

            }
        });
}

注解式事务

@Transaction失效场景

在方法修饰符不是public时,会失效

在rooback回滚时,捕捉到异常,会失效

在同个类中调用被@Transaction标识的方法,不会执行,只有在当前事务方法被其他类以外的方法调用时,才会被spring aop的代理对象进行拦截管理

spring web(MVC执行流程在webFLux中)

spring web MVC和spring web的区别

sprin web mvc 主要是对mvc的支持,包括restful协议、国际化等模块,依赖web模块,在引入webmvc就会传递引入web模块

spring-web提供核心的HTTP集成,包括一些方便的Servlet过滤器,Spring HTTP Invoker,用于与其他Web框架和HTTP技术集成的基础设施。

spring5新功能(WebFlux)

webflux和spring mvc功能相似

异步和同步:主要针对调用者而言,调用者发送请求后,一直等待对方回应,就是同步,如果发送后,不等对方回应就去做其他事情就是异步

阻塞和非阻塞:主要针对被调用者,被调用者在接收到请求后,直到处理完任务后,才会给出反应,就是阻塞,如果是在未做完任务,就给出反应就是非阻塞

webFlux新特点:

非阻塞式

函数式

函数式,就不多提,之前写过

stream流

public class Test{

    public static void main(String[] args){
        //数组
        Long[] arr={"","",""};
        Arrays.stream(arr).forEach(System.out:println);     、
        //集合
        List<Integer> list=new ArrayList<>();
        list.stream.forEach(System.out:println);
        //
         Stream.of(arr).forEach(System.out:println);
        //迭代器打印10个元素
        Stream.iterate(1,i->i+1).limit(10).forEach(System.out:println);
        //generate
        Stream.generate(new Random().nextInt(10)).limit(10).forEach(System.out:println);
       
    }

}

采用异步响应式编程

响应式:面向数据流和变化的范式

SpringMVC和webflux的区别

mvc是命令式编程,而webflux是响应式编程

 Spring Web MVC 是 专为 Servlet API 和 Servlet 容器构建。反应式堆栈 Web 框架, Spring WebFlux,后来在 5.0 版中添加。它是完全非阻塞的,支持反应流背压,并在以下服务器上运行: Netty、Undertow 和 Servlet 3.1+ 容器。

Observe和Observeable的理解

这里涉及到小丑和观众,小丑的数量是1,而观众的数量是n,观众会对小丑的举动做出相应的反应。这里很符合观察者模式的场景,因此,我们需要创建一个小丑类Clown,作为被观察对象,因此需要继承Observable类,同时具有表演的行为,退场的行为;同时需要创建一个观众类Viewer,作为观察者,因此需要实现Observer接口,同时观众具有喝彩的行为,倒喝彩的行为,退场的行为,每个观众还对应一个座位号。

public class Observe extends Observable {
    
    public static void main(String[] args) {
        Observe observe = new Observe();
        observe.addObserver((o,arg)->{
            System.out.println("发生变化");
        });
        observe.addObserver((o,arg)->{
            System.out.println("被观察者通知,发生变化");
        });
        
        observe.setChanged();//告知数据要发生变化
        observe.notifyObservers();//告知所有观察者
    }
}

webflux是基于reactor实现,而reactor是满足Reactive规范的框架

reactor的观察者模式废弃了java8的是基于java9的java.util.current.flux实现的,是发布和订阅模式

reactor有两个核心类Mono 和Flux,这两个类实现接口Publisher,提供丰富操作符。Flux对象实现发布者,返回N个元素;Mono实现发布者,返回0或1个元素

Flux和Mono都是数据流的发布者,使用Flux和Mono可以发出三中信号:元素值、错误信号、完成信号,错误信号和完成信号都是终止信号,终止信号是告诉订阅者数据流结束了,错误信号终止数据流同时会把错误信息传递给订阅者

使用时,需要添加依赖

<dependency>
      <groupId>io.projectreactor</groupId>
      <artifactId>reactor-core</artifactId>
      <version>3.3.4.RELEASE</version>
</dependency>

三中信号流的特点

错误信号和完成信号都是终止信号,不能直接共享

如果没有发送任何元素值,而是直接发送错误或者完成信号,表示是空数据流

如果没有错误信号,没有完成信号,表示是无限数据流

just声明

调用just琥珀这其他方法只是声明数据流,数据流并没有发出,只是进行订阅之后才会触发数据流,不订阅什么都不会发生

public class Test{
        
        public  static void main(String[] args){

         //只是声明 ,输出还需要订阅
        Flux.just(1,2,3,4,5).subscribe(System.out::print);
        Flux.just(1).subscribe(System.out::print);
    }
}

其他方式声明

public  class Test{

     public static  void main(String[] args){
        //需要包装类数组
        Integer[] array={1,2,3,4,5};
        //声明数组
        Flux.fromArray(array);
        //声明集合
        Flux.fromIterable(Arrays.asList(array));
        //声明Stream流
        Flux.fromStream(Stream.of(array));
      }
}

 操作符

对数据流进行一道道操作,称为操作符,比如工厂流水线

 1.map将元素映射为新元素

2.flatMap将元素映射为流(先将各个元素转变为各个流,再将流合并成一个大流,最后输出)

Netty

springWebFlux是基于reactor的,而reactor是默认使用Netty容器的,Netty是一个异步非阻塞框架,采用的是NIO模型

NIO(同步非阻塞)

WebFlux

 底层使用的DispatcherHandler实现了 webHandler

public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    @Nullable
    private List<HandlerMapping> handlerMappings;//负责查询相应的处理器
    @Nullable
    private List<HandlerAdapter> handlerAdapters; //真正负责响应处理
    @Nullable
    private List<HandlerResultHandler> resultHandlers; //响应结果处理
}
public interface WebHandler {
    Mono<Void> handle(ServerWebExchange var1);
}

 执行的Handler如下

public class DispatcherHandler implements WebHandler, ApplicationContextAware {



public Mono<Void> handle(ServerWebExchange exchange) { //获取http请求响应消息
        //判断是否映射器为空,为空就创建一个createNotFoundError()异常
        return this.handlerMappings == null ? this.createNotFoundError() : 

Flux.fromIterable(this.handlerMappings).concatMap((mapping) -> {

            return mapping.getHandler(exchange);

        }).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> {

            //执行具体的Mapping,也就是业务
            return this.invokeHandler(exchange, handler); 

        }).flatMap((result) -> {
            return this.handleResult(exchange, result); //将执行结果返回
        });
    }
}

WebFlux写法

import com.middletest.jhdmiddletest.entity.User;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public interface UserService {

    /**
     *   根据id查询用户
     * @param id
     * @return
     */
    public Mono<User> getUserById(Integer id);

    /**
     *   返回全部用户
     * @return
     */
    public Flux<User> getAllUser();

    /**
     *   添加用户
     * @param userMono
     * @return
     */

    public Mono<Void> addUser(Mono<User> userMono);
}
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {


     private static Map<Integer,User> users= new HashMap<Integer,User>(){
         {
             put(1,new User(1,"lisi",26,"呼兰区24号大街"));
             put(2,new User(2,"lisi",27,"呼兰区24号大街"));
             put(3,new User(3,"lisi",24,"呼兰区24号大街"));
         }
     };
    @Override
    public Mono<User> getUserById(Integer id) {

        return Mono.just(users.get(id));
    }

    @Override
    public Flux<User> getAllUser() {
        return Flux.fromIterable(users.values());
    }

    @Override
    public Mono<Void> addUser(Mono<User> userMono) {
        return userMono.doOnNext(user->{
            Integer id=users.size()+1;
            users.put(id,user);
            //记得写终止信号,不然是一个无线数据流
        }).thenEmpty(Mono.empty());
    }
}

WebFlux函数式编程

在使用函数式编程时,需要自己初始化服务器

它的函数式编程实现了两个接口

RouterFunction(路由处理,实现路由功能,请求转发给对应的Handler)

HandlerFunction(处理函数,处理请求生成响应的函数)

webflux的请求和相应已经变,是ServeRequest、ServeResponse

第一步创建注解编程模型

第二步创建handler

package com.alpaca.handler;

import com.alpaca.entity.User;
import com.alpaca.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class UserHandler {
    @Autowired
    private UserService userService;

    /**
     * 查询
     * @param request
     * @return
     */
    public Mono<ServerResponse> getUserById(ServerRequest request){
        Integer id= Integer.parseInt(request.pathVariable("id"));
        Mono<User> userMono = userService.getUserById(id);
        Mono<ServerResponse> notfound = ServerResponse.notFound().build();

        return userMono.flatMap(user->ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject(user)))
                .switchIfEmpty(notfound);
    }
    public Mono<ServerResponse> getAllUsers(){

        Flux<User> allUser = userService.getAllUser();
       return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(allUser,User.class);
    }
    public Mono<ServerResponse> addUser(ServerRequest request){
        Mono<User> userMono = request.bodyToMono(User.class);
        return   ServerResponse.ok().build(userService.addUser(userMono));
    }
}

 第三步 初始化服务器,完成Router

package com.alpaca.route;

import com.alpaca.handler.UserHandler;
import com.alpaca.service.UserService;
import com.alpaca.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;


import org.springframework.web.reactive.function.server.RequestPredicates;
import  org.springframework.web.reactive.function.server.RouterFunctions;
import reactor.netty.http.server.HttpServer;

import java.io.IOException;


public class Server {


    private UserService userService=new UserServiceImpl();

    private UserHandler userHandler=new UserHandler(userService);

    public RouterFunction router(){

      return RouterFunctions.route(
              RequestPredicates.GET("/getUser/{id}").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),userHandler::getUserById)
              .andRoute(RequestPredicates.GET("/users").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)),userHandler::getAllUsers);
    }

    /**
     * 完成服务器适配
     */
    public void createReactorServer(){
        RouterFunction router=router();
        HttpHandler httpHandler = RouterFunctions.toHttpHandler(router);
        ReactorHttpHandlerAdapter handlerAdapter = new ReactorHttpHandlerAdapter(httpHandler);

        //创建服务器
        HttpServer httpServer=HttpServer.create();
        httpServer.handle(handlerAdapter).bindNow();
    }

    public static void main(String[] args) throws IOException {
        Server server = new Server();
        server.createReactorServer();
        System.out.println("enter to  exit");
        System.in.read();
    }
}

调用客户端

可以直接使用浏览器,也可以自己直接用代码实现客户端

import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class Client {

    public static void main(String[] args) {
        
        WebClient webClient=WebClient.create("http://localhost:999");
        
        User user=webClient.get().uri("getUser/{id}","1")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve().bodyToMono(User.class).block();
        System.out.println(user);
        
        Iterable<User> users = webClient.get().uri("/users").accept(MediaType.APPLICATION_JSON)
                .retrieve().bodyToFlux(User.class).toIterable();
        while (users.iterator().hasNext()){
            System.out.println(users.iterator().next());
        }
        Flux<User> userFlux = webClient.get().uri("/users").accept(MediaType.APPLICATION_JSON)
                .retrieve().bodyToFlux(User.class);
        userFlux.buffer().doOnNext(System.out::println);
    }

spring webflux在流程上和spring MVC的区别

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羊驼有点累

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值