• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
lvym
博客园    首页    新随笔    联系   管理    订阅  订阅
Spring5笔记

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

◆目的:解决企业应用开发的复杂性

◆创建原因:软件开发的复杂性

◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
◆范围:任何Java应用
◆Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。
Spring有两个核心部分:IOC和Aop
(1)IOC:控制反转,把创建对象过程交给Spring进行管理
(2)Aop:面向切面,不修改源代码进行功能增强
Spring特点
(1)方便解耦,简化开发
(2)Aop编程支持
(3)方便程序测试
(4)方便和其他框架进行整合
(5)方便进行事务操作
(6)降低API开发难度
什么是IOC
(1)控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
(2)使用IOC目的:为了耦合度降低
IOC底层原理
(1)xml解析、工厂模式、反射

 

 IOC(BeanFactory接口)

1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

2、Spring提供IOC容器实现两种方式:(两个接口)

(1)BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员进行使用* 加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象(2)ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用* 加载配置文件时候就会把在配置文件对象进行创建

Bean管理指的是两个操作
(1)Spring创建对象
(2)Spirng注入属性
Bean管理操作有两种方式
(1)基于xml配置文件方式实现
(2)基于注解方式实现
基于xml方式创建对象

 <bean id=".." class="..."></bean>
(1)在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
(2)在bean标签有很多属性,介绍常用的属性* id属性:唯一标识* class属性:类全路径(包类路径)
(3)创建对象时候,默认也是执行无参数构造方法完成对象创建
基于xml方式注入属性
(1)DI:依赖注入,就是注入属性
第一种注入方式:使用set方法进行注入
1)创建类,定义属性和对应的set方法
2)在spring配置文件配置对象创建,配置属性注入
 
 <bean id=".." class="...">
        <!-- 要事先在实体创建   使用property完成属性注入name:类里面属性名称value:向属性注入的值-->
        <property name=".." value=".."></property>
    </bean>

第二种注入方式:使用有参数构造进行注入

(1)创建类,定义属性,创建属性对应有参数构造方法

bean id=".." class="...">
        <!--要事先在实体类中先创建构造参数-->
      <constructor-arg name="" value=""></constructor-arg>
    </bean>

字面量

(1)null值

<!--null值-->

<property name="...">

<null/>

</property>

属性值包含特殊符号

<!--属性值包含特殊符号 1 把<>进行转义&lt; &gt; 2 把带特殊符号内容写到CDATA-->

<property name="..">

<value><![CDATA[<<...>>]]>

</value>

</property>

注入属性-外部bean

1)创建两个类service类和dao类

2)在service调用dao里面的方法

3)在spring配置文件中进行配置

public class UserService{

//创建UserDao类型属性,生成set方法

private UserDao userDao;

public void setUserDao(UserDao userDao){

this.userDao = userDao;}

public void add() { System.out.println("service add..............."); userDao.update();}} <!--1 service和dao对象创建--> <bean id="userService" class="..."> <!--注入userDao对象name属性:类里面属性名称ref属性:创建userDao对象bean标签id值--> <property name="userDao" ref="userDaoImpl"></property></bean> <bean id="userDaoImpl" class="..."></bean>

注入属性-级联赋值

IOC操作Bean管理(xml注入集合属性)

把集合注入部分提取出来

       使用util标签完成list集合注入提取

 

注入属性-内部bean

1)一对多关系:部门和员工一个部门有多个员工,一个员工属于一个部门部门是一,员工是多
2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示

//部门类
public class Dept {
private String dname;
public void setDname(String dname) {this.dname = dname;}}

//员工类
public class Emp {
private String ename;
private String gender;
//员工属于某一个部门,使用对象形式表示
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;}
public void setEname(String ename) {
this.ename = ename;}
public void setGender(String gender) {this.gender = gender;
}}

(3)在spring配置文件中进行配置<!--内部bean-->
<bean id="emp" class="...Emp">
<!--设置两个普通属性-->
<property name="" value="lucy"></property>
<property name="" value=""></property>
<!--设置对象类型属性-->
<property name="dept">
<bean id="dept" class="...Dept">
<property name="dname" value=""></property>
</bean>
</property>
</bean>

IOC操作Bean管理(FactoryBean)

1、Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)

2、普通bean:在配置文件中定义bean类型就是返回类型

3、工厂bean:在配置文件定义bean类型可以和返回类型不一样

第一步创建类,让这个类作为工厂bean,实现接口FactoryBean

第二步实现接口里面的方法,在实现的方法中定义返回的bean类型

public class MyBean implements FactoryBean<Course> {

//定义返回bean
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("abc");
return course;}
@Override
public Class<?> getObjectType() {
return null;}
@Override
public boolean isSingleton() {
return false;}}
//定义的是myBean
<bean id="myBean" class="...factorybean.MyBean"></bean>
@Testpublic void test3() {
ApplicationContext context =new ClassPathXmlApplicationContext("bean3.xml");
//返回的是 Course
Course course = context.getBean("myBean", Course.class);System.out.println(course);}

IOC操作Bean管理(bean作用域)

1、在Spring里面,设置创建bean实例是单实例还是多实例

2、在Spring里面,默认情况下,bean是单实例对象

如何设置单实例还是多实例

(1)在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例

(2)scope属性值第一个值默认值,singleton,表示是单实例对象第二个值prototype,表示是多实例对象

<bean id=".." class="..." scope="prototype"></bean>

singleton和prototype区别

第一singleton单实例,prototype多实例

第二设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象

       设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法时候创建多实例对象

IOC操作Bean管理(bean生命周期)
1、生命周期
(1)从对象创建到对象销毁的过程
2、bean生命周期
(1)通过构造器创建bean实例(无参数构造)
(2)为bean的属性设置值和对其他bean引用(调用set方法)
(3)调用bean的初始化的方法(需要进行配置初始化的方法)
(4)bean可以使用了(对象获取到了)
(5)当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
//无参数构造
public Orders() {
System.out.println("第一步执行无参数构造创建bean实例");}
private String oname;
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步调用set方法设置属性值");}

//创建执行的初始化的方法
public void initMethod() {
System.out.println("第三步执行初始化的方法");}

//创建执行的销毁的方法
public void destroyMethod() {
System.out.println("第五步执行销毁的方法");}}
<bean id="orders" class="....bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="手机"></property>
</bean>
@Test
public void testBean3() {

ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步获取创建bean实例对象");
System.out.println(orders);
//手动让bean实例销毁
context.close();

bean的后置处理器,实现接口BeanPostProcessor,创建后置处理器

bean生命周期有七步

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

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

(3)把bean实例传递bean后置处理器的方法postProcessBeforeInitialization

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

(5)把bean实例传递bean后置处理器的方法postProcessAfterInitialization

(6)bean可以使用了(对象获取到了)

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

 什么是自动装配
(1)根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入
           根据属性名称自动注入
<!--实现自动装配bean标签属性autowire,配置自动装配autowire属性常用两个值:byName根据属性名称注入,注入值bean的id值和类属性名称一样。byType根据属性类型注入-->
<bean id="emp" class="....autowire.Emp" autowire="byType">
不需要这样赋值:
<bean id=".." class="...">
<!--使用property完成属性注入name:类里面属性名称value:向属性注入的值-->
<property name=".." value=".."></property>
</bean>

<!--引入外部属性文件--><context:property-placeholder location="classpath:jdbc.properties"/>

 什么是注解
(1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值..)
(2)使用注解,注解作用在类上面,方法上面,属性上面
(3)使用注解目的:简化xml配置
Spring针对Bean管理中创建对象提供注解
(1)@Component
(2)@Service
(3)@Controller
(4)@Repository
上面四个注解功能是一样的,都可以用来创建bean实例
 基于注解方式实现对象
<!--开启组件扫描
1 如果扫描多个包,多个包使用逗号隔开  2 扫描包上层目录-->
<context:component-scan base-package="com..."></context:component-scan>
第三步创建类,在类上面添加创建对象注解
//在注解里面value属性值可以省略不写,
//默认值是类名称,首字母小写
//UserService --userService
 
开启组件扫描细节配置
<!--示例1
use-default-filters="false" 表示现在不使用默认filter,自己配置filtercontext:include-filter ,设置扫描哪些内容-->
<context:component-scan base-package="com...." use-default-filters="false">
<context:include-filter type="annotation"expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--示例2下面配置扫描包所有内容context:exclude-filter:设置哪些内容不进行扫描-->
<context:component-scan base-package="com...">
<context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller"/></context:component-scan>

基于注解方式实现属性注入

1)@Autowired:根据属性类型进行自动装配

第一步把service和dao对象创建,在service和dao类添加创建对象注解

第二步在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解

 2)@Qualifier:根据名称进行注入
  这个@Qualifier注解的使用,和上面@Autowired一起使用
 
 
//添加注入属性注解
@Autowired
//根据类型进行注入
@Qualifier(value = "userDaoImpl1")
//根据名称进行注入
3)@Resource:可以根据类型注入,可以根据名称注入
//@Resource //根据类型进行注入
@Resource(name = "userDaoImpl1") //根据名称进行注入

4)@Value:注入普通类型属性
@Value(value = "abc")

 什么是AOP

(1)面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

 AOP底层使用动态代理
(1)有两种情况动态代理
第一种有接口情况,使用JDK动态代理
1.使用JDK动态代理,使用Proxy类里面的方法创建代理对象
(1)调用newProxyInstance方法
方法有三个参数:
第一参数,类加载器
第二参数,增强方法所在的类,这个类实现的接口,支持多个接口
第三参数,实现这个接口InvocationHandler,创建代理对象,写增强的部分
2.编写JDK动态代理代码
 (1)创建接口,定义方法
package com.lvym.spring.dao;
public interface UserDao {
    public int add(int a, int b);

    public String update(String id);
} 
 (2)创建接口实现类,实现方法
package com.lvym.spring.dao.impl;
import com.lvym.spring.dao.UserDao;

public class UserDaoimpl implements UserDao {
    public int add(int a, int b) {
        System.out.println("执行add方法----");
        return a + b;
    }

    public String update(String id) {
        return id;
    }
}
(3)使用Proxy类创建接口代理对象

package
com.lvym.spring.proxy; import com.lvym.spring.dao.UserDao; import com.lvym.spring.dao.impl.UserDaoimpl; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; public class JdkProxy { public static void main(String[] args) { //创建接口实现类代理对象 Class[] interfaces = {UserDao.class}; UserDaoimpl userDao = new UserDaoimpl(); UserDao dao = (UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); int result = dao.add(1, 2); System.out.println("result:" + result); } } //创建代理对象代码 class UserDaoProxy implements InvocationHandler { //1 把创建的是谁的代理对象,把谁传递过来//有参数构造传递 这里表示的是 UserDaoimpl private Object obj; public UserDaoProxy(Object obj) { this.obj = obj; } //增强的逻辑 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法之前执行...." + method.getName() + " :传递的参数..." + Arrays.toString(args)); //被增强的方法执行 Object res = method.invoke(obj, args); //方法之后 System.out.println("方法之后执行...." + obj); return res; } }

第二种没有接口情况,使用CGLIB动态代理

     创建子类的代理对象,增强类的方法

 
 

 

 

 Spring框架一般都是基于AspectJ实现AOP操作

(1)AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spirng框架一起使用,进行AOP操作

基于AspectJ实现AOP操作

(1)基于xml配置文件实现

(2)基于注解方式实现(使用)

语法结构:execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]) )

    在增强类上面添加注解@Aspect

//前置通知@Before(value = "execution(* ....r.add(..))")

//后置通知(返回通知)@AfterReturning

//最终通知@After

//异常通知@AfterThrowing

//环绕通知@Around

/相同切入点抽取@Pointcut(value = "execution(* ....r.add(..))")

 在spring配置文件中开启生成代理对象

<!--开启Aspect生成代理对象-->

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

 有多个增强类多同一个方法进行增强,设置增强类优先级(1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高

@Order(1)

public class PersonProxy

 
<!--配置aop增强-->
<aop:config>
<!--切入点-->
<aop:pointcut id="p" expression="execution(* ...y(..))"/>
<!--配置切面-->
<aop:aspect ref="bookProxy">
<!--增强作用在具体的方法上-->
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>

 

 什么是JdbcTemplate
(1)Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库操作
 
什么事务
(1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
            事务四个特性(ACID)(1)原子性(2)一致性(3)隔离性(4)持久性    
 
 事务操作(Spring事务管理介绍)
1、事务添加到JavaEE三层结构里面Service层(业务逻辑层)
2、在Spring进行事务管理操作
(1)有两种方式:编程式事务管理和声明式事务管理(使用)
3、声明式事务管理
(1)基于注解方式(使用)
<!--创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>

<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

 

(2)基于xml配置文件方式
<!--1 创建事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2 配置通知-->
<tx:advice id="txadvice">
<!--配置事务参数-->
<tx:attributes>
<!--指定哪种规则的方法上面添加事务-->
<tx:method name="accountMoney" propagation="REQUIRED"/>
<!--<tx:method name="account*"/>-->
</tx:attributes></tx:advice>
<!--3 配置切入点和切面-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pt" expression="execution(* .....*(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/></aop:config>

 

4、在Spring进行声明式事务管理,底层使用AOP原理

 

 

 

 

 
 

 

 

timeout:超时时间
(1)事务需要在一定时间内进行提交,如果不提交进行回滚
(2)默认值是-1 ,设置时间以秒单位进行计算
readOnly:是否只读
(1)读:查询操作,写:添加修改删除操作
(2)readOnly默认值false,表示可以查询,可以添加修改删除操作
(3)设置readOnly值是true,设置成true之后,只能查询
rollbackFor:回滚
(1)设置出现哪些异常进行事务回滚
noRollbackFor:不回滚
(1)设置出现哪些异常不进行事务回滚
 
 1.整个Spring5框架的代码基于Java8,运行时兼容JDK9,许多不建议使用的类和方法在代码库中删除
2.Spring 5.0框架自带了通用的日志封装
(1)Spring5已经移除Log4jConfigListener,官方建议使用Log4j2
(2)Spring5框架整合Log4j2
 
<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,可以看到log4j2内部各种详细输出-->
<configuration status="INFO"><!--先定义所有的appender-->
<appenders><!--输出日志信息到控制台-->
<console name="Console" target="SYSTEM_OUT"><!--控制日志输出的格式-->
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} -%msg%n"/>
</console>
</appenders>
<!--然后定义logger,只有定义logger并引入的appender,appender才会生效-->
<!--root:用于指定项目的根日志,如果没有单独指定Logger,则会使用root作为默认的日志输出-->
<loggers>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>

Spring5框架核心容器支持  @Nullable注解

(1)@Nullable注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空

(2)注解用在方法上面,方法返回值可以为空

 (3)注解使用在方法参数里面,方法参数可以为空
 (4)注解使用在属性上面,属性值可以为空
 
 Spring5核心容器支持函数式风格GenericApplicationContext
Spring5支持整合JUnit5
 
 
@ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:bean1.xml")
使用一个复合注解替代上面两个注解完成整合
@SpringJUnitConfig(locations = "classpath:bean1.xml")

Spring5框架新功能(Webflux)

  (1)是Spring5添加新的模块,用于web开发的,功能和SpringMVC类似的,Webflux使用当前一种比较流程响应式编程出现的框架。

(2)使用传统web框架,比如SpringMVC,这些基于Servlet容器,Webflux是一种异步非阻塞的框架,异步非阻塞的框架在Servlet3.1以后才支持,核心是基于Reactor的相关API实现的。
(3)解释什么是
异步非阻塞*
异步和同步*
非阻塞和阻塞**
上面都是针对对象不一样**
异步和同步针对调用者,调用者发送请求,如果等着对方回应之后才去做其他事情就是同步,如果发送请求之后不等着对方回应就去做其他事情就是异步**
阻塞和非阻塞针对被调用者,被调用者受到请求之后,做完请求任务之后才给出反馈就是阻塞,受到请求之后马上给出反馈然后再去做事情就是非阻塞
(4)Webflux特点:第一非阻塞式:在有限资源下,提高系统吞吐量和伸缩性,以Reactor为基础实现响应式编程
                                第二函数式编程:Spring5框架基于java8,Webflux使用Java8函数式编程方式实现路由请求
 (5)比较SpringMVC
第一两个框架都可以使用注解方式,都运行在Tomet等容器中
第二SpringMVC采用命令式编程,Webflux采用异步响应式编程

 什么是响应式编程

     (1) 响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似"=B1+C1"的公式,而包含公式的单元格的值会依据其他单元格的值的变化而变化。

 (2)Java8及其之前版本* 提供的观察者模式两个类Observer和Observable

 
public class ObserverDemo extends Observable {

public static void main(String[] args) {
ObserverDemo observer = new ObserverDemo();

//添加观察者
observer.addObserver((o,arg)->{System.out.println("发生变化");});
observer.addObserver((o,arg)->{System.out.println("手动被观察者通知,准备改变");});
observer.setChanged();

//
数据变化
observer.notifyObservers();
//通知}}

响应式编程(Reactor实现)

(1)响应式编程操作中,Reactor是满足Reactive规范框架

(2)Reactor有两个核心类,Mono和Flux,这两个类实现接口Publisher,提供丰富操作符。Flux对象实现发布者,返回N个元素;Mono实现发布者,返回0或者1个元素(3)Flux和Mono都是数据流的发布者,使用Flux和Mono都可以发出三种数据信号:元素值,错误信号,完成信号,错误信号和完成信号都代表终止信号,终止信号用于告诉订阅者数据流结束了,错误信号终止数据流同时把错误信息传递给订阅者

 
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.1.5.RELEASE</version>
</dependency>
public static void main(String[] args) {

//just方法直接声明

Flux.just(1,2,3,4);Mono.just(1);

//其他的方法

Integer[] array = {1,2,3,4};

Flux.fromArray(array);

List<Integer> list = Arrays.asList(array);

Flux.fromIterable(list);

Stream<Integer> stream = list.stream();

Flux.fromStream(stream);}
 

(4)三种信号特点

* 错误信号和完成信号都是终止信号,不能共存的

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

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

(5)调用just或者其他方法只是声明数据流,数据流并没有发出,只有进行订阅之后才会触发数据流,不订阅什么都不会发生的

(6)操作符
* 对数据流进行一道道操作,成为操作符
第一map 元素映射为新元素
第二flatMap 元素映射为流
      把每个元素转换流,把转换之后多个流合并大的流
 
SpringWebflux执行流程和核心API
    (1)SpringWebflux基于Reactor,默认使用容器是Netty,Netty是高性能的NIO框架,异步非阻塞的框架
2)SpringWebflux执行过程和SpringMVC相似的
* SpringWebflux核心控制器DispatchHandler,实现接口WebHandler
* 接口WebHandler有一个方法
 (3)SpringWebflux里面DispatcherHandler,负责请求的处理* HandlerMapping:请求查询到处理的方法* HandlerAdapter:真正负责请求处理* HandlerResultHandler:响应结果处理
(4)SpringWebflux实现函数式编程,两个接口:RouterFunction(路由处理)和HandlerFunction(处理函数)
5、SpringWebflux(基于注解编程模型)
SpringWebflux实现方式有两种:注解编程模型和函数式编程模型使用注解编程模型方式,和之前SpringMVC使用相似的,只需要把相关依赖配置到项目中,SpringBoot自动配置相关运行容器,默认情况下使用Netty服务器
SpringMVC方式实现,同步阻塞的方式,基于SpringMVC+Servlet+Tomcat
SpringWebflux方式实现,异步非阻塞方式,基于SpringWebflux+Reactor+Netty
 
    注解式
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
               </dependency>
package com.lvym.springwebflux.server;
import com.lvym.springwebflux.entity.User;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public interface UserService {

    Mono<User> getUserByid(int id);
    Flux<User> getAll();
    Mono<Void> insertUser(Mono<User> userMono);
}
package com.lvym.springwebflux.server.impl;
import com.lvym.springwebflux.entity.User;
import com.lvym.springwebflux.server.UserService;
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 {
    //创建map集合存储数据
    private final Map<Integer,User> users = new HashMap<>();

    public UserServiceImpl(){
        this.users.put(1,new User("lucy","男",20));
        this.users.put(2,new User("mary","女",30));
        this.users.put(3,new User("jack","女",50));
    }

    /**
     * 根据id查询
     * @param id
     * @return
     */
    @Override
    public Mono<User> getUserByid(int id) {
        return Mono.justOrEmpty(this.users.get(id));
    }

    /**
     * 查询所有用户
     * @return
     */
    @Override
    public Flux<User> getAll() {
        return Flux.fromIterable(this.users.values());
    }

    /**
     *  添加
     * @param userMono
     * @return
     */
    @Override
    public Mono<Void> insertUser(Mono<User> userMono) {
               //先把值取出来再放回map
        return userMono.doOnNext(user -> {
            int id = users.size() + 1;
            this.users.put(id,user);
        }).thenEmpty(Mono.empty());
    }
}
package com.lvym.springwebflux.controller;
import com.lvym.springwebflux.entity.User;
import com.lvym.springwebflux.server.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/getUserByid/{id}")
    public Mono<User> getUserByid(@PathVariable int id){
     return userService.getUserByid(id);
    }
    @GetMapping("/getAll")
    public Flux<User> getAll(){
        return userService.getAll();
    }
    @PostMapping("/insertUser")
    public Mono<Void> insertUser(@RequestBody User user){
        Mono<User> userMono = Mono.just(user);
        return userService.insertUser(userMono);
   }
}

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted on 2020-07-07 19:11  lvym777  阅读(165)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3