简介
一款基于 Spring Boot 的博客系统,支持多用户,支持切换主题!
技术栈
前端: Freemarker、Bootstrap、SeaJs
后端: JDK8、MySQL、Spring Boot、Spring-Data-JPA、Shiro、Lombok
Github:github.com/langhsu/mbl…
功能介绍
- 个人注册登录
- 个人信息修改保存
- 发表博客
- 文章评论、点赞
- 消息通知
- 后台博客管理、评论管理、系统配置等
项目启动步骤、项目详情
启动步骤
配置:src/main/resources/application-mysql.yml (数据库账号密码)、新建db_mblog的数据库
运行:src/main/java/com/mtons/mblog/BootApplication
访问:http://localhost:8080/
后台:http://localhost:8080/admin
账号:默认管理员账号为 admin/12345
web前台截图
项目代码结构分析
└─com
└─mtons
└─mblog
│ BootApplication.java #启动类
│
├─base
│ ├─lang
│ │ Consts.java
│ │ EntityStatus.java
│ │ MtonsException.java
│ │ Result.java
│ │ Theme.java
│ │
│ ├─oauth #第三方登录
│ │ │ APIConfig.java
│ │ │ Oauth.java
│ │ │ OauthBaidu.java
│ │ │ OauthDouban.java
│ │ │ OauthGithub.java
│ │ │ OauthOsc.java
│ │ │ OauthQQ.java
│ │ │ OauthRenren.java
│ │ │ OauthSina.java
│ │ │
│ │ └─utils
│ │ Display.java
│ │ ...
│ │
│ ├─storage #存储相关
│ │ │ Storage.java
│ │ │ StorageFactory.java
│ │ │
│ │ └─impl
│ │ AbstractStorage.java
│ │ AliyunStorageImpl.java
│ │ NativeStorageImpl.java
│ │ QiniuStorageImpl.java
│ │ UpYunStorageImpl.java
│ │
│ └─utils
│ BeanMapUtils.java
. │
│
├─config
│ ContextStartup.java #启动时候初始化全局配置、首页导航等
│ RedisConfig.java
│ ShiroConfig.java
│ SiteConfig.java
│ SiteOptions.java
│ WebMvcConfig.java
│
├─modules
│ ├─aspect
│ │ HibernateFilterAspect.java
│ │ PostStatusFilter.java #文章状态过滤注解
│ │
│ ├─data #vo,一些传输对象
│ │ AccountProfile.java
│ │ BadgesCount.java
│ │ CommentVO.java
│ │ ...
│ │
│ ├─entity
│ │ Channel.java
│ │ Comment.java
│ │ ...
│ │
│ ├─event #基于spring的事件
│ │ │ MessageEvent.java #消息事件
│ │ │ PostUpdateEvent.java #文章发布事件(文章数统计、推送通知)
│ │ │
│ │ └─handler
│ │ MessageEventHandler.java
│ │ PostUpdateEventHandler.java
│ │
│ ├─hook #钩子,拦截器
│ │ │ Hook.java
│ │ │
│ │ └─interceptor
│ │ │ InterceptorHook.java
│ │ │ InterceptorHookManager.java
│ │ │ InterceptorHookSupport.java
│ │ │
│ │ └─impl
│ │ HidenContentPugin.java #因此部分内容的钩子
│ │ ViewCopyrightPugin.java #声明内容版权的钩子
│ │
│ ├─repository
│ │ ChannelRepository.java
│ │ ...
│ │
│ ├─service
│ │ │ ChannelService.java
│ │ │ ...
│ │ │
│ │ └─impl
│ │ ChannelServiceImpl.java
│ │ ...
│ │
│ └─template #freemarker的模板引擎相关
│ │ BaseMethod.java
│ │ DirectiveHandler.java
│ │ TemplateDirective.java
│ │ TemplateModelUtils.java
│ │
│ ├─directive #声明模板
│ │ ChannelDirective.java
│ │ ContentsDirective.java
│ │ ...
│ │
│ └─method #声明模板方法
│ TimeAgoMethod.java
│
├─shiro #shiro相关
│ │ AccountRealm.java
│ │ AccountSubjectFactory.java
│ │ AuthenticatedFilter.java
│ │ ICredentialsMatcher.java
│ │
│ └─tags #shiro与freemarker相关的标签
│ AuthenticatedTag.java
│ GuestTag.java
│ HasAnyRolesTag.java
│ ...
│
└─web
├─controller
│ │ BaseController.java
│ │
│ ├─admin #后台管理接口
│ │ AdminController.java
│ │ ChannelController.java
│ │ ...
│ │
│ ├─api
│ │ ApiController.java
│ │ package-info.java
│ │
│ └─site #博客接口
│ │ ChannelController.java
│ │ IErrorController.java
│ │ IndexController.java
│ │ SearchController.java
│ │ TagController.java
│ │ Views.java
│ │
│ ├─auth
│ │ CallbackController.java
│ │ ...
│ │
│ ├─comment
│ │ CommentController.java
│ │
│ ├─posts
│ │ MindMapController.java
│ │ PostController.java
│ │ UploadController.java
│ │
│ └─user
│ FavorController.java
│ SettingsController.java
│ UsersController.java
│
├─exceptions
│ DefaultExceptionHandler.java
│
├─filter
│ RequestCostFilter.java
│
├─formatter
│ JsonUtils.java
│ StringEscapeEditor.java
│
├─interceptor
│ BaseInterceptor.java
│
└─menu
Menu.java
MenuJsonUtils.java
MenusDirective.java
项目技术详情解读
发布与通知
在开发的过程中,事件会遇到这种场景:
做完一件事情之后,需要广播一系诶消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个去发送请求通知,但是这种方式比较耗时,且效率极低,那有没有比较好的解决方案呢?那就是事件监听,事件监听也是设计模式中 发布-订阅模式、观察者模式的一种实现。
观察者模式:在对象之间定义了一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象会收到通知并自动更新。
Spring的事件为Bean和Bean之间的消息传递提供支持。当一个对象处理完某种任务后,通知另外的对象进行某些处理,常用的场景有进行某些操作后发送通知,消息,操作记录,发送短信、邮件等情况。
Spring事件遵循的流程
自定义事件,继承ApplicationEvent(org.springframework.context.ApplicationEvent)
自定义事件监听,实现ApplicationListener(org.springframework.context.ApplicationListener)
使用容器触发事件:
发布事件,使用applicationContext发布事件, ApplicationEvent中,在自定义事件的构造方法中除了第一个source参数,其他参数都可以去自定义, 可以根据项目实际情况进行监听传参,这里就只定义个简单的String字符串的透传。
整体的逻辑实现步骤
第一步:分配自定义订阅和通知时间,继承ApplicationEvent
第二步:分配定义事件监听器,实现ApplicationListener
第三步:使用容器发布事件(订阅时间、通知事件)