分享 LaraForum | rest 后端论坛应用 | Springboot+jpa | 轻量级 | 完整单测

2019-03-14 21:03:25 +08:00
 Allianzcortex

LaraForum

一个提供论坛纯后端 API 的应用

项目地址:Github

最近开发了这个应用,包括用户的注册 /登陆 /登出权限管理,发帖 /删帖 /评论 /删评 /信息提醒,主题创造 /删除,文章分类分页搜索,以及基于 MySQL Full-text SearchLucene 的模糊匹配关键词搜索。

列举 API 如下:

得到某篇单独发帖:

get /api/articles/get/single/{slug}

return:

{
    'id':{id},
    'name':{name},
    'tag':[1,2,3]
}

多重条件设置:

get /api/articles/get/batch?tag=xx&author=yy

为某个用户增加消息提醒

post /api/read/notice/{userId}

为某个用户设置权限

/api/permission/add/{user}/2

为某个用户设置角色

/api/role/add/{user}/2

根据关键字进行搜索,默认采用 MySQL,可以配置为 Lucene

/api/search/{keyWord}

etc...


除了大家都会用到的 @ControllerAdvice 全局处理 Exception 和 @ResponseEntity 返回数据外,这里主要想描述一下这个应用的几个特点吧:

  1. 轻量级:

这里轻量级指的是除了 Springboot+Spring JPA+Spring MVC 外其它的 组件都没有涉及到,两个比较重要的功能①认证(authentication)鉴权(authorization)没有用到 spring-security 或者 shrio,是单独 实现的。

① 对认证 authentication,默认采用的是 JWT,每次验证是由 filter 提供,参见 代码,每次判断则是由 interceptor 提供,参见 代码。得到的值会用 request.setAttribute 写入后由后端应用读取,避免 重复验证。关于 jwt 实现过期 logout 在纯后端应用里相对难实现(前端直接删除 jwtToken 即可,现在 采用的方法是存储到数据库里,不符合 stateless 无状态思想,因为原话是会 requires a DB lookup each time)。比较理想 的做法是在 SO 上看到的这个 评论,在写入 Token 的值里进行操作,后续会实现这一点。

② 对权限管理 authorization,采用的是注解 @+ 用 AspectJ 实现 AOP 去做。实现的两个注解分别是 @RequirePermissiona(代码) 和 @RequireRoles(代码),之后统一 [管理](代码),分别判断用户是否可以去执行对应行为。使用时只需要在方法前加入 @RequirePermission("youPermission") ,就会自动判断,对业务逻辑代码没有影响,类似于 Python 的装饰器。比如对于这段 代码,用户必须有 create_post 的权限,才能发表帖子。

@RequirePermissions("create_post")
@Transactional
@PostMapping("permission/add/{userName}/{pNumber}")
public void addUserPermission(@PathVariable String userName, @PathVariable Integer pNumber) {
   // logic
}


  1. UnitTest 与 IntegrationTest

这一点主要是因为看到的很多 sprint boot 代码里都缺少相应的测试,所以希望能补充完整。看到的文章里也有关于这两个测试的争论,比如有 SO 的回答说因为 spring 应用与现实交互所以 IntegrationTest 能更好反映程序的运行,也有文章说要以 UnitTest 为主测试单个函数的正确性,所以就都做了.... 主要用的框架是 JunitMockito,在 Repository 层面进行了 IntegrationTest,判断是否能真的写入 数据库里(代码),在 Service 层面进行了 UnitTest,判断是否会调用对应 Repository 的行为(代码).

@Test
public void whenUserSave_thenCheckSuccess(){
     userServiceMock.save(user);
     verify(userRepositoryMock).save(user);
}

在 Controller 层面则同时进行两种测试,判断得到的对应结果是否符合期望,同时判断是否会调用对应 Service 的行为(代码)。暂时测试了 User/UserRepositor/UserService/UserController ,后续会进一步补充。

因为是纯后端应用所以暂时没有界面,就发一张 Postman 的截图吧(:

整体来说还有很多要优化的点,后续也会一直开发这个项目并写前端进行匹配,多谢大家的支持 quq

1565 次点击
所在节点    分享创造
2 条回复
Kilerd
2019-03-14 22:03:09 +08:00
问题是你这个 API 设计得一点都不 restful 啊
Allianzcortex
2019-03-14 22:08:55 +08:00
@Kilerd 谢谢谢谢,是的,这个问题在 Spring 官方教程里专门提到过,https://spring.io/guides/tutorials/rest/ 里有一节在讨论:

What makes something RESTful?
So far, you have a web-based service that handles the core operations involving employee data. But that ’ s not enough to make things "RESTful".

Pretty URLs like /employees/3 aren ’ t REST.

Merely using GET, POST, etc. aren ’ t REST.

最关键的是这句话:Having all the CRUD operations laid out aren ’ t REST.
目前 API 没有全部遵守 RESTful 的要求,这是最近两周开发的项目,后续会进一步完成。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/544712

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX