【SpringBoot从初学者到专家的成长23】利用SpringBoot构建高效的Web应用-拥抱你的第一个SpringBoot项目

news/2025/11/22 20:14:19/文章来源:https://www.cnblogs.com/yangykaifa/p/19258493

随着软件开发的不断发展,知识体系变得越来越庞大和复杂。它不仅包括编程技能,还涉及到数据库、网络、架构、设计模式等多个知识领域。对于初学者而言,面对浩如烟海的资料和庞大的知识体系,很容易感到迷茫,不知道该学什么、怎么学,也不清楚该从何入手。其实,有一句话说得好:“书山有路勤为径,学海无涯苦作舟。”越是看似复杂的事物,学习的方法往往越简单。关键在于:首先要做好规划,理清学习的内容;然后安排合理的学习顺序,做到循序渐进;最重要的是,不断地写代码,将所学知识融入到自己的知识体系中。只有通过持续产出学习成果——比如可运行的代码、自己的开源项目、技术文章等,才能真正实现知识的内化与提升。

一、创建SpringBoot Web应用项目

首先,确保你已经安装了JDK 8及以上版本,并且安装了开发工具(例如IDEA或Spring Tool Suite)。

  1. 通过Spring Initializr创建项目

    访问 Spring Initializr 创建项目。

  2. 导入项目

    将生成的项目导入到IDE中。

  3. 创建数据库
    选择一个自己熟悉的数据库,建立数据表,并构造初始化数据;

  4. 编写测试代码
    通过单元测试和接口测试,保证项目运行后能够正常执行

  5. 部署运行
    将开发完成的项目打包构建成可部署运行的应用服务。

二、创建Web应用代码

创建项目前,基于SpringBoot先规划项目的基本结构

1. Application.java - 启动类

package com.example.registration;
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);
}
}

2. UserController.java - 控制器

创建一个用户注册和查询的REST控制器,提供相关API接口。

package com.example.registration.controller;
import com.example.registration.model.User;
import com.example.registration.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/register")
public User registerUser(@RequestBody User user) {
return userService.registerUser(user);
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
}

3. User.java - 用户实体类

定义一个用户实体类,用于存储用户的基本信息。

package com.example.registration.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.IDENTITY)
private Long id;
private String username;
private String password;
private String email;
// Constructors
public User() {}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

4. UserService.java - 服务层

创建服务层来处理用户注册逻辑和用户查询。

package com.example.registration.service;
import com.example.registration.model.User;
import com.example.registration.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 注册新用户
public User registerUser(User user) {
return userRepository.save(user);
}
// 根据ID查询用户
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
}

5. UserRepository.java - 用户仓库

使用Spring Data JPA来操作数据库中的用户表。

package com.example.registration.repository;
import com.example.registration.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {// 可以添加自定义查询方法}

基于上述代码,下面是相应的数据库建表语句以及一些初始化数据。

三、数据库建表语句

假设我们使用的是MySQL数据库,下面是创建users表的SQL语句:

1. users表建表语句

CREATE TABLE users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,         -- 用户ID,主键,自增
username VARCHAR(255) NOT NULL,               -- 用户名,不为空
password VARCHAR(255) NOT NULL,               -- 密码,不为空
email VARCHAR(255) NOT NULL,                  -- 邮箱,不为空
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,  -- 创建时间,默认当前时间
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP  -- 更新时间,自动更新时间
);

2. users表字段解释

  • id:自增的用户ID。
  • username:用户的用户名,唯一且不为空。
  • password:加密后的密码,存储的是加密结果。
  • email:用户的邮箱,唯一且不为空。
  • created_at:记录创建时间,默认为当前时间。
  • updated_at:记录更新时间,默认和created_at相同,但会在每次更新时自动更新。

四、初始化数据

为了测试应用,我们可以插入一些初始用户数据。

1. 插入示例用户数据

INSERT INTO users (username, password, email)
VALUES
('johndoe', '$2a$10$K1r6vHk5Ez24T.9swI1J7eLIfJhbHMZtk9g2w3BzFejCsl1/J9UyC', 'johndoe@example.com'),
('janedoe', '$2a$10$06FrX.QBkERl7BhaV45X0ZxZZg.wMi9E8AzMZVzO9b1c3OUfzywAm', 'janedoe@example.com'),
('samsmith', '$2a$10$8dFddKjJ8rd6bmJZfdG5htmzoE0cn7Jz.M0VZZ7TpJdmZPlDpBL1i', 'samsmith@example.com');

2. 生成的密码(BCrypt加密)

上面的密码字段使用了BCrypt加密算法来存储加密后的密码。为了生成加密的密码,可以使用Spring Security中的BCryptPasswordEncoder工具:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class PasswordEncoderExample {
public static void main(String[] args) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String encodedPassword = encoder.encode("password123");  // 输入原始密码
System.out.println("Encoded Password: " + encodedPassword);
}
}

运行后,你会得到一个加密的密码,可以将这个加密密码替换上面的$2a$10$...部分。

3.数据库初始化脚本

如果你使用的是SpringBoot 的自动化配置,可以使用data.sql文件来初始化数据。你可以将以下内容放入src/main/resources/data.sql中:

-- 创建用户表
CREATE TABLE IF NOT EXISTS users (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 插入初始用户数据
INSERT INTO users (username, password, email)
VALUES
('johndoe', '$2a$10$K1r6vHk5Ez24T.9swI1J7eLIfJhbHMZtk9g2w3BzFejCsl1/J9UyC', 'johndoe@example.com'),
('janedoe', '$2a$10$06FrX.QBkERl7BhaV45X0ZxZZg.wMi9E8AzMZVzO9b1c3OUfzywAm', 'janedoe@example.com'),
('samsmith', '$2a$10$8dFddKjJ8rd6bmJZfdG5htmzoE0cn7Jz.M0VZZ7TpJdmZPlDpBL1i', 'samsmith@example.com');

三、配置application.properties

这里为了简单选择properties文件,当然也可以选择yml文件,具体配置方法和详细内容可参考:【SpringBoot从初学者到专家的成长11】SpringBoot 中的application.properties与application.yml详解

为你的应用配置数据库连接、端口、日志等信息。

# 设置SpringBoot 内嵌服务器端口
server.port=8080
# 配置数据库(使用H2内存数据库)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
# 启用SpringBoot  DevTools
spring.devtools.restart.enabled=true

四、单元测试

使用SpringBoot 的单元测试功能来测试注册和查询功能是否正确。单元测试是开发质量的重要保证
涉及单元测试更多的内容可参考:【SpringBoot从初学者到专家的成长12】聊聊SpringBoot 中的测试:如何编写高效的单元与集成测试

1. UserControllerTest.java - 控制器单元测试

package com.example.registration;
import com.example.registration.controller.UserController;
import com.example.registration.model.User;
import com.example.registration.service.UserService;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import static org.hamcrest.Matchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
@SpringBootTest
public class UserControllerTest {
@Autowired
private UserController userController;
private MockMvc mockMvc;
@MockBean
private UserService mockUserService;
@Test
public void testRegisterUser() throws Exception {
User mockUser = new User("johndoe", "password123", "johndoe@example.com");
// 模拟注册返回
Mockito.when(mockUserService.registerUser(Mockito.any(User.class))).thenReturn(mockUser);
mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
mockMvc.perform(post("/users/register")
.contentType("application/json")
.content("{\"username\":\"johndoe\", \"password\":\"password123\", \"email\":\"johndoe@example.com\"}"))
.andExpect(jsonPath("$.username", is("johndoe")))
.andExpect(jsonPath("$.email", is("johndoe@example.com")));
}
}

测试解释:

  • @SpringBootTest:启动SpringBoot 应用上下文。
  • @MockBean:模拟UserService,避免依赖数据库。
  • MockMvc:模拟POST请求并验证响应内容。

2. UserServiceTest.java - 服务层单元测试

package com.example.registration;
import com.example.registration.model.User;
import com.example.registration.repository.UserRepository;
import com.example.registration.service.UserService;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBootTest
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
public void testRegisterUser() {
User mockUser = new User("johndoe", "password123", "johndoe@example.com");
// 模拟保存用户
Mockito.when(userRepository.save(Mockito.any(User.class))).thenReturn(mockUser);
User result = userService.registerUser(mockUser);
assertEquals("johndoe", result.getUsername());
assertEquals("johndoe@example.com", result.getEmail());
}
}

五、客户端调用服务示例代码

假设我们有一个客户端服务需要调用上面提供的注册API。

1. UserClient.java - 客户端服务

package com.example.registration.client;
import com.example.registration.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class UserClient {
@Autowired
private RestTemplate restTemplate;
public User registerUser(User user) {
return restTemplate.postForObject("http://localhost:8080/users/register", user, User.class);
}
}

2. UserClientTest.java - 客户端服务单元测试

package com.example.registration;
import com.example.registration.client.UserClient;
import com.example.registration.model.User;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.client.RestTemplate;
import static org.mockito.Mockito.when;
@SpringBootTest
public class UserClientTest {
@Autowired
private UserClient userClient;
@Mock
private RestTemplate restTemplate;
@Test
public void testRegisterUser() {
User mockUser = new User("johndoe", "password123", "johndoe@example.com");
// 模拟RestTemplate的返回
when(restTemplate.postForObject(Mockito.anyString(), Mockito.any(), Mockito.eq(User.class)))
.thenReturn(mockUser);
User result = userClient.registerUser(mockUser);
assert(result.getUsername()).equals("johndoe");
assert(result.getEmail()).equals("johndoe@example.com");
}
}

六、整合前端

如果需要为该注册功能创建一个简单的前端界面,您可以使用HTML和JavaScript进行实现。下面是一个使用HTML和JavaScript的简单前端注册页面示例。

1. index.html - 用户注册页面

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>User Registration</title><script>async function registerUser() {const username = document.getElementById('username').value;const password = document.getElementById('password').value;const email = document.getElementById('email').value;const response = await fetch('http://localhost:8080/users/register', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({username: username,password: password,email: email})});const data = await response.json();if (response.ok) {alert('Registration successful! Welcome ' + data.username);} else {alert('Error: ' + data.message);}}</script></head><body><h1>User Registration</h1><form id="registrationForm" onsubmit="event.preventDefault(); registerUser();"><label for="username">Username:</label><br><input type="text" id="username" name="username" required><br><br><label for="password">Password:</label><br><input type="password" id="password" name="password" required><br><br><label for="email">Email:</label><br><input type="email" id="email" name="email" required><br><br><button type="submit">Register</button></form></body></html>

2. 启动应用

确保后端SpringBoot 应用正在运行,并且前端页面可以通过浏览器访问。如果后端服务运行在本地,确保前端页面正确配置了API请求地址。

通过浏览器访问index.html,并填写用户信息进行注册。用户信息会通过POST请求发送到后端,后端会处理并返回注册成功的响应。

七、部署和监控

1. 部署到生产环境

可以将该应用部署到云服务(如AWS、Heroku、Azure等)或本地服务器。确保数据库连接、服务器配置和安全设置(如SSL/TLS)都适配生产环境的需求。具体的部署方法超过了该文章的范围,大家可自行查询相关资料。

2. 监控和日志记录

为了确保应用在生产环境中的正常运行,可以集成一些日志记录和监控工具,如:

3. 配置日志记录

application.properties中启用日志记录。

logging.level.org.springframework.web=INFO
logging.level.com.example.registration=DEBUG

4. 安全性

考虑使用Spring Security来保护应用,确保用户的敏感数据(如密码)安全地存储和传输。

例如,可以加密用户的密码:

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
public class UserService {
private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
public User registerUser(User user) {
// 对密码进行加密
String encodedPassword = passwordEncoder.encode(user.getPassword());
user.setPassword(encodedPassword);
return userRepository.save(user);
}
}

八、卸载最后

学海无涯苦作舟,开发之路也是如此,没有什么捷径,都是多学多写多练。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/973384.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PyCharm,Run Configurations,Python interpreter下拉框会显示哪些地方的python.exe

PyCharm,Run Configurations,Python interpreter 下拉框会显示哪些地方的 python.exe 在 PyCharm 中,当你配置 Run Configurations 时,Python Interpreter 下拉框会列出所有可用的 Python 解释器,这些解释器通常来…

Deepseek大模型结合Chrome搜索爬取2025AI投资趋势数据 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

聚焦GeoAI!6本遥感地学好刊全解析,助你精准投稿

详细盘点了2025最新影响因子、JCR分区、发文趋势,并深度剖析Antonio Plaza、张良培等高引作者及GeoAI等前沿研究方向,助您高效选刊,精准把握科研风向。AMiner 收录了10万余种高质量期刊会议,共覆盖100+全一级学科,…

call 与 delegatecall - all-in

一、为什么要用底层调用 我们知道,在一个合约中调用另一个合约的接口,通常使用contractName(address).functionName() 来进行调用,比如: contract MyContract {function add(address _counter) public {// 调用 Co…

20232417 2025-2026-1 《网络与系统攻防技术》实验六实验报告

1.实验内容 1.1实验要求 本实践目标是掌握metasploit的用法,通过实战演练理解常见漏洞的利用原理和渗透测试流程。 1.2学习内容 2.实验过程 2.1前期渗透 2.1.1主机发现 在靶机中输入ipconfig得到靶机的IP地址。其IP地址…

Trick——字符串

Part1 问题:两个等长字符串的不同后缀与另两个字符串的不同后缀分别匹配。 问题有些抽象,举个例子: aaaaaaabbbc aaaaaaddcdbsdscabbbc sdscddcdb这样的两组字符串就存在匹配。 可以用字符串\(hash\)解决。 设字符串…

2022年春季研究资助计划征集技术提案

某中心研究奖项计划发布2022年春季提案征集,涵盖AI信息安全、公平AI、广告技术、社区机器学习等五大技术领域,提供资金和云计算资源支持学术研究。某中心研究奖项发布2022年春季提案征集 某中心研究奖项(ARA)宣布启…

BLOG-1-电梯调度算法

一、前言 对三次题目总结: 三次题目难度逐渐递增。题目数量适当,规定时间内足已完成。每一次题目集前面小题像是练手最后一题难度飙升是真正考验学习成果的时候。第一次题目集让人眼前一亮以前从没做过类似的题目,光…

线圈公司质量排名,线圈生产厂家性价比推荐,变压器公司行业排名,变压器生产厂家客户推荐。滤波器公司技术排名,开关变压器公司性价比榜单

线圈公司质量排名,线圈生产厂家性价比推荐,变压器公司行业排名,变压器生产厂家客户推荐。滤波器公司技术排名,开关变压器公司性价比榜单线圈公司质量排名,线圈生产厂家性价比推荐,变压器公司行业排名,变压器生产…

IDA之修复结构体

修复结构体有两种方法 一是C语言式修复(麻烦) 二是直接设置(更简单,更推荐) 首先学会设置IDB快照(其实本人很少使用) IDB快照:.idb文件,可快速帮我们恢复某个时间点的快照,可以防止错误太多View - Database sn…

2025年专业集成房屋安装公司排名,集成活动房十大靠谱厂家推荐榜,石家庄集成房屋公司十大排行:义广达彩钢口碑推荐榜,河北集成活动房厂家十大推荐榜

2025年专业集成房屋安装公司排名,集成活动房十大靠谱厂家推荐榜,石家庄集成房屋公司十大排行:义广达彩钢口碑推荐榜,河北集成活动房厂家十大推荐榜2025年专业集成房屋安装公司排名,集成活动房十大靠谱厂家推荐榜,…

真的好怪题解:P14314 [Aboi Round 2] Oneshot

来一篇真的好怪的题解。 正文 首先有一个很低级的做法,就是每次询问直接拉出来 \(\frac np\) 个数,然后排好序,用另外 \(\frac nq\) 个数在那上面二分就结束了。 这样做的复杂度是 \(\mathcal{O}(nm\log n)\)。 然后…

ElasticSearch索引库操作 - 努力-

ElasticSearch索引库操作一、ElasticSearch基础概念 1.1 文档和字段:ElasticSearch是面向文档(Document)存储的,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为json格式后存储在ElasticSearch…

2025年集成房屋设计公司十大排名,岗亭加工厂家十大排行榜,专业岗亭定制工厂怎么选?彩钢移动厕所厂家推荐。

2025年集成房屋设计公司十大排名,岗亭加工厂家十大排行榜,专业岗亭定制工厂怎么选?彩钢移动厕所厂家推荐。2025年集成房屋设计公司十大排名,岗亭加工厂家十大排行榜,专业岗亭定制工厂怎么选?彩钢移动厕所厂家推荐…

洛谷 P5658 [CSP-S 2019] 括号树 题解

题目大意 给定一棵树,每个节点有一个括号。对于每个节点 \(i\),定义 \(s_i\) 为从根节点到 \(i\) 的路径上所有括号按顺序组成的字符串。求每个 \(s_i\) 中互不相同的合法括号子串的个数 \(k_i\)。 思路 首先,\(k_i…

礼盒拖车公司推荐,礼盒拖车定制公司排行榜,礼盒拖车厂家口碑推荐,礼盒拖车生产厂家-航利通达

礼盒拖车公司推荐,礼盒拖车定制公司排行榜,礼盒拖车厂家口碑推荐,礼盒拖车生产厂家-航利通达礼盒拖车公司推荐,礼盒拖车定制公司排行榜,礼盒拖车厂家口碑推荐,礼盒拖车生产厂家-航利通达在当下这个视觉至上的时代…

360笔试

看到 PC 客户端对 ACMer 有加分项,就投了下这个。 \(2\) 个小时,前面有 \(40\) 道选择题,涉及内容包含数学、数据结构、操作系统、网络安全,还有一些关于 C++ 的类什么的和一些简单算法的原理什么的,不过前面那些…

图像的颜色模式

图像的颜色模式0.1 灰度模式 也就是灰度图(黑白照片),每个像素只有明暗变化,用0~255共256个亮度级来表示,用8个bit来表示,所以每个像素信息用8bit储存. 0.2 位图模式(二值图像) 即只有纯黑和纯白两种亮度,没有渐变…

.NET+AI | MEAI | Function Caling 实操(4)

.NET+AI | MEAI | Function Caling 实操 TL;DR✅ 注册你的方法为工具(Tool) ✅ 启用中间件 UseFunctionInvocation() ✅ 设置 ChatOptions.ToolMode = Auto ✅ 发起对话,MEAI 自动完成:请求 → 调用 → 回填 → 作…

高频变压器公司口碑榜单,电感公司技术排名,电感厂家交付效率排名,磁性元器件公司客户推荐,电感器公司产能排名,线圈公司行业排名-汉翔电子

高频变压器公司口碑榜单,电感公司技术排名,电感厂家交付效率排名,磁性元器件公司客户推荐,电感器公司产能排名,线圈公司行业排名-汉翔电子高频变压器公司口碑榜单,电感公司技术排名,电感厂家交付效率排名,磁性…