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

Spring Boot企业级开发学习:从入门到初级实战

标签:
SpringBoot
概述

Spring Boot企业级开发学习涵盖了从环境搭建到核心功能介绍,再到常用技术集成和项目优化部署的全面内容。文章详细讲解了数据库访问、RESTful服务开发和安全性集成等关键技术点,并通过实战案例解析了如何构建企业级应用。此外,还提供了常见问题与解决方案,帮助开发者解决开发过程中的疑难问题。

Spring Boot简介与环境搭建

Spring Boot是什么

Spring Boot 是由 Pivotal 团队提供的一个用于简化 Spring 应用初始搭建以及开发过程的框架。它通过约定优于配置的方式,帮助开发者快速搭建独立的、生产级别的 Spring 项目。Spring Boot 支持数据库访问、安全性、缓存、消息、嵌入式服务器等功能,能够大幅减少开发、测试和部署的复杂性。

开发环境准备

Spring Boot 应用开发需要以下环境:

  1. Java 开发环境:建议使用 JDK 1.8 或以上版本。
  2. IDE:推荐使用 IntelliJ IDEA 或 Eclipse。
  3. Maven 或 Gradle:用于构建和管理依赖。
  4. Git:版本控制工具。

创建第一个Spring Boot项目

  1. 通过Spring Initializr创建项目

    • 访问https://start.spring.io/,选择合适的项目配置。
    • 选择 Maven 项目,选择 Java 语言。
    • 选择 Spring Boot 版本,例如 2.5.0。
    • 设置项目的基本信息,如:Group、Artifact、Name、Description、Package Name等。
    • 添加所需依赖,如 Web、Thymeleaf、JPA 等。
    • 下载并解压创建的项目。
  2. 手动创建项目

    • 创建一个新的 Maven 项目。
    • 在 pom.xml 文件中添加 Spring Boot 相关的依赖:
      <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.5.0</version>
      </parent>
      <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-data-jpa</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-thymeleaf</artifactId>
       </dependency>
      </dependencies>
  3. 创建主类

    • 创建一个主类,并使用 @SpringBootApplication 注解来启动 Spring Boot 应用。

      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      
      @SpringBootApplication
      public class Application {
       public static void main(String[] args) {
           SpringApplication.run(Application.class, args);
       }
      }
  4. 启动项目
    • 在IDE中运行主类中的 main 方法,或使用命令行:
      mvn spring-boot:run
    • 访问 http://localhost:8080 来验证应用是否成功启动。

总结

通过以上步骤,我们已经成功搭建了第一个 Spring Boot 项目。接下来我们将深入探讨 Spring Boot 的核心功能和常用技术集成。

Spring Boot核心功能介绍

自动配置详解

Spring Boot 通过自动配置功能简化了 Spring 应用的配置流程。自动配置会根据应用中存在的一些依赖来智能地完成配置工作。例如,如果项目中引入了 Spring Web 依赖,Spring Boot 会默认配置一个 Tomcat 容器。通过 spring-boot-autoconfigure 模块,Spring Boot 可以自动配置各种组件,如数据源、事务管理器、Web 服务器等。

自动配置原理

Spring Boot 通过以下步骤实现自动配置:

  1. 配置类:每个自动配置功能通常会有一个配置类,该类被 @Configuration 注解标记。
  2. 条件注解:在配置类上使用 @Conditional 注解(如 @ConditionalOnClass@ConditionalOnMissingBean 等),确保在满足特定条件时才会进行配置。
  3. 配置属性:通过 @EnableAutoConfiguration 启用自动配置,并在 spring.factories 文件中指定自动配置的类。

自动配置示例

假设我们有一个简单的 REST API 应用,Spring Boot 会自动配置 Tomcat 服务器来处理 HTTP 请求。当我们在 pom.xml 中引入了 spring-boot-starter-web 依赖时,Spring Boot 会自动配置 SpringApplication,注入 DispatcherServletSpringResourceServlet

@Configuration
public class MyAutoConfiguration {
    @ConditionalOnClass(MyService.class)
    @Bean
    public MyService myService() {
        return new MyService();
    }
}

开启或关闭自动配置

可以通过 spring.autoconfigure.exclude 属性来禁用不需要的自动配置。例如:

spring:
  .autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

以上配置会禁用 Spring Security 自动配置。

依赖管理和启动器

Spring Boot 的依赖管理和启动器简化了依赖管理过程。启动器是一个方便的功能,可以自动添加所需的依赖项,从而减少手动添加重复依赖的麻烦。

启动器使用

启动器是一个包含一组依赖项的 JAR 文件,通常用于启动和开发 Spring Boot 应用。例如,如果你想要创建一个 Web 应用,你可以添加 spring-boot-starter-web 启动器,它会自动包含所有构建 Web 应用所需的依赖项。

示例代码

pom.xml 中添加 spring-boot-starter-web 依赖:

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

自定义依赖

除了使用内置的启动器,你也可以定义自己的启动器,以包含项目特定的依赖项。例如,你可以在 pom.xml 中定义一个新的启动器:

<dependency>
    <groupId>com.example</groupId>
   . <artifactId>my-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

配置文件使用

Spring Boot 支持多种配置文件格式,如 application.propertiesapplication.yml。这些配置文件可以用来控制应用的配置选项,如数据源、端口号、日志级别等。

配置文件格式

  • application.properties:使用键值对的形式进行配置。
  • application.yml:使用 YAML 格式进行配置,支持更复杂的配置结构。

配置示例

application.properties 中配置数据库连接参数:

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

application.yml 中配置同样的数据库连接参数:

spring:
  datasource:
  url: jdbc:mysql://localhost:3306/mydb
  username: root
  password: root
  driver-class-name: com.mysql.cj.jdbc.Driver

总结

通过以上内容,我们了解了 Spring Boot 的自动配置、依赖管理和配置文件的使用。这些功能使得 Spring Boot 应用的开发更加简单快捷。接下来我们将学习如何在项目中集成常用的技术,如数据库访问、RESTful 服务开发和安全性集成。

Spring Boot常用技术集成

数据库访问(JPA, MyBatis等)

Spring Boot 对多种数据库访问技术提供了良好的支持,包括 JPA 和 MyBatis。JPA(Java Persistence API)是 Java 平台中的一种持久化框架,而 MyBatis 则是一个优秀的持久层框架,它支持定制化 SQL 和存储过程调用,同时也提供了强大的对象关系映射。

JPA 使用

JPA 的核心是 EntityManager 接口,它封装了对数据库的所有操作。Spring Boot 提供了 JpaRepositoriesJpaSpecificationExecutor 等接口来简化数据访问层的操作。

示例代码

创建一个简单的 User 实体类:

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;

    // Getters and Setters
}

创建对应的 UserRepository 接口:

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

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

MyBatis 使用

MyBatis 是一个优秀的持久层框架,它支持定制化 SQL 和存储过程调用,同时提供强大的对象关系映射。

示例代码

创建一个 UserMapper 接口:

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id = #{id}")
    User findById(Long id);
}

在 Spring Boot 中配置 MyBatis:

spring:
  mybatis:
    mapper-locations: classpath:mapper/*.xml

RESTful服务开发(Spring MVC)

Spring Boot 集成了 Spring MVC,可以方便地开发 RESTful API。Spring MVC 支持注解驱动的 RESTful API 开发,包括 @RestController@RequestMapping@GetMapping@PostMapping 等注解。

示例代码

创建一个 UserController

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

import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserRepository userRepository;

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

    @PostMapping("/")
    public User createUser(@RequestBody User user) {
        return userRepository.save(user);
    }

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

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userRepository.save(user);
    }

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

安全性集成(Spring Security)

Spring Boot 集成了 Spring Security,可以方便地为应用添加安全保护。Spring Security 支持多种认证和授权方式,如 HTTP Basic、OAuth、JWT 等。

示例代码

spring-security.xml 中配置 Spring Security:

<http auto-config="true">
    <intercept-url pattern="/users/**" access="hasRole('USER')" />
    <form-login login-page="/login" default-target-url="/dashboard" />
    <logout logout-success-url="/login?logout" />
</http>

创建一个 UserDetailsService 实现类:

import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 实现从数据库中获取用户信息逻辑
        // 示例中简化为直接返回一个用户对象
        return User.withDefaultPasswordEncoder()
                .username(username)
                .password("password")
                .roles("USER")
                .build();
    }
}

配置 WebSecurityConfigurerAdapter

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }

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

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

总结

通过上述内容,我们可以看到 Spring Boot 框架对数据库访问、RESTful 服务开发和安全性集成的支持。这些功能使得开发者可以快速地构建出功能完备的应用程序。接下来,我们将学习如何优化和部署 Spring Boot 应用。

Spring Boot项目优化与部署

性能优化

性能优化是提高应用响应速度和稳定性的重要手段。Spring Boot 提供了多种优化策略,如优化数据库操作、减少网络延迟和提高并发性能等。

数据库优化

  • 连接池优化:使用 HikariCP 或其他高性能连接池管理数据库连接。
  • 查询优化:避免 N+1 查询问题,使用分页查询。
  • 索引优化:合理使用索引减少查询时间。
示例代码

使用 HikariCP 配置数据库连接池:

spring:
  datasource:
  url: jdbc:mysql://localhost:3306/mydb
  username: root
  password: root
  driver-class-name: com.mysql.cj.jdbc.Driver
  hikari:
    pool-name: MyDataSourcePool
    minimum-idle: 10
    maximum-pool-size: 20
    connection-timeout: 30000
    idle-timeout: 600000
    max-lifetime: 1800000

网络延迟优化

  • 异步处理:使用异步任务处理耗时操作。
  • 缓存:使用 Redis 或其他缓存系统减少数据库访问。
示例代码

使用 Spring Boot 的异步任务处理:

import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

@EnableAsync
@Component
public class AsyncConfig {

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(25);
        executor.setThreadNamePrefix("MyAsync-");
        executor.initialize();
        return executor;
    }
}

日志配置

日志是应用运行时的重要信息来源。Spring Boot 使用 Logback 作为默认的日志系统,支持多种日志框架,如 SLF4J、Logback 和 Log4j。

日志配置示例

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>

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>logs/app.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

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

应用打包与部署

Spring Boot 提供了 spring-boot-maven-plugin 插件来简化应用的打包和部署。打包后的应用可以使用 java -jar 命令来启动。

打包应用

pom.xml 中配置打包插件:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

使用 Maven 命令打包应用:

mvn clean package

生成的 jar 文件位于 target 目录下。

部署应用

将生成的 jar 文件部署到生产环境中:

java -jar target/myapp.jar

总结

通过上述内容,我们学习了如何优化和部署 Spring Boot 应用。性能优化和日志配置可以有效提高应用的响应速度和稳定性,而打包与部署则简化了生产环境的部署过程。接下来,我们将通过一个实战案例来解析如何构建简单企业级应用。

实战案例解析

构建简单企业级应用

我们将构建一个简单的企业级应用,其中包括用户管理模块、商品管理模块和订单管理模块。通过该示例,我们了解如何在实际项目中应用 Spring Boot 的各种功能。

项目架构

  • 用户管理模块:包含用户注册、登录、信息修改等功能。
  • 商品管理模块:包含商品列表、商品详情、商品添加等功能。
  • 订单管理模块:包含订单查询、订单创建、订单支付等功能。

示例代码

创建一个 User 实体类:

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;
    private String password;

    // Getters and Setters
}

创建对应的 UserRepository 接口:

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

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

创建一个 UserController

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

import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserRepository userRepository;

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

    @PostMapping("/")
    public User createUser(@RequestBody User user) {
        return userRepository.save(user);
    }

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

    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userRepository.save(user);
    }

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

模块划分与组件设计

在构建企业级应用时,我们需要将应用划分为多个模块,并设计合理的组件结构。这样可以提高代码的可维护性和可扩展性。

模块划分

  • 用户模块:包含用户相关的所有操作。
  • 商品模块:包含商品相关的所有操作。
  • 订单模块:包含订单相关的所有操作。
  • 公共模块:包含所有模块共用的组件,如日志记录、异常处理等。

组件设计

每个模块可以进一步划分为多个组件,如服务层、数据访问层、控制器层等。

示例代码

创建一个 UserService

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

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

    public User createUser(User user) {
        return userRepository.save(user);
    }

    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }

    public User updateUser(Long id, User user) {
        user.setId(id);
        return userRepository.save(user);
    }

    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
}

项目测试与调试

项目测试是保证应用质量的重要环节。Spring Boot 提供了多种测试工具,如 JUnit、Spring Test、Mockito 等。

单元测试

单元测试是针对单个组件或方法进行的测试。

示例代码

创建一个 UserControllerTest

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;

import java.util.Arrays;
import java.util.List;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@WebMvcTest(UserController.class)
public class UserControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserRepository userRepository;

    @Test
    public void testGetAllUsers() throws Exception {
        List<User> users = Arrays.asList(new User(1L, "Alice", "alice@example.com"), new User(2L, "Bob", "bob@example.com"));
        when(userRepository.findAll()).thenReturn(users);

        mockMvc.perform(get("/users/"))
            .andExpect(status().isOk())
            .andExpect(content().json("[{\"id\":1,\"name\":\"Alice\",\"email\":\"alice@example.com\"},{\"id\":2,\"name\":\"Bob\",\"email\":\"bob@example.com\"}]", true));
    }
}

调试技巧

  • 使用断点调试:在 IDE 中设置断点,通过调试模式运行代码,逐步查看变量值和调用栈。
  • 使用日志:通过添加日志输出,分析应用运行时的行为。

总结

通过上述实战案例,我们学习了如何构建一个简单的企业级应用,并了解了模块划分、组件设计和项目测试的技巧。这些知识和实践经验将帮助你在实际项目中更好地应用 Spring Boot。

常见问题与解决方案

常见异常及解决方法

在开发过程中,经常会遇到各种异常,下面列举了一些常见的异常及其解决方法。

示例代码

  1. NoSuchBeanDefinitionException:当 Spring 容器找不到某个 Bean 时,会抛出此异常。

    import org.springframework.beans.factory.NoSuchBeanDefinitionException;
    import org.springframework.context.ApplicationContext;
    
    public class Example {
       public static void main(String[] args) {
           ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
           try {
               context.getBean("nonExistentBean");
           } catch (NoSuchBeanDefinitionException e) {
               System.out.println("No such bean definition");
           }
       }
    }
  2. DataIntegrityViolationException:当发生数据完整性异常时,如违反数据库约束时,会抛出此异常。

    import org.springframework.dao.DataIntegrityViolationException;
    import org.springframework.jdbc.core.JdbcTemplate;
    
    public class Example {
       private JdbcTemplate jdbcTemplate;
    
       public void createUser(User user) {
           try {
               jdbcTemplate.update("INSERT INTO users (name, email) VALUES (?, ?)", user.getName(), user.getEmail());
           } catch (DataIntegrityViolationException e) {
               System.out.println("Data integrity violation");
           }
       }
    }

开发中遇到的疑难问题

  1. 内存溢出(OutOfMemoryError):当 JVM 内存不足时,会抛出此异常。

    • 解决方案:增加 JVM 内存配置,如 -Xms-Xmx 参数。
      java -Xms512m -Xmx1024m -jar myapp.jar
  2. 线程死锁(Deadlock):多个线程互相等待对方释放资源,导致死锁。

    • 解决方案:合理设计线程同步机制,避免资源竞争。
      
      import java.util.concurrent.locks.Lock;
      import java.util.concurrent.locks.ReentrantLock;

    public class Example {
    private final Lock lock1 = new ReentrantLock();
    private final Lock lock2 = new ReentrantLock();

    public void methodA() {
    lock1.lock();
    try {
    lock2.lock();
    try {
    // Do something
    } finally {
    lock2.unlock();
    }
    } finally {
    lock1.unlock();
    }
    }

    public void methodB() {
    lock2.lock();
    try {
    lock1.lock();
    try {
    // Do something
    } finally {
    lock1.unlock();
    }
    } finally {
    lock2.unlock();
    }
    }
    }

常用工具推荐

  1. IDEA:强大的 Java 开发工具,支持智能代码提示、代码重构等。
  2. Postman:方便的 API 测试工具,支持多种 HTTP 请求,可以测试和调试 RESTful API。
  3. Swagger:API 文档生成工具,可以自动生成和展示 API 文档,方便开发者查看和测试接口。
  4. Logback:强大的日志框架,支持多种日志输出格式和配置。
  5. JProfiler:Java 应用性能分析工具,可以帮助定位性能瓶颈和内存泄漏问题。

总结

通过上述内容,我们了解了如何处理 Spring Boot 开发过程中常见的异常和疑难问题,以及推荐了一些常用的开发工具。这些知识和工具将帮助你更好地进行 Spring Boot 应用的开发和调试。

点击查看更多内容
TA 点赞

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

评论

作者其他优质文章

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

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消