## 使用Spring Boot和Hibernate开发OA系统邮件管理模块
使用Spring Boot和Hibernate开发一个OA系统的邮件管理模块。该模块将支持邮件发送、接收、存储、查找、分类、标签管理,以及附件的上传和接收。前端部分使用Thymeleaf模板引擎,数据库选择MySQL。
### 项目结构
项目结构如下:
```
oa-system/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── oasystem/
│ │ │ ├── controller/
│ │ │ │ ├── MailController.java
│ │ │ ├── model/
│ │ │ │ ├── Mail.java
│ │ │ │ ├── Attachment.java
│ │ │ │ └── Label.java
│ │ │ ├── repository/
│ │ │ │ ├── MailRepository.java
│ │ │ │ ├── AttachmentRepository.java
│ │ │ │ └── LabelRepository.java
│ │ │ ├── service/
│ │ │ │ ├── MailService.java
│ │ │ │ └── AttachmentService.java
│ │ │ └── OasystemApplication.java
│ │ ├── resources/
│ │ │ ├── templates/
│ │ │ │ ├── mail/
│ │ │ │ │ ├── compose.html
│ │ │ │ │ ├── inbox.html
│ │ │ │ │ └── view.html
│ │ │ ├── application.properties
│ └── test/
├── pom.xml
```
### 主要功能实现
#### 1. 创建模型类
定义三个模型类:Mail、Attachment 和 Label。
```java
// Mail.java
package com.example.oasystem.model;
import javax.persistence.*;
import java.util.Date;
import java.util.List;
@Entity
public class Mail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String sender;
private String receiver;
private String subject;
private String content;
private Date sentDate;
@OneToMany(mappedBy = "mail", cascade = CascadeType.ALL)
private List<Attachment> attachments;
@ManyToMany
@JoinTable(
name = "mail_label",
joinColumns = @JoinColumn(name = "mail_id"),
inverseJoinColumns = @JoinColumn(name = "label_id")
)
private List<Label> labels;
// getters and setters
}
// Attachment.java
package com.example.oasystem.model;
import javax.persistence.*;
@Entity
public class Attachment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String fileName;
private String fileType;
private byte[] data;
@ManyToOne
@JoinColumn(name = "mail_id")
private Mail mail;
// getters and setters
}
// Label.java
package com.example.oasystem.model;
import javax.persistence.*;
import java.util.List;
@Entity
public class Label {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToMany(mappedBy = "labels")
private List<Mail> mails;
// getters and setters
}
```
#### 2. 创建仓库接口
接下来,定义仓库接口来访问数据库:
```java
// MailRepository.java
package com.example.oasystem.repository;
import com.example.oasystem.model.Mail;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MailRepository extends JpaRepository<Mail, Long> {
List<Mail> findBySubjectContainingOrContentContaining(String subject, String content);
}
// AttachmentRepository.java
package com.example.oasystem.repository;
import com.example.oasystem.model.Attachment;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AttachmentRepository extends JpaRepository<Attachment, Long> {
}
// LabelRepository.java
package com.example.oasystem.repository;
import com.example.oasystem.model.Label;
import org.springframework.data.jpa.repository.JpaRepository;
public interface LabelRepository extends JpaRepository<Label, Long> {
}
```
#### 3. 创建服务类
为邮件和附件创建服务类:
```java
// MailService.java
package com.example.oasystem.service;
import com.example.oasystem.model.Attachment;
import com.example.oasystem.model.Mail;
import com.example.oasystem.repository.MailRepository;
import com.example.oasystem.repository.AttachmentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class MailService {
@Autowired
private MailRepository mailRepository;
@Autowired
private AttachmentRepository attachmentRepository;
public Mail saveMail(Mail mail, List<Attachment> attachments) {
Mail savedMail = mailRepository.save(mail);
for (Attachment attachment : attachments) {
attachment.setMail(savedMail);
attachmentRepository.save(attachment);
}
return savedMail;
}
public List<Mail> getAllMails() {
return mailRepository.findAll();
}
public Mail getMailById(Long id) {
return mailRepository.findById(id).orElse(null);
}
public void deleteMail(Long id) {
mailRepository.deleteById(id);
}
public List<Mail> searchMails(String keyword) {
return mailRepository.findBySubjectContainingOrContentContaining(keyword, keyword);
}
}
```
#### 4. 创建控制器类
控制器类处理前端请求:
```java
// MailController.java
package com.example.oasystem.controller;
import com.example.oasystem.model.Attachment;
import com.example.oasystem.model.Mail;
import com.example.oasystem.service.MailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping("/mail")
public class MailController {
@Autowired
private MailService mailService;
@GetMapping("/inbox")
public String inbox(Model model) {
List<Mail> mails = mailService.getAllMails();
model.addAttribute("mails", mails);
return "mail/inbox";
}
@GetMapping("/compose")
public String compose() {
return "mail/compose";
}
@PostMapping("/send")
public String sendMail(@ModelAttribute Mail mail,
@RequestParam("files") MultipartFile[] files) throws IOException {
List<Attachment> attachments = new ArrayList<>();
for (MultipartFile file : files) {
Attachment attachment = new Attachment();
attachment.setFileName(file.getOriginalFilename());
attachment.setFileType(file.getContentType());
attachment.setData(file.getBytes());
attachments.add(attachment);
}
mailService.saveMail(mail, attachments);
return "redirect:/mail/inbox";
}
@GetMapping("/view/{id}")
public String viewMail(@PathVariable Long id, Model model) {
Mail mail = mailService.getMailById(id);
model.addAttribute("mail", mail);
return "mail/view";
}
@GetMapping("/search")
public String search(@RequestParam("keyword") String keyword, Model model) {
List<Mail> mails = mailService.searchMails(keyword);
model.addAttribute("mails", mails);
return "mail/inbox";
}
}
```
#### 5. 配置应用程序属性
在 `src/main/resources/application.properties` 文件中添加以下内容:
```properties
spring.datasource.url=jdbc:mysql://localhost:3306/oasystem
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
```
#### 6. 创建HTML模板
创建或更新HTML模板来支持新功能。
`compose.html` 支持附件上传:
```html
<!DOCTYPE html>
<html>
<head>
<title>Compose Mail</title>
</head>
<body>
<h1>Compose Mail</h1>
<form action="/mail/send" method="post" enctype="multipart/form-data">
<label for="sender">Sender:</label>
<input type="text" id="sender" name="sender" required><br>
<label for="receiver">Receiver:</label>
<input type="text" id="receiver" name="receiver" required><br>
<label for="subject">Subject:</label>
<input type="text" id="subject" name="subject" required><br>
<label for="content">Content:</label>
<textarea id="content" name="content" required></textarea><br>
<label for="files">Attachments:</label>
<input type="file" id="files" name="files" multiple><br>
<button type="submit">Send</button>
</form>
</body>
</html>
`inbox.html` 增加搜索功能:
```html
<!DOCTYPE html>
<html>
<head>
<title>Inbox</title>
</head>
<body>
<h1>Inbox</h1>
<form action="/mail/search" method="get">
<input type="text" name="keyword" placeholder="Search mails...">
<button type="submit">Search</button>
</form>
<ul>
<li th:each="mail : ${mails}">
<a th:href="@{/mail/view/{id}(id=${mail.id})}" th:text="${mail.subject}">Mail Subject</a>
</li>
</ul>
<a href="/mail/compose">Compose Mail</a>
</body>
</html>
### 完成