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

Springboot单体架构搭建项目实战教程

概述

本文将详细介绍如何使用Springboot单体架构搭建项目实战,包括环境配置、项目创建和依赖库添加等内容。文章还将详细介绍配置文件的使用方法,并通过构建一个简单的REST API进行实战演示。此外,还将介绍如何部署和运行Spring Boot应用,以及如何使用Docker进行部署。

Spring Boot 简介

Spring Boot 是一个基于 Spring 框架的开源微框架,旨在简化新 Spring 应用的初始搭建及开发过程。Spring Boot 通过约定大于配置的方式,帮助开发者快速构建独立的、生产级别的应用。

Spring Boot 的定义和主要特性

Spring Boot 由 Pivotal 团队中的克劳斯·福瑞德 (Klaas Pieter Ruiter) 设计,并且由 Peter Čermák 和克劳斯·福瑞德 (Klaas Pieter Ruiter) 撰写。它提供了一种全新的方式来简化 Spring 应用的配置,使开发者可以快速地构建独立的 Spring 应用。

主要特性

  • 独立性: 基于 Spring Boot 应用可以打包成一个可执行的 jar 文件,该文件包含运行应用所需的一切,包括依赖库、配置文件和应用代码。
  • 生产级应用: Spring Boot 为生产环境应用提供了多种配置选项,例如嵌入式 Tomcat 服务器、默认的错误处理和日志记录。
  • 约定优于配置: Spring Boot 提供了一套默认配置,帮助开发者快速启动应用,同时允许开发者根据需求进行自定义。
  • 自动配置: Spring Boot 会根据依赖库的配置来自动配置 Spring 应用的内容。
  • 内嵌的运行时: 支持内嵌的 Tomcat、Jetty 和 Undertow 服务器,使得应用可以直接运行,而不需要部署到外部的容器中。
  • 外部化配置: 支持从命令行参数、环境变量、JNDI 等多种来源读取配置。
  • 健康检查: 提供了套默认的健康检查功能,可以用于监控应用的状态。
为什么选择 Spring Boot

使用 Spring Boot 可以快速搭建应用,因为它已经包含了很多常见的配置,如数据源、缓存等,开发者不需要手动配置这些细节。此外,Spring Boot 的应用可以非常轻量级地打包成 jar 文件,易于部署和迁移。

避免重复配置

使用 Spring Boot 可以避免重复配置,因为它已经包含了默认配置。例如,Spring Boot 可以自动配置数据源、缓存等组件,开发者只需在配置文件中指定数据库类型和连接信息即可。

快速启动应用

Spring Boot 提供了快速启动应用的功能,可以将应用打包成 jar 文件,并使用 java -jar 命令启动应用。这使得开发者可以更快地进行开发和部署。

Spring Boot 与传统 Spring 框架的区别

自动配置

Spring Boot 提供了自动配置功能,可以根据类路径中的类和 jar 依赖自动配置 Spring 应用。而传统 Spring 框架需要手动配置 bean 和依赖关系。

内嵌服务器

Spring Boot 内置了 Tomcat、Jetty 和 Undertow 服务器,可以将应用打包成可执行的 jar 文件,直接运行。而传统 Spring 框架需要将应用部署到外部容器中,例如 Tomcat 或 Jetty。

外部化配置

Spring Boot 支持从命令行参数、环境变量、JNDI 等多种来源读取配置。而传统 Spring 框架需要手动配置数据源、缓存等组件的配置信息。

健康检查

Spring Boot 提供了健康检查功能,可以监控应用的状态。而传统 Spring 框架需要手动编写代码来监控应用的状态。

环境配置
开发环境搭建

开发环境的搭建是每个项目的基础。Spring Boot 项目可以使用多种工具进行开发,包括 IntelliJ IDEA、Eclipse、Visual Studio Code 等。这里推荐 IntelliJ IDEA 和 Eclipse,因为这两个工具都提供了良好的 Spring Boot 集成支持。

安装 JDK

首先,需要安装 Java Development Kit (JDK),确保版本支持 Spring Boot。通常选择最新版本或稳定版本,例如 JDK 11 或 JDK 17。

# 下载 JDK
wget https://download.java.net/java/GA/jdk17.0.1/2657f01a823143cbb0fe5b42d650b09b/6/GPL/openjdk-17.0.1_linux-x64_bin.tar.gz

# 解压 JDK
tar -xzf openjdk-17.0.1_linux-x64_bin.tar.gz

# 设置环境变量
export JAVA_HOME=/path/to/jdk17
export PATH=$JAVA_HOME/bin:$PATH

# 验证安装
java -version

安装 IDE

安装 IDE 是开发 Spring Boot 应用的重要步骤。以下是安装 IntelliJ IDEA 的步骤:

  1. 下载 IntelliJ IDEA

    访问 JetBrains 官网 (https://www.jetbrains.com/idea/download/),下载适合的操作系统的安装包

    wget https://download.jetbrains.com/idea/ideaIC-2021.3.3.tar.gz
  2. 安装 IntelliJ IDEA

    解压下载的安装包,并按照安装向导进行安装。

    tar -xzf ideaIC-2021.3.3.tar.gz
    cd ideaIC-2021.3.3/bin
    ./idea.sh
  3. 配置 IntelliJ IDEA

    安装完成后,配置 IntelliJ IDEA,确保它能够访问到 JDK 和 Maven 或 Gradle 的安装路径。可以通过 File -> Settings -> Build, Execution, Deployment -> Build Tools 设置。

Maven 或 Gradle 简介及配置

Maven 和 Gradle 是两种常用的构建工具,用于管理项目的依赖和构建过程。

Maven

Maven 是一个项目管理和构建工具,基于 POM (Project Object Model) 文件进行配置。以下是 Maven 的基本配置步骤:

  1. 安装 Maven

    从 Maven 官网 (https://maven.apache.org/download.cgi) 下载 Maven,然后进行解压和安装。

    wget https://downloads.apache.org/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.tar.gz
    tar -xzf apache-maven-3.8.6-bin.tar.gz
    export M2_HOME=/path/to/apache-maven-3.8.6
    export PATH=$M2_HOME/bin:$PATH
  2. 配置 Maven

    在 IntelliJ IDEA 中,可以通过 File -> Settings -> Build, Execution, Deployment -> Build Tools -> Maven 设置 Maven 的安装路径,并确保配置正确。

Gradle

Gradle 是一个基于 Groovy 和 Ant 构建工具,用于自动化构建过程。以下是 Gradle 的基本配置步骤:

  1. 安装 Gradle

    从 Gradle 官网 (https://gradle.org/) 下载 Gradle,然后进行解压和安装。

    wget https://services.gradle.org/distributions/gradle-7.4.2-bin.zip
    unzip gradle-7.4.2-bin.zip
    export GRADLE_HOME=/path/to/gradle-7.4.2
    export PATH=$GRADLE_HOME/bin:$PATH
  2. 配置 Gradle

    在 IntelliJ IDEA 中,可以通过 File -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle 设置 Gradle 的安装路径,并确保配置正确。

创建 Spring Boot 项目
使用 Spring Initializr 创建新项目

Spring Initializr 是一个快速构建 Spring Boot 应用的工具,提供了多种选择来创建项目。以下是创建新项目的步骤:

  1. 访问 Spring Initializr

    访问 Spring Initializr 网站 (https://start.spring.io/),选择项目配置

    # 打开浏览器访问 https://start.spring.io/
  2. 选择项目信息

    填写项目的基本信息,如项目名称、语言等。

    Project name: demo
    Language: Java
    Packaging: Jar
    Java version: 17
  3. 选择依赖

    选择所需的依赖库,例如 Web、JPA、Thymeleaf 等。

    Dependencies:
    - Spring Web
    - Spring Data JPA
    - Spring Boot DevTools
    - Thymeleaf
  4. 下载项目

    下载生成的项目压缩包,然后解压到本地。

    wget https://start.spring.io/starter.zip
    unzip starter.zip
  5. 导入项目到 IDE

    将下载的项目导入到 IntelliJ IDEA 或 Eclipse 中。

    # 打开 IntelliJ IDEA 或 Eclipse
    # File -> Open -> 选择解压后的项目目录
添加依赖库

在 Spring Boot 项目中,依赖库是通过 Maven 的 pom.xml 文件或 Gradle 的 build.gradle 文件进行管理的。以下是添加依赖库的步骤:

Maven

pom.xml 文件中添加所需的依赖库,例如 Spring Web、Spring Data JPA、Spring Boot DevTools 等。

<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>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Gradle

build.gradle 文件中添加所需的依赖库,例如 Spring Web、Spring Data JPA、Spring Boot DevTools 等。

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    runtimeOnly 'org.springframework.boot:spring-boot-devtools'
}
配置文件详解

Spring Boot 项目可以使用 application.propertiesapplication.yml 文件来配置应用的属性。以下是配置文件的基本结构:

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

# 应用端口
server.port=8080

# JPA 配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

# Thymeleaf 配置
spring.thymeleaf.cache=false

application.yml

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

server:
  port: 8080

jpa:
  hibernate:
    ddl-auto: update
    show-sql: true
    dialect: org.hibernate.dialect.MySQLDialect

thymeleaf:
  cache: false
项目实战:构建一个简单的 REST API

本节将通过构建一个简单的 REST API,演示 Spring Boot 的基本使用方法。项目将包括创建 Controller、使用 Repository 和 Service 层、集成 JPA 与数据库,以及测试 REST API。

创建 Controller

Controller 是处理 HTTP 请求和响应的类。Spring Boot 提供了 @RestController 注解,用于标记处理 REST 风格的 Web 请求的控制器。

UserRestController.java

package com.example.demo.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
public class UserRestController {

    @GetMapping("/users")
    public List<String> getUsers() {
        return Arrays.asList("User1", "User2", "User3");
    }
}
使用 Repository 与 Service 层

Repository 层用于与数据库交互,Service 层用于业务逻辑处理。Spring Data JPA 提供了 @Repository@Service 注解,用于定义 Repository 和 Service 类。

UserRepository.java

package com.example.demo.repository;

import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

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

UserService.java

package com.example.demo.service;

import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    UserRepository userRepository;

    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}
数据库集成:JPA 与 SQL 数据库

JPA (Java Persistence API) 是一种对象关系映射 (ORM) 标准,用于将 Java 对象持久化到关系型数据库中。Spring Boot 的 spring-boot-starter-data-jpa 依赖库已经包含了 JPA 所需的所有配置。

User.java

package com.example.demo.model;

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

@Entity
public class User {

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

    public User() {}

    public User(String name) {
        this.name = name;
    }

    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;
    }
}
测试 REST API

测试 REST API 是确保应用功能正确的重要步骤。Spring Boot 提供了 @SpringBootTest 注解,用于定义 Spring Boot 的测试类。

DemoApplicationTests.java

package com.example.demo;

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.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

@WebMvcTest
public class DemoApplicationTests {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnDefaultMessage() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/users"))
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.content().string("User1, User2, User3"));
    }
}
部署与运行
打包 Spring Boot 应用

Spring Boot 应用可以打包成一个可执行的 jar 文件,使用 mvn packagegradle build 命令进行打包。

打包命令

# Maven
mvn package

# Gradle
gradle build
将项目部署到本地服务器

部署 Spring Boot 应用可以通过以下几种方式:

  1. 直接运行

    使用 java -jar 命令运行打包后的 jar 文件。

    java -jar target/demo.jar
  2. 使用 Web 服务器

    将应用部署到 Tomcat、Jetty 或 Undertow 等 Web 服务器中。

    # 启动 Tomcat
    mvn tomcat7:run
使用 Docker 部署(可选)

Docker 是一个开源的容器化平台,可以用来构建、部署和运行 Spring Boot 应用。以下是使用 Docker 部署 Spring Boot 应用的步骤:

  1. 创建 Dockerfile

    创建 Dockerfile 文件,定义构建镜像的指令。

    FROM openjdk:17-jdk-alpine
    COPY target/demo.jar app.jar
    ENTRYPOINT ["java", "-jar", "/app.jar"]
  2. 构建 Docker 镜像

    使用 docker build 命令构建 Docker 镜像。

    docker build -t myapp .
  3. 运行 Docker 容器

    使用 docker run 命令运行 Docker 容器。

    docker run -p 8080:8080 -d myapp
应用监控与日志配置

监控和日志记录是应用运行过程中非常重要的部分,帮助开发者更好地了解应用的状态和问题。

应用监控

Spring Boot 可以集成多种监控工具,例如 Actuator。Actuator 提供了多种端点来监控应用的状态。

日志配置

Spring Boot 默认使用 Logback 作为日志框架,可以通过 application.propertiesapplication.yml 文件来配置日志输出。

# application.properties
logging.level.root=INFO
logging.file.path=/path/to/logs
logging.file.name=springboot.log
# application.yml
logging:
  level:
    root: INFO
  file:
    path: /path/to/logs
    name: springboot.log
实战进阶
安全性:使用 Spring Security

Spring Security 是一个强大的认证和授权框架,用于保护 Spring 应用的安全。以下是使用 Spring Security 的基本步骤:

  1. 添加依赖

    pom.xmlbuild.gradle 文件中添加 Spring Security 依赖。

    <!-- pom.xml -->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    // build.gradle
    implementation 'org.springframework.boot:spring-boot-starter-security'
  2. 配置安全

    使用 @Configuration 注解的类来配置 Spring Security。

    package com.example.demo.config;
    
    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.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
       @Override
       protected void configure(AuthenticationManagerBuilder auth) throws Exception {
           auth
                   .inMemoryAuthentication()
                   .withUser("user").password("{noop}password").roles("USER")
                   .and()
                   .withUser("admin").password("{noop}password").roles("ADMIN");
       }
    
       @Override
       protected void configure(HttpSecurity http) throws Exception {
           http
                   .authorizeRequests()
                   .antMatchers("/admin/**").hasRole("ADMIN")
                   .antMatchers("/user/**").hasRole("USER")
                   .anyRequest().permitAll()
                   .and()
                   .formLogin()
                   .loginPage("/login")
                   .permitAll()
                   .and()
                   .logout()
                   .permitAll();
       }
    }
  3. 创建登录页面

    创建一个简单的登录页面,并使用 Spring Security 进行认证。

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
       <title>Login Page</title>
    </head>
    <body>
       <form th:action="@{/login}" method="post">
           Username: <input type="text" name="username"/>
           Password: <input type="password" name="password"/>
           <input type="submit" value="Login"/>
       </form>
    </body>
    </html>
模板引擎:Thymeleaf 和 FreeMarker

Spring Boot 提供了多种模板引擎的支持,例如 Thymeleaf 和 FreeMarker。以下是使用 Thymeleaf 的基本步骤:

  1. 添加依赖

    pom.xmlbuild.gradle 文件中添加 Thymeleaf 依赖。

    <!-- pom.xml -->
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    // build.gradle
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
  2. 创建模板文件

    src/main/resources/templates 目录下创建模板文件,例如 index.html

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
       <title>Home Page</title>
    </head>
    <body>
       <h1>Welcome to Home Page</h1>
       <p th:text="${message}">Hello, World!</p>
    </body>
    </html>
  3. 创建控制器

    创建控制器类,返回模板文件。

    package com.example.demo.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    public class HomeController {
    
       @GetMapping("/")
       public String index(Model model) {
           model.addAttribute("message", "Hello, World!");
           return "index";
       }
    }
实战案例:搭建一个简单的用户管理系统

本节将通过搭建一个简单的用户管理系统,演示 Spring Boot 的实际应用。项目将包括用户注册、登录、列表查看等功能。

用户注册页面

创建用户注册页面,通过表单提交用户信息到后端。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>User Registration</title>
</head>
<body>
    <form th:action="@{/register}" method="post">
        Username: <input type="text" name="username"/>
        Password: <input type="password" name="password"/>
        <input type="submit" value="Register"/>
    </form>
</body>
</html>

用户登录页面

创建用户登录页面,通过表单提交用户信息进行登录验证。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>User Login</title>
</head>
<body>
    <form th:action="@{/login}" method="post">
        Username: <input type="text" name="username"/>
        Password: <input type="password" name="password"/>
        <input type="submit" value="Login"/>
    </form>
</body>
</html>

用户列表页面

创建用户列表页面,显示所有用户的信息。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>User List</title>
</head>
<body>
    <h1>User List</h1>
    <table>
        <tr>
            <th>ID</th>
            <th>Username</th>
        </tr>
        <tr th:each="user : ${users}">
            <td th:text="${user.id}">1</td>
            <td th:text="${user.username}">User1</td>
        </tr>
    </table>
</body>
</html>

用户注册控制器

创建用户注册控制器,处理用户注册的逻辑。

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;

import com.example.demo.model.User;
import com.example.demo.service.UserService;

@Controller
public class UserController {

    @Autowired
    UserService userService;

    @Autowired
    PasswordEncoder passwordEncoder;

    @PostMapping("/register")
    public String register(User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userService.registerUser(user);
        return "redirect:/login";
    }
}

用户登录控制器

创建用户登录控制器,处理用户登录的逻辑。

package com.example.demo.controller;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class LoginController {

    @GetMapping("/login")
    public String login(Model model, @RequestParam(value = "error", required = false) String error) {
        if (error != null && error.equals("true")) {
            model.addAttribute("error", "Invalid username or password.");
        }
        return "login";
    }

    @PostMapping("/login")
    public String handleLogin(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            return "redirect:/users";
        } else {
            return "redirect:/login";
        }
    }

    @GetMapping("/logout")
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        new SecurityContextLogoutHandler().logout(request, response, SecurityContextHolder.getContext().getAuthentication());
        return "redirect:/login";
    }
}

用户服务

创建用户服务类,处理用户注册和登录的业务逻辑。

package com.example.demo.service;

import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    UserRepository userRepository;

    @Autowired
    PasswordEncoder passwordEncoder;

    public void registerUser(User user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userRepository.save(user);
    }

    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}
点击查看更多内容
TA 点赞

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

评论

作者其他优质文章

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

100积分直接送

付费专栏免费学

大额优惠券免费领

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

举报

0/150
提交
取消