Spring学习笔记二

三. JdbcTemplate

1.基本概念

Spring框架对Jdbc进行了封装形成了JdbcTemplate,使用它可以很方便的对数据库进行操作。
准备工作:首先要引入相关依赖包

<!--引入依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.8</version>
        </dependency>

        <!--spring-tx:针对事务的一些操作-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.3.8</version>
        </dependency>

        <!--orm可用于对其他各种框架进行整合-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>5.3.8</version>
        </dependency>

其次要对数据库进行操作,自然需要数据库连接池,因此需要配置连接池

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        ">
    <!--配置连接池-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClassName}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.username}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>
    
</beans>


<!--jdbc.properties-->
prop.driverClassName=com.mysql.cj.jdbc.Driver
prop.url=jdbc:mysql:///user_db
prop.username=root
prop.password=root

配置JdbcTemplate对象,注入DataSource

jdbcTemplate是对jdbc的一个封装,在spring中使用jdbcTemplate需要创建jdbcTemplate的对象,查看JdbcTemplate的底层源码,有三个构造器,两个有参构造器一个无参构造器,在有参构造器中需要传入DataSource对象,但是其函数体内是采用setDataSource()方法,因此实际上是采用set方法。

    <!--创建jdbcTemplate对象,注入dataSource-->
    <bean id="jdbcTemplate" class="com.org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean> 

2.一个完整的demo逻辑

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        ">

    <!--开启注解扫描-->
    <context:component-scan base-package="com.alibaba.springExercise1"/>


    <!--配置连接池-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClassName}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.username}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>

    <!--创建jdbcTemplate对象,注入dataSource-->
    <bean id="jdbcTemplate" class="com.org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>
//创建AppClient类和AppService类,在AppClient中注入AppService对象,
//AppService中注入JdbcTemplate对象,AppService中实现一个addUser方法(借助JdbcTemplate对数据库
//进行操作)。AppClient中调用AppService中的addUser方法完成对数据库的操作
//创建一个UserInfo类用于管理数据库中的字段。

//AppClient类
@Component
public class AppClient {

    //AppClient中注入AppService对象
    @Autowired
    private AppService appService;

    public void addUser(UserInfo userInfo){
        appService.addUser(userInfo);
    }
}

//AppService类
@Component
public class AppService {

    //注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;


    public void addUser(UserInfo userInfo) {

        //jdbcTemplate.update()的方法可以实现对数据库的增加和修改操作
        //参数一:SQL语句,参数二:可变参数,设置sql语句值
        //table_User是数据库表的值,values是该表的字段,一个问号表示一个字段
        String sqlInsert = "insert into table_User values(?,?,?)";

        Object[] args = {userInfo.getUserId(), userInfo.getUserName(), userInfo.getUserStatus()};
        int update = jdbcTemplate.update(sqlInsert, args);

        System.out.println(update);
    }
}

//UserInfo类
public class UserInfo {
    private String userId;
    private String userName;
    private String userStatus;

    public void setUserId(String userId) {
        this.userId = userId;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public void setUserStatus(String userStatus) {
        this.userStatus = userStatus;
    }

    public String getUserId() {
        return userId;
    }
    public String getUserName() {
        return userName;
    }
    public String getUserStatus() {
        return userStatus;
    }
}

//测试demo
    @Test
    public void testJdbcTemplate(){

        ApplicationContext context = new ClassPathXmlApplicationContext("beanjdbc.xml");
        AppClient appClient = context.getBean("appClient", AppClient.class);

        UserInfo userInfo = new UserInfo();
        appClient.addUser(userInfo);

    }

使用JdbcTemplate对数据库进行crud操作

    //修改数据库
    public void updateUser(UserInfo userInfo){
        String sqlUpdate = "update table_User set userName=?,userStatus=? where userId=?";
        Object[] args = { userInfo.getUserName(), userInfo.getUserStatus(),userInfo.getUserId()};
        int update = jdbcTemplate.update(sqlUpdate, args);
        System.out.println(update);
    }

    //根据id删除对象
    public void deleteUser(String userId){
        String sqlDelete = "delete from table_user where userId=?";
        Object[] args = {userId};
        int delete = jdbcTemplate.update(sqlDelete, args);
        System.out.println(delete);
    }

    //查询表里面有多少条记录,返回是某个值
    public int findCount(){
        String sqlSelect = "select count(*) from table_user";
        //queryForObject:参数一是sql语句,参数二是返回值类型
        Integer count = jdbcTemplate.queryForObject(sqlSelect, Integer.class);
        return count;
    }

    //查询返回对象
    public UserInfo findObject(String id){
        String sqlObject = "select * from table_user where userId=?";
        Object[] args = {id};
        UserInfo userInfo = jdbcTemplate.queryForObject(sqlObject, new BeanPropertyRowMapper<UserInfo>(UserInfo.class), args);
        return userInfo;
    }

    //查询返回集合
    public List<UserInfo> findAll(){
        String sqlObject = "select * from table_user";
        List<UserInfo> query = jdbcTemplate.query(sqlObject, new BeanPropertyRowMapper<UserInfo>(UserInfo.class));
        return query;
    }

使用JdbcTemplate实现批量操作

    //批量添加
    public void batchAdd(List<Object[]> args){
        String sqlBatchAdd = "insert into table_User value(?,?,?)";
        int[] ints = jdbcTemplate.batchUpdate(sqlBatchAdd, args);
        System.out.println(Arrays.toString(ints));
    }


    public void batchUpdate(List<Object[]> args){
        String sqlBatchupdate = "update table_User set userName=?,userStatus=? where userId=?";
        int[] ints = jdbcTemplate.batchUpdate(sqlBatchupdate, args);
        System.out.println(Arrays.toString(ints));

//        Test
//        List<Object[]> batchArgs = new ArrayList<>();
//        Object[] o1 = {};
//        Object[] o2 = {};
//        batchArgs.add(o1);
//        batchArgs.add(o2);
//        batchUpdate(batchArgs);
    }

    public void batchDelete(List<Object[]> args){
        String sqlDelete = "delete from table_User where userId=?";
        int[] delete = jdbcTemplate.batchUpdate(sqlDelete,args);
        System.out.println(delete);
    }

四. 事务

1. 基本概念

事务是数据库操作的最基本单元,逻辑上是一组操作,要么都成功,如果有一个失败那么所有操作都失败。典型场景:银行转账。A给B转100,只有A少100 B才会多100。如果A少100的时候出现了问题,那么整个过程就会失败。
事务的四个基本特性(ACID)
(1)原子性:整个过程不可分割,要么都成功要么就失败。
(2)一致性:操作前后的总量不变
(3)隔离性:多事务操作时不会产生影响
(4)持久性:事务最终是要进行提交的,提交之后表中数据真正发生变化。

2. Spring中搭建事务操作环境

以银行转账为例,把整个project分为三层,web层、service层、DAO层,其中service层主要进行业务逻辑代码的编写,DAO层进行数据库操作的相关内容。

流程如下:

  1. 创建数据库表,添加记录; 2. 创建service,搭建dao,完成对象创建和属性注入。(service中注入dao,dao中注入jdbcTemplate,jdbcTemplate中注入datasource)参考上面jdbcTemplate的内容中的demo即可,只需要替换一下业务逻辑代码和对数据库的操作代码即可,整体的代码框架是一摸一样的,不赘述。

按照上述逻辑操作,如果不出现异常那么事务是会正常进行的,倘若出现异常,比如A转钱之后突然网络瘫痪或断电,那么此时B并没有收到钱,所以事务就失败。因此需要事务场景引入。Spring进行事务管理操作,有两种方式:编程式事务管理和声明式事务管理。 编程式事务管理一般就是按照以下的代码逻辑写每个事务,比较繁琐:

        try{
            //Step1: 开启事务操作
            //Step2:执行业务操作
            dao.addMoney();
            dao.conductMoney();
            //Step3:没有发生异常时则提交事务
        }catch (Exception e){
            //Step4:发生异常时则事务回滚
        }

一般使用声明式事务管理(基于注解方式/基于xml配置文件方式),底层使用的是AOP原理。

3. Spring声明式事务管理

Spring事务管理API:提供了一个接口,代表事务管理器,该接口针对不同框架都有其实现类。

在代码中支持不同框架对应的相同功能的代码格式:在代码中支持不同框架对应的相同功能,可以先在本代码中声明一个顶层接口(在顶层接口下可以有一些子接口),然后定义实现该接口的实现父类,在该父类下针对不同框架的相同功能进行编写。比如Spring框架下支持操作数据库的不同框架,则创建一个顶层接口,在该顶层接口下有一些实现类,分别针对jdbc、mybatis等框架做一些api管理即可。在这里插入图片描述


#### 3.1 基于注解的声明式事务管理 > 在Spring配置文件中配置事务管理器;在Spring配置文件中开启事务注解@Transactional(首先引入名称空间tx,开启事务注解);在service类上或service类的方法上添加事务注解。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
        ">
    <!--开启注解扫描-->
    <context:component-scan base-package="com.alibaba.*"/>
    
    <!--配置连接池-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClassName}"></property>
        <property name="url" value="${prop.url}"></property>
        <property name="username" value="${prop.username}"></property>
        <property name="password" value="${prop.password}"></property>
    </bean>

    <!--创建jdbcTemplate对象,注入dataSource-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--创建事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--利用名称空间tx开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>
//DAO.java
@Component
public class DAO {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void addMoney() {
        String sqlAdd = "update table_user set money=money+? where user_name=? ";
        Object[] args={100,"marry"};
        int update = jdbcTemplate.update(sqlAdd, args);
        System.out.println(update);
    }

    public void conductMoney() {

        String sqlConduct = "update table_user set money=money-? where user_name=? ";
        Object[] args={100,"lucy"};
        int update = jdbcTemplate.update(sqlConduct, args);
        System.out.println(update);
    }
}

//Service.java
@Component
@Transactional
public class Service {

    @Autowired
    private DAO dao;

    public void countMoney(){
        dao.conductMoney();
        int i = 7/0;//即使这里发生异常,转账人的账户余额不会变
        dao.addMoney();
//        try{
//            //Step1: 开启事务操作
//            //Step2:执行业务操作
//            dao.addMoney();
//            dao.conductMoney();
//            //Step3:没有发生异常时则提交事务
//        }catch (Exception e){
//            //Step4:发生异常时则事务回滚
//        }
    }
}

//Test
    @Test
    public void testJdbcTemplate(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beanjdbc.xml");
        Service service = context.getBean("service", Service.class);
        service.countMoney();
    }

完全注解的方式


@Configuration
@ComponentScan(basePackages = "com.alibaba.springAffairs")
@EnableTransactionManagement
public class AffairsConfig {

    //创建数据库连接池
    @Bean
    public DruidDataSource getDruidDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///user_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

    //创建JdbcTemplate对象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){
        //到ioc容器中根据类型找到datasource
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    //创建事务管理器对象
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

3.2 @Transactional事务注解的一些配置

propagation:事务传播行为
事务方法:对数据库表数据进行变化的操作的方法就叫事务方法。
事务传播行为指的是一个事务方法调用另一个事务方法,这一过程叫做事务传播行为。
Spring框架提供了7种事务传播行为:REQUIRES,REQUIRES_NEW,…有需要进一步查看即可
在这里插入图片描述

isolation:事务隔离级别
事务有一个隔离性的特性,多事务操作之间才不会产生影响,如果不考虑隔离性会产生很多问题。
有三个读的问题:脏读、不可重复读、虚读
脏读(一个比较严重的问题):一个未提交事务读取到另一个未提交事务的数据

比如现在数据表中有一条记录,“id=1,money=500”,现在有两个人同时去操作这一条记录。小明开启事务A去操作这个记录,要把这个money从500变到100,而此时小红开启事务B也要去操作这个记录,要把这个money从500变为5000,假设现在小红将其先变为了5000,而此时小明恰好去读这个数据,因此小明读到的是5000,但是由于小红目前还处于事务中并未提交事务,又进行了事务回滚,因此此时这条记录中的money变为了500,但是小明读到的是5000。

不可重复读:一个未提交事务读取到另一个提交事务已经修改后的数据
虚读:一个未提交事务读渠道另一个已提交事务添加数据。
在这里插入图片描述
在这里插入图片描述

timeout:超时时间
事务在一定时间内要进行提交,如果不提交就进行回滚。
默认值是-1,设置时间以秒为单位进行计算。
readOnly:是否只读
读:查询操作 写:修改添加删除
默认是false
rollbackFor:回滚
设置出现哪些异常进行事务回滚
noRollbackFor:不回滚
设置出现哪些异常不进行事务回滚

3.3 基于xml的声明式事务管理
    <!--创建事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--利用名称空间tx开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

    <!--配置通知-->
    <tx:advice id="txadvice" >
        <!--配置事务参数-->
        <!--countMoney要创建事务的方法名-->
        <tx:attributes>
            <tx:method name="countMoney" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--配置切入点和切面-->
    <aop:config>
        <aop:pointcut id="servicepointcut" expression="execution(* com.alibaba.springAffairs.layerService.Service.*(..))"/>
        <aop:advisor advice-ref="txadvice" pointcut-ref="servicepointcut"></aop:advisor>
    </aop:config>

## 五. Spring5的新特性 ### 1. 通用的日志封装Log4j2
  1. 整个Spring5框架的代码基于Java8实现,运行时兼容JDK9,把jdk中不建议使用的类和方法已经删除。
  2. Spring5.0框架自带了通用的日志封装。

Spring5中已经移除Log4jConfigListener,官方建议使用Log4j2;Spring5框架整合Log4j2

定义一个log4j2.xml(名称不可变)

<?xml version="1.0" encoding="UTF-8"?>
<!--  日志级别以及优先级排序:OFF>FATAL>ERROR>WARN>INFO>DEBUG>TRACE>ALL  从左到右优先级逐渐升高-->
<!--  Configuration后面的status用于设置log4j2自身内部的信息输出,可以不设置 -->
<configuration status="INFO">
    <!--先定义所有的appenders-->
    <appenders>
        <!--输出日志信息到控制台-->
        <console name="Console" target="SYSTEM_OUT">
            <!--控制日志输出格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"> </PatternLayout>
        </console>
    </appenders>
    <!--然后定义logger,只有定义了logger并引入appender的,appender才会生效-->
    <!--root:用于指定项目的根日志,如果没有单独指定logger,则会使用root作为默认的日志输出-->
    <loggers>
        <root level="info">
            <appender-ref ref="Console"/>
        </root>
    </loggers>
</configuration>


导入log4j2依赖包

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.11.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.11.2</version>
        </dependency>

2. 支持@Nullable注解

可以作用在方法、属性、参数上,表示方法返回为空,属性可以为空,参数可以为空。

3. 支持函数式风格GenericApplicationContext

Spring中引入bean管理对对象进行管理,要在spring中使用对象自然需要在spring中注册对象,之前我们可以通过注解的方式来在spring中注册对象。spring5中支持函数式风格创建对象,从而交给spring进行管理。

    public void test(){
        GenericApplicationContext context = new GenericApplicationContext();
        context.refresh();
        context.registerBean(DAO.class,()->new DAO());
        Object bean = context.getBean("com.alibaba.springAffairs.DAO");
    }

4. 支持整合JUnit5

        <!--test单元测试-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.8</version>
        </dependency>
@RunWith(SpringJUnit4ClassRunner.class) //配置单元测试框架
@ContextConfiguration("classpath:beanjdbc.xml")//加载配置文件
//@SpringJUnitConfig(locations = "classpath:beanjdbc.xml") //使用一个复合注解代替上面两个注解
public class TestJunit {
    @Autowired
    private Service service; //注入属性
    
    @Test
    public void test(){
        service.countMoney();
    }
}

//之前需要这么写
    @Test
    public void testJdbcTemplate(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beanjdbc.xml");
        Service service = context.getBean("service", Service.class);
        service.countMoney();
    }

5. Spring5框架新功能Webflux

1⃣️SpringWebflux是Spring5中添加的新的模块,用于web开发,功能与SpringMVC类似,Webflux使用当前一种比较流行的响应式编程出现的框架。
2⃣️web框架比如SpringMVC,这些都是基于Servlet容器,Webflux是一种异步非阻塞框架,异步非阻塞框架在Servlet3.1以后才支持,核心是基于Reactor的相关API实现的。
3⃣️异步非阻塞:同步和异步针对的是调用者,调用者发送请求如果等着对方回应之后才去做其他事情就是同步,如果发送请求之后不用等着对方回应就去做其他事情就是异步。阻塞和非阻塞针对的是被调用者,被调用者收到请求之后,做完请求任务之后才做出反馈就是阻塞,如果收到请求之后马上给出反馈然后再去做任务就是非阻塞。
4⃣️Webflux特点:第一非阻塞式,在有限资源下,提高系统吞吐量和伸缩性,以Reactor为基础实现响应式编程;第二函数式编程,Spring5框架基于java8,Webflux使用java8函数式编程方式实现路由请求。
在这里插入图片描述

Webflux响应式编程

所谓的响应式编程是面向数据流和变化传播的编程范式。电子表格就是其中一个典型例子,比如在excel中的列末端计算这一列的数字总和,当这一列的其中某个数字发生变化时,其sum值也会发生变化,这就是响应式编程的例子。Java8提供了观察者模式的两个类Observer和Observable。

Reactor实现响应式编程
  • 响应式编程操作中都要满足Reactive规范框架,Reactor是满足Reactive规范的框架;Reactor(响应式标准流)有两个核心类,Mono和Flux,这两个类都实现了Publisher接口。Flux对象可以实现发布者,返回N个元素;Mono也可以实现发布者,返回0或1个元素。
  • 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) {
        Flux<Integer> just = Flux.just(1, 12, 23, 2);
        System.out.println("testea");
        just.subscribe(System.out::println); 
    }

错误信号和完成信号都是终止信号,但是二者不能共存。如果没有发送任何元素值,而是直接发送错误信号或完成信号,表示是空数据流。如果没有错误信号,没有完成信号,表示是无限数据流。
操作符的概念:对数据流进行一道道操作,成为操作符,比如工厂流水线。常见的两种:map:把元素映射为新元素,flatMap是把元素映射为流。

SpringWebflux执行流程和核心API

SpringWebflux是基于Reactor,默认容器是Netty,Netty是高性能,NIO框架(是一个异步非阻塞框架)。
SpringWebflux中的DispatcherHandler负责请求的处理,实现函数式编程的两个接口:RouterFunction和HandlerFunction。

基于注解编程方式的Webflux的使用

添加相关依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

在application.properties中添加server.port

server.port=8081

//Entity类
public class Entity {

    private String name;
    private String gender;

    public Entity(String name,String gender){
        this.name = name;
        this.gender=gender;
    }

    public String getGender() {
        return gender;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }

}

//ServiceClass类对Entity进行操作
@Repository
public class ServiceClass {


    //创建map集合存储数据(当然数据来源也可以是数据库,这里仅仅是为了方便展示流程)
    private final Map<Integer,Entity> entities = new HashMap<>();

    public ServiceClass(){
        this.entities.put(1,new Entity("lucy","woman"));
        this.entities.put(2,new Entity("tom","man"));
    }

    public Mono<Entity> getUserById(int id){
        return Mono.just(this.entities.get(1));
    }

    public Flux<Entity> getAllUser(){
        return Flux.fromIterable(this.entities.values());
    }

    public Mono<Void> saveUserInfo(Mono<Entity> entity ){
        //person的含义:把Mono流中的对象转换为一个实体对象,然后在map中放入
        return entity.doOnNext(person ->{
            //向map集合放值
            int id = entities.size()+1;
            entities.put(id,person);
        }).thenEmpty(Mono.empty());//thenEmpty(Mono.empty())表示的实际上是一个终止信号
    }
}

//ControllerClass类
@RestController
public class ControllerClass {

    //注入service
    @Autowired
    private ServiceClass serviceClass;

    @GetMapping("/user/{id}")
    public Mono<Entity> getUserById(@PathVariable int id)
    {
        return serviceClass.getUserById(id);

    }

    @GetMapping("/user")
    public Flux<Entity> getUsers(){
        return serviceClass.getAllUser();
    }

    @PostMapping("/saveuser")
    public Mono<Void> saveUser(@RequestBody Entity entity){

        return serviceClass.saveUserInfo(Mono.just(entity));
    }
}

//test
@SpringBootApplication
public class TestWebFlux {
    public static void main(String[] args) {
        SpringApplication.run(TestWebFlux.class,args);
    }
}
Spring是一个开源的Java框架,用于构建企业级应用程序。它提供了一种轻量级的、非侵入式的开发方式,通过依赖注入和面向切面编程等特性,简化了Java应用程序的开发过程。 以下是关于Spring学习的一些笔记: 1. IoC(控制反转):Spring通过IoC容器管理对象的创建和依赖关系的注入。通过配置文件或注解,将对象的创建和依赖关系的维护交给Spring容器来管理,降低了组件之间的耦合度。 2. DI(依赖注入):Spring通过依赖注入将对象之间的依赖关系解耦。通过构造函数、Setter方法或注解,将依赖的对象注入到目标对象中,使得对象之间的关系更加灵活和可维护。 3. AOP(面向切面编程):Spring提供了AOP的支持,可以将与业务逻辑无关的横切关注点(如日志、事务管理等)从业务逻辑中分离出来,提高了代码的可重用性和可维护性。 4. MVC(模型-视图-控制器):Spring提供了一个MVC框架,用于构建Web应用程序。通过DispatcherServlet、Controller、ViewResolver等组件,实现了请求的分发和处理,将业务逻辑和视图展示进行了分离。 5. JDBC和ORM支持:Spring提供了对JDBC和ORM框架(如Hibernate、MyBatis)的集成支持,简化了数据库访问的操作,提高了开发效率。 6. 事务管理:Spring提供了对事务的支持,通过声明式事务管理和编程式事务管理,实现了对数据库事务的控制和管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值