JAVAEE框架整合技术之spring03-SpringJdbcTemplate模板技术和事务处理

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: JAVAEE框架整合技术之spring03-SpringJdbcTemplate模板技术和事务处理

SpringJdbcTemplate

Spring的JdbcTemplate是一个对JDBC的模板封装,它提供了一套JDBC的模板,能让我们写持久层代码时减少多余的代码,简化JDBC代码,使代码看起来更简洁。在介绍Spring的JdbcTemplate使用方法之前我们先来讨论一个问题,以下这是一段常见的往数据库写入数据的JDBC代码:

public int jdbcInsert(Student student) throws SQLException {
    Connection connection = null;
    try {
        connection = dataSource.getConnection();
        String sql = "INSERT INTO student(sname,age,sex,address) VALUES (?,?,?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1, student.getName());
        preparedStatement.setInt(2, student.getAge());
        preparedStatement.setString(3, student.getSex());
        preparedStatement.setString(4, student.getAddress());
        return preparedStatement.executeUpdate();
    } finally {
        connection.close();
    }
}
public int jdbcUpdate(Student student) throws SQLException {
    Connection connection = null;
    try {
        connection = dataSource.getConnection();
        String sql = "UPDATE student SET sname=?,age=?,sex=?,address=?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1, student.getName());
        preparedStatement.setInt(2, student.getAge());
        preparedStatement.setString(3, student.getSex());
        preparedStatement.setString(4, student.getAddress());
        return preparedStatement.executeUpdate();
    } finally {
        connection.close();
    }
}

从如上的代码中,可以看到两个方法中基本99%的代码都是重复的,除了sql语句之外,都是重复的代码,重复的代码就是坏味道,会让我们的产生大量的冗余代码,不易于维护和修改,而且写起来还累。

所以Spring提供的JdbcTemplate正是用来解决这个问题的,其实Spring的JDBCTemplate有点像DBUtils,但是有时候还没有DBUitls好用。这里来学习一下使用Spring的JdbcTemplate来玩一下CRUD,毕竟JdbcTemplate在实际开发中一般不会使用,通常都是使用Mybatis、Hibernate等成熟、优秀的数据持久层框架,不过还是得知道Spring有一个这样的jdbc模板类

添加依赖

spring核心包4+2 jdbc模板包2个

<!--spring-jdbc-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.2.9.RELEASE</version>
</dependency>

测试

@Test
public void test(){
    //构建数据源
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql:///test");
    dataSource.setUsername("root");
    dataSource.setPassword("root");
  //获取对象
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);    
    //创建表
    jdbcTemplate.execute("create table test01(name varchar(10) )");
}

Spring配置数据源

目标:将数据源和jdbcTemplate都交给Spring来管理:

在applicationContext.xml中配置dataSource连接池和jdbcTemplate模版对象。

spring内置数据源

<!--spring内置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql:///test"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>
<!--jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JdbcTempleTest {
    //注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test(){
        this.jdbcTemplate.execute("create table jdbctest05(name varchar(10))");
    }
}

dbcp数据源

Apache commons-dbcp 需要导入dbcp包和 pool包

添加依赖

<dependency>
  <groupId>commons-dbcp</groupId>
  <artifactId>commons-dbcp</artifactId>
  <version>1.4</version>
</dependency>
<!--dbcp数据源-->
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql:///test"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>
<!--jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource2"/>
</bean>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JdbcTempleTest {
    //注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test(){
        this.jdbcTemplate.execute("create table jdbctest06(name varchar(10))");
    }
}

C3P0 数据源

<dependency>
  <groupId>com.mchange</groupId>
  <artifactId>c3p0</artifactId>
  <version>0.9.5.2</version>
</dependency>
<!--c3p0数据源-->
<bean id="dataSource3" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc:mysql:///test"/>
    <property name="user" value="root"/>
    <property name="password" value="root"/>
</bean>
<!--jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource3"/>
</bean>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JdbcTempleTest {
    //注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test(){
        this.jdbcTemplate.execute("create table jdbctest07(name varchar(10))");
    }
}

Druid数据源

<!--druid-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.3</version>
</dependency>
<!--druid数据源-->
<bean id="dataSource4" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql:///test"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    <!--最大连接数-->
    <property name="maxActive" value="5"/>
    <!--最小连接数-->
    <property name="minIdle" value="1"/>
</bean>
<!--jdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource4"/>
</bean>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JdbcTempleTest {
    //注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Test
    public void test(){
        this.jdbcTemplate.execute("create table jdbctest07(name varchar(10))");
    }
}
  • 相关配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F5402RTk-1664592948340)(assets/image-20211217000623540.png)]

外部属性文件的配置

  • db.properties
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.jdbcurl=jdbc:mysql:///test?serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=root
  • applicationContext.xml
<!--引入外部的文件-->
<context:property-placeholder location="classpath:db.properties"/>
<!--druid数据源-->
<bean id="dataSource4" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driverClass}"/>
    <property name="url" value="${jdbc.jdbcurl}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <!--最大连接数-->
    <property name="maxActive" value="5"/>
    <!--最小连接数-->
    <property name="minIdle" value="1"/>
</bean>

基于JdbcTemplate实现CURD

数据库准备

CREATE TABLE `t_book` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `price` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

查询

实体类

@Data
public class Book {
    private Integer id;
    private String name;
    private Double price;
}

dao层

/**
 * @Auther: yanqi
 * @Desc: 继承 JdbcDaoSupport类,父类中已注入JdbcTemplate对象
 */
public class BookDao extends JdbcDaoSupport {
    /**
     * 查询所有
     */
    public List<Book> queryAll(){
        return super.getJdbcTemplate().query("select * from t_book", new BeanPropertyRowMapper<>(Book.class));
    }
}

数据源

<!--引入外部的配置文件db.properties-->
<context:property-placeholder location="classpath:db.properties"/>
<!--Druid连接池-->
<bean id="dataSource4" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driverClass}"/>
    <property name="url" value="${jdbc.jdbcurl}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>
<!--dao层-->
<bean id="bookDao" class="cn.yanqi.dao.BookDao">
    <property name="dataSource" ref="dataSource4"/>
</bean>
  • db.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcurl=jdbc:mysql:///test
jdbc.username=root
jdbc.password=root
  • 测试
/**
 * @Auther: yanqi
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JdbcTemplateTest {
    @Autowired
    private BookDao bookDao;
    @Test
    public void test2(){
        List<Book> books = this.bookDao.queryAll();
        for(Book book : books){
            System.out.println(book);
        }
    }
}

实现增加、删除、修改功能

/**
 * 添加
 */
public void addBook(Book book){
    String sql = "insert into t_book(id,name,price) values(null,?,?)";
    super.getJdbcTemplate().update(sql,book.getId(),book.getName(),book.getPrice());
}
/**
 * 删除
 */
public void deleteBook(Integer id){
    String sql = "delete from t_book where id = ?";
    super.getJdbcTemplate().update(sql,id);
}
/**
 * 修改
 */
public void updateBook(Book book){
    String sql = "update t_book set name = ? where id = ?";
    super.getJdbcTemplate().update(sql,book.getName(),book.getId());
}

Spring事务管理

基于_XML的事务管理

编写转账案例,引出事务问题

  • 数据库准备
CREATE TABLE `t_account` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `money` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

spring-transaction

  • 添加依赖
<dependencies>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.3</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.4</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
  • dao层
public class AccountDao extends JdbcDaoSupport {
    public void out(String outName , double money){
        String sql = "update t_account set money = money - ? where name = ?";
        this.getJdbcTemplate().update(sql,money,outName);
    }
    public void in(String inName , double money){
        String sql = "update t_account set money = money + ? where name = ?";
        this.getJdbcTemplate().update(sql,money,inName);
    }
}
  • service层
public class AccountService {
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    public void tranfar(String outName , String  inName , double money){
        this.accountDao.out(outName,money);
        int a = 1/0;
        this.accountDao.in(inName,money);
    }
}
  • db.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///test
jdbc.username=root
jdbc.password=root
  • applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       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/aop
   http://www.springframework.org/schema/aop/spring-aop.xsd
   http://www.springframework.org/schema/context
   http://www.springframework.org/schema/context/spring-context.xsd">
    <!--引入外部的文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--druid数据源-->
    <bean id="dataSource4" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driverClass}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!--最大连接数-->
        <property name="maxActive" value="5"/>
        <!--最小连接数-->
        <property name="minIdle" value="1"/>
    </bean>
    <!--dao-->
    <bean id="accountDao" class="cn.yanqi.dao.AccountDao">
        <property name="dataSource" ref="dataSource4"/>
    </bean>
    <!--service-->
    <bean id="accountService" class="cn.yanqi.service.AccountService">
        <property name="accountDao" ref="accountDao"/>
    </bean>
</beans>
  • 测试
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AccountServiceTest {
    @Autowired
    private AccountService accountService;
    @Test
    public void tranfar() {
        this.accountService.tranfar("jack","rose",100);
    }
}
发现事务管理问题:没有事务的情况下,如果出现异常,则会转账不成功,数据异常。
扩展:如果不配置事务,那么每一个数据库的操作都是单独的一个事务。

加入事务

  • 添加tx事务约束
<?xml version="1.0" encoding="UTF-8"?>
<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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop
   http://www.springframework.org/schema/aop/spring-aop.xsd
   http://www.springframework.org/schema/tx 
   http://www.springframework.org/schema/tx/spring-tx.xsd">
  • 事务控制
<!--事务平台管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource4"/>
    </bean>
    <!--配置事务方法-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--
                name:事务所管理的方法
                isolation: 事务隔离级别,默认值DEFAULT,使用的是数据库的默认隔离级别(mysql默认隔离级别:repeatable read 可重重读)
                propagation: 事务传播形为,默认值REQUIRED  支持当前事务, A调用B,如果A事务存在,B和A处于同一个事务
                timeout:事务超时时间(单位是秒),默认值-1,使用的数据库的超时时间
                rollback-for: 指哪些异常可以回滚
                no-rollback-for: 指哪些异常不回滚,其他都回滚
            -->
            <tx:method name="transactionAccount"
                       isolation="DEFAULT"
                       propagation="REQUIRED"
                       timeout="-1"
                       rollback-for=""
                       no-rollback-for=""/>
            <!--<tx:method name="update*"/>-->
            <!--<tx:method name="save*"/>-->
        </tx:attributes>
    </tx:advice>
    <!--配置aop-->
    <aop:config>
        <!--切入点-->
        <aop:pointcut id="txPointcut" expression="bean(*Service)"/>
        <!--切面-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>
</beans>
  • 测试
/**
 * @Auther: yanqi
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class AccountServiceTest {
    @Autowired
    private AccountService accountService;
    @Test
    public void transactionAccount() {
        this.accountService.transactionAccount("jack","rose",100.0);
    }
}

遇到异常不回滚(相当于没有事务)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kb1d6f3J-1664592948342)(assets/image-20211217202707415.png)]

事务的传播行为PropagationBehavior

什么是事务的传播行为?

一个事务调用了另 一个事务,如果出现错误,两个事务是否属于同一个事务

有什么作用?

事务传播行为用于解决两个被事务管理的方法互相调用问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlTaNfFY-1664592948344)(assets/image-20211217202839587.png)]

  • 事务的传播行为的7种类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J1A4nxQU-1664592948345)(assets/image-20211217202857824.png)]

  • 主要分为三大类
 PROPAGATION_REQUIRED(默认值)、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY
支持当前事务, A调用B,如果A事务存在,B和A处于同一个事务 。
事务默认传播行为 REQUIRED。最常用的。
 PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER 
不会支持原来的事务 ,A调用B, 如果A事务存在, B肯定不会和A处于同一个事务。
常用的事务传播行为:PROPAGATION_REQUIRES_NEW
 PROPAGATION_NESTED
嵌套事务 ,只对DataSourceTransactionManager有效 ,底层使用JDBC的SavePoint机制,允许在同一个事务设置保存点,回滚保存点

基于_注解声明式事务

导入的依赖包跟xml方式一样

pring-transactional-ann

声明式事务

/**
 * @Auther: yanqi
 */
@Service
// @Transactional //当前类都会被 事务管理
public class AccountService {
    @Autowired
    private AccountDao accountDao;
    @Transactional //事务管理
    public void transactionAccount(String outName, String inName , Double money){
        this.accountDao.out(outName,money);
        int a = 1/0;
        this.accountDao.in(inName,money);
    }
}
  • dao层
/**
 * @Auther: yanqi
 * @Desc: 先用jdbcTemplate完成对数据库的操作
 */
@Repository
public class AccountDao extends JdbcDaoSupport {
    /**
     * 随便写一个set方法,注入DataSource,使用父数据源
     * @param dataSource
     */
    @Autowired
    public void setJdbcDaoSupport(DataSource dataSource){
        super.setDataSource(dataSource);
    }
    /**
     * 减钱
     */
    public void out(String name , Double money){
        String sql = "update t_account set money = money - ? where name = ?";
        super.getJdbcTemplate().update(sql,money, name);
    }
    /**
     * 加钱
     */
    public void in(String name , Double money){
        String sql = "update t_account set money = money + ? where name = ?";
        super.getJdbcTemplate().update(sql,money, name);
    }
}

配置注解事务

<!--开启注解-->
<context:component-scan base-package="cn.yanqi"/>
<!--引入外部的配置文件db.properties-->
<context:property-placeholder location="classpath:db.properties"/>
<!--Druid连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>
<!--事务的平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!--开启事务的注解-->
<tx:annotation-driven transaction-manager="transactionManager"/>
  • 配置事务的定义属性信息,在注解中直接配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EpZrVRlh-1664592948346)(assets/image-20211217203126239.png)]

  • 优化配置

配置注解驱动事务管理的时候,tx:annotation-driven/默认会自动查找并加载名字为transactionManager的事务管理器Bean,因此,当事务管理器的bean的名字为transactionManager 时,可以省略transaction-manager的属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pNV522gW-1664592948347)

(assets/image-20211217203218262.png)]
taSource">


- **配置事务的定义属性信息,在注解中直接配置**
[外链图片转存中...(img-EpZrVRlh-1664592948346)] 
- **优化配置**
>配置注解驱动事务管理的时候,<tx:annotation-driven/>默认会自动查找并加载名字为transactionManager的事务管理器Bean,因此,当事务管理器的bean的名字为transactionManager 时,可以省略transaction-manager的属性
[外链图片转存中...(img-pNV522gW-1664592948347)]


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
23天前
|
XML 安全 Java
|
26天前
|
缓存 NoSQL Java
什么是缓存?如何在 Spring Boot 中使用缓存框架
什么是缓存?如何在 Spring Boot 中使用缓存框架
39 0
|
1天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
8天前
|
IDE Java 测试技术
互联网应用主流框架整合之Spring Boot开发
通过本文的介绍,我们详细探讨了Spring Boot开发的核心概念和实践方法,包括项目结构、数据访问层、服务层、控制层、配置管理、单元测试以及部署与运行。Spring Boot通过简化配置和强大的生态系统,使得互联网应用的开发更加高效和可靠。希望本文能够帮助开发者快速掌握Spring Boot,并在实际项目中灵活应用。
25 5
|
19天前
|
缓存 Java 数据库连接
Spring框架中的事件机制:深入理解与实践
Spring框架是一个广泛使用的Java企业级应用框架,提供了依赖注入、面向切面编程(AOP)、事务管理、Web应用程序开发等一系列功能。在Spring框架中,事件机制是一种重要的通信方式,它允许不同组件之间进行松耦合的通信,提高了应用程序的可维护性和可扩展性。本文将深入探讨Spring框架中的事件机制,包括不同类型的事件、底层原理、应用实践以及优缺点。
47 8
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
239 2
|
1天前
|
Java 数据库连接 Maven
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
自动装配是现在面试中常考的一道面试题。本文基于最新的 SpringBoot 3.3.3 版本的源码来分析自动装配的原理,并在文未说明了SpringBoot2和SpringBoot3的自动装配源码中区别,以及面试回答的拿分核心话术。
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
|
8天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
52 14
|
1月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
49 1
SpringBoot入门(7)- 配置热部署devtools工具
|
1月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
47 2
 SpringBoot入门(7)- 配置热部署devtools工具