javaweb小组---团队合作相关

团队开发相关

说明:

建议一开始就是按着接口文档,从控制层找到对应接口开始一点点看下

不会的把对应的前后文都丢给gpt,让他给你解析

开发规范

RESTful API规范

本处可以不用管,了解下就行,按照接口文档写的那样就行(apifox接口)

RESTful API规范(详细版)_restful api接口规范-优快云博客

后端三层结构

深入浅出讲解JavaWeb后端的三层架构:Controller、Service、DAO 以及详解结合MyBatis和XML映射的DAO层设计_三层架构controller,service,dao-优快云博客

在这里插入图片描述

其他的你们都不用管,先点进去几个接口,看看具体的代码,其他包用到了再看

实体类命名规划(POJO)

Java学习笔记——实体类(ENTITY,VO,DTO,BO)_entity结尾的是-优快云博客

在这里插入图片描述

本处建议最好还是遵守下,特别是 前端给后端的数据 或者 后端给前端的数据 属性名称有区别时

  • 不要再entity设置json别名,这样就是一次性的,比如当后续前端又换一个名字时

例子:

前端需要的comment响应数据:

在这里插入图片描述

数据库对应的表单:

-- 创建 comment 表,用于存储商品评价信息
CREATE TABLE comments (
                          id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL, -- 评价ID,自增主键
                          userId BIGINT NOT NULL, -- 评价用户的ID
                          goodsId BIGINT NOT NULL, -- 商品ID
                          goodsDetailId BIGINT NOT NULL, -- 商品规格详情ID
                          orderId BIGINT NOT NULL, -- 订单ID
                          content VARCHAR(500), -- 评价内容
                          score INT NOT NULL, -- 评分(如 1-5 分)
                          createtime DATETIME NOT NULL -- 创建时间
);

本处评价内容等字段是不同的

对应的实体设计:

package com.wawu.pojo.entity;

import lombok.Data;

import java.time.LocalDateTime;

@Data
public class Comment {
    private Long id;

    private User user;

    private int score;
//    @JsonProperty("comment")//TODO 探究下这里是否有问题?
    //尽量别用这种这样可能会一次性
    private String content;//comment
//    @JsonProperty("time")
    private LocalDateTime createTime;
    private String specName;

    private Long userId;
    private Long goodsId;
    private Long goodsDetailId;
    private Long orderId;

}

vo设计:

本处需要返回的字段,也不需要那么多,最好不要直接用entity

package com.wawu.pojo.vo.GetGoodsCommentVO;

import lombok.Data;

import java.time.LocalDateTime;

@Data
public class CommentVO {
    private Long id;
    private UserVO user;
    private int score;
    private String comment;
    private LocalDateTime time;
    private String specName;
}


package com.wawu.pojo.vo.GetGoodsCommentVO;


import lombok.Data;

import java.util.List;


@Data
public class GoodCommentVO {
    private double rate;//均分=sum(评论评分)/总评论
    private List<CommentVO> commentList;
}


package com.wawu.pojo.vo.GetGoodsCommentVO;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserVO {
    private String nickname;
    private String headimg;//头像
}

响应结果规范

返回一个Result泛型对象

不懂代码的丢给gpt,让他给你例子

package com.wawu.common.result;

import lombok.Data;

import java.io.Serializable;

/**
 * 后端统一返回结果
 * @param <T>
 */
@Data
public class Result<T> implements Serializable {

    private Integer code; //编码:0成功,1000和其它数字为失败
    private String message; //错误信息
    private T data; //数据

    public static <T> Result<T> success() {
        Result<T> result = new Result<T>();
        result.code = 0;
        return result;
    }

    public static <T> Result<T> success(T object) {
        Result<T> result = new Result<T>();
        result.data = object;
        result.code = 0;
        return result;
    }

    public static <T> Result<T> error(String msg) {
        Result result = new Result();
        result.message = msg;
        result.code = 1000;
        return result;
    }

}

例子:

public static <T> Result<T> success(T object):

在这里插入图片描述

public static <T> Result<T> success():

在这里插入图片描述

package com.wawu.server.controller;

import com.wawu.common.annotation.IOC.Autowired;
import com.wawu.common.annotation.IOC.component.RestController;
import com.wawu.common.annotation.controller.mapping.PostMapping;
import com.wawu.common.annotation.controller.mapping.RequestMapping;
import com.wawu.common.annotation.controller.parameter.RequestBody;
import com.wawu.common.result.Result;
import com.wawu.pojo.dto.LoginDTO;
import com.wawu.pojo.entity.User;
import com.wawu.pojo.vo.LoginVO;
import com.wawu.server.service.UserService;

import java.sql.SQLException;

@RestController
@RequestMapping("/api/user")
public class UserController {
    @Autowired
    UserService userService;

    /**
     * 用户登录
     * @param loginDTO
     * @return
     */
    @PostMapping("/login")
//    @OptionsMapping("/login")
    public Result<LoginVO> login(@RequestBody LoginDTO loginDTO) throws SQLException {
        LoginVO loginVO=userService.login(loginDTO);
        return Result.success(loginVO);
    }

    /**
     * 注册用户(这里就不用dto了,跟数据库表都是对应的)
     * @param user
     * @return
     */
    @PostMapping("/signup")
    public Result<LoginVO> signup(@RequestBody User user) throws SQLException {
        LoginVO loginVO=userService.signup(user);
        return Result.success(loginVO);
    }
}

异常情况:

这里你们只需要抛出异常即可,其他的都不用管,自动调用public static <T> Result<T> error(String msg)

异常的信息建议都要直接写在代码中,最好封装到类中的静态变量中

例子:

在这里插入图片描述

package com.wawu.server.service;

import com.wawu.common.annotation.IOC.Autowired;
import com.wawu.common.annotation.IOC.component.Service;
import com.wawu.common.annotation.controller.parameter.RequestBody;
import com.wawu.common.constant.JwtClaimsConstant;
import com.wawu.common.constant.MessageConstant;
import com.wawu.common.exception.LoginException;
import com.wawu.common.property.JwtProperties;
import com.wawu.common.utils.JwtUtil;
import com.wawu.pojo.dto.LoginDTO;
import com.wawu.pojo.entity.User;
import com.wawu.pojo.vo.LoginVO;
import com.wawu.server.dao.UsersDAO;
import org.mindrot.jbcrypt.BCrypt;

import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserService {
    @Autowired
    private UsersDAO usersDAO;
    
    public LoginVO login(@RequestBody LoginDTO loginDTO) throws SQLException {
        User user = usersDAO.getUser(User.builder().email(loginDTO.getAccount()).build());
        //账号没有注册
        if(user==null){
            throw new LoginException(MessageConstant.LOGIN_EMAIL_NOT_REGISTER);
        }
        
        ///。。。。其他代码省略

        return loginVO;
    }

}

备注:异常类也能直接用BaseException或者它的子类即可

在这里插入图片描述

package com.wawu.common.exception;

public class LoginException extends BaseException{
    public LoginException() {
    }

    public LoginException(String msg) {
        super(msg);
    }
}

BaseException子类

package com.wawu.common.constant;

public class MessageConstant {
    public static final String LOGIN_EMAIL_NOT_REGISTER ="该邮箱还没注册,请前往注册";
    public static final String LOGIN_PWD_NOT_ERROR="密码错误";
    public static final String LOGIN_EMAIL_HAD_REGISTER="该邮箱已被注册";
    public static final String LOGIN_NICKNAME_HAD_REGISTER="该昵称已被注册";


    public static final String GOODS_DETAILS_STOCKNUM_LACK="当前规格的商品库存不足";
    public static final String ORDER_NOT_EXIST ="订单不存在";
    public static final String ORDER_COUNT_NOT_REPEAT_PURCHASE="订单不能重复购买";
}

本项目封装

只需会用,无需看懂所有代码

数据库开发小技巧

本处已经封装好了,具体代码请看对应的工具类

主要就是持久层的代码,这里不让用mybatis,只能自己封装了

设计思想:sql语句的生成与sql语句的执行分离

查询操作

对应工具类:SelectSQLBuilder

主要方法:

其他大概看看,那部分还没有测试过,后续可能悔改

  • 构造函数
  • 动态条件中的普通条件
  • 排序
  • 获取sql和参数

这里就是借助chatgpt生成的

SelectSQLBuilder 使用文档

SelectSQLBuilder 是一个用于构建 SQL 查询语句的工具类,支持动态条件构建、排序、分组和分页等功能。


1. 初始化
SelectSQLBuilder builder = new SelectSQLBuilder("tableName");

传入表名 tableName,初始化查询。


2. 动态条件
添加普通条件
builder.addDynamicCondition("fieldName", "operator", value);
  • fieldName:字段名。
  • operator:运算符(=, LIKE, >, < 等)。
  • value:条件值(null 值会被忽略)。

示例:

builder.addDynamicCondition("email", "=", "test@example.com");
builder.addDynamicCondition("age", ">", 18);

添加 IN 条件
builder.addInCondition("fieldName", values);
  • fieldName:字段名。
  • values:值的列表(List<?> 类型)。

示例:

builder.addInCondition("status", List.of("active", "pending", "blocked"));

添加 BETWEEN 条件
builder.addBetweenCondition("fieldName", start, end);
  • fieldName:字段名。
  • start:起始值。
  • end:结束值。

示例:

builder.addBetweenCondition("created_at", "2023-01-01", "2023-12-31");

3. 查询字段
builder.selectFields("field1", "field2", "field3");
  • 替换默认的 SELECT *

示例:

builder.selectFields("id", "name", "email");

4. 分组
builder.addGroupBy("field1", "field2");
  • 添加 GROUP BY 条件。

示例:

builder.addGroupBy("category", "status");

5. 排序
builder.addOrderBy("fieldName", "ASC/DESC");
  • fieldName:字段名。
  • ASC/DESC:排序方向。

示例:

builder.addOrderBy("created_at", "DESC");

6. 分页
builder.addLimit(limit, offset);
  • limit:每页的记录数。
  • offset:偏移量。

示例:

builder.addLimit(10, 0);

7. 获取 SQL 和参数
String sql = builder.getSQL();    // 获取生成的 SQL 语句
Object[] params = builder.getParams(); // 获取对应的参数数组

示例:

String sql = builder.getSQL();
Object[] params = builder.getParams();

System.out.println("SQL: " + sql);
System.out.println("Params: " + Arrays.toString(params));

完整示例

SelectSQLBuilder builder = new SelectSQLBuilder("users");

// 添加动态条件
builder.addDynamicCondition("email", "=", "test@example.com")
       .addInCondition("status", List.of("active", "pending"))
       .addBetweenCondition("created_at", "2023-01-01", "2023-12-31");

// 查询指定字段
builder.selectFields("id", "name", "email");

// 分组、排序和分页
builder.addGroupBy("status")
       .addOrderBy("created_at", "DESC")
       .addLimit(10, 0);

// 获取 SQL 和参数
String sql = builder.getSQL();
Object[] params = builder.getParams();

System.out.println("Generated SQL: " + sql);
System.out.println("Parameters: " + Arrays.toString(params));

输出示例:

Generated SQL: SELECT id, name, email FROM users WHERE email = ? AND status IN (?, ?) AND created_at BETWEEN ? AND ? GROUP BY status ORDER BY created_at DESC LIMIT 10 OFFSET 0
Parameters: [test@example.com, active, pending, 2023-01-01, 2023-12-31]
基于动态条件加强复用

例子:

package com.wawu.server.dao;

import com.wawu.common.annotation.IOC.component.Repository;
import com.wawu.common.utils.SQLBuilder.SelectSQLBuilder;
import com.wawu.common.utils.SQLExcutorUtil;
import com.wawu.pojo.entity.Good;

import java.sql.SQLException;
import java.util.List;

@Repository
public class GoodsDAO {
    /**
     * 动态条件查询商品列表
     * @param goodQuery
     * @return
     * @throws SQLException
     */
    public List<Good> getGoods(Good goodQuery) throws SQLException {
        SelectSQLBuilder selectSqlBuilder =new SelectSQLBuilder("goods")
                .addDynamicCondition("typeId","=", goodQuery.getTypeId())
                .addDynamicCondition("id","=",goodQuery.getId())
                .addOrderBy("createtime","DESC");
        return SQLExcutorUtil.queryList(selectSqlBuilder.getSQL(),Good.class, selectSqlBuilder.getParams());
    }
    /**
     * 根据类型动态获取商品基础信息(动态sql)(后续可以作废了,用类封装版)
     * @param typeId
     * @return
     * @throws SQLException
     */
    public List<Good> getGoodsByType(Long typeId) throws SQLException {
        SelectSQLBuilder selectSqlBuilder =new SelectSQLBuilder("goods")
                .addDynamicCondition("typeId","=", typeId)
                .addOrderBy("createtime","DESC");
//        System.out.println(sqlBuilder.getSQL());
        return SQLExcutorUtil.queryList(selectSqlBuilder.getSQL(),Good.class, selectSqlBuilder.getParams());
    }

    //获取商品资料
    public List<Good> getGoodsById(Long id) throws SQLException {
        SelectSQLBuilder sqlBuilder=new SelectSQLBuilder("goods")
                .addDynamicCondition("id","=", id)
                .addOrderBy("createtime","DESC");
        return SQLExcutorUtil.queryList(sqlBuilder.getSQL(),Good.class,sqlBuilder.getParams());
    }


    //搜索商品
    public List<Good> searchGoods(String keyword) throws SQLException {
        SelectSQLBuilder sqlBuilder=new SelectSQLBuilder("goods")
                .addDynamicCondition("name","LIKE", keyword)
                .addOrderBy("createtime","DESC");
        return SQLExcutorUtil.queryList(sqlBuilder.getSQL(),Good.class,sqlBuilder.getParams());
    }

}

此处像很多方法都能够整合到getGoods,不要写那么多方法,到时候把goodQuery不要的字段设置为空值或者不设置值就行

更新操作

对应的工具类:public class UpdateSQLBuilder extends BaseSQLBuilder

跟上面是同理的动态更新

UpdateSQLBuilder 使用文档

UpdateSQLBuilder 是一个用于构建动态 SQL 更新语句的工具类,支持添加动态更新字段、批量字段更新以及条件约束。


1. 初始化
UpdateSQLBuilder builder = new UpdateSQLBuilder("tableName");
  • 传入表名 tableName,初始化更新构造器。

2. 添加更新字段
单个字段
builder.setField("fieldName", value);
  • fieldName:字段名。
  • value:更新值(null 值会被忽略)。

示例:

builder.setField("name", "John Doe");
builder.setField("age", 25);

多个字段
builder.setFields(Map<String, Object> fields);
  • fieldsMap<String, Object> 类型,键为字段名,值为更新值。

示例:

builder.setFields(Map.of(
    "name", "John Doe",
    "age", 25,
    "email", "john.doe@example.com"
));

3. 添加动态条件

动态条件用于构建 WHERE 子句,支持动态添加。

builder.addDynamicCondition("fieldName", "operator", value);
  • fieldName:字段名。
  • operator:操作符(=, LIKE, >, < 等)。
  • value:条件值(null 值会被忽略)。

示例:

builder.addDynamicCondition("id", "=", 1);
builder.addDynamicCondition("status", "=", "active");

4. 获取 SQL 和参数
获取 SQL
String sql = builder.getSQL();
  • 获取完整的更新语句。
获取参数
Object[] params = builder.getParams();
  • 获取与 SQL 对应的参数数组。

完整示例

UpdateSQLBuilder builder = new UpdateSQLBuilder("users");

// 设置更新字段
builder.setField("name", "Jane Doe")
       .setField("email", "jane.doe@example.com")
       .setFields(Map.of(
           "age", 30,
           "status", "active"
       ));

// 添加条件
builder.addDynamicCondition("id", "=", 123)
       .addDynamicCondition("is_deleted", "=", false);

// 获取 SQL 和参数
String sql = builder.getSQL();
Object[] params = builder.getParams();

System.out.println("Generated SQL: " + sql);
System.out.println("Parameters: " + Arrays.toString(params));

输出示例

Generated SQL: UPDATE users SET name = ?, email = ?, age = ?, status = ? WHERE id = ? AND is_deleted = ?
Parameters: [Jane Doe, jane.doe@example.com, 30, active, 123, false]

例子:

package com.wawu.server.dao;

import com.wawu.common.annotation.IOC.component.Repository;
import com.wawu.common.exception.BaseException;
import com.wawu.common.utils.SQLBuilder.SelectSQLBuilder;
import com.wawu.common.utils.SQLBuilder.UpdateSQLBuilder;
import com.wawu.common.utils.SQLExcutorUtil;
import com.wawu.pojo.entity.GoodDetail;

import java.sql.SQLException;
import java.util.List;

@Repository
public class GoodsDetailsDAO {

    /**
     * 根据id更新商品详情(目前只设置个库存)
     * @param goodDetail
     */
    public void update(GoodDetail goodDetail){
        //先限制整一个异常,后续在搞吧,没啥时间了
        if(goodDetail.getId()==null){
            throw new BaseException("商品详情id为空,无法继续");
        }
        UpdateSQLBuilder updateSQLBuilder=new UpdateSQLBuilder("goodsdetails")
                .setField("stockNum",goodDetail.getStockNum())
                .addDynamicCondition("id","=",goodDetail.getId());//TODO: 待优化:这里不应该整成动态条件的

        //这里异常其实可以先不加的
        try {
            // 调用 SQLExcutorUtil 的 update 方法执行更新
            int rowsAffected = SQLExcutorUtil.update(updateSQLBuilder.getSQL(), updateSQLBuilder.getParams());
            if (rowsAffected == 0) {
                throw new BaseException("更新失败,未找到对应的记录");
            }
        } catch (SQLException e) {
            throw new BaseException("数据库更新操作失败"+e);
        }

    } 
}
  • 此处也是动态更新,当为空值时不更新
sql语句执行

对应类SQLExcutorUtil:负责数据库的执行操作,以及封装了数据库的连接池

只看主要方法,其他方法没有测试,特别是事务的,那个还没想好

主要方法:

  • 单个对象查询
  • 多个对象查询
  • 查询标量值(就是像基础类型那样的)
  • 更新操作(这里名字后续改:不仅仅是更新)
  • 插入并获取生成的主键

SQLExcutorUtil 使用文档

SQLExcutorUtil 是一个简化数据库操作的工具类,支持通用的查询、更新、插入、批量更新和事务操作。调用者只需提供 SQL 语句和参数,无需关心底层数据库连接与资源管理。


1. 单个对象查询

<T> T SQLExcutorUtil.querySingle(String sql, Class<T> resultType, Object... params)
  • 参数:
    • sql:SQL 查询语句。
    • resultType:结果对象的类型。
    • params:SQL 参数。
  • 返回值: 查询的单个结果,类型为 T
  • 示例:
User user = SQLExcutorUtil.querySingle("SELECT * FROM users WHERE id = ?", User.class, 1);

2. 多个对象查询

<T> List<T> SQLExcutorUtil.queryList(String sql, Class<T> resultType, Object... params)
  • 参数:
    • sql:SQL 查询语句。
    • resultType:结果对象的类型。
    • params:SQL 参数。
  • 返回值: 查询结果的 List<T>
  • 示例:
List<User> users = SQLExcutorUtil.queryList("SELECT * FROM users WHERE age > ?", User.class, 18);

3. 查询标量值

<T> T SQLExcutorUtil.queryScalar(String sql, Class<T> resultType, Object... params)
  • 参数:
    • sql:SQL 查询语句。
    • resultType:结果值的类型。
    • params:SQL 参数。
  • 返回值: 单个标量值,类型为 T
  • 示例:
long userCount = SQLExcutorUtil.queryScalar("SELECT COUNT(*) FROM users", Long.class);

4. 更新操作

int SQLExcutorUtil.update(String sql, Object... params)
  • 参数:
    • sql:更新语句(INSERTUPDATEDELETE)。
    • params:SQL 参数。
  • 返回值: 影响的行数。
  • 示例:
int rowsUpdated = SQLExcutorUtil.update("UPDATE users SET name = ? WHERE id = ?", "John Doe", 1);

5. 插入并获取生成的主键

long SQLExcutorUtil.updateAndGetGeneratedKey(String sql, Object... params)
  • 参数:
    • sql:插入语句。
    • params:SQL 参数。
  • 返回值: 生成的主键(long 类型)。
  • 示例:
long generatedId = SQLExcutorUtil.updateAndGetGeneratedKey("INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 22);

6. 批量更新

int[] SQLExcutorUtil.batchUpdate(String sql, Object[][] params)
  • 参数:
    • sql:更新语句。
    • params:二维数组,每行代表一组参数。
  • 返回值: 每个批量操作影响的行数。
  • 示例:
int[] results = SQLExcutorUtil.batchUpdate(
    "INSERT INTO users (name, age) VALUES (?, ?)", 
    new Object[][] {
        {"Alice", 22}, 
        {"Bob", 30}
    }
);

7. 事务操作

void SQLExcutorUtil.transaction(Runnable... operations)
  • 参数:
    • operations:需要执行的多个操作,使用 Runnable 实现。
  • 行为:
    • 开启事务,依次执行所有操作,成功后提交事务。
    • 如果任一操作抛出异常,则回滚事务。
  • 示例:
SQLExcutorUtil.transaction(
    () -> SQLExcutorUtil.update("UPDATE accounts SET balance = balance - ? WHERE id = ?", 100, 1),
    () -> SQLExcutorUtil.update("UPDATE accounts SET balance = balance + ? WHERE id = ?", 100, 2)
);

完整示例

// 查询单个用户
User user = SQLExcutorUtil.querySingle("SELECT * FROM users WHERE id = ?", User.class, 1);

// 查询多个用户
List<User> users = SQLExcutorUtil.queryList("SELECT * FROM users WHERE age > ?", User.class, 18);

// 获取用户总数
long userCount = SQLExcutorUtil.queryScalar("SELECT COUNT(*) FROM users", Long.class);

// 更新用户信息
int rowsUpdated = SQLExcutorUtil.update("UPDATE users SET name = ? WHERE id = ?", "John Doe", 1);

// 插入用户并获取主键
long generatedId = SQLExcutorUtil.updateAndGetGeneratedKey(
    "INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 22
);

// 批量插入用户
int[] batchResults = SQLExcutorUtil.batchUpdate(
    "INSERT INTO users (name, age) VALUES (?, ?)", 
    new Object[][] {
        {"Alice", 22}, 
        {"Bob", 30}
    }
);

// 使用事务更新账户余额
SQLExcutorUtil.transaction(
    () -> SQLExcutorUtil.update("UPDATE accounts SET balance = balance - ? WHERE id = ?", 100, 1),
    () -> SQLExcutorUtil.update("UPDATE accounts SET balance = balance + ? WHERE id = ?", 100, 2)
);

JWT令牌

你只要知道就是解析token获取部分字段的工具就行

对应代码JWTUtil:主要跟登录校验相关

用法例子:

挑着token

package com.wawu.server.service;

import com.wawu.common.annotation.IOC.Autowired;
import com.wawu.common.annotation.IOC.component.Service;
import com.wawu.common.annotation.controller.parameter.RequestBody;
import com.wawu.common.constant.JwtClaimsConstant;
import com.wawu.common.constant.MessageConstant;
import com.wawu.common.exception.LoginException;
import com.wawu.common.property.JwtProperties;
import com.wawu.common.utils.JwtUtil;
import com.wawu.pojo.dto.LoginDTO;
import com.wawu.pojo.entity.User;
import com.wawu.pojo.vo.LoginVO;
import com.wawu.server.dao.UsersDAO;
import org.mindrot.jbcrypt.BCrypt;

import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserService {
    @Autowired
    private UsersDAO usersDAO;

    //涉及到各种密码加密的一些东西
    int saltRounds = 5; // 定义盐的复杂度
    String salt = BCrypt.gensalt(saltRounds);

    public LoginVO login(@RequestBody LoginDTO loginDTO) throws SQLException {
        User user = usersDAO.getUser(User.builder().email(loginDTO.getAccount()).build());
        //账号没有注册
        if(user==null){
            throw new LoginException(MessageConstant.LOGIN_EMAIL_NOT_REGISTER);
        }
        System.out.println(loginDTO);
        System.out.println(user);
        LoginVO loginVO=new LoginVO();
        //校验密码
        if(BCrypt.checkpw(loginDTO.getPwd(),user.getPwd())){
            loginVO.setName(user.getNickname());
                //JWT令牌存储内容:用户id
            Map<String,Object> claims=new HashMap<>();//存放对应的的角色信息
            claims.put(JwtClaimsConstant.USER_ID,user.getId());
            loginVO.setToken(JwtUtil.createJWT(JwtProperties.secretKey,JwtProperties.ttl,claims));
            System.out.println(JwtUtil.parseJWT(JwtProperties.secretKey,loginVO.getToken()));
        }else{
            throw new LoginException(MessageConstant.LOGIN_PWD_NOT_ERROR);
        }

        return loginVO;
    }

    /**
     * 注册用户
     * @param newUser
     * @return
     */
    public LoginVO signup(User newUser) throws SQLException {
        //1. 判断是否已经被注册
        User user = usersDAO.getUser(User.builder()
                .email(newUser.getEmail()).build());
        if(user!=null){
            throw new LoginException(MessageConstant.LOGIN_EMAIL_HAD_REGISTER);
        }
        user = usersDAO.getUser(User.builder()
                .nickname(newUser.getNickname()).build());
        if(user!=null){
            throw new LoginException(MessageConstant.LOGIN_NICKNAME_HAD_REGISTER);
        }

        //2. 插入数据
        newUser.setCreatetime(LocalDateTime.now());
        newUser.setUpdatetime(LocalDateTime.now());
        newUser.setPwd(BCrypt.hashpw(newUser.getPwd(),salt));
        newUser.setId(usersDAO.insert(newUser));
        //3. 前端需要的返回数据
        LoginVO loginVO=new LoginVO();
        loginVO.setName(newUser.getNickname());
            //JWT令牌存储内容:用户id
        Map<String,Object> claims=new HashMap<>();//存放对应的的角色信息
        claims.put(JwtClaimsConstant.USER_ID,newUser.getId());
        loginVO.setToken(JwtUtil.createJWT(JwtProperties.secretKey,JwtProperties.ttl,claims));
        System.out.println(JwtUtil.parseJWT(JwtProperties.secretKey,loginVO.getToken()));
        return loginVO;
    }
}

易错

JSON格式

这里一定要对应对了,不然前端会报错

具体看着:json的几种标准格式_json格式-优快云博客

重点区分对象和数组

例子:

在这里插入图片描述

与这个响应为例

{
  "code": 0,
  "data": {
    "rate": 32,
    "commentList": [
      {
        "id": "7",
        "user": {
          "nickname": "wawu",
          "headimg": "http://tvax4.sinaimg.cn/crop.0.0.480.480.180/768c39d5ly8fjje1d0teej20dc0dcq35.jpg"
        },
        "score": 60,
        "comment": "起毛呀",
        "time": "11-29 05:54",
        "specName": "Size M"
      },
      {
        "id": "2",
        "user": {
          "nickname": "User Two",
          "headimg": "http://example.com/user2.jpg"
        },
        "score": 4,
        "comment": "The t-shirt is very comfortable.",
        "time": "10-22 09:32",
        "specName": "Size M"
      }
    ]
  }
}

结构:

result{
	code;
	data{//对应的VO类
	
	}
}

对应VO对象封装:

package com.wawu.pojo.vo.GetGoodsCommentVO;

import lombok.Data;

import java.time.LocalDateTime;

@Data
public class CommentVO {
    private Long id;
    private UserVO user;
    private int score;
    private String comment;
    private LocalDateTime time;
    private String specName;
}



package com.wawu.pojo.vo.GetGoodsCommentVO;


import lombok.Data;

import java.util.List;


@Data
public class GoodCommentVO {
    private double rate;//均分=sum(评论评分)/总评论
    private List<CommentVO> commentList;
}



package com.wawu.pojo.vo.GetGoodsCommentVO;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserVO {
    private String nickname;
    private String headimg;//头像
}

协作开发

代码仓库协作

冲突处理

此处一定一定一定要特别谨慎,出现冲突,最好别自己处理,直接来找我

教程:IDEA解决gitee,git冲突(stash changes和unstash changes的使用,两个人同时写在一行)_git unstash changes-优快云博客

接口文档

使用apifox,具体看那里,这里只是简单提一下

运行:
在这里插入图片描述

千万别动示例,如果是用示例运行,千万别保存

具体仓库参考示例

文档:

一定要看看

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值