当前位置: 首页 > article >正文

基于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;

    @ManyToOne
    private 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 {
    @Autowired
    private NotificationRepository notificationRepository;

    @GetMapping
    public 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 {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(notificationHandler(), "/api/ws/notifications")
                .setAllowedOrigins("*");
    }

    @Bean
    public WebSocketHandler notificationHandler() {
        return new NotificationHandler();
    }
}

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

 
public class NotificationHandler extends TextWebSocketHandler {

    // 存储 WebSocket 会话
    private final Map<Long, WebSocketSession> sessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // ... 建立连接后的逻辑 ...
    }

    @Override
    protected 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 {

    @Autowired
    private 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 {

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private 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 {

    // ... 其他配置 ...

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService);
    }

    @Override
    protected 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();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint() {
        return (request, response, authException) -> {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
        };
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return (request, response, accessDeniedException) -> {
            response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
        };
    }
}

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

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

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

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


http://www.kler.cn/a/10108.html

相关文章:

  • Mysql数据类型面试题15连问
  • MySQL中的事务与锁
  • Java面试要点02 - 自动装箱与拆箱的原理与性能解析
  • 【韩老师零基础30天学会Java 】06章 数组、排序和查找
  • 高德地图通过经纬度查找位置和轨迹回放
  • 【Python无敌】在 QGIS 中使用 Python
  • 数据技术嘉年华星光璀璨,云和恩墨全栈数据技术能力闪耀会场
  • Vue实现自动化平台(五)--用例编辑页面
  • ​InnoDB引擎之flush脏页​
  • 大数据4 - 分布式计算
  • 电话机器人开发
  • c++学习之c++对c的扩展2
  • Zebec Protocol 出席香港 Web3 峰会,带来了哪些信息?
  • ROS开发之如何制作launch启动文件?
  • windows服务器自带IIS搭建网站并发布公网访问【内网穿透】
  • 怎么恢复永久删除的文件
  • vscode中的配置
  • ARM与C语言的混合编程【嵌入式系统】
  • STC89C52定时器的简介
  • Shader 海面/水面
  • 一次弄懂gzip模块启用和配置指令
  • TypeScript类成员的存取器
  • 《八次危机》速读笔记
  • 【ROS2指南-1】配置ROS2环境
  • 机器学习实战:Python基于K近邻KNN进行分类预测(四)
  • 【举一反三】只出现一次的数字