ToB企服应用市场:ToB评测及商务社交产业平台
标题:
实验9 JSP访问数据库(二)
[打印本页]
作者:
慢吞云雾缓吐愁
时间:
2024-11-30 23:42
标题:
实验9 JSP访问数据库(二)
目的:
1、认识JDBC的数据库访问模式。
2、掌握预处理语句的利用
实验要求:
利用Tomcat作为Web服务器
通过JDBC访问数据库,实现增删改查功能的实现
要求提交实验陈诉,将代码和实验结果页面截图放入陈诉中
实验内容:
1.编写一个网页,实现根据输入门生姓名的暗昧查询,假如查找不到就显示“查无此人”
StudentQueryServlet.java
这是一个Servlet,负责接收用户的哀求,毗连数据库执行查询,并返回查询结果。
package com.example.servlet;
import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class StudentQueryServlet extends HttpServlet {
// JDBC数据库连接配置
private static final String DB_URL = "jdbc:mysql://localhost:3307/student"; // 替换成你的数据库地址,我这里写的是3307不是3306
private static final String DB_USER = "root"; // 数据库用户名
private static final String DB_PASS = "123456"; // 数据库密码
// 处理GET请求
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取用户输入的学生姓名
String studentName = request.getParameter("studentName");
// 设置响应内容类型为HTML
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 默认返回“查无此人”信息
String result = "查无此人";
// 连接数据库并执行查询
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS)) {
String sql = "SELECT * FROM students WHERE name LIKE ?"; // SQL模糊查询
try (PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, "%" + studentName + "%"); // 设置模糊查询的姓名
ResultSet rs = stmt.executeQuery();
// 如果查询到结果,则显示学生信息
if (rs.next()) {
result = "<h3>查询结果:</h3>";
do {
result += "<p>姓名:" + rs.getString("name") + "<br>"
+ "年龄:" + rs.getInt("age") + "<br>"
+ "专业:" + rs.getString("major") + "</p>";
} while (rs.next());
}
}
} catch (SQLException e) {
e.printStackTrace();
result = "数据库连接错误";
}
// 输出HTML响应
out.println("<html><body>");
out.println("<h1>学生信息查询</h1>");
out.println("<form method='GET' action='StudentQueryServlet'>");
out.println("请输入学生姓名:<input type='text' name='studentName' />");
out.println("<input type='submit' value='查询' />");
out.println("</form>");
out.println("<hr>");
out.println(result);
out.println("</body></html>");
}
}
复制代码
web.xml 设置
web.xml 是Web应用的设置文件,用于设置Servlet、映射等信息。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- Web应用名称 -->
<display-name>sample</display-name>
<!-- Servlet配置 -->
<servlet>
<servlet-name>StudentQueryServlet</servlet-name>
<servlet-class>com.example.servlet.StudentQueryServlet</servlet-class>
<load-on-startup>1</load-on-startup> <!-- 应用启动时加载 -->
</servlet>
<!-- Servlet映射 -->
<servlet-mapping>
<servlet-name>StudentQueryServlet</servlet-name>
<url-pattern>/StudentQueryServlet</url-pattern> <!-- URL访问路径 -->
</servlet-mapping>
<!-- 欢迎文件配置 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file> <!-- 默认首页 -->
</welcome-file-list>
</web-app>
复制代码
index.jsp 页面
这是用户输入门生姓名并提交查询哀求的页面。
<%@ page contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>学生信息查询</title>
</head>
<body>
<h1>学生信息查询</h1>
<form method="GET" action="StudentQueryServlet">
<label for="studentName">请输入学生姓名:</label>
<input type="text" id="studentName" name="studentName" required />
<input type="submit" value="查询" />
</form>
</body>
</html>
复制代码
JDBC驱动
将MySQL JDBC驱动(mysql-connector-java-x.x.x.jar)放入 WEB-INF/lib 目录中,如许Tomcat在启动时可以找到并加载该驱动。或者也可以放在tomcat的lib下
数据库设置
create database student;
use student;
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
age INT,
major VARCHAR(255)
);
INSERT INTO students (name, age, major) VALUES ('John Doe', 21, 'Computer Science');
INSERT INTO students (name, age, major) VALUES ('Jane Smith', 22, 'Physics');
INSERT INTO students (name, age, major) VALUES ('Alice Johnson', 20, 'Mathematics');
复制代码
2.实现门生注册和登录功能,输入门生学号(stuId)和暗码(stuPwd),假如学号不存在,跳转到注册界面,完成注册功能;假如学号存在,暗码匹配显示“登录成功”,否则显示“登录失败”。注:
要求用P
reparedStatement
实现。
java
package com.example.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.*;
public class StudentLogin extends HttpServlet {
private static final String DB_URL = "jdbc:mysql://localhost:3307/student";
private static final String DB_USER = "root";
private static final String DB_PASS = "123456";
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String pwd = request.getParameter("pwd");
response.setContentType("text/html;charset=UTF-8");
String result = null;
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS)) {
String sql = "SELECT * FROM student02 WHERE id = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, id);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
String dbPwd = rs.getString("pwd");
if (dbPwd.equals(pwd)) {
result = "登录成功";
} else {
result = "密码错误";
}
} else {
result = "学号不存在,请注册";
response.sendRedirect("register.jsp"); // 学号不存在,重定向到注册页面
return;
}
}
} catch (SQLException e) {
e.printStackTrace();
result = "数据库连接错误";
}
response.getWriter().write(result);
}
}
复制代码
package com.example.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.*;
public class StudentRegister extends HttpServlet {
private static final String DB_URL = "jdbc:mysql://localhost:3307/student";
private static final String DB_USER = "root";
private static final String DB_PASS = "123456";
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String id = request.getParameter("id");
String pwd = request.getParameter("pwd");
String name = request.getParameter("name");
response.setContentType("text/html;charset=UTF-8");
String result = null;
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS)) {
// 检查学号是否已经存在
String sql = "SELECT * FROM student02 WHERE id = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, id);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
result = "学号已存在,请重新输入";
response.getWriter().write(result);
} else {
// 插入新学生
sql = "INSERT INTO student02 (id, pwd, name) VALUES (?, ?, ?)";
try (PreparedStatement insertStmt = conn.prepareStatement(sql)) {
insertStmt.setString(1, id);
insertStmt.setString(2, pwd);
insertStmt.setString(3, name);
insertStmt.executeUpdate();
result = "注册成功";
response.getWriter().write(result);
}
}
} catch (SQLException e) {
e.printStackTrace();
result = "数据库连接错误";
response.getWriter().write(result);
}
} catch (SQLException e) {
e.printStackTrace();
result = "数据库连接错误";
response.getWriter().write(result);
}
}
}
复制代码
jsp:
<%--
Created by IntelliJ IDEA.
User: d'd'd
Date: 2024/11/15
Time: 14:07
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h1>学生登录</h1>
<form action="StudentLogin" method="post">
<label for="id">学号:</label>
<input type="text" id="id" name="id" required>
<br>
<label for="pwd">密码:</label>
<input type="password" id="pwd" name="pwd" required>
<br>
<input type="submit" value="登录">
</form>
<a href="register.jsp">没有账号?去注册</a>
</body>
</html>
复制代码
<%--
Created by IntelliJ IDEA.
User: d'd'd
Date: 2024/11/15
Time: 14:08
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册</title>
</head>
<body>
<h1>学生注册</h1>
<form action="StudentRegister" method="post">
<label for="id">学号:</label>
<input type="text" id="id" name="id" required>
<br>
<label for="pwd">密码:</label>
<input type="password" id="pwd" name="pwd" required>
<br>
<label for="name">姓名:</label>
<input type="text" id="name" name="name" required>
<br>
<input type="submit" value="注册">
</form>
</body>
</html>
复制代码
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!-- Web应用名称 -->
<display-name>StudentApp</display-name>
<!-- 登录Servlet配置 -->
<servlet>
<servlet-name>StudentLogin</servlet-name>
<servlet-class>com.example.servlet.StudentLogin</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 注册Servlet配置 -->
<servlet>
<servlet-name>StudentRegister</servlet-name>
<servlet-class>com.example.servlet.StudentRegister</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<!-- 登录Servlet映射 -->
<servlet-mapping>
<servlet-name>StudentLogin</servlet-name>
<url-pattern>/StudentLogin</url-pattern>
</servlet-mapping>
<!-- 注册Servlet映射 -->
<servlet-mapping>
<servlet-name>StudentRegister</servlet-name>
<url-pattern>/StudentRegister</url-pattern>
</servlet-mapping>
<!-- 默认欢迎页面 -->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
复制代码
用springboot+mybatis完成一个门生登录注册系统,并具有增删改查信息功能
后端
1.创建 Spring Boot 项目,依赖包含:
2.建表
-- 删除数据库
drop database students;
-- 创建数据库
create database students;
-- 使用数据库
use students;
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(255) NOT NULL,
full_name VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL,
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
复制代码
3.设置数据库
设置 application.properties 来毗连 MySQL 数据库。
spring.application.name=M-stu-sys
# 数据库连接配置
# 这一行指定了数据库的连接URL。
spring.datasource.url=jdbc:mysql://localhost:3306/students?useSSL=false&serverTimezone=UTC
# 用于指定连接数据库的用户名,这里设置为root,你需要将其替换为你实际使用的数据库用户名。
spring.datasource.username=root
# 这是连接数据库的密码,将yourpassword替换为你的数据库密码。
spring.datasource.password=123456
# 明确指定使用的MySQL JDBC驱动类,com.mysql.cj.jdbc.Driver是MySQL 8.0及以上版本使用的驱动类。
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis配置
# 告诉MyBatis在哪里查找映射文件(XML文件)。classpath:mapper/*.xml表示在类路径下的mapper目录中查找所有以.xml结尾的文件,这些文件包含了SQL语句和数据库操作的映射定义。
mybatis.mapper-locations=classpath:mapper/*.xml
# 用于设置MyBatis的类型别名包。这样在映射文件中可以使用短名称来代替全限定类名,方便书写SQL语句,提高代码的可读性。例如,如果在com.example.demo.model包中有一个User类,在映射文件中可以直接使用User来代替com.example.demo.model.User。
mybatis.type-aliases-package=org.example.mstusys.entity
# JPA配置(如果项目中用到JPA)
# 这个配置用于控制Hibernate(JPA的实现)如何根据实体类自动创建、更新或验证数据库表结构。update表示根据实体类的定义自动更新数据库表结构,例如添加新的字段、创建新的表等。但在生产环境中使用时要谨慎,因为可能会意外修改数据库结构。其他可选值包括create(每次启动应用时创建新的数据库表,删除旧表,慎用)、create-drop(在应用启动时创建表,关闭时删除表)、validate(只验证表结构是否与实体类定义一致,不进行修改)等。如果你的项目中没有使用JPA,可以删除这一行配置。
spring.jpa.hibernate.ddl-auto=update
复制代码
4.实体类
package org.example.mstusys.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private Integer id;
private String username;
private String password;
private String fullName;
private String email;
private String phone;
private String createdAt;
}
复制代码
5.创建 Mapper 接口和 XML 文件
创建一个 StudentMapper 接口,并提供 SQL 语句映射。
package org.example.mstusys.mapper;
import org.apache.ibatis.annotations.*;
import org.example.mstusys.entity.Student;
import java.util.List;
@Mapper
public interface StudentMapper {
// 向students表中插入一条学生记录,插入的字段包括用户名、密码、全名、邮箱和电话,参数为一个Student对象
@Insert("INSERT INTO students (username, password, full_name, email, phone) " +
"VALUES (#{username}, #{password}, #{fullName}, #{email}, #{phone})")
int registerStudent(Student student);
// 根据用户名查找学生记录,返回一个Student对象,如果未找到则返回null
@Select("SELECT * FROM students WHERE username = #{username}")
Student findByUsername(String username);
// 根据学生id查找学生记录,返回一个Student对象,如果未找到则返回null
@Select("SELECT * FROM students WHERE id = #{id}")
Student findById(int id);
// 查询students表中的所有学生记录,返回一个包含所有学生记录的List<Student>集合
@Select("SELECT * FROM students")
List<Student> findAll();
// 根据学生id更新学生记录,更新的字段包括用户名、密码、全名、邮箱和电话,参数为一个Student对象
@Update("UPDATE students SET username = #{username}, password = #{password}, full_name = #{fullName}, " +
"email = #{email}, phone = #{phone} WHERE id = #{id}")
int updateStudent(Student student);
// 根据学生id删除学生记录,返回受影响的行数,如果删除成功则返回1,否则返回0
@Delete("DELETE FROM students WHERE id = #{id}")
int deleteStudent(int id);
}
复制代码
6.创建 Service 层
创建一个 StudentService 类,用于处理业务逻辑。
package org.example.mstusys.service;
import org.example.mstusys.entity.Student;
import org.example.mstusys.mapper.StudentMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class StudentService {
// 注入StudentMapper
@Autowired
private StudentMapper studentMapper;
/**
* 注册学生
* @param student
* @return
*/
public int registerStudent(Student student) {
return studentMapper.registerStudent(student);
}
/**
* 登录
* @param username
* @return
*/
public Student login(String username){
return studentMapper.findByUsername(username);
}
/**
* 根据id获取学生信息
* @param id
* @return
*/
public Student getStudentById(int id){
return studentMapper.findById(id);
}
/**
* 获取所有学生信息
* @return
*/
public List<Student> getAllStudents() {
return studentMapper.findAll();
}
/**
* 更新学生信息
* @param student
* @return
*/
public int updateStudent(Student student) {
return studentMapper.updateStudent(student);
}
/**
* 删除学生信息
* @param id
* @return
*/
public int deleteStudent(int id) {
return studentMapper.deleteStudent(id);
}
}
复制代码
7.创建 Controller 层
创建一个 StudentController 控制器来处理 HTTP 哀求。
package org.example.mstusys.controller;
import org.example.mstusys.entity.Student;
import org.example.mstusys.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/students")
public class StudentController {
@Autowired
private StudentService studentService;
/**
* 注册
* @param student
* @return
*/
@PostMapping("/register")
public String register(@RequestBody Student student){
int result = studentService.registerStudent(student);
return result > 0 ? "Registration successful" : "Registration failed";
}
/**
* 登录
* @param username
* @param password
* @return
*/
@PostMapping("/login")
public String login(@RequestParam String username,@RequestParam String password){
Student student = studentService.login(username);
if(student != null && student.getPassword().equals(password)){
return "Login successful";
}else{
return "Invalid username or password";
}
}
/**
* 根据id查询学生
* @param id
* @return
*/
@GetMapping("/{id}")
public Student getStudentById(@PathVariable int id){
return studentService.getStudentById(id);
}
/**
* 查询所有学生
* @return
*/
@GetMapping("/all")
public List<Student> getAllStudents(){
return studentService.getAllStudents();
}
/**
* 更新学生信息
* @param student
* @return
*/
@PutMapping("/update")
public String updateStudent(@RequestBody Student student) {
int result = studentService.updateStudent(student);
return result > 0 ? "Student updated successfully" : "Update failed";
}
/**
* 删除学生
* @param id
* @return
*/
@DeleteMapping("/delete/{id}")
public String deleteStudent(@PathVariable int id) {
int result = studentService.deleteStudent(id);
return result > 0 ? "Student deleted successfully" : "Delete failed";
}
}
复制代码
8.启动 Spring Boot 应用
确保你的 @SpringBootApplication 类设置准确
package org.example.mstusys;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MStuSysApplication {
public static void main(String[] args) {
SpringApplication.run(MStuSysApplication.class, args);
}
}
复制代码
9. 测试接口
利用 Postman 或其他 API 测试工具来测试接口:
POST /students/register
:注册门生
POST /students/login
:登录门生
GET /students/{id}
:查询单个门生信息
GET /students/all
:查询全部门生信息
PUT /students/update
:更新门生信息
DELETE /students/delete/{id}
:删除门生信息
通过 Postman 测试 Spring Boot + MyBatis 项目中的接口非常方便。你可以发送差异的 HTTP 哀求(如 POST、GET、PUT、DELETE)来测试用户注册、登录、查询、更新和删除等功能。记得在测试时保证服务器已经启动,而且数据库已经设置好。
10. 利用 Spring Security(可选)
假如须要对登录举行更严酷的身份验证,发起集成
Spring Security
举行加密和认证。
前端
确保你已经安装了 Node.js 和 npm。你可以通过以下命令查抄是否安装了:
node -v
npm -v
复制代码
我用的是
docker-compose 部署node.js和mysql
1.设置 docker-compose.yml
我们将在项目根目录(M-stu-sys/)下创建一个 docker-compose.yml 文件。它将定义如何启动 Node.js(前端)和 MySQL 服务。
version: '3.8'
services:
# 前端服务(Node.js)
frontend:
build:
context: ./frontend # 假设你的 Vue.js 项目位于 ./frontend 目录中
ports:
- "8080:80" # 映射容器的 80 端口到主机的 8080 端口
environment:
- VUE_APP_API_URL=http://backend:8080/api # Vue.js 调用后端的 API 地址
depends_on:
- backend # 前端依赖后端服务
networks:
- mynetwork
# 后端服务(Spring Boot)
backend:
build:
context: . # 后端的 Dockerfile 位于根目录下
ports:
- "8081:8080" # 将后端服务暴露在宿主机的 8081 端口
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/student # 配置数据库连接
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=123456
depends_on:
- mysql # 后端依赖 MySQL 服务
networks:
- mynetwork
# MySQL 服务
mysql:
image: mysql:8.0
container_name: mysql8-test05
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: student # 这里将数据库名改为了mysql8,可按需修改
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
networks:
- mynetwork
# 定义数据卷,持久化 MySQL 数据
volumes:
mysql_data:
# 定义网络
networks:
mynetwork:
driver: bridge # 使用桥接网络
复制代码
2.设置前端 Dockerfile(Vue.js)
frontend/Dockerfile 内容
# 使用 Node.js 作为构建镜像
FROM node:16-alpine as build
# 设置工作目录
WORKDIR /app
# 复制 package.json 和 package-lock.json 文件
COPY package*.json ./
# 安装前端依赖
RUN npm install
# 复制剩余的项目文件
COPY . .
# 构建 Vue.js 项目
RUN npm run build
# 使用 Nginx 作为生产环境的静态文件服务器
FROM nginx:alpine
# 将构建的 Vue.js 应用拷贝到 Nginx 容器中
COPY --from=build /app/dist /usr/share/nginx/html
# 暴露端口 80
EXPOSE 80
复制代码
3.设置后端 Dockerfile(Spring Boot)
# 使用 OpenJDK 作为基础镜像
FROM openjdk:17-jdk-slim
# 将 Spring Boot 可执行 JAR 文件复制到容器内
COPY target/*.jar app.jar
# 设置容器启动时执行的命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
# 暴露端口 8080
EXPOSE 8080
复制代码
4.设置 Vue.js 前端的 frontend/package.json
{
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"vue": "^2.6.14",
"vue-router": "^3.5.1"
},
"devDependencies": {
"@vue/cli-service": "^4.5.13"
},
"env": {
"VUE_APP_API_URL": "http://localhost:8080/api"
}
}
复制代码
可以在 Vue.js 的代码中利用 process.env.VUE_APP_API_URL 来访问后端 API 所在。
5: 启动 Docker Compose
docker-compose up --build
复制代码
启动成功后,Vue.js 前端会通过 Nginx 在容器中运行,可以在浏览器中访http://localhost:8080 来查看前端应用
项目结构:
遇到一些错误可以手动拉镜像
docker pull nginx:alpine
docker pull node:16-alpine
复制代码
通过以下命令查抄后端是否正常启动:
3.
(选做)
参考学习平台上“JDBC操作_增删改”的视频,利用表格展示数据库中stuinfo表中的个人信息,每行一条个人信息,表格新增两列,分别提供“修改”和“删除”两个链接。点击“修改”链接时,跳转到新页面可供用户修改和保存;点击“删除”时,跳转到新页面完成删除操作并提示操作结果
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4