为了账号安全,请及时绑定邮箱和手机立即绑定

SpringBoot3教程:轻松入门与实践指南

标签:
SpringBoot
概述

Spring Boot 3教程详细介绍了Spring Boot 3的新特性、环境搭建、核心概念解析、常用功能详解、项目实战、安全性配置、部署与监控以及调试技巧,帮助开发者快速上手并掌握Spring Boot 3的各项功能。

SpringBoot3简介与环境搭建

什么是Spring Boot

Spring Boot 是一个基于 Spring 框架的开源框架,旨在简化基于 Spring 的 Java 应用程序的开发过程。它提供了一种快速开发独立的、生产级别的基于 Spring 的应用的方式,只需要很少的配置。Spring Boot 使开发人员能够快速地开发出具有各种功能的应用程序,如数据库集成、消息代理、安全性和缓存,同时保持应用程序的可扩展性和可维护性。

Spring Boot 3的新特性

Spring Boot 3 引入了一些新的特性和改进,旨在进一步简化开发流程和提高应用程序的性能和安全性。以下是 Spring Boot 3 的一些新特性:

  1. Java 17 支持:Spring Boot 3 开始支持 Java 17,确保与最新的 Java 版本兼容。
  2. Spring Framework 6 支持:Spring Boot 3 依赖于 Spring Framework 6,提供了最新的功能和改进。
  3. 新的默认缓存实现:默认情况下,Spring Boot 3 使用 Caffeine 作为缓存实现,替代了之前的 ConcurrentMapCache。
  4. 微服务支持增强:Spring Boot 3 对微服务的集成和管理进行了增强,包括更强大的服务发现和配置功能。
  5. 安全性改进:Spring Boot 3 提供了更强大的安全特性,简化了安全配置。
  6. 新的管理端点:Spring Boot 3 引入了新的管理端点和改进的监控功能,便于开发者进行故障排除和性能调优。
  7. 改进的持久层支持:Spring Boot 3 对数据库集成进行了改进,提供了更多的数据库驱动支持和连接池优化。

开发环境搭建

为了使用 Spring Boot 3 开发应用程序,你需要先配置开发环境。以下步骤展示了如何搭建一个基本的开发环境:

  1. 安装 Java 17:确保你的计算机上安装了 Java 17。
  2. 设置 JAVA_HOME 环境变量:将 Java 17 的安装路径设置为 JAVA_HOME,并将其添加到 PATH 中。
  3. 安装 Maven 或 Gradle:选择一个构建工具来构建你的项目。Maven 和 Gradle 都是常见的选择。
  4. 安装 IDE:推荐使用 IntelliJ IDEA 或 Eclipse,这些 IDE 支持 Spring Boot 项目创建和运行。

示例代码

以下是一个简单的 Maven 配置文件 pom.xml,用于创建一个基于 Spring Boot 3 的项目:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.0</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </build>
</project>

创建第一个Spring Boot 3项目

创建一个简单的 Spring Boot 3 应用程序,可以按照以下步骤进行:

  1. 创建一个新的 Maven 项目:通过命令行或在 IDE 中创建一个新的 Maven 项目。
  2. 配置 pom.xml:使用上面提供的 pom.xml 配置文件,确保依赖项正确设置。
  3. 创建主应用程序类:在 src/main/java 目录下创建一个新的 Java 类,并添加 @SpringBootApplication 注解。

示例代码

下面是一个简单的 Spring Boot 应用程序主类:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

这个主类是应用程序的入口点。@SpringBootApplication 注解集成了 @Configuration@EnableAutoConfiguration@ComponentScan,这三个注解的作用分别是配置类、自动配置和组件扫描。

SpringBoot3核心概念解析

在本节中,我们将详细介绍 Spring Boot 3 的一些核心概念,包括自动配置、依赖注入、Starter 依赖以及配置文件解析。

自动配置

Spring Boot 的一个关键特性是自动配置。自动配置是指 Spring Boot 根据类路径中的特定依赖项,自动配置适当的配置。例如,如果你在项目中添加了 spring-boot-starter-web 依赖,Spring Boot 会自动配置一个嵌入式的 Tomcat 服务器和一个 DispatcherServlet

示例代码

自动配置通常通过 @SpringBootApplication 注解实现。以下是一个使用自动配置的示例:

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

当添加上述依赖项时,Spring Boot 会自动配置一个 Web 应用程序所需的组件。

依赖注入

依赖注入(Dependency Injection,DI)是 Spring 框架的一个核心特性。使用 DI,Spring 容器可以自动地将组件的依赖项注入到组件中。这简化了组件之间的协作和管理。

示例代码

下面是一个简单的依赖注入示例:

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class DependencyInjectionApplication {

    @Autowired
    private MyService myService;

    public static void main(String[] args) {
        SpringApplication.run(DependencyInjectionApplication.class, args);
    }

    @Bean
    public CommandLineRunner commandLineRunner() {
        return (args) -> {
            myService.doSomething();
        };
    }
}

interface MyService {
    void doSomething();
}

class MyServiceImpl implements MyService {
    @Override
    public void doSomething() {
        System.out.println("Doing something");
    }
}

在这个示例中,MyService 接口和 MyServiceImpl 类被定义,MyService 被注入到 DependencyInjectionApplication 类中。

Starter依赖

Spring Boot 使用 Starter 来简化依赖管理。Starter 是一组预定义的依赖集合,用于特定的场景,如 Web 开发、数据库访问等。通过添加适当的 Starter 依赖,你可以快速设置项目所需的组件。

示例代码

以下是一个使用 spring-boot-starter-web 的示例:

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

添加 spring-boot-starter-web 依赖项,Spring Boot 会自动配置一个 Web 应用程序,包括嵌入式的 Tomcat 服务器和 DispatcherServlet

配置文件解析

Spring Boot 使用 application.propertiesapplication.yml 文件来配置应用程序的属性。这些属性可以用于数据库连接、端口设置、日志级别等。

示例代码

以下是一个 application.properties 文件的示例:

server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=root

这些配置属性会被 Spring Boot 自动加载和解析。

SpringBoot3常用功能详解

本节将详细介绍一些 Spring Boot 3 的常用功能,包括数据库集成与使用、RESTful API 开发、日志管理和异常处理与自定义异常。

数据库集成与使用

Spring Boot 3 提供了简单的数据库集成和使用方法。通过添加适当的 Starter 依赖,你可以轻松地配置数据库连接,并使用 JPA 或 MyBatis 等持久层框架。

示例代码

以下是一个使用 spring-boot-starter-data-jpa 的示例:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>

相应的 application.properties 配置:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.h2.console.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update

创建一个简单的实体类:

package com.example.demo;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

创建一个简单的 JPA Repository:

package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

RESTful API开发

创建 RESTful API 是 Spring Boot 的常见任务。通过添加 spring-boot-starter-web 依赖,你可以快速设置一个 Web 服务器,并使用 @RestController@RequestMapping 注解来定义 API 端点。

示例代码

以下是一个简单的 RESTful API 示例:

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

创建一个 REST 控制器:

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users")
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}

日志管理

Spring Boot 3 提供了强大的日志管理功能。通过配置 logback-spring.xmllogback.xml,你可以自定义日志级别和输出格式。

示例代码

以下是一个 logback-spring.xml 的配置示例:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

异常处理与自定义异常

Spring Boot 3 提供了强大的异常处理功能,使你能够捕获和处理应用程序中的异常。自定义异常类可以提供更具体的错误信息和状态码。

示例代码

以下是一个简单的异常处理示例:

package com.example.demo;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex) {
        ErrorResponse errorResponse = new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
    }

    public static class ErrorResponse {
        private int status;
        private String message;

        public ErrorResponse(int status, String message) {
            this.status = status;
            this.message = message;
        }

        public int getStatus() {
            return status;
        }

        public void setStatus(int status) {
            this.status = status;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }

    @ResponseStatus(HttpStatus.NOT_FOUND)
    public static class ResourceNotFoundException extends RuntimeException {
        public ResourceNotFoundException(String message) {
            super(message);
        }
    }
}

在这个示例中,ResourceNotFoundException 是一个自定义异常类,GlobalExceptionHandler 是一个全局异常处理器,它捕获 ResourceNotFoundException 并返回一个自定义的 ErrorResponse 对象。

SpringBoot3项目实战

本节将通过三个具体的项目实战来展示如何使用 Spring Boot 3 实现实际的应用程序。这三个项目包括简易博客系统、用户注册与登录系统和商品展示与购物车系统。

实战一:简易博客系统

简易博客系统是一个基本的博客应用,允许用户发布和查看博客文章,支持评论和点赞功能。

示例代码

以下是一个简单的博客系统 REST 控制器示例:

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/posts")
public class PostController {

    @Autowired
    private PostRepository postRepository;

    @GetMapping
    public List<Post> getAllPosts() {
        return postRepository.findAll();
    }

    @GetMapping("/{id}")
    public Post getPostById(@PathVariable Long id) {
        return postRepository.findById(id).orElse(null);
    }

    @PostMapping
    public Post createPost(@RequestBody Post post) {
        return postRepository.save(post);
    }

    @PutMapping("/{id}")
    public Post updatePost(@PathVariable Long id, @RequestBody Post post) {
        if (postRepository.existsById(id)) {
            post.setId(id);
            return postRepository.save(post);
        }
        return null;
    }

    @DeleteMapping("/{id}")
    public void deletePost(@PathVariable Long id) {
        postRepository.deleteById(id);
    }
}

实战二:用户注册与登录系统

用户注册与登录系统是一个基本的身份验证应用,允许用户注册账号、登录、修改密码和获取个人信息。

示例代码

以下是一个简单的用户注册与登录系统 REST 控制器示例:

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @GetMapping
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userRepository.findById(id).orElse(null);
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        return userRepository.save(user);
    }

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        if (userRepository.existsById(id)) {
            user.setId(id);
            user.setPassword(passwordEncoder.encode(user.getPassword()));
            return userRepository.save(user);
        }
        return null;
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userRepository.deleteById(id);
    }
}

实战三:商品展示与购物车系统

商品展示与购物车系统是一个基本的电子商务应用,允许用户浏览商品、添加到购物车、结算订单和查看订单历史。

示例代码

以下是一个简单的商品展示与购物车系统 REST 控制器示例:

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/products")
public class ProductController {

    @Autowired
    private ProductRepository productRepository;

    @GetMapping
    public List<Product> getAllProducts() {
        return productRepository.findAll();
    }

    @GetMapping("/{id}")
    public Product getProductById(@PathVariable Long id) {
        return productRepository.findById(id).orElse(null);
    }

    @PostMapping
    public Product createProduct(@RequestBody Product product) {
        return productRepository.save(product);
    }

    @PutMapping("/{id}")
    public Product updateProduct(@PathVariable Long id, @RequestBody Product product) {
        if (productRepository.existsById(id)) {
            product.setId(id);
            return productRepository.save(product);
        }
        return null;
    }

    @DeleteMapping("/{id}")
    public void deleteProduct(@PathVariable Long id) {
        productRepository.deleteById(id);
    }
}
SpringBoot3安全性与部署

在本节中,我们将介绍如何在 Spring Boot 3 中实现安全性配置、用户认证与授权,以及如何部署和监控 Spring Boot 应用程序。

安全性配置

Spring Boot 3 提供了强大的安全性配置功能,使你可以轻松地实现用户认证和授权。通过使用 spring-boot-starter-security 依赖,你可以快速配置基本的安全设置。

示例代码

以下是一个简单的安全性配置示例:

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

配置一个自定义的安全配置类:

package com.example.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
            .and()
            .logout()
                .permitAll();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

用户认证与授权

Spring Boot 3 提供了多种用户认证和授权的实现方式。常见的认证方式包括基本认证、JWT 认证和 OAuth 认证,而授权则可以通过访问控制列表(ACL)或角色来实现。

示例代码

以下是一个使用 JWT 认证的示例:

package com.example.demo;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private UserDetailsService userDetailsService;
    private String secret;

    public JwtAuthenticationFilter(UserDetailsService userDetailsService, String secret) {
        this.userDetailsService = userDetailsService;
        this.secret = secret;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String authorizationHeader = request.getHeader("Authorization");

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            String token = authorizationHeader.substring(7);
            try {
                Claims claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();

                String username = claims.getSubject();
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);

                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    userDetails, null, Arrays.asList(new SimpleGrantedAuthority("USER"))
                );

                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            } catch (Exception e) {
                // Handle token validation error
            }
        }
        chain.doFilter(request, response);
    }
}

应用部署与监控

Spring Boot 3 提供了多种部署和监控应用程序的方法。常见的部署方式包括在本地、Docker 容器或云平台(如 AWS、Google Cloud)上部署。监控则可以通过 Actuator 端点或外部监控工具(如 Prometheus)来实现。

示例代码

以下是一个使用 Spring Boot Actuator 的示例:

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

配置 application.properties 以启用 Actuator 端点:

management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

可以通过访问 /actuator 路径来访问各种监控信息。

SpringBoot3调试与问题排查

本节将介绍一些常用的调试技巧、日志分析和常见问题的解决方案。

常用调试技巧

调试是开发过程中不可或缺的一部分。Spring Boot 提供了一些有用的调试工具和配置,使你可以轻松地进行调试。

示例代码

以下是一些常用的调试技巧:

  1. 启用调试日志:在 application.propertiesapplication.yml 中设置日志级别。
  2. 使用断点调试:在 IDE 中设置断点,以检查代码执行过程。
  3. 使用 @Profile 注解:根据环境配置不同的配置文件和类。
  4. 启用 Spring Boot 自带的调试功能:通过 spring.devtools.restart.enabled=true 启用开发工具的重启功能。
spring.devtools.restart.enabled=true
logging.level.org.springframework=DEBUG

日志分析

日志是调试和监控应用程序的重要手段。Spring Boot 使用 Logback 进行日志管理,可以通过配置 logback-spring.xml 来自定义日志格式。

示例代码

以下是一个 logback-spring.xml 的配置示例:

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

常见问题与解决方案

以下是一些常见的 Spring Boot 问题及其解决方案:

问题:依赖冲突

依赖冲突会导致应用程序无法正常启动。可以通过以下步骤来解决依赖冲突:

  1. 检查 pom.xmlbuild.gradle 文件:确保依赖项版本一致。
  2. 使用 mvn dependency:treegradle dependencies 查看依赖树:识别冲突的依赖项。
  3. 排除冲突的依赖项:在 pom.xmlbuild.gradle 中排除冲突的依赖项。

示例代码

排除冲突的依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

问题:应用程序启动失败

应用程序启动失败通常是由于配置错误或依赖缺失导致的。可以通过以下步骤来解决启动失败的问题:

  1. 检查 application.propertiesapplication.yml 文件:确保所有配置项正确。
  2. 查看启动日志:找到具体的错误信息并根据错误信息进行调试。
  3. 检查依赖项:确保所有必要的依赖项都已添加。

示例代码

检查启动日志:

2023-08-30T12:34:56.789+08:00 ERROR 12345 --- [           main] o.s.boot.SpringApplication               : Application run failed

根据上述日志信息,找到具体的错误原因并进行修正。

通过以上介绍,你已经掌握了 Spring Boot 3 的基本概念、常用功能、实战应用、安全性配置、部署和调试技巧。希望这些内容能够帮助你更好地理解和使用 Spring Boot 3。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消