基于Spring Boot+vue2的平台工具迭代

后端

框架调用说明:

  1. 用户通过前端发送HTTP请求到Controller
  2. Controller接收请求,并将请求数据(Request)传递给Service层
  3. Service层处理业务逻辑,可能调用DAO层访问数据库,或者调用Client层与远程服务交互
  4. DAO层执行数据库操作,将结果返回给Service层
  5. Service层将处理结果(或来自远程服务的结果)返回给Controller
  6. Controller将结果封装成HTTP响应(Response)发送给客户端

1. 申请git权限

2. git项目中点击我的-Settings-SSH Keys添加公钥

3. 公钥生成步骤

ssh-keygen -o -t rsa -b 4096 -C "your email"

cd ~/.ssh/

cat id_rsa.pub 把公钥内容粘贴到SSH Keys

4. 创建本地分支git checkout -b branchname

git远程仓库创建远程分支 branchname

关联远程分支 与 本地分支

# 将本地newbranch分支与远端branch分支关联 git branch --set-upstream-to=origin/branch newbranch

如git branch --set-upstream-to=origin/yutu yutu
git push -u 

删除远程分支  git push origin --delete name 

删除本地分支  git push origin --delete name

5. git修改提交的作者 mac如何修改git本地提交代码的用户名和邮箱

# 查看全局配置列表,按 q 退出
git config --global --list 
# 查看当前本地全局配置的用户名
git config --global user.name
# 查看当前本地全局配置的邮箱
git config --global user.email
# 本地项目仓库配置
# 修改当前本地全局配置的用户名
git config --global user.name yutu
# 修改当前本地全局配置的邮箱
git config --global user.email yutu@qq.com


6. 要公司的settings.xml  每个公司的配置都不一样

检查文件内容

Default: ${user.home}/.m2/repository 为自己的repository 不需要修改

在idea-Settings 搜索Maven 修改User settings file为最新的settings.xml文件

确认后 加载Maven

7. 启动Spring Boot项目

/Users/qa/Desktop/2024/codenew/xx/src/main/java/com/xx/xx/xxApplication.java

控制台看到端口8090启动成功


8. 在公司配置系统查看/配置项目名称/端口

/Users/qa/Desktop/2024/codenew/xx/src/main/resources/application.yaml

为配置文件

查看 urlpath

/Users/qa/Desktop/2024/codenew/toolkit/src/main/java/com/xx/xx/controller/TrackController.java

接口名=projectname(servlet:context-path)+url commonname+urlpath

9. 在浏览器访问http://127.0.0.1:8090/projectname/urlpath?pageNum=1&pageSize=10

接口正常返回

10. 代码设计流程

step1 定义controller 为QA自己设计的接口:定义请求域名、接口路径,调用自己的接口 传参调用/model/request/的request.java

step2 定义service 为QA自己设计的接口:定义请求接口请求参数和返回,调用自己的接口 返回的数据data有数据不为null调用invokeSilent,返回的数据data无数据为null调用metaResponse

step3 定义client 为要调用RD的接口:定义域名、接口请求路径、传参、返回

step4 运行Application 在控制台Run看到如下图形。意味着Spring Boot应用已经成功运行,并且正在监听8090端口以接受HTTP请求

step5 在浏览器访问 http://127.0.0.1:8090/xx/v1/user/token/invalid?userId=xx&oauthType=all可以看到接口正常返回

11. 重命名方法名 被引用的地方一并修改

右击方法名-Refactor-Rename

右击方法名-Refactor-Rename 修改后回车 select all - ok

12. 编码规范

Controller层:调SpringBoot里的annotation

import org.springframework.web.bind.annotation.*;

    // 1强制登出
    @GetMapping(Apis.API_USERFORCELOGOUT)
    public MetaResponse userForceLogout(UserForceLoginPageRequest userForceLoginPageRequest) {
        // 如果不需要对返回的字段判断给前端 则直接return MetaResponse.success();
        return MetaResponse.success();
    }

    // 2账号关联
    @GetMapping(Apis.API_USERACCOUNTBH)
    public MetaResponse userAccountBindHistory(UserAccountBindHistoryRequest userAccountBindHistoryRequest) {
        // 如果需要对返回的字段判断给前端 则需要调用service
        return userManageService.accountBindHistory(userAccountBindHistoryRequest);
    }

    // 3用户中心-查询手机号 get拼接post的部分要@RequestParam("opId") Long opId
    // opId必传 其他参数非必传
    @PostMapping(Apis.API_USERPHONEQUERY)
    public MetaResponse<UserCenterResp> userPhoneQuery(@RequestParam("opId") Long opId,
                                                       @RequestParam(required = false) Long id,
                                                       @Valid @RequestBody UserPhoneQueryRequest userPhoneQueryRequest) {
        return userManageService.userPhoneQuery(opId, id, userPhoneQueryRequest);
    }

Service层:传参返参校验

    // 5用户管理-账号封禁-列表 get
    public MetaResponse userBlockStatus(UserBlockStatusRequest userBlockStatusRequest) {
        Util.check(NumberUtil.isPositive(userBlockStatusRequest.getUserId()), "userId不能为空");
        log.info("用户id是{}", userBlockStatusRequest.getUserId());
        try {
            MetaResponse<JSONObject> metaResponse = userManageClient.getUserBlockStatus(userBlockStatusRequest.getUserId()).execute().body();
//            System.out.println("账号封禁-列表=" + metaResponse);
            return metaResponse;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 6账号封禁-更新核对结果 post  无get传参单独的post传参 需要throws IOException
    public void userBlockSet(UserBlockSetRequest userBlockSetRequest) throws IOException {
        Util.check(StringUtils.isNotBlank(userBlockSetRequest.getCauseRemarks()), "录入人工核对结果-判定结果不能为空");
        Util.check(NumberUtil.isPositive(userBlockSetRequest.getManualDecisionResult()), "录入人工核对结果-原因说明不能为空");
        log.info("getCauseRemarks是{}", userBlockSetRequest.getCauseRemarks());
        log.info("getManualDecisionResult是{}", userBlockSetRequest.getManualDecisionResult());
//        String metaResponse = RetrofitInvokeUtil.invokeSilent(() -> userManageClient.getUserBlockSet(userBlockSetRequest));
//        log.error("metaResponse是{}", metaResponse);
        JSONObject metaResponse = userManageClient.getUserBlockSet(userBlockSetRequest).execute().body();

        System.out.println("账号封禁-更新核对结果-接口metaResponse==" + metaResponse);
        // 接口返回字段校验
        int errCode = metaResponse.getInteger("errCode");
        String data = metaResponse.getString("data");

        if (metaResponse == null || errCode != 0 || !"OK".equals(data)) {
            log.error("账号封禁-更新核对结果-接口返回为空:{}", metaResponse);
            throw new BizException(ErrorCode.ERROR_PARAM, "接口返回错误,请重试");
        }
    }
}

Client层:调用retrofit2的call

import retrofit2.Call;
import retrofit2.http.*;


@RetrofitService("api-online")
public interface UserManageClient {
    //    token为Apoll配置中开发写死的值 4个接口一共3个token 登录为用户自己的token 其他token传参为服务间的传参
    // 1用户管理-强制登出
    @GET("/login/v1/user/token/invalid")
    @Headers(value = {"token:xx", "Content-Type: application/json"})
    Call<MetaResponse<JSONObject>> getDevUserforcelogoutList(@Query("userId") Long userId, @Query("oauthType") String oauthType);

    // 2用户管理-账号关联
    //    token为Apoll配置中开发写死的值 4个接口一共3个token 登录为用户自己的token 其他token传参为服务间的传参
    @GET("/login/v1/internal/account/xx")
    @Headers(value = {"token:xx"})
    Call<MetaResponse<JSONObject>> getDevUserAccountBindHistoryList(@Query("opId") Long xx, @Query("xx") Long phoneNumber, @Query("userId") Long userId);

    // 3用户管理-用户中心-手机号查询
    //    token为Apoll配置中开发写死的值 4个接口一共3个token 登录为用户自己的token 其他token传参为服务间的传参
    @POST("/user_center/v1/db/user")
    Call<MetaResponse<JSONObject>> getUserCenterPhoneCheck(@Query("opId") Long opId, @Body UserPhoneQueryRequest userPhoneQueryRequest);

    // 4用户管理-用户中心-更新手机号
    @PUT("/user_center/v1/user/{userid}")
    Call<MetaResponse<JSONObject>> getUserCenterPhoneUpdate(@Path("userid") Long userid,@Query("opId") Long opId, @Body UserPhoneUpdateRequest userPhoneUpdateRequest);

13. 如遇 Web server failed to start. Port 8090 was already in use.

Action:
Identify and stop the process that's listening on port 8090 or configure this application to listen on another port

lsof -i:8090 查找端口占用进程号

sudo kill -9 2848 杀掉进程 重启spring boot

15. 编码规范之方法调用

RetrofitInvokeUtil.invokeSilent(() 里面封装了try catch 不需要在调用的时候捕获异常

MetaResponse<JSONObject> metaResponse 时要加try catch

  public JSONObject accountBindHistory(UserAccountBindHistoryRequest userAccountBindHistoryRequest) {
        Util.check(NumberUtil.isPositive(userAccountBindHistoryRequest.getOpId()), "opId不能为空");
        log.info("当前opId是{},用户id是{}", userAccountBindHistoryRequest.getOpId(), userAccountBindHistoryRequest.getUserId());

//        返回的数据data有数据不为null调用invokeSilent 无数据不可调用该方法
//        JSONObject jsOne = RetrofitInvokeUtil.invokeSilent(() -> userForceLogoutClient.getDevuserforcelogoutList(userAccountBindHistoryRequest.getUserId(),userAccountBindHistoryRequest.getOauthType()));
//        System.out.println("jsOne="+metaResponse);

//        返回的数据data无数据为null调用metaResponse 无数据调用该方法
        try {
//            MetaResponse<JSONObject> metaResponse = userManageClient.getDevUserAccountBindHistoryList(userAccountBindHistoryRequest.getOpId(), userAccountBindHistoryRequest.getPhoneNumber(), userAccountBindHistoryRequest.getUserId()).execute().body();
            JSONObject metaResponse = RetrofitInvokeUtil.invokeSilent(() -> userManageClient.getDevUserAccountBindHistoryList(userAccountBindHistoryRequest.getOpId(), userAccountBindHistoryRequest.getPhoneNumber(), userAccountBindHistoryRequest.getUserId()));
//            System.out.println("账号关联=" + metaResponse);

            JSONArray rcords = metaResponse.getJSONArray("rcords");
//            for(){
            JSONArray records = metaResponse.getJSONArray("records");
//            JSONArray jsonArray = new JSONArray();
//            for (int i = 0; i < records.size(); i++) {
//                UserAccountBindHistoryResp userAccountBindHistoryResp1 = new UserAccountBindHistoryResp();
//                BeanUtils.copyProperties(thirdPartyOrder, userAccountBindHistoryResp1);
//                userAccountBindHistoryResp.add(userAccountBindHistoryResp1);
//                BeanUtils.copyProperties(records.get(i),userAccountBindHistoryResp1);
//                jsonArray.add(userAccountBindHistoryResp1);
//            }

            return rcords;
            System.out.println("用户管理-账号管理=" + metaResponse);
            System.out.println("用户管理-账号管理records=" + records);
//            JSONObject jsonObject = new JSONObject();
//            jsonObject.put("records", records);

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("records", records);


            return jsonObject;

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

16. 编码规范之注释

1> 单行代码注释不要用//

2> 方法注释不要用

/**

*

* @param userId

*/

统一要用注解

import io.swagger.annotations.ApiOperation;

@ApiOperation(value = "用户管理-用户信息")

16. 编码规范之方法传参get post put

协议://主机名[:端口号]/路径[?查询参数]

1> get传参为标准的key value格式 接口名?userid=xx

    @CheckToken
    @ApiOperation(value = "用户管理-用户信息-基本信息查询")
    @GetMapping("/xx/xx")
    public MetaResponse<List<UserDto>> userInfoList(Long userId) {
        return new MetaResponse<>(userManageService.userInfoList(userId));
    }

2> put传参为接口名/参数+其他参数在body

get部分的参数要使用注解@PathVariable 定义,body体的参数使用注解@RequestBody定义 

    @CheckToken
    @ApiOperation(value = "用户管理-用户信息-换绑手机号")
    @PutMapping("/xx/xx/{userId}")
    public MetaResponse userInfoChange(@PathVariable("userId") Long userId, @RequestBody UserUpdateReq req) {
        userManageService.userInfoChange(userId, req);
        return MetaResponse.success();
    }

3> post传参为接口名+所有参数在body

    @CheckToken
    @ApiOperation(value = "用户管理-账号封禁-更新判定结果")
    @PostMapping("/xx/xx")
    public MetaResponse userBlockSet(@RequestBody UserBlockSetRequest userBlockSetRequest) {
        userManageService.userBlockSet(userBlockSetRequest);
        return MetaResponse.success();
    }

4> get传参为接口名/所有参数在请求头

<=4个参数使用注解@RequestParam 可以设置默认值 是否必传@RequestParam(value = "version", required = false) String version

请求参数较多时 封装单独的request类 通过new request调用或者Request<requestClassName> reques调用

    @CheckToken
    @ApiOperation(value = "用户管理-账号封禁-封禁记录历史列表")
    @GetMapping("/block/list")
    public MetaResponse<List<UserBlockDto>> userBlockList
(@RequestParam("userId") Long userId,
                                                          
@RequestParam(value = "current", defaultValue = "1") Integer current,
                                                          
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) 
{
        return new MetaResponse<>(userManageService.userBlockList(userId, current, pageSize));
    }

17. 编码规范之返参Dto

返回的userid有问题

需要对返回的数组单独封装类

格式data.log.userid

"data": {

    "logs": [

       {

"userId": 40692902,

"manualDecisionResult": 1

}

返参定义在Dto

@Data
public class UserBlockDto {

    private Long userId;
    private Long userBlockLogId;
    private Long ruleId;
    private String ruleName;
    private String ruleDetailInfo;
    private Long ruleCalcFinishTime;
    private Long status;
    private String statusDesc;

返参数组定义为list 

@Data
public class UserBlockLogsDto {

    private List<UserBlockDto> logs;

}
    public List<UserBlockDto> userBlockList(Long userId, Integer current, Integer pageSize) {
        Util.check(NumberUtil.isPositive(userId), "用户Id不能为空");
        UserBlockLogsDto respDto = RetrofitInvokeUtil.invokeSilent(() -> userManageClient.getUserBlockList(userId, current, pageSize));
        if (Objects.isNull(respDto)) {
            throw new BizException(ErrorCode.ERROR_THIRD_SERVER);
        }

        List<UserBlockDto> respList = respDto.getLogs();
        respList.sort(Comparator.comparing(UserBlockDto::getCTime).reversed());
        respList.forEach(UserBlockDto::fromUserBlockDto);

        return respList;
    }

18.  编码规范之前端联调

给前端返回的字段不要封装为JSONObject 否则userid的值会返回科学记数法

改为MetaResponse 单独封装Dto

@ApiOperation(value = "用户管理-用户信息-换绑手机号")

@PUT("/xx/xx/xx/{userId}")

Call<MetaResponse<UserDto>> userInfoChange(@Path("userId") Long userId, @Body UserUpdateReq userUpdateReq);

19. 数据库配置连接

在系统配置文件新增数据库配置

20. 查询4个数据表

-- 学生表新:根据学生账号username查询id aa

SELECT id FROM student where user_name="xx";

-- 查询学生在的班级 aa 班级和学生对应关系表

SELECT class_id FROM class_student where student_id in (SELECT id FROM student where user_name="username");

-- 查询学生在的班级 bb 班级表 cc

select id from class WHERE id =(SELECT class_id FROM class_student where student_id in (SELECT id FROM student where user_name="username"));

-- 查询关联的老师userid cc 课程表

SELECT user_id FROM class WHERE id =(SELECT class_id FROM class_student where student_id in (SELECT id FROM student where user_name="username"));

SELECT * FROM class WHERE id =(SELECT class_id FROM class_student where student_id in (SELECT id FROM student where user_name="username"));

-- 查询学生username关联的老师手机号等信息给前端展示

SELECT * FROM user where id ="cc"

@Service
@Slf4j
public class QaDevService {

    @Resource
    private QaDevStudentMapper QaDevStudentMapper;

    @Resource
    private QaDevClassStudentMapper QaDevClassStudentMapper;

    @Resource
    private QaDevClassMapper QaDevClassMapper;

    @Resource
    private QaDevTeacherMapper QaDevTeacherMapper;


    @ApiOperation(value = "学生表student:根据学生username查询学生id")
    public Long selectStudentId(String userName) {

        Util.check(StringUtils.isNotBlank(userName), "参数有误");

        // 学生表新:根据学生账号fsz96b1d查询id 200006234
        Example example = new Example(QaDevStudent.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userName", userName);
        QaDevStudent QaDevStudent = QaDevStudentMapper.selectOneByExample(example);

        QaDevStudentResp QaDevStudentResp = new QaDevStudentResp();
//        BeanUtils.copyProperties(QaDevStudent, QaDevStudentIdResp);
        QaDevStudentResp.setStudentId(QaDevStudent.getId());

        return QaDevStudentResp.getStudentId();

    }

    @ApiOperation(value = "班级和学生对应关系表class_student:根据学生id查询id student_id class_id")
    public Long selectClassStudentId(String userName) {
        Long studentId = selectStudentId(userName);
//        System.err.println("studentId==" + studentId);
        Util.check(NumberUtil.isPositive(studentId), "学生Id不能为空");

        // 班级和学生对应关系:查询学生在的班级 41663
        Example example = new Example(QaDevClassStudent.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("studentId", studentId);
        QaDevClassStudent QaDevClassStudent = QaDevClassStudentMapper.selectOneByExample(example);
//        System.err.println("sql==" + QaDevClassStudentMapper.selectOneByExample(example));

        QaDevClassStudentResp QaDevClassStudentResp = new QaDevClassStudentResp();
        QaDevClassStudentResp.setClassId(QaDevClassStudent.getClassId());

        return QaDevClassStudentResp.getClassId();
    }

    @ApiOperation(value = "班级和学生对应关系表class:根据class_id查询老师user_id")
    public Long selectClassId(String userName) {

        Util.check(StringUtils.isNotBlank(userName), "参数有误");

        Long classId = selectClassStudentId(userName);
//        System.err.println("classId==" + classId);
        Util.check(NumberUtil.isPositive(classId), "班级Id不能为空");

        Example example = new Example(QaDevClass.class);
        Example.Criteria criteria = example.createCriteria();
        // class_student数据表查询出来的class_id赋值到class表的id property的字段为数据库字段 一定不能错
        criteria.andEqualTo("id", classId);
        QaDevClass QaDevClass = QaDevClassMapper.selectOneByExample(example);
//        System.err.println("sql==" + QaDevClassMapper.selectOneByExample(example));

        QaDevClassResp QaDevClassResp = new QaDevClassResp();
        QaDevClassResp.setUserId(QaDevClass.getUserId());

        return QaDevClassResp.getUserId();

    }


    @ApiOperation(value = "老师表:根据老师user_id查询老师手机号")
    public QaDevTeacherResp selectUserTeacherPhone(String userName) {

        Util.check(StringUtils.isNotBlank(userName), "参数有误");

        Long teacherId = selectClassId(userName);
//        System.err.println("classId==" + classId);
        Util.check(NumberUtil.isPositive(teacherId), "老师userId不能为空");

        Example example = new Example(QaDevTeacher.class);
        Example.Criteria criteria = example.createCriteria();
        // class课程表数据表查询出来的userid赋值到userid表的id property的字段为数据库字段 一定不能错
        criteria.andEqualTo("id", teacherId);
        QaDevTeacher QaDevTeacher = QaDevTeacherMapper.selectOneByExample(example);
//        System.err.println("sql==" + QaDevTeacherMapper.selectOneByExample(example));

        QaDevTeacherResp QaDevTeacherResp = new QaDevTeacherResp();
        QaDevTeacherResp.setId(QaDevTeacher.getId());
        QaDevTeacherResp.setUserPhone(QaDevTeacher.getUserPhone());
        QaDevTeacherResp.setUserName(QaDevTeacher.getUserName());
        QaDevTeacherResp.setUserPwdText(QaDevTeacher.getUserPwdText());

        return QaDevTeacherResp;

    }
}

效果图

21. 0812优化 如果定义的返回和查询的数据库的字段一致 不需要对接口response单独封装 调用

BeanUtils.copyProperties(sqlQueryParam, expectRespParam); 

copyProperties 方法支持把前者sqlQueryParam类的变量 拷贝到后者expectRespParam,sqlQueryParam为数据库字段(全部or部分数据库字段),expectRespParam为接口返回定义的字段。如sqlQueryParam定义了变量ABCDEFG,expectRespParam定义了ABC 那么调用copyProperties方法则把sqlQueryParam的ABC赋值到expectRespParam 接口返回ABC 取交集

// sqlQueryParam
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "user")
@ApiOperation(value = "老师表")

public class QaDevTeacher {
    @Id
    @GeneratedValue(generator = "JDBC")
    private Long id;

    @Column(name = "user_phone")
    private String userPhone;

    @Column(name = "username")
    private String userName;

    @Column(name = "user_pwd")
    private String userPwd;

    @Column(name = "user_pwd_text")
    private String userPwdText;

    @Column(name = "enable")
    private Integer enable;

}
// expectRespParam
@Data
public class QaDevTeacherResp {
    private Long id;
    private String userPhone;
    private String userName;
    private String userPwdText;

}
@Service
@Slf4j
public class QaDevService {

    @Resource
    private QaDevStudentMapper QaDevStudentMapper;

    @Resource
    private QaDevClassStudentMapper QaDevClassStudentMapper;

    @Resource
    private QaDevClassMapper QaDevClassMapper;

    @Resource
    private QaDevTeacherMapper QaDevTeacherMapper;

    /**
     * 学生表student:根据学生username查询学生id
     *
     * @param userName
     * @return
     */
    public Long selectStudentId(String userName) {

        Util.check(StringUtils.isNotBlank(userName), "参数有误");

        // 学生表新:根据学生账号fsz96b1d查询id 200006234
        Example example = new Example(QaDevStudent.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userName", userName);
        QaDevStudent QaDevStudent = QaDevStudentMapper.selectOneByExample(example);
//        System.err.println("QaDevStudent=" + QaDevStudent);

        if (Objects.isNull(QaDevStudent)) {
            throw new BizException(ErrorCode.ERROR_TESTUSERID_NULL, "学生账号不存在");
        }

        QaDevStudentResp QaDevStudentResp = new QaDevStudentResp();

        BeanUtils.copyProperties(QaDevStudent, QaDevStudentResp);
//        System.err.println("QaDevStudentResp=" + QaDevStudentResp);

        return QaDevStudentResp.getId();

    }

    /**
     * 班级和学生对应关系表class_student:根据学生id查询id student_id class_id
     *
     * @param userName
     * @return
     */
    public Long selectClassStudentId(String userName) {
        Long studentId = selectStudentId(userName);
//        System.err.println("studentId==" + studentId);
        Util.check(NumberUtil.isPositive(studentId), "学生Id不能为空");

        // 班级和学生对应关系:查询学生在的班级 41663
        Example example = new Example(QaDevClassStudent.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("studentId", studentId);
        QaDevClassStudent QaDevClassStudent = QaDevClassStudentMapper.selectOneByExample(example);
//        System.err.println("sql==" + QaDevClassStudentMapper.selectOneByExample(example));

        QaDevClassStudentResp QaDevClassStudentResp = new QaDevClassStudentResp();
        BeanUtils.copyProperties(QaDevClassStudent, QaDevClassStudentResp);
//        System.err.println("QaDevClassStudentResp=" + QaDevClassStudentResp);
        return QaDevClassStudentResp.getClassId();
    }

    /**
     * 班级和学生对应关系表class:根据class_id查询老师user_id
     *
     * @param userName
     * @return
     */
    public Long selectClassId(String userName) {

        Util.check(StringUtils.isNotBlank(userName), "参数有误");

        Long classId = selectClassStudentId(userName);
//        System.err.println("classId==" + classId);
        Util.check(NumberUtil.isPositive(classId), "班级Id不能为空");

        Example example = new Example(QaDevClass.class);
        Example.Criteria criteria = example.createCriteria();
        // class_student数据表查询出来的class_id赋值到class表的id property的字段为数据库字段 一定不能错
        criteria.andEqualTo("id", classId);
        QaDevClass QaDevClass = QaDevClassMapper.selectOneByExample(example);
//        System.err.println("sql==" + QaDevClassMapper.selectOneByExample(example));
        QaDevClassResp QaDevClassResp = new QaDevClassResp();
        BeanUtils.copyProperties(QaDevClass, QaDevClassResp);
//        System.err.println("QaDevClassResp=" + QaDevClassResp);
        return QaDevClassResp.getUserId();

    }

    /**
     * 老师表:根据老师user_id查询老师手机号
     *
     * @param userName
     * @return
     */
    public QaDevTeacherResp selectUserTeacherPhone(String userName) {

        Util.check(StringUtils.isNotBlank(userName), "参数有误");

        Long teacherId = selectClassId(userName);
        System.err.println("teacherId==" + teacherId);
        Util.check(NumberUtil.isPositive(teacherId), "老师userId不能为空");

        Example example = new Example(QaDevTeacher.class);
        Example.Criteria criteria = example.createCriteria();
        // class课程表数据表查询出来的userid赋值到userid表的id property的字段为数据库字段 一定不能错
        criteria.andEqualTo("id", teacherId);
        QaDevTeacher QaDevTeacher = QaDevTeacherMapper.selectOneByExample(example);
//        System.err.println("QaDevTeacher="+QaDevTeacher);
//        System.err.println("sql==" + QaDevTeacherMapper.selectOneByExample(example));
        if (Objects.isNull(QaDevTeacher)) {
            throw new BizException(ErrorCode.ERROR_TESTUSERID_NULL, "用户名不存在");
        }

        QaDevTeacherResp QaDevTeacherResp = new QaDevTeacherResp();
        BeanUtils.copyProperties(QaDevTeacher, QaDevTeacherResp);
//        System.err.println("QaDevTeacherResp="+QaDevTeacherResp);
        return QaDevTeacherResp;

    }
}

22. 0815 java服务8090端口被占用

qa@yueyutu:~$lsof -i:8090
COMMAND   PID USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
java    70507   qa  252u  IPv6 0xca7eeffd3e9b73ff      0t0  TCP *:8090 (LISTEN)

lsof -i:8090|awk {'print $2'} 

lsof -i:8090|awk {'print $2'}|xargs sudo kill -9

重启spring boot

23. 10月16

本地启动SpringBoot 请求本地接口报错

checkToken has exception. e:javax.net.ssl.SSLHandshakeException: 
sun.security.validator.ValidatorException: PKIX path building failed:
 sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target --> at 
sun.security.ssl.Alert.createSSLException(Alert.java:131) --> at 

解决办法:关闭代理

24. 【方案设计】账号与微信号解绑

功能模块

学生端

负责人

陆禄

使用场景

使用学生账号时需要绑定微信,切换新账号需要解绑微信。学生账号可以有N个,每次微信扫码绑定再解绑再扫码进班重新生成新的学生账号。久而久之,不知道是哪个学生账号绑定了微信。该功能要实现学生账号与微信解绑

现状步骤

  1. BtoC后台配置好课程信息,学生通过微信扫码领取课程

  2. 学生扫码会展示二维码,用此账号登录学生端

  3. 如果该微信之前绑定过学生账号并领取过课程,则需要登录账号解绑

  4. 解绑后,学生重新扫码领取 生成新的登录账号

期望

通过微信昵称/微信openid直接查询到账号,并解绑

方案描述

  1. 根据用户微信名称查询openid

  2. 根据用户openid查询绑定的学生账号

  3. 学生账号与微信解绑-微信昵称(考虑兼容脏数据,可能有多个重复的微信昵称)

  4. 学生账号与微信解绑-微信openid(openid数据库已有去重校验)

25. 解绑接口authorization的认证是Bearer token

service层封装登录接口

public class BtoCTokenService {

    @Resource
    private BtoCTokenClient btoCTokenClient;

    public String getBtoCToken(String studentName) {
        JSONObject reqBody = new JSONObject();
        reqBody.put("loginName", studentName);
        reqBody.put("loginCode", "xx");
        reqBody.put("loginType", 1);
        BtoCLoginResp resp = RetrofitInvokeUtil.invokeSilent(() -> btoCTokenClient.getBtoCToken(reqBody));
        return Optional.ofNullable(resp).map(BtoCLoginResp::getToken).orElse("");
    }

}

前端

前端Vue2学习资料

介绍 — Vue.js

1. 前端环境搭建:

设置npm源    

(base) qa@yueyutu: npm config set registry https://npm.xx.xx.com/  地址为公司私有源

安装依赖 依然报错

(base) qa@yueyutu: npm install

查看npm的用户名

(base) qa@yueyutu: npm whoami  

npm ERR! code ENEEDAUTH
npm ERR! need auth This command requires you to be logged in.
npm ERR! need auth You need to authorize this machine using `npm adduser`

npm ERR! A complete log of this run can be found in: /Users/qa/.npm/_logs/2024-07-18T09_57_25_137Z-debug-0.log

(base) qa@yueyutu: npm login
输入域账号 密码

再次查看npm的用户名

(base) qa@yueyutu: npm whoami  

显示域账号

2. 如遇npm run serve时报错

error:0308010C:digital envelope routines::unsupported

快速解决Error: error:0308010C:digital envelope routines::unsupported的三种解决方案-CSDN博客

在vscode输入

export NODE_OPTIONS=--openssl-legacy-provider  完美解决

3. git status

git reset HEAD . 撤销提交所有

git status

git checkout src/views/user/xx.vue 放弃提交某个文件

运维问题排查

1. 新增数据源测试集群无法创建数据库连接,本地连接正常

后端代码部署到toolkit线上环境报错【数据库无法连接】

rancher搜索toolkit

表现:

  1. 阿波罗配置数据库为外网Host:本地正常连接数据库,toolkit测试环境集群无法连接数据库

  2. 阿波罗配置数据库改为内网Host:本地无法连接数据库,toolkit测试环境集群正常连接数据库

解决办法:

  1. 阿波罗配置访问Host为外网Host

  2. 登录测试环境服务 pod(选择第二个pod,Execute Shell )

  3. curl cip.cc 获取 pod 外网IP

  4. 联系DBA将线上集群外网IP添加至阿里云访问白名单

原因:BtoC是新业务 服务不在toolkit

效果验证:本地代码正常连接数据库,测试环境正常连接数据库 接口正常

2. 工具平台:服务从阿里云迁到了腾讯云,数据库没迁移

解决办法:

外网IP加白名单,内网路由到运维的网段

数据库内网host解析到数据库外网IP

表现:

  1. 阿波罗配置数据库为外网Host:本地正常连接数据库,toolkit测试环境集群无法连接数据库

  2. 阿波罗配置数据库改为内网Host:本地无法连接数据库,toolkit测试环境集群正常连接数据库

效果验证:本地代码正常连接数据库,测试环境正常连接数据库 接口正常

报错日志

Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.

at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)

at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)

联系DBA将线上集群外网IP添加至腾讯云访问白名单 依然报错

Caused by: java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东方狱兔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值