前言:

本周我们小组进行了最基本的功能开发,包括用户注册和登录,以及基本错题本部分的开发。我负责设计最基本的数据库表结构和接口。用户的注册和登录使用阿里云OSS存储图片,登录后会生成jwt令牌,让用户端可以访问相关的后端接口;本周错题本的开发包括对于错题本和错题的增删改查。

一.数据库表设计

       以上的业务功能涉及到的表结构如下,对于以下的这些表中数据的删除,都采用逻辑删除的形式,即将deleted设为1,以防出现查找的时候产生空指针异常。

      用户表,包含用户最基本的信息,包括姓名,头像,密码等内容。

    错题本表,用于表示错题本实体,用于存储错题,与用户关联,一个用户可以有多个错题本:

      错题表,用于存储错题的基本信息,包含标题,题干和答案

    错题本-错题表,错题本和错题设计为多对多的关系,一个错题本可以存储多个错题,一个错题可以在多个错题本中使用:

      错题-图片表,用于专门存储错题本中含有的图片,图片为阿里云OSS中的图片路径,type表示此图片是属于答案的图片还是题干的图片,0表示题干图片,1表示答案图片,在代码中专门用TopicConstant类存储:

public class TopicConstant {

    public static final Integer TOPIC_PICTURE_STEM = 0 ;
    public static final Integer TOPIC_PICTURE_ANSWER =1 ;

}

二.相关接口和代码设计

2.1 相关基础代码设计

       创建这些表信息的实体类,与表中字段一一对应,这里以Topic为例,其他表亦有对应的实体类:

@Schema(description = "题目")
public class Topic extends BaseEntity{

 @TableId(type = IdType.AUTO)
 @Schema(description = "题目id")
 private Long id;

 @Schema(description = "题目标题")
 private String title;

 @Schema(description = "题干")
 private String questionStem;

 @Schema(description = "答案")
 private String answer;
 
}

        此外我添加了一些实体类,用于处理特殊的数据:

Result类:用于规范传给前端的格式,其中包括响应码,信息和数据,采用泛型的形式来规范传递给前端的数据类型

BaseRequest类:将id等信息封装成RequestBody形式,用于规范

BaseEntity类:用于存储最基本的信息,包括创建时间,修改时间和是否删除,许多类可以继承这个实体类以进行最基本的三个操作

/*

Result类,用于封装后端传给前端的数据,包括数据本身和响应码等

*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> implements Serializable {
    private Integer code;//响应码,1 代表成功; 0 代表失败
    private String msg;  //响应信息 描述字符串
    private T data; //返回的数据

    //增删改 成功响应
    public static <T> Result<T> success(){
        return new Result<>(1,"success",null);
    }
    //查询 成功响应
    public static <T> Result<T> success(T data){
        return new Result<>(1,"success",data);
    }
    //失败响应
    public static <T> Result<T> error(String msg){
        return new Result<>(0,msg,null);
    }
}


/*

BaseRequest类,用于接受前端的基础请求参数,比如id等信息,使用字符串为主体,在后端转换

*/
@Data
@Schema(description = "基础请求参数")
public class BaseRequest {
    @Schema(description = "id")
    private String id;
}


/*

BaseEntity类,用于整合出多数数据实体的公共数据,这样重复的部分只要继承其就行了

*/


public class BaseEntity {

    @Schema(description = "创建时间")
    private LocalDateTime createTime;
    @Schema(description = "更新时间")
    private LocalDateTime updateTime;
    @Schema(description = "是否删除")
    private Integer deleted;
}

    

 2.2 相关接口的设计:

    此为错题部分的相关接口,包含获取题目列表,获取题目详情,添加题目,删除题目和更新题目接口,采用Post形式进行访问。此为基本的增删改查功能

@PostMapping("/list")
    @Operation(summary = "获取题目列表")
    public Result<List<TopicListVO>> list(@RequestBody TopicQueryDTO topicQueryDTO){

        log.info("获取题目列表,参数:{}", topicQueryDTO);
          List<TopicListVO> topicList = topicService.listVO(topicQueryDTO);
          return Result.success(topicList);


    }

    @PostMapping("/detail")
    @Operation(summary = "获取题目详情")
    public Result<TopicVO> detail(@RequestBody BaseRequest baseRequest){

        log.info("获取题目详情,参数:{}", baseRequest);
        TopicVO topic = topicService.getDetailById(baseRequest);
        return Result.success(topic);


    }



    @PostMapping("/add")
    @Operation(summary = "添加题目")
    public Result add(@RequestBody TopicDTO topicDTO){
            log.info("添加题目参数,{}", topicDTO);
            topicService.add(topicDTO);
            return Result.success();
    }



    @PostMapping("/delete")
    @Operation(summary = "删除题目")
    public Result delete(@RequestBody BaseRequest baseRequest){
        log.info("删除题目参数,{}", baseRequest);
        topicService.delete(baseRequest);
        return Result.success();
    }
//
//
    @PostMapping("/update")
    @Operation(summary = "更新题目")
    public Result update(@RequestBody TopicDTO topicDTO){
        log.info("更新题目参数,{}", topicDTO);
        topicService.updateIt(topicDTO);
        return Result.success();
    }

此为错题本相关接口,包含对错题本基本的增删改查

public class NoteBookController {

    private final INoteBookService notebookService;

    @PostMapping("/add")
    @Operation(summary = "添加错题本")
    public Result add(@RequestBody NoteBookDTO noteBookDTO) {
      notebookService.add(noteBookDTO);
      return Result.success();
    }

    @PostMapping("/list")
    @Operation(summary = "获取错题本列表")
    public Result<List<NoteBookListVO>> list() {
        List<NoteBookListVO> noteBookList = notebookService.listVO();
        return Result.success(noteBookList);
    }

    @PostMapping("/delete")
    @Operation(summary = "删除错题本")
    public Result delete(@RequestBody BaseRequest  request) {
        notebookService.deleteById(request);
        return Result.success();
    }

    @PostMapping("detail")
    @Operation(summary = "获取错题本详情")
    public Result<NoteBookVO> detail(@RequestBody BaseRequest  request) {

        log.info("获取错题本详情,id:{}", request);
       NoteBookVO noteBookVO = notebookService.detail(request);
        return Result.success(noteBookVO);
    }

    @PostMapping("/update")
    @Operation(summary = "更新错题本基本信息")
    public Result update(@RequestBody NoteBookDTO noteBookDTO) {
        notebookService.updateIt(noteBookDTO);
        return Result.success();
    }

}

用户登录与注册相关接口,包含用户登录和注册模块。用户登录模块需要生成令牌,作为用户端每次访问后端端口的凭据。除了访问不需要通过令牌授权,其他接口都需要

public class UserController {


    @Autowired
    IUserService userService;

    @PostMapping("/login")
    @Operation(summary = "用户登录")
    public Result<LoginVO> login(@RequestBody LoginDTO loginDTO){
        User user = userService.login(loginDTO);
        if(user == null) {
            return Result.error("用户名或密码错误");

        }

        Map claims = new HashMap<>();
        claims.put("userId",user.getId());


        //为用户生成令牌
        String token = JwtUtils.generateJwt(claims);
        BaseContext.setCurrentId(user.getId());
        LoginVO userLoginVO = LoginVO.builder()
                .id(user.getId())
                .name(user.getName())
                .password(user.getPassword())
                .avatar(user.getAvatar())
                .token(token)
                .build();

        return Result.success(userLoginVO);
    }

    @PostMapping("/register")
    @Operation(summary = "用户注册")
    public Result register(@RequestBody RegisterDTO registerDTO) {
        log.info("用户注册信息,{}",registerDTO);
        userService.register(registerDTO);
        return Result.success();
    }

    @PostMapping("/update")
    @Operation(summary = "更新用户信息")
    public Result update(@RequestBody UserDTO userDTO) {
        log.info("更新用户信息,{}",userDTO);
        userService.updateIt(userDTO);
        return Result.success();
    }




}

      同时设置了上传头像接口,后端可以通过此接口将前端传过来的数据传给阿里云OSS,实现云存储功能:

public class UploadController {
    @Autowired
    private AliOSSUtils aliOSSUtils;

    @PostMapping("/upload/avatar")
    @Operation(summary = "上传头像")
    //获取文件之方法
    public Result<String> upload(@RequestParam("file") MultipartFile image) throws IOException {
        log.info("文件上传:{}",image.getOriginalFilename());
        //调用阿里云工具类进行文件上传
        String url = aliOSSUtils.upload(image);
        log.info("文件上传完成,url:{}",url);
        return Result.success(url);
    }
}

2.3 相关DTO和VO的设计

错题模块的DTO主要包含以下部分:

查询错题参数,以开始时间和结束时间为条件,以错题title作为模糊查询

@Data
@Schema(description = "查询错题参数")
public class TopicQueryDTO {

    @Schema(description = "错题本id")
    private Long noteBookId;



    @Schema(description = "题目的title")
      private String topicStem;

    @Schema(description = "开始时间")
      private LocalDateTime startTime;

    @Schema(description = "结束时间")
      private LocalDateTime endTime;

}

保存错题的参数,即TopicDTO,包含以下内容

@Data
@Builder
@Schema(description = "添加题目")
public class TopicDTO {

    @Schema(description = "题目id")
    private Long id;

    @Schema(description = "题目标题")
    private String title;

    @Schema(description = "错题本id")
    private Long noteBookId;

    @Schema(description = "题干")
    private String questionStem;

    @Schema(description = "题干图片")
    private List<String> questionStemPictureList;

    @Schema(description = "答案")
    private String answer;

    @Schema(description = "答案图片")
    private List<String> answerPictureList;

    @Schema(description = "标签")
    private List<String> labels;
}

用于显示错题详情的TopicVO,包含题目标题,题干等信息,对于图片等信息需要后端连表查询:

public class TopicVO implements Serializable {
    // 添加 implements Serializable
    // 添加 serialVersionUID
    private static final long serialVersionUID = 1L;

    @Schema(description = "题目id")
    private Long id;

    @Schema(description = "题目标题")
    private String title;

    @Schema(description = "题干")
    private String questionStem;

    @Schema(description = "题干图片")
    private List<String> questionStemPictureUrls;

    @Schema(description = "答案")
    private String answer;

    @Schema(description = "答案图片")
    private List<String> answerPictureUrls;

    @Schema(description = "创建时间")
    private LocalDateTime createTime;

    @Schema(description = "更新时间")
    private LocalDateTime updateTime;

    @Schema(description = "题目标签")
    private List<Label> labels;
}

TopicListVO,用于展示错题的缩略图形式,包含以下信息:

public class TopicListVO implements Serializable{
    // 添加 implements Serializable
    @Schema(description = "题目id")
    private Long id;

    @Schema(description = "题目标题")
    private String title;

    @Schema(description = "题干")
    private String topicStem;

    @Schema(description = "图片")
    private List<String> pictureUrls;

    @Schema(description = "创建时间")
    private LocalDateTime createTime;

    @Schema(description = "修改时间")
    private LocalDateTime updateTime;

    @Schema(description = "标签")
    private List<Label> labels;



}

错题本相关DTO参数,包含错题本名称,简介等信息:

@Schema(description = "错题本添加信息")
@Data
public class NoteBookDTO {


    @Schema(description = "错题本id")
    private Long id;

    @Schema(description = "错题本名称")
    private String name;

    @Schema(description = "错题本简介")
    private String brief;
}

错题本相关的VO参数,包含错题本的缩略图VO以及错题本的详情VO

public class NoteBookListVO {

    @Schema(description = "错题本id")
    private Long id;
    @Schema(description = "错题本名称")
    private String name;
    @Schema(description = "错题本简介")
    private String brief;
    @Schema(description = "创建时间")
    private LocalDateTime createTime;
    @Schema(description = "更新时间")
    private LocalDateTime updateTime;

}
public class NoteBookVO {

    @Schema(description = "错题本id")
    private Long id;
    @Schema(description = "错题本名称")
    private String name;
    @Schema(description = "错题本简介")
    private String brief;
    @Schema(description = "创建时间")
    private LocalDateTime createTime;
    @Schema(description = "更新时间")
    private LocalDateTime updateTime;
}

用户模块相关的DTO,包含用户登录DTO和注册DTO,用于接受,来自前端的登录和注册信息:

@Data
@Schema(description = "用户登录信息")
public class LoginDTO {


    @Schema(description = "用户名")
    private String name;

    @Schema(description = "密码")
    private String password;
}


@Data
public class RegisterDTO {

    private String name;

    private String password;

    private String avatar;
}

用户模块相关的VO,其中除了基础的id,名字头像,还包含token,作为令牌访问后端

public class LoginVO {

    private Long id;
    private String name;


    private String avatar;

 
    private String token;
}

三.总结

本周小组围绕用户体系与错题本核心功能完成了基础开发工作,我主要负责数据库表结构与接口设计,整体采用逻辑删除机制保障数据安全,通过阿里云OSS实现头像存储、JWT令牌校验用户身份,构建了覆盖用户全生命周期及错题管理的基础架构。在数据库层面,设计了用户表、错题本表、错题表及关联中间表,通过BaseEntity统一封装创建时间、更新时间与删除标记,配合TopicConstant常量类规范图片类型,实现了多对多错题关联与图片分离存储的灵活结构。接口设计上,基于RESTful风格封装了Result统一响应格式与BaseRequest基础参数模型,完成了用户注册登录(含令牌生成)、错题本与错题的增删改查全流程接口,并通过DTO/VO分层隔离前后端数据交互,既保障了数据传输的规范性,也为后续功能扩展预留了清晰的架构边界,为系统后续迭代奠定了稳定可靠的基础。   

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐