后端
框架调用说明:
- 用户通过前端发送HTTP请求到Controller
- Controller接收请求,并将请求数据(Request)传递给Service层
- Service层处理业务逻辑,可能调用DAO层访问数据库,或者调用Client层与远程服务交互
- DAO层执行数据库操作,将结果返回给Service层
- Service层将处理结果(或来自远程服务的结果)返回给Controller
- 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个,每次微信扫码绑定再解绑再扫码进班重新生成新的学生账号。久而久之,不知道是哪个学生账号绑定了微信。该功能要实现学生账号与微信解绑 | ||
现状步骤 |
| ||
期望 | 通过微信昵称/微信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学习资料
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
表现:
-
阿波罗配置数据库为外网Host:本地正常连接数据库,toolkit测试环境集群无法连接数据库
-
阿波罗配置数据库改为内网Host:本地无法连接数据库,toolkit测试环境集群正常连接数据库
解决办法:
-
阿波罗配置访问Host为外网Host
-
登录测试环境服务 pod(选择第二个pod,Execute Shell )
-
curl cip.cc 获取 pod 外网IP
-
联系DBA将线上集群外网IP添加至阿里云访问白名单
原因:BtoC是新业务 服务不在toolkit
效果验证:本地代码正常连接数据库,测试环境正常连接数据库 接口正常
2. 工具平台:服务从阿里云迁到了腾讯云,数据库没迁移
解决办法:
外网IP加白名单,内网路由到运维的网段
数据库内网host解析到数据库外网IP
表现:
-
阿波罗配置数据库为外网Host:本地正常连接数据库,toolkit测试环境集群无法连接数据库
-
阿波罗配置数据库改为内网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.