1. 项目背景与核心需求
Spring框架作为Java生态中最流行的轻量级容器,在企业级应用开发中占据着不可替代的地位。最近在给团队新人做技术培训时,我发现很多初学者虽然能照着文档完成基础配置,但对Spring的核心机制理解不够深入。于是设计了这个结合计算器和用户登录的综合性小项目,通过两个看似简单的功能模块,帮助开发者掌握Spring的核心技术栈。
这个项目看似基础,实则涵盖了Spring MVC的请求处理流程、依赖注入的实际应用、表单验证机制等关键知识点。计算器模块重点演示控制器(Controller)如何接收并处理参数,而用户登录模块则涉及更复杂的会话(Session)管理和安全控制。选择这两个功能组合教学,是因为它们分别代表了Spring中最典型的无状态和有状态两种处理模式。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与项目搭建
2.1 基础环境配置
推荐使用以下环境组合:
- JDK 17(LTS版本,长期支持)
- Spring Boot 3.1.5(当前稳定版)
- Maven 3.8.6(依赖管理工具)
- IntelliJ IDEA 2023.2(社区版即可)
在pom.xml中需要配置的核心依赖包括:
xml复制<dependencies>
<!-- Spring Web MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Thymeleaf模板引擎 -->
<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>
<optional>true</optional>
</dependency>
</dependencies>
2.2 项目结构规划
采用标准的Maven项目结构:
code复制src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── demo/
│ │ ├── controller/ # 控制器层
│ │ ├── model/ # 数据模型
│ │ ├── service/ # 业务逻辑层
│ │ └── DemoApplication.java # 启动类
│ └── resources/
│ ├── static/ # 静态资源
│ ├── templates/ # 模板文件
│ └── application.properties # 配置文件
注意:Spring Boot默认静态资源路径为/static,模板文件应放在/templates下,这是约定优于配置的典型体现。
3. 加法计算器实现详解
3.1 控制器设计与参数绑定
创建CalculatorController处理计算逻辑:
java复制@Controller
@RequestMapping("/calculator")
public class CalculatorController {
@GetMapping
public String showCalculatorForm(Model model) {
model.addAttribute("calculation", new Calculation());
return "calculator";
}
@PostMapping("/add")
public String addNumbers(@ModelAttribute Calculation calculation,
Model model) {
double result = calculation.getNum1() + calculation.getNum2();
model.addAttribute("result", result);
return "calculator";
}
}
对应的数据模型类Calculation:
java复制public class Calculation {
private double num1;
private double num2;
// getters and setters
}
这里有几个关键设计点:
- 使用@ModelAttribute自动绑定表单参数到POJO
- 采用GET/POST分离的RESTful风格设计
- 计算结果通过Model对象传递到视图
3.2 视图层实现
使用Thymeleaf模板引擎创建calculator.html:
html复制<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Spring Calculator</title>
</head>
<body>
<h2>加法计算器</h2>
<form th:action="@{/calculator/add}" th:object="${calculation}" method="post">
数字1: <input type="number" th:field="*{num1}" step="any"/><br/>
数字2: <input type="number" th:field="*{num2}" step="any"/><br/>
<button type="submit">计算</button>
</form>
<div th:if="${result != null}">
计算结果: <span th:text="${result}"></span>
</div>
</body>
</html>
实际开发中发现:Thymeleaf的th:field会自动绑定到后端对象的属性,这种双向绑定机制比传统JSP更安全高效。但要注意字段名必须与POJO属性严格一致。
4. 用户登录系统实现
4.1 安全基础配置
在application.properties中添加基础安全配置:
properties复制# 会话超时时间(秒)
server.servlet.session.timeout=1800
# 启用HTTPOnly和Secure Cookie
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true
4.2 用户认证流程实现
创建AuthController处理登录逻辑:
java复制@Controller
@RequestMapping("/auth")
public class AuthController {
@GetMapping("/login")
public String showLoginForm(Model model) {
model.addAttribute("user", new User());
return "login";
}
@PostMapping("/login")
public String processLogin(@ModelAttribute User user,
HttpSession session,
Model model) {
if(authenticate(user)) {
session.setAttribute("currentUser", user.getUsername());
return "redirect:/dashboard";
}
model.addAttribute("error", "用户名或密码错误");
return "login";
}
private boolean authenticate(User user) {
// 实际项目中应加密存储和验证密码
return "admin".equals(user.getUsername())
&& "123456".equals(user.getPassword());
}
}
用户模型类User:
java复制public class User {
private String username;
private String password;
// getters and setters
}
4.3 会话管理与视图保护
创建拦截器检查登录状态:
java复制public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
HttpSession session = request.getSession(false);
if(session == null || session.getAttribute("currentUser") == null) {
response.sendRedirect("/auth/login");
return false;
}
return true;
}
}
注册拦截器配置:
java复制@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/dashboard/**")
.excludePathPatterns("/auth/**", "/static/**");
}
}
5. 项目优化与常见问题
5.1 计算器模块的增强
实际项目中应考虑:
- 输入验证:防止非数字输入
java复制@PostMapping("/add")
public String addNumbers(@Valid @ModelAttribute Calculation calculation,
BindingResult result,
Model model) {
if(result.hasErrors()) {
model.addAttribute("error", "请输入有效数字");
return "calculator";
}
// ...原有逻辑
}
- 支持更多运算类型:
java复制public enum Operation {
ADD, SUBTRACT, MULTIPLY, DIVIDE
}
public class Calculation {
private Operation operation;
// ...其他字段
}
5.2 登录系统的安全加固
生产环境必须:
- 密码加密存储:
java复制private String encryptPassword(String raw) {
return DigestUtils.md5DigestAsHex(raw.getBytes());
}
- 防止暴力破解:
java复制@PostMapping("/login")
public String processLogin(..., HttpServletRequest request) {
String ip = request.getRemoteAddr();
if(loginAttemptService.isBlocked(ip)) {
model.addAttribute("error", "尝试次数过多,请稍后再试");
return "login";
}
// ...原有逻辑
}
5.3 高频问题排查
- 表单提交后参数绑定失败:
- 检查POJO是否有正确的setter方法
- 确认th:object和th:field的对应关系
- 使用@RequestParam逐个参数调试
- 会话丢失问题:
- 检查cookie配置是否正确
- 确保没有多个Filter修改session
- 分布式环境需要配置session共享
- 静态资源404:
- 确认资源放在/static或/public目录
- 检查SecurityConfig是否放行了静态资源路径
6. 项目扩展思路
这个基础项目可以进一步扩展为:
- RESTful API版本:使用@RestController和ResponseEntity
- 集成Spring Security:替代自定义认证逻辑
- 添加数据库持久化:使用Spring Data JPA
- 前端框架整合:Vue/React与Spring Boot结合
- 微服务化改造:拆分为独立服务
我在实际教学中发现,通过这个项目学员可以掌握:
- Spring MVC的请求处理流程
- 表单数据绑定原理
- 会话管理机制
- 分层架构设计思想
- 基础安全防护意识
建议开发时开启Spring Boot的Actuator端点,实时监控应用状态:
properties复制management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=always
