本章将通过一个实战项目演示如何应用前面所学的Java知识,构建一个完整的个人记账本Web应用。
10.1 实战项目:个人记账本Web应用
10.1.1 项目概述
我们将构建一个简单的个人记账本Web应用,用户可以记录和查看他们的收入和支出。
10.1.2 技术栈
- Spring Boot:用于快速构建和部署Web应用。
- Spring Data JPA:用于数据持久化。
- H2 Database:嵌入式数据库,用于快速开发和测试。
- Thymeleaf:用于服务器端模板引擎,生成动态HTML页面。
10.2 项目架构设计与实现
10.2.1 创建项目结构
使用Spring Initializr创建一个新的Spring Boot项目,包含以下依赖:
- Spring Web
- Spring Data JPA
- H2 Database
- Thymeleaf
10.2.2 定义实体类
示例:定义交易记录实体类
import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import java.time.LocalDate;@Entitypublic class Transaction {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String type; // "income" or "expense"private double amount;private String description;private LocalDate date;// Getters and setters// ... 省略getter和setter代码}
10.2.3 创建JPA仓库接口
示例:创建交易记录仓库
import org.springframework.data.jpa.repository.JpaRepository;public interface TransactionRepository extends JpaRepository<Transaction, Long> {// JPA会自动生成CRUD操作的方法}
10.2.4 创建服务类
示例:创建交易记录服务
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;import java.util.Optional;@Servicepublic class TransactionService {private final TransactionRepository transactionRepository;@Autowiredpublic TransactionService(TransactionRepository transactionRepository) {this.transactionRepository = transactionRepository;}public List<Transaction> getAllTransactions() {return transactionRepository.findAll();}public Optional<Transaction> getTransactionById(Long id) {return transactionRepository.findById(id);}public Transaction saveTransaction(Transaction transaction) {return transactionRepository.save(transaction);}public void deleteTransaction(Long id) {transactionRepository.deleteById(id);}}
10.2.5 创建控制器类
示例:创建交易记录控制器
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.*;import java.util.List;@Controller@RequestMapping("/transactions")public class TransactionController {private final TransactionService transactionService;@Autowiredpublic TransactionController(TransactionService transactionService) {this.transactionService = transactionService;}@GetMappingpublic String getAllTransactions(Model model) {List<Transaction> transactions = transactionService.getAllTransactions();model.addAttribute("transactions", transactions);return "transactions"; // 返回的视图名称}@GetMapping("/new")public String showNewTransactionForm(Model model) {model.addAttribute("transaction", new Transaction());return "new_transaction";}@PostMappingpublic String saveTransaction(@ModelAttribute("transaction") Transaction transaction) {transactionService.saveTransaction(transaction);return "redirect:/transactions";}@GetMapping("/delete/{id}")public String deleteTransaction(@PathVariable Long id) {transactionService.deleteTransaction(id);return "redirect:/transactions";}}
10.2.6 创建视图模板
示例:创建显示交易记录的视图模板
transactions.html
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head><title>Transaction List</title></head><body><h1>All Transactions</h1><table><tr><th>ID</th><th>Type</th><th>Amount</th><th>Description</th><th>Date</th><th>Actions</th></tr><tr th:each="transaction : ${transactions}"><td th:text="${transaction.id}">1</td><td th:text="${transaction.type}">income</td><td th:text="${transaction.amount}">100.0</td><td th:text="${transaction.description}">Salary</td><td th:text="${transaction.date}">2024-05-24</td><td><a th:href="@{/transactions/delete/{id}(id=${transaction.id})}">Delete</a></td></tr></table><a href="/transactions/new">Add New Transaction</a></body></html>
示例:创建新增交易记录的视图模板
new_transaction.html
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head><title>New Transaction</title></head><body><h1>New Transaction</h1><form th:action="@{/transactions}" th:object="${transaction}" method="post"><label>Type:</label><select th:field="*{type}"><option value="income">Income</option><option value="expense">Expense</option></select><br><label>Amount:</label><input type="text" th:field="*{amount}" /><br><label>Description:</label><input type="text" th:field="*{description}" /><br><label>Date:</label><input type="date" th:field="*{date}" /><br><button type="submit">Save</button></form></body></html>
10.3 测试与部署
10.3.1 单元测试
使用JUnit和Spring Test来编写和运行单元测试,以确保代码的正确性。
示例:测试交易记录服务
import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;@SpringBootTestclass TransactionServiceTest {@Autowiredprivate TransactionService transactionService;@Testvoid testSaveTransaction() {Transaction transaction = new Transaction();transaction.setType("income");transaction.setAmount(100.0);transaction.setDescription("Test Income");transaction.setDate(LocalDate.now());Transaction savedTransaction = transactionService.saveTransaction(transaction);assertNotNull(savedTransaction);assertEquals("income", savedTransaction.getType());}}
10.3.2 集成测试
集成测试用于测试完整系统的功能,确保各个部分协同工作。
10.3.3 部署应用
将应用打包为JAR文件或WAR文件,并部署到服务器(如Tomcat)或云平台(如AWS、Heroku)。
示例:打包和运行Spring Boot应用
# 打包应用mvn clean package# 运行JAR文件java -jar target/myapp-0.0.1-SNAPSHOT.jar
