# vitamin-project-management
**Repository Path**: scut-skyworth-club/vitamin-project-management
## Basic Information
- **Project Name**: vitamin-project-management
- **Description**: 项目管理项目demo
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 0
- **Created**: 2021-01-15
- **Last Updated**: 2021-05-02
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# vitamin-project-management
#### 介绍
维生素俱乐部项目管理项目后端demo
开发接口时尽量站在前端开发角度,考虑需要什么参数、返回值、接口功能等。
有问题一起讨论:-)
#### 软件架构
demo目前有三个模块:1. 项目管理模块;2. 文件上传下载模块;3. 登录认证模块
#### 安装教程
1. clone到本地,用idea打开
#### 任务
1. 登录认证模块服务与接口设计与编写(一人)
2. 项目管理模块服务与接口设计与编写(两人)
3. 文件上传下载模块服务与接口设计与编写(一人)
#### 服务与接口描述
##### 用户认证服务与接口:
```
1. 用户登录:用户名密码登录,记录token于数据库,返回token作为登录凭证
2. 用户认证:根据用户名和token认证用户登录信息是否有效
3. 权限认证:用户是否有权限对当前项目进行改动,如只有项目创建者才可以修改项目信息
```
##### 项目管理服务与接口:
```
1. 发布新项目,在数据库中写入数据
2. 发布新需求,在数据库中写入数据
3. 查看现有项目(返回项目描述、文件(包含下载链接)、项目需求、参与者等有关信息)
4. 对现有项目进行更改(创建者)
```
##### 文件加载服务与接口:
```
1. 上传文件
2. 下载文件
3. 生成文件下载链接
4. 查看项目对应文件
5. FileUtils类
```
#### 代码规范:
1. 除了用户登录接口以外,其他接口在调用服务执行业务逻辑前都要调用*用户认证服务*确保用户登录信息有效。
2. 基本属性用project_id这种形式,方法用getUsername()这种驼峰法写。
3. 项目使用swagger2创建接口文档,每一个接口类上的注释要写上负责人,修改日期,每一个接口都要写上用途、参数、返回值类型,接口内调用服务时最好写好调用逻辑。swagger2常用注解如下:
```sql
@Api:用在请求的类上,表示对类的说明
tags="说明该类的作用,可以在UI界面上看到的注解"
value="该参数没什么意义,在UI界面上也看到,所以不需要配置"
@ApiOperation:用在请求的方法上,说明方法的用途、作用
value="说明方法的用途、作用"
notes="方法的备注说明"
@ApiImplicitParams:用在请求的方法上,表示一组参数说明
@ApiImplicitParam:用在@ApiImplicitParams注解中,指定一个请求参数的各个方面
name:参数名
value:参数的汉字说明、解释
required:参数是否必须传
paramType:参数放在哪个地方
· header --> 请求参数的获取:@RequestHeader
· query --> 请求参数的获取:@RequestParam
· path(用于restful接口)--> 请求参数的获取:@PathVariable
· body(不常用)
· form(不常用)
dataType:参数类型,默认String,其它值dataType="Integer"
defaultValue:参数的默认值
@ApiResponses:用在请求的方法上,表示一组响应
@ApiResponse:用在@ApiResponses中,一般用于表达一个错误的响应信息
code:数字,例如400
message:信息,例如"请求参数没填好"
response:抛出异常的类
@ApiModel:用于响应类上,表示一个返回响应数据的信息
(这种一般用在post创建的时候,使用@RequestBody这样的场景,
请求参数无法使用@ApiImplicitParam注解进行描述的时候)
@ApiModelProperty:用在属性上,描述响应类的属性
```
参考代码如下:
```java
/**
* 负责人:某美女
* 修改日期:1.15
*/
@RestController
@Api(tags = "用户认证接口") // swagger2注解
public class CertificationController {
@Autowired
CertificationMapper mapper;
@Autowired
CertificationService service;
@PostMapping("/login")
@ApiOperation("用户登录接口") // swagger2注解
@ApiImplicitParams({
@ApiImplicitParam(name = "username", value = "用户名"),
@ApiImplicitParam(name = "password", value = "密码")
})
public String login(HttpServletRequest request, @RequestBody Project p){
// 调用用户登录服务进行登录,传入用户名和密码,返回用户token
return service.loginService(request.getParameter("username"), request.getParameter("password"));
}
}
```
4. 编写各类方法时,注释应写上名称、用途、负责人、修改日期、参数、返回值。
除了返回实际信息的,其他以成功/失败为返回值的服务直接用ResultUtils工具类里的方法作为返回值:
```java
/**
* 做某事
* 通过这个方法完成某件事情
*
* 负责人:某帅哥
* 修改日期:1.15
*
* @param username 用户名
* @return 成功200 失败-100
*/
public String doSomething(String username){
return ResultUtils.doFail(); // ResultUtils.doSuccess();
}
```
5. 工具包内包含各类辅助方法,可以写也可以用:
```java
/**
* 创建人:某靓女
* 普通工具类
*/
public class Utils {
// 生成n为随机数字+字母组合的字符串
public static String getRandCode(int n){
StringBuilder rand = new StringBuilder();
Random random = new Random();
for (int i = 0; i < n; i++) {
// 输出字母还是数字
boolean charOrNum = random.nextInt(2) % 2 == 0;
// 字符串
if (charOrNum) {
// 取得大写字母还是小写字母
int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
rand.append((char) (choice + random.nextInt(26)));
} else { // 数字
rand.append(String.valueOf(random.nextInt(10)));
}
}
return rand.toString();
}
}
```
6. Mapper接口与Mybatis接口编写,mapper接口写上负责人、修改日期、接口功能,xml里写上功能:
```java
@Repository
public interface CertificationMapper {
/*
* 负责人:某某
* 修改日期:1.15
*
* 通过用户名查找密码
*/
String findPwdByUsername(String username);
}
```
```xml
```
7. 目前已有默认的与数据库表对应的实体类,数据库具体参数详见实体类注释;需要进一步封装实体类时,参考数据库设计,属性名与数据库一致,写上负责人,实体类用途,修改日期,写明swagger2的注解:
```java
/**
* 负责人:某靓仔
* 创建新实体类的示例,用于返回项目信息
* 修改日期:1.15
*/
@ApiModel
public class ProjectExtends {
@ApiModelProperty(value = "项目id")
private String project_id;
@ApiModelProperty(value = "创建者昵称")
private String creator_nickname;
@ApiModelProperty(value = "参与者列表")
private List participants;
@ApiModelProperty(value = "文件列表")
private List file_list;
@ApiModelProperty(value = "基本描述")
private String basic_description;
@ApiModelProperty(value = "详细描述")
private String detailed_description;
@ApiModelProperty(value = "技术栈")
private String technology_stack;
@ApiModelProperty(value = "创建时间")
private String create_time;
@ApiModelProperty(value = "预计完成时间")
private String finish_time;
public Project() {
}
// 全参数构造函数,getter和setter方法
public Project(String project_id, String creator_username, String basic_description,
String detailed_description, String technology_stack, String create_time,
String finish_time) {
this.project_id = project_id;
this.creator_username = creator_username;
this.basic_description = basic_description;
this.detailed_description = detailed_description;
this.technology_stack = technology_stack;
this.create_time = create_time;
this.finish_time = finish_time;
}
public String getProject_id() {
return project_id;
}
public void setProject_id(String project_id) {
this.project_id = project_id;
}
```