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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
云数据库 RDS PostgreSQL,高可用系列 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)]


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
2月前
|
安全 Java Ruby
我尝试了所有后端框架 — — 这就是为什么只有 Spring Boot 幸存下来
作者回顾后端开发历程,指出多数框架在生产环境中难堪重负。相比之下,Spring Boot凭借内置安全、稳定扩展、完善生态和企业级支持,成为构建高可用系统的首选,真正经受住了时间与规模的考验。
240 2
|
1月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
1月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
116 8
|
2月前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
195 1
|
2月前
|
监控 Kubernetes Cloud Native
Spring Batch 批处理框架技术详解与实践指南
本文档全面介绍 Spring Batch 批处理框架的核心架构、关键组件和实际应用场景。作为 Spring 生态系统中专门处理大规模数据批处理的框架,Spring Batch 为企业级批处理作业提供了可靠的解决方案。本文将深入探讨其作业流程、组件模型、错误处理机制、性能优化策略以及与现代云原生环境的集成方式,帮助开发者构建高效、稳定的批处理系统。
342 1
|
2月前
|
监控 Java API
Spring WebFlux 响应式编程技术详解与实践指南
本文档全面介绍 Spring WebFlux 响应式编程框架的核心概念、架构设计和实际应用。作为 Spring 5 引入的革命性特性,WebFlux 提供了完全的响应式、非阻塞的 Web 开发栈,能够显著提升系统的并发处理能力和资源利用率。本文将深入探讨 Reactor 编程模型、响应式流规范、WebFlux 核心组件以及在实际项目中的最佳实践,帮助开发者构建高性能的响应式应用系统。
492 0
|
2月前
|
监控 Cloud Native Java
Spring Integration 企业集成模式技术详解与实践指南
本文档全面介绍 Spring Integration 框架的核心概念、架构设计和实际应用。作为 Spring 生态系统中的企业集成解决方案,Spring Integration 基于著名的 Enterprise Integration Patterns(EIP)提供了轻量级的消息驱动架构。本文将深入探讨其消息通道、端点、过滤器、转换器等核心组件,以及如何构建可靠的企业集成解决方案。
234 0
|
4月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
859 0
|
1月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
250 3
|
1月前
|
Java 测试技术 数据库连接
【SpringBoot(四)】还不懂文件上传?JUnit使用?本文带你了解SpringBoot的文件上传、异常处理、组件注入等知识!并且带你领悟JUnit单元测试的使用!
Spring专栏第四章,本文带你上手 SpringBoot 的文件上传、异常处理、组件注入等功能 并且为你演示Junit5的基础上手体验
739 2

热门文章

最新文章