> 文章列表 > 基于Spring boot和Vue3的博客平台:系统通知、评论回复通知、专栏更新通知、用户角色与权限管理模块

基于Spring boot和Vue3的博客平台:系统通知、评论回复通知、专栏更新通知、用户角色与权限管理模块

基于Spring boot和Vue3的博客平台:系统通知、评论回复通知、专栏更新通知、用户角色与权限管理模块

目录

一、系统通知、评论回复通知、专栏更新通知

1.前端通知展示

2.后端通知实现

3.发送评论回复通知

4.发送专栏更新通知

二、实时通知与邮件通知

1.实时通知

三、用户角色与权限管理

1.角色与权限数据模型

2.分配角色与权限

3.基于角色的访问控制


在这篇博客中,我们将介绍如何为我们的博客平台实现通知功能。这将包括系统通知、评论回复通知以及专栏更新通知。

一、系统通知、评论回复通知、专栏更新通知

1.前端通知展示

在前端项目中,创建一个新的 Notification.vue 组件。在这个组件中,我们将展示用户收到的所有通知。

<template><div class="notifications"><h3>Notifications</h3><ul><li v-for="notification in notifications" :key="notification.id">{{ notification.content }}</li></ul></div>
</template><script>
export default {data() {return {notifications: [],};},async mounted() {await this.fetchNotifications();},methods: {async fetchNotifications() {// ... 获取通知的逻辑 ...},},
};
</script>

2.后端通知实现

在后端项目中,创建一个新的 Notification 实体类,用于存储通知。

@Entity
public class Notification {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@ManyToOneprivate User recipient;private String content;// ... getter 和 setter ...
}

接下来,在 NotificationRepository 中,添加一个方法,根据接收者查找通知。


public interface NotificationRepository extends JpaRepository<Notification, Long> {List<Notification> findByRecipientId(Long recipientId);
}

接下来,在 NotificationController 中添加获取用户通知的接口。


@RestController
@RequestMapping("/api/notifications")
public class NotificationController {@Autowiredprivate NotificationRepository notificationRepository;@GetMappingpublic ResponseEntity<?> getUserNotifications(Principal principal) {// ... 获取用户通知的逻辑 ...}
}

3.发送评论回复通知

在评论回复功能中,当用户回复了某篇文章或其他评论时,我们可以为被回复的用户发送一条通知。在 CommentControllersubmitArticleComment 方法中,添加发送通知的逻辑。

@PostMapping
public ResponseEntity<?> submitArticleComment(@PathVariable Long articleId, @RequestBody CommentDto commentDto, Principal principal) {// ... 提交评论的逻辑 ...// 发送通知Notification notification = new Notification();notification.setRecipient(/* 被回复的用户 */);notification.setContent(/* 通知内容 */);notificationRepository.save(notification);return ResponseEntity.ok(comment);
}

4.发送专栏更新通知

当专栏作者发布新文章时,我们可以为订阅了该专栏的用户发送一条通知。首先,我们需要在 SubscriptionRepository 中添加一个方法,根据专栏 ID 查找订阅者。

public interface SubscriptionRepository extends JpaRepository<Subscription, Long> {List<Subscription> findByColumnId(Long columnId);
}

接下来,在 ArticleController 的 createArticle 方法中,添加发送通知的逻辑。


@PostMapping
public ResponseEntity<?> createArticle(@RequestBody ArticleDto articleDto, Principal principal) {// ... 创建文章的逻辑 ...// 获取专栏订阅者List<Subscription> subscriptions = subscriptionRepository.findByColumnId(article.getColumn().getId());// 遍历订阅者,发送通知for (Subscription subscription : subscriptions) {Notification notification = new Notification();notification.setRecipient(subscription.getUser());notification.setContent("专栏 [" + article.getColumn().getName() + "] 有新文章发布: " + article.getTitle());notificationRepository.save(notification);}return ResponseEntity.ok(article);
}

现在,每当专栏作者发布新文章时,系统将自动向订阅了该专栏的用户发送更新通知。这样,用户可以随时关注他们感兴趣的专栏,并获取最新文章的信息。

通过以上实现,我们已经为博客平台添加了系统通知、评论回复通知以及专栏更新通知功能。用户可以在通知页面查看他们收到的所有通知,这将极大地提高用户的参与度和互动体验。你可以根据需要进一步完善和扩展通知功能,例如提供邮件通知、实时通知等。

二、实时通知与邮件通知

在本节中,我们将为博客平台添加实时通知功能,以便用户在浏览网站时立即收到新通知。我们还将实现邮件通知功能,以便用户在收到关键通知时通过电子邮件获得提醒。

1.实时通知

为了实现实时通知,我们将使用 WebSocket 技术。首先,在后端项目中引入 Spring Boot WebSocket 依赖项。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

接下来,在 WebSocketConfig 类中配置 WebSocket。


@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(notificationHandler(), "/api/ws/notifications").setAllowedOrigins("*");}@Beanpublic WebSocketHandler notificationHandler() {return new NotificationHandler();}
}

然后,创建一个 NotificationHandler 类,用于处理 WebSocket 通信。


public class NotificationHandler extends TextWebSocketHandler {// 存储 WebSocket 会话private final Map<Long, WebSocketSession> sessions = new ConcurrentHashMap<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {// ... 建立连接后的逻辑 ...}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {// ... 处理接收到的消息 ...}// 发送实时通知public void sendNotification(Notification notification) {// ... 发送通知的逻辑 ...}
}

在前端项目中,使用 WebSocket API 连接到后端 WebSocket 服务器,并监听新通知。


// Notification.vue
export default {data() {return {// ...socket: null,};},mounted() {this.connectWebSocket();},methods: {// ...connectWebSocket() {this.socket = new WebSocket("ws://localhost:8080/api/ws/notifications");this.socket.addEventListener("message", this.handleNotification);},handleNotification(event) {const notification = JSON.parse(event.data);this.notifications.push(notification);},},
};

现在,每当用户收到新通知时,他们将立即在前端收到实时提醒。

2.邮件通知

为了实现邮件通知功能,我们将使用 JavaMailSender 发送电子邮件。首先,在后端项目中引入 Spring Boot Mail 依赖项。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>

接下来,在 application.properties 文件中配置邮件发送相关属性。

spring.mail.host=smtp.example.com
spring.mail.port=587
spring.mail.username=your_email@example.com
spring.mail.password=your_email_password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

创建一个 EmailService 类,用于发送邮件通知。


@Service
public class EmailService {@Autowiredprivate JavaMailSender javaMailSender;/* 发送邮件通知* @param to 收件人* @param subject 邮件主题* @param content 邮件内容*/public void sendNotificationEmail(String to, String subject, String content) {SimpleMailMessage message = new SimpleMailMessage();message.setTo(to);message.setSubject(subject);message.setText(content);try {javaMailSender.send(message);} catch (MailException e) {// 如果发送邮件失败,记录错误信息System.err.println("发送邮件失败: " + e.getMessage());}}
}

现在,我们已经创建了一个 EmailService 类,用于发送邮件通知。你可以在需要发送邮件通知的地方调用此服务。例如,在发送评论回复通知时,可以同时发送一封邮件提醒被回复的用户:

@PostMapping
public ResponseEntity<?> submitArticleComment(@PathVariable Long articleId, @RequestBody CommentDto commentDto, Principal principal) {// ... 提交评论的逻辑 ...// 发送通知Notification notification = new Notification();notification.setRecipient(/* 被回复的用户 */);notification.setContent(/* 通知内容 */);notificationRepository.save(notification);// 发送邮件通知String recipientEmail = /* 被回复用户的邮箱地址 */;String emailSubject = "您在博客平台上收到了一条新评论";String emailContent = "您在文章《" + article.getTitle() + "》上收到了一条新评论:" + commentDto.getContent();emailService.sendNotificationEmail(recipientEmail, emailSubject, emailContent);return ResponseEntity.ok(comment);
}

通过以上实现,我们已经为博客平台添加了实时通知和邮件通知功能。用户在浏览网站时将实时收到新通知,并在关键通知发生时通过电子邮件获得提醒。这将极大地提高用户的参与度和互动体验。

三、用户角色与权限管理

为了实现不同类型的用户具有不同的权限,我们需要引入角色与权限管理。本节将介绍如何为用户分配角色,并根据角色分配权限。

1.角色与权限数据模型

首先,我们创建两个实体类:RolePermission,表示用户角色和权限。一个角色可以拥有多个权限,一个权限可以分配给多个角色。

@Entity
public class Role {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@ManyToMany@JoinTable(name = "role_permission",joinColumns = @JoinColumn(name = "role_id"),inverseJoinColumns = @JoinColumn(name = "permission_id"))private Set<Permission> permissions;
}@Entity
public class Permission {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;@ManyToMany(mappedBy = "permissions")private Set<Role> roles;
}

接下来,更新 User 实体类,添加与 Role 的多对多关联。


@Entity
public class User {// ... 其他字段 ...@ManyToMany@JoinTable(name = "user_role",joinColumns = @JoinColumn(name = "user_id"),inverseJoinColumns = @JoinColumn(name = "role_id"))private Set<Role> roles;
}

2.分配角色与权限

创建一个 RoleRepository 和一个 PermissionRepository,用于操作角色和权限数据。

public interface RoleRepository extends JpaRepository<Role, Long> {
}public interface PermissionRepository extends JpaRepository<Permission, Long> {
}

接下来,创建一个初始化角色与权限的方法。例如,我们可以创建一个管理员角色,拥有所有权限,以及一个普通用户角色,只拥有部分权限。


@Service
public class InitService {@Autowiredprivate RoleRepository roleRepository;@Autowiredprivate PermissionRepository permissionRepository;public void initRolesAndPermissions() {// 创建权限Permission createArticle = new Permission("CREATE_ARTICLE");Permission editArticle = new Permission("EDIT_ARTICLE");Permission deleteArticle = new Permission("DELETE_ARTICLE");permissionRepository.saveAll(Arrays.asList(createArticle, editArticle, deleteArticle));// 创建普通用户角色Role userRole = new Role("USER");userRole.setPermissions(Collections.singleton(createArticle));roleRepository.save(userRole);// 创建管理员角色Role adminRole = new Role("ADMIN");adminRole.setPermissions(new HashSet<>(Arrays.asList(createArticle, editArticle, deleteArticle)));roleRepository.save(adminRole);}
}

3.基于角色的访问控制

为了实现基于角色的访问控制,我们需要在 SecurityConfig 类中配置权限控制规则。例如,只有管理员才能编辑和删除文章。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {// ... 其他配置 ...@Autowiredprivate CustomUserDetailsService customUserDetailsService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(customUserDetailsService);}@Overrideprotected void configure(HttpSecurity http) throws Exception {http// ... 其他配置 ....authorizeRequests().antMatchers(HttpMethod.POST, "/api/articles").hasAnyRole("USER", "ADMIN").antMatchers(HttpMethod.PUT, "/api/articles/").hasRole("ADMIN").antMatchers(HttpMethod.DELETE, "/api/articles/").hasRole("ADMIN").antMatchers("/api/admin/").hasRole("ADMIN").anyRequest().permitAll();}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Beanpublic AuthenticationEntryPoint authenticationEntryPoint() {return (request, response, authException) -> {response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");};}@Beanpublic AccessDeniedHandler accessDeniedHandler() {return (request, response, accessDeniedException) -> {response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");};}
}

在这个重写的基于角色的访问控制配置中,我们首先配置了用户创建文章的权限,允许具有 USERADMIN 角色的用户创建文章。接下来,我们为文章的编辑和删除操作设置了权限,仅允许具有 ADMIN 角色的用户进行这些操作。

我们还为 /api/admin/ 设置了访问权限,只允许具有 ADMIN 角色的用户访问该路径下的所有资源。

此外,我们添加了一个 AuthenticationEntryPoint 和一个 AccessDeniedHandler,用于自定义身份验证失败和访问被拒绝时的错误响应。

这样,我们已经实现了基于角色的访问控制,确保了不同类型的用户只能访问其被授权的资源。