SpringBoot入门

目录

SpringBoot、SpringMVC、SpringCloud区别

快速入门

1、用IntelliJ IDEA新建一个项目

2、编写HelloWorld

Web开发

静态资源访问

模板引擎

使用FreeMarker模板引擎渲染Web视图

1、pom文件引入

2、在配置文件中增加freeMarker相关配置

3、页面代码

4、后端代码

使用JSP渲染Web视图

1、pom文件引入

2、 在配置文件中增加JSP相关配置

全局捕获异常

数据访问

springboot整合mybatis

1、pom文件引入

2、 在配置文件中增加mybatis相关配置

 3、后端相关代码

 springboot整合多数据源

1、配置文件中新增两个数据源

2、 读取数据源配置文件

 事务管理

1、pom文件引入

2、相关配置文件 

3、读取配置信息

 4、后端相关代码

缓存

1、 pom文件引入

2、新建ehcache.xml 文件 

3、后端相关代码

性能优化

扫包优化

将Servlet容器变成Undertow

JVM参数调优

SpringBoot配置文件

使用@Scheduled创建定时任务


简介    

       Spring Boot 简化了基于Spring的应用开发,只需要“run”就能创建一个独立的、生产级别的Spring应用。Spring Boot为Spring平台及第三方库提供开箱即用的设置(提供默认设置),这样我们就可以简单的开始。多数Spring Boot应用只需要很少的Spring配置。

      我们可以使用SpringBoot创建java应用,并使用java –jar 启动它,或者采用传统的war部署方式。

SpringBoot、SpringMVC、SpringCloud区别

  • SpringBoot 是一个快速开发的框架,能够快速的整合第三方框架,简化XML配置,全部采用注解形式,内置Web容器,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。SpringBoot并不是微服务框架。
  • SpringMVC是控制层。
  • SpringCloud依赖与SpringBoot组件,使用SpringMVC编写Http协议接口,同时SpringCloud是一套完整的微服务解决框架。

快速入门

1、用IntelliJ IDEA新建一个项目

2、编写HelloWorld

//1.在上加上RestController 表示修饰该Controller所有的方法返回JSON格式
//直接可以编写Restful接口
@RestController
//2.作用在于让 Spring Boot   根据应用所声明的依赖来对 Spring 框架进行自动配置
@EnableAutoConfiguration
public class HelloWorldController {
    @RequestMapping("/helloWorld")
    public String index(){
        return "Hello World";
    }
}

//@SpringBootApplication 被 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解
// 所修饰,换言之 Springboot 提供了统一的注解来替代以上三个注解
//扫包范围:在启动类上加上@SpringBootApplication注解,当前包下或者子包下所有的类都可以扫到。
@SpringBootApplication
public class SpringbootHelloworldApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootHelloworldApplication.class, args);
    }
}

访问页面:http://127.0.0.1:8080/helloWorld

Web开发

静态资源访问

Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:

  • /static
  • /public
  • /resources 
  • /META-INF/resources

例如:我们可以在src/main/resources目录下创建static,在该位置放置一个图片文件。启动程序后,直接访问根路径加图片名称,就能显示图片。

模板引擎

       在动态HTML实现上Spring Boot依然可以完美胜任,并且提供了多种模板引擎的默认配置支持,所以在推荐的模板引擎下,我们可以很快的上手开发动态网站。

Spring Boot提供了默认配置的模板引擎主要有以下几种:

  • Thymeleaf
  • FreeMarker
  • Velocity
  • Groovy
  • Mustache

     当你使用上述模板引擎中的任何一个,它们默认的模板配置路径为:src/main/resources/templates。

使用FreeMarker模板引擎渲染Web视图

1、pom文件引入

<!-- 引入freeMarker的依赖包. -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2、在配置文件中增加freeMarker相关配置

spring.freemarker.allow-request-override=false
spring.freemarker.cache=true
spring.freemarker.check-template-location=true
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.expose-spring-macro-helpers=false
spring.freemarker.suffix=.ftl
spring.freemarker.template-loader-path=classpath:/templates/

3、页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    ${name}:欢迎你
</body>
</html>

4、后端代码

//1.在上加上RestController 表示修饰该Controller所有的方法返回JSON格式
//直接可以编写Restful接口
@RestController
//2.作用在于让 Spring Boot   根据应用所声明的依赖来对 Spring 框架进行自动配置
@EnableAutoConfiguration
public class HelloWorldController {
    @RequestMapping("/helloWorld")
    public ModelAndView index(Map<String,Object> map){
        map.put("name","demo");
        return new ModelAndView("index");
    }
}

这里面有一个坑,由于加上了@RestController注解,所有方法都会返回JSON格式。如果此时直接返回页面的名称,会导致返回给浏览器一个json字符串,不会经过视图解析器。有两种解决方案如下:

1)将@RestController注解换成@Controller注解即可。

2)直接返回视图数据。返回值类型改成ModelAndView

使用JSP渲染Web视图

1、pom文件引入

<groupId>springboot</groupId>
<artifactId>springboot-jsp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- SpringBoot 外部tomcat支持 -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

    </dependencies>

注意:打包类型一定选择war类型,否则找不到页面 

2、 在配置文件中增加JSP相关配置

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

 注意:不用把jsp页面放到resources下,需要新建目录

全局捕获异常

  • @ExceptionHandler 表示拦截异常
  • @ControllerAdvice 是 controller 的一个辅助类,最常用的就是作为全局异常处理的切面类
  • @ControllerAdvice 可以指定扫描范围
  • @ControllerAdvice 约定了几种可行的返回值,如果是直接返回 model 类的话,需要使用 @ResponseBody 进行 json 转换
//定义扫包范围
@ControllerAdvice(basePackages = "springboot.springboothelloworld")
public class GlobalExceptionHandler {

	//拦截异常
	@ExceptionHandler(RuntimeException.class)
	// @ResponseBody 返回json格式
	// modeAndView 返回页面
	@ResponseBody
	public Map<String, Object> errorResult() {

		Map<String, Object> errorResultMap = new HashMap<String, Object>();
		errorResultMap.put("errorCode", "400");
		errorResultMap.put("errorMsg", "全局捕获异常系统错误!");
		return errorResultMap;
	}
}

模拟一个异常,前端页面就会返回json数据。

@RequestMapping("/helloWorld")
    public ModelAndView index(Map<String,Object> map){
        map.put("name","demo");
        int i = 1 / 0;
        return new ModelAndView("index");
}

数据访问

springboot整合mybatis

1、pom文件引入

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

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

        <!-- 引入freeMarker的依赖包. -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

        <!-- mysql 依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>

</dependencies>

2、 在配置文件中增加mybatis相关配置

spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

 3、后端相关代码

@RequestMapping("/findByName")
    @ResponseBody
    public User findByName(String name){
        return userService.findByName(name);
}
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public User findByName(String name){
        User user = userMapper.findByName(name);
        return user;
    }
}

 

@Mapper
public interface UserMapper {
    @Select("select * from user where name = #{name}")
    User findByName(@Param("name") String name);
}

 springboot整合多数据源

1、配置文件中新增两个数据源

spring.datasource.test1.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.test1.jdbc-url = jdbc:mysql://localhost:3306/test01?serverTimezone=UTC
spring.datasource.test1.username = root
spring.datasource.test1.password = root

spring.datasource.test2.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.test2.jdbc-url = jdbc:mysql://localhost:3306/test02?serverTimezone=UTC
spring.datasource.test2.username = root
spring.datasource.test2.password = root

2、 读取数据源配置文件

读取数据源1

@Configuration // 注册到springboot容器中
@MapperScan(basePackages = "springboot.springboothelloworld.test01", sqlSessionFactoryRef = "test1SqlSessionFactory")
public class DataSource1Config {

	//配置test01数据库
	//注入到Spring容器中
	@Bean(name = "test1DataSource")
	//prefix解析前缀
	@ConfigurationProperties(prefix = "spring.datasource.test1")
	public DataSource testDataSource() {
		return DataSourceBuilder.create().build();
	}

	//test1 sql会话工厂
	@Bean(name = "test1SqlSessionFactory")
	@Primary
	public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)
			throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		// bean.setMapperLocations(
		// new
		// PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test1/*.xml"));
		return bean.getObject();
	}

	//test1 事物管理
	@Bean(name = "test1TransactionManager")
	public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}

}

3、后端相关代码

注意:需要指定事务管理器

@Service
public class UserServiceTest01 {
	@Autowired
	private UserMapperTest01 userMapperTest01;

	@Transactional(transactionManager = "test1TransactionManager")
	public int insertUser(String name, Integer id) {
		int insertUserResult = userMapperTest01.insert(name, id);
		//验证事务是否成功
		int i = 1 / id;
		return insertUserResult;
	}
}
public interface UserMapperTest01 {
	// 查询语句
	@Select("SELECT * FROM USER WHERE NAME = #{name}")
	User findByName(@Param("name") String name);

	// 添加
	@Insert("INSERT INTO user(name, id) VALUES(#{name}, #{id})")
	int insert(@Param("name") String name, @Param("id") Integer id);
}

 springboot默认集成事物,只主要在方法上加上@Transactional即可。测试时,输入id为0时,数据库未插入数据,输入id为非0时,则插入成功,验证事务管理成功。数据源2同数据源1。

 事务管理

使用springboot+jta+atomikos 分布式事物管理

1、pom文件引入

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

2、相关配置文件 

# Mysql 1
mysql.datasource.test1.url = jdbc:mysql://localhost:3306/test01?serverTimezone=UTC
mysql.datasource.test1.username = root
mysql.datasource.test1.password = root
mysql.datasource.test1.minPoolSize = 3
mysql.datasource.test1.maxPoolSize = 25
mysql.datasource.test1.maxLifetime = 20000
mysql.datasource.test1.borrowConnectionTimeout = 30
mysql.datasource.test1.loginTimeout = 30
mysql.datasource.test1.maintenanceInterval = 60
mysql.datasource.test1.maxIdleTime = 60



# Mysql 2
mysql.datasource.test2.url =jdbc:mysql://localhost:3306/test02?serverTimezone=UTC
mysql.datasource.test2.username =root
mysql.datasource.test2.password =root

mysql.datasource.test2.minPoolSize = 3
mysql.datasource.test2.maxPoolSize = 25
mysql.datasource.test2.maxLifetime = 20000
mysql.datasource.test2.borrowConnectionTimeout = 30
mysql.datasource.test2.loginTimeout = 30
mysql.datasource.test2.maintenanceInterval = 60
mysql.datasource.test2.maxIdleTime = 60

3、读取配置信息

读取数据源1

@Data
@ConfigurationProperties(prefix = "mysql.datasource.test1")
public class DBConfig1 {
	private String url;
	private String username;
	private String password;
	private int minPoolSize;
	private int maxPoolSize;
	private int maxLifetime;
	private int borrowConnectionTimeout;
	private int loginTimeout;
	private int maintenanceInterval;
	private int maxIdleTime;
	private String testQuery;
}

 

@Configuration
// basePackages 最好分开配置 如果放在同一个文件夹可能会报错
@MapperScan(basePackages = "springboot.springboothelloworld.test01", sqlSessionTemplateRef = "testSqlSessionTemplate")
public class MyBatisConfig1 {

	// 配置数据源

	@Bean(name = "testDataSource")
	public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
		MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
		mysqlXaDataSource.setUrl(testConfig.getUrl());
		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
		mysqlXaDataSource.setPassword(testConfig.getPassword());
		mysqlXaDataSource.setUser(testConfig.getUsername());
		mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);

		// 将本地事务注册到 Atomikos全局事务
		AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
		xaDataSource.setXaDataSource(mysqlXaDataSource);
		xaDataSource.setUniqueResourceName("testDataSource");

		xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
		xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
		xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
		xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
		xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
		xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
		xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
		xaDataSource.setTestQuery(testConfig.getTestQuery());
		return xaDataSource;
	}

	@Bean(name = "testSqlSessionFactory")
	public SqlSessionFactory testSqlSessionFactory(@Qualifier("testDataSource") DataSource dataSource)
			throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		return bean.getObject();
	}

	@Bean(name = "testSqlSessionTemplate")
	public SqlSessionTemplate testSqlSessionTemplate(
			@Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
}

 4、后端相关代码

@RequestMapping("/insertUserTest01AndTest02")
public int insertUserTest01AndTest02(String name, Integer id) {
	return userServiceTest02.insertUserTest01AndTest02(name, id);
}

 

@Transactional()
public int insertUserTest01AndTest02(String name, Integer age) {
	// 传统分布式事务解决方案 jta+atomikos 注册同一个全局事务中
	// 第一个数据源
	int insertUserResult01 = userMapperTest01.insert(name, age);
	// 第二个数据源
	int insertUserResult02 = userMapperTest02.insert(name, age);
	int i = 1 / 0;
	int result = insertUserResult01 + insertUserResult02;
	// test01入库 test02回滚
	return result;
}

此时就不需要制定事务管理器,因为都交到了全家事务中,只有一个事务管理器。

缓存

1、 pom文件引入

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

2、新建ehcache.xml 文件 

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <diskStore path="java.io.tmpdir/Tmp_EhCache" />

    <!-- 默认配置 -->
    <defaultCache maxElementsInMemory="5000" eternal="false"
                  timeToIdleSeconds="120" timeToLiveSeconds="120"
                  memoryStoreEvictionPolicy="LRU" overflowToDisk="false" />

    <!--
	       name:缓存名称。
	       maxElementsInMemory:缓存最大个数。
	       eternal:对象是否永久有效,一但设置了,timeout将不起作用。
	       timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
	       timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
	       overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
	       diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
	       maxElementsOnDisk:硬盘最大缓存个数。
	       diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
	       diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
	       memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
	       clearOnFlush:内存数量最大时是否清除。
	    -->
    
    <cache name="baseCache" maxElementsInMemory="10000"
           maxElementsOnDisk="100000" />
</ehcache>

3、后端相关代码

@Mapper
//1.设置缓存名称
@CacheConfig(cacheNames = "userMapperCache")
public interface UserMapper {
	//2.加上注解,将查询结果保存到缓存中
	@Cacheable
	@Select("SELECT * FROM USER WHERE id = #{id}")
	User findById(@Param("id") Integer id);
}

 需要注意的是:需要在springboot启动器上加入开启缓存注解

@SpringBootApplication
@EnableCaching // 开启缓存注解
public class SpringbootHelloworldApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootHelloworldApplication.class, args);
    }
}

管理缓存

//将缓存管理器注入进来
@Autowired
private CacheManager cacheManager;

清除缓存

//清楚缓存
@RequestMapping("/remoKey")
public void remoKey() {
   cacheManager.getCache("userMapperCache").clear();
}

性能优化

扫包优化

       默认情况下,我们会使用 @SpringBootApplication 注解来自动获取应用的配置信息,但这样也会给应用带来一些副作用。使用这个注解后,会触发自动配置( auto-configuration )和 组件扫描 ( component scanning ),这跟使用 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 三个注解的作用是一样的。但是这样导致:

1、会导致项目启动时间变长。当启动一个大的应用程序,或将做大量的集成测试启动应用程序时,影响会特别明显。

2、会加载一些不需要的多余的实例(beans)。

3、会增加 CPU 消耗。

针对以上三个情况,我们可以移除 @SpringBootApplication 和 @ComponentScan 两个注解来禁用组件自动扫描,然后在我们需要的 bean 上进行显式配置:

//移除 @SpringBootApplication and @ComponentScan, 用 @EnableAutoConfiguration 来替代
//@SpringBootApplication
@Configuration
@EnableAutoConfiguration
public class SpringbootHelloworldApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootHelloworldApplication.class, args);
    }
}

将Servlet容器变成Undertow

默认情况下,Spring Boot 使用 Tomcat 来作为内嵌的 Servlet 容器

可以将 Web 服务器切换到 Undertow 来提高应用性能。Undertow 是一个采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。Undertow 是红帽公司的开源产品,是 Wildfly 默认的 Web 服务器。首先,从依赖信息里移除 Tomcat 配置:

<exclusions>
	<exclusion>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-tomcat</artifactId>
	</exclusion>
</exclusions>

然后添加 Undertow

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

JVM参数调优

这个根据服务器的内存大小,来设置堆参数。

-Xms :设置Java堆栈的初始化大小

-Xmx :设置最大的java堆大小

实例参数-XX:+PrintGCDetails -Xmx32M -Xms1M

调优策略:初始化堆内存和最大堆内存相等,这样可以减少垃圾回收次数

SpringBoot配置文件

  • application.properties
  • application.yml

YML 比properties配置文件更加节约 简约(结构)

server:
  port:  8090
  context-path: /springboot

自定义参数

name=lun

 后端代码中直接就可以通过${ }拿到配置文件中的参数值

 

@Value("${name}")
private String name;

使用@Scheduled创建定时任务

@SpringBootApplication
//开启定时任务
@EnableScheduling
public class SpringbootHelloworldApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootHelloworldApplication.class, args);
    }
}
@Component
public class ScheduledTasks {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
    @Scheduled(fixedRate = 1000)
    public void reportCurrentTime() {
        System.out.println("现在时间:" + dateFormat.format(new Date()));
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它提供了一种简化的方法来配置和部署应用程序,使开发人员能够更快地开发和运行应用程序。 Spring Boot Actuator是Spring Boot的一个组件,它可以帮助我们监控和管理Spring Boot应用程序,包括健康检查、审计、统计和HTTP追踪等功能。要使用Spring Boot Actuator,只需引入相应的起步依赖,并在应用程序的入口点类上添加@SpringBootApplication注解即可。在该类中,使用@SpringBootApplication注解相当于同时添加了@Configuration、@EnableAutoConfiguration和@ComponentScan注解,它标识了当前应用程序是一个Spring Boot应用程序。要启动Spring Boot应用程序,只需在主启动类中编写main函数,通过调用SpringApplication.run(Application.class, args)方法来启动应用程序。在开发过程中,<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [SpringBoot入门](https://blog.csdn.net/weixin_45905210/article/details/121712027)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [spring boot 入门](https://blog.csdn.net/zhshx19900318/article/details/129476812)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值