User user=dao.findUserByCode(code);

本文介绍了一个基于Java的用户注册、激活及登录服务的具体实现细节。包括使用UUID作为用户ID,通过DAO层操作数据库完成用户的注册、激活状态更新及登录验证等功能。
package com.itheima.tfy.service.impl;


import java.util.UUID;


import com.itheima.tfy.dao.UserDao;
import com.itheima.tfy.dao.impl.UserDaoImpl;
import com.itheima.tfy.domain.User;


public class UserServiceImpl {
private UserDao dao=new UserDaoImpl();
//激活码由上一层传过来
public void regist(User user){
if(user.getCode()!=null &&user.getCode().equals("")){
throw new RuntimeException("激活码没有传过来");
}
user.setId(UUID.randomUUID().toString());
dao.addUser(user);

}
public void actived(String code){
User user=dao.findUserByCode(code);
if(user==null)
throw new RuntimeException("激活码有误");
user.setActived(true);
dao.update(user);
}
/**
* 登录
* @param username
* @param password
* @return 用户名或密码错误 或没有激活码都返回null
*/
public User login(String username,String password){
User user=dao.findUser(username, password);
//判断是否激活
if(user!=null){
if(!user.isActived()){
user=null;
}
}
return user;
}
}
@Slf4j @Service @Profile("mysql") public class AdminServiceImpl implements AdminService{ @Autowired private UserRepository userRepository; @Autowired private PasswordUtil passwordUtil; @Value("${app.max-users}") private long maxUserCount; @Override public OperationResponse<UserRegisterSuccessDTO> addUser(UserRegisterDTO userRegisterDTO) { if (!userRegisterDTO.getEmail().contains("@")) { return OperationResponse.failure(ErrorCode.INVALID_EMAIL); } if (userRegisterDTO.getPassword().length() < 6) { return OperationResponse.failure(ErrorCode.PASSWORD_TOO_SHORT); } // 检查是否达到最大用户数 long currentCount = userRepository.count(); if(currentCount >= maxUserCount) { log.error("Maximum user limit reached"); return OperationResponse.failure(ErrorCode.MAX_USER_LIMIT); } // 检查邮箱是否重复 if (userRepository.existsByEmail(userRegisterDTO.getEmail())) { log.error("Email already exists"); return OperationResponse.failure(ErrorCode.EMAIL_EXISTS); } // 创建用户 UserInfo user = new UserInfo(); user.setUsername(userRegisterDTO.getUsername()); // 密码加密处理 String encodedPwd = passwordUtil.encodePassword(userRegisterDTO.getPassword()); user.setPassword(encodedPwd); user.setEmail(userRegisterDTO.getEmail()); user.setAddress(userRegisterDTO.getAddress()); userRepository.save(user); return OperationResponse.success(new UserRegisterSuccessDTO("User added", user.getId())); } @Transactional @Override public OperationResponse<ResponseDTO> deleteUserByEmail(String email) { if (!userRepository.existsByEmail(email)) { log.error("User not existed"); return OperationResponse.failure(ErrorCode.USER_NOT_FOUND); } UserInfo user = userRepository.findByEmail(email).get(); userRepository.deleteByEmail(email); return OperationResponse.success(new ResponseDTO(user.getUsername(), user.getEmail(), user.getAddress())); } @Override public OperationResponse<ResponseDTO> updateUser(UserDTO userDTO) { Optional<UserInfo> userOpt = userRepository.findByEmail(userDTO.getEmail()); UserInfo user = userOpt.get(); if (userDTO.getUsername() != null && !userDTO.getUsername().trim().isEmpty()) { user.setUsername(userDTO.getUsername()); } if (userDTO.getPassword() != null && !userDTO.getPassword().trim().isEmpty()) { String encodedPwd = passwordUtil.encodePassword(userDTO.getPassword()); user.setPassword(encodedPwd); } if (userDTO.getEmail() != null && !userDTO.getEmail().trim().isEmpty()) { user.setEmail(userDTO.getEmail()); } if (userDTO.getAddress() != null && !userDTO.getAddress().trim().isEmpty()) { user.setAddress(userDTO.getAddress()); } userRepository.save(user); return OperationResponse.success(new ResponseDTO(user.getUsername(), user.getEmail(), user.getAddress())); } @Override public OperationResponse<ResponseDTO> getUserByEmail(String email) { if (!userRepository.existsByEmail(email)) { log.error("User not existed"); return OperationResponse.failure(ErrorCode.USER_NOT_FOUND); } UserInfo user = userRepository.findByEmail(email).get(); return OperationResponse.success(new ResponseDTO(user.getUsername(), user.getEmail(), user.getAddress())); } } 生成相应的测试代码
最新发布
09-03
package servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import dao.DAO; import bean.User; public class addUserServlet extends HttpServlet { /** * Destruction of the servlet. */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); String user1 = request.getParameter("user"); String pwd = request.getParameter("pwd"); String name = new String(request.getParameter("name").getBytes( "ISO8859_1"), "utf-8"); String xxx = new String(request.getParameter("xxx").getBytes( "ISO8859_1"), "utf-8"); String age1 = request.getParameter("age"); User user = new User(); user.setUser(user1); user.setPwd(pwd); user.setName(name); user.setxxx(xxx); int age; if (age1 != null) { age = Integer.parseInt(age1); user.setAge(age); } DAO dao = new DAO(); dao.addUser(user); request.setAttribute("info", new String(" 添加成功!恭喜!!" + " ")); request.setAttribute("id", new String("a")); request.setAttribute("denglu", new String(" 登陆")); request.getRequestDispatcher("info.jsp").forward(request, response); } public void init() throws ServletException { // Put your code here } }
06-10
package com.example.demo.service.impl; import com.alibaba.fastjson2.JSONObject; import com.example.demo.dao.BenefitAdminDao; import com.example.demo.dao.IdentityAdminDao; import com.example.demo.dao.IdentityBenefitRelationDao; import com.example.demo.entity.*; import com.example.demo.service.IdentityBenefitAdminService; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.update.UpdateChain; import io.micrometer.common.util.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.*; import java.util.function.Consumer; import java.util.stream.Collectors; @Service public class IdentityBenefitAdminServiceImpl implements IdentityBenefitAdminService { @Autowired private BenefitAdminDao benefitAdminDao; @Autowired private IdentityAdminDao identityAdminDao; @Autowired private IdentityBenefitRelationDao identityBenefitRelationDao; @Override public ResultPage<BenefitInfo> listBenefit(ArguBenefitQuery query) { QueryWrapper wrapper = QueryWrapper.create() .select("b.id", "b.code", "b.name","b.description") .from("benefit").as("b") .leftJoin("identity_benefit_relation").as("ibr") .on("b.code = ibr.benefitCode") .leftJoin("identity").as("i") .on("i.id = ibr.idIdentity") .where("i.isDeleted = FALSE") .and("ibr.isDeleted = FALSE"); if (StringUtils.isNotBlank(query.getIdentityName())) { wrapper.and((Consumer<QueryWrapper>) w -> w.like("i.name", query.getIdentityName())); } if (StringUtils.isNotBlank(query.getBenefitName())) { wrapper.and((Consumer<QueryWrapper>) w -> w.like("b.name", query.getBenefitName())); } wrapper.groupBy("b.id", "b.code", "b.name","b.description"); wrapper.orderBy("b.code"); Page<BenefitInfoSub> benefitInfoSubPage = benefitAdminDao.paginateAs( new Page<>(query.getCurrent(), query.getPageSize()), wrapper, BenefitInfoSub.class ); List<BenefitInfoSub> records = benefitInfoSubPage.getRecords(); List<BenefitInfo> benefitInfoList = records.stream() .map(this::convertToBenefitInfo) .collect(Collectors.toList()); return new ResultPage<>( benefitInfoSubPage.getTotalRow(), benefitInfoSubPage.getPageSize(), benefitInfoSubPage.getPageNumber(), benefitInfoList ); } @Override public ResultPage<IdentityInfo> queryIdentity(ArguIdentityQuery query) { QueryWrapper wrapper = QueryWrapper.create() .select("i.id", "i.name", "i.description") .select("JSON_AGG(JSON_BUILD_OBJECT('name', b.name, 'code', ibr.benefitCode)) AS benefit") .from("identity").as("i") .leftJoin("identity_benefit_relation").as("ibr") .on("i.id = ibr.idIdentity") .leftJoin("benefit").as("b") .on("b.code = ibr.benefitCode") .where("i.isDeleted = FALSE"); if (StringUtils.isNotBlank(query.getIdentityName())) { wrapper.and((Consumer<QueryWrapper>) w -> w.like("i.name", query.getIdentityName())); } wrapper.groupBy("i.id", "i.name", "i.description"); Page<IdentityInfoSub> page = identityAdminDao.paginateAs( new Page<>(query.getCurrent(), query.getPageSize()), wrapper, IdentityInfoSub.class ); List<IdentityInfoSub> records = page.getRecords(); // 将 records 转换为 IdentityInfo List<IdentityInfo> identityInfoList = convertToIdentityInfo(records); // 返回 ResultPage ResultPage<IdentityInfo> resultPage = new ResultPage<>( page.getTotalRow(), page.getPageSize(), page.getPageNumber(), identityInfoList ); return resultPage; } /** * 删除身份 * * @param del * @return */ @Override @Transactional public Boolean delIdentity(ArguDelIdentity del, Long idUser) { LocalDateTime now = LocalDateTime.now(); //删除身份 UpdateChain.of(Identity.class) .set(Identity::getOperator, idUser) .set(Identity::getTimeUpdate, now) .set(Identity::isDeleted, true) .eq(Identity::getId, del.getId()) .update(); //并且删除身份权益关联 UpdateChain.of(IdentityBenefitRelation.class) .set(IdentityBenefitRelation::isDeleted, true) .set(IdentityBenefitRelation::getOperator, idUser) .set(IdentityBenefitRelation::getTimeUpdate, now) .eq(IdentityBenefitRelation::getIdIdentity, del.getId()) .update(); return true; } /** * 修改身份 * * @param update * @return */ @Override @Transactional public Boolean updateIdentity(ArguUpdateIdentity update, Long idUser) { LocalDateTime now = LocalDateTime.now(); UpdateChain.of(Identity.class) .set(Identity::getName, update.getName()) .set(Identity::getDescription, update.getDescription()) .set(Identity::getOperator, idUser) .set(Identity::getTimeUpdate, now) .where(Identity::getId).eq(update.getId()) .update(); List<String> dbBenefitCodes = identityBenefitRelationDao.queryBenefitCodeByIdentityId(update.getId()); List<String> voBenefitCodes = new ArrayList<>(); if (update.getMatchBenefits() != null) for (BenefitItem benefitItem : update.getMatchBenefits()) if (benefitItem.getCode() != null) voBenefitCodes.addAll(Collections.singleton(benefitItem.getCode())); //找出数据库有但入参没有的 benefitCode List<String> dbOnlyBenefitCodes = dbBenefitCodes.stream() .filter(code -> !voBenefitCodes.contains(code)) .collect(Collectors.toList()); if (!dbOnlyBenefitCodes.isEmpty()) for (String code : dbOnlyBenefitCodes) { UpdateChain.of(IdentityBenefitRelation.class) .set(IdentityBenefitRelation::isDeleted, true) .set(IdentityBenefitRelation::getTimeUpdate, now) .set(IdentityBenefitRelation::getOperator, idUser) .where(IdentityBenefitRelation::getBenefitCode).eq(code) .and(IdentityBenefitRelation::getIdIdentity).eq(update.getId()) .update(); } //找出共有的benefitCode并更新config List<String> bothExistBenefitCodes = voBenefitCodes.stream() .filter(dbBenefitCodes::contains) .collect(Collectors.toList()); if (!bothExistBenefitCodes.isEmpty()) { for (String benefitCode : bothExistBenefitCodes) { BenefitItem result = update.getMatchBenefits().stream() .filter(item -> benefitCode.equals(item.getCode())) .findFirst() .orElseThrow(() -> new NoSuchElementException("没找到code:" + benefitCode)); JSONObject benefitConfig = result.getConfig(); UpdateChain.of(IdentityBenefitRelation.class) .set(IdentityBenefitRelation::getTimeUpdate, now) .set(IdentityBenefitRelation::getOperator, idUser) .set(IdentityBenefitRelation::getBenefitConfig,benefitConfig) .where(IdentityBenefitRelation::getBenefitCode).eq(benefitCode) .and(IdentityBenefitRelation::getIdIdentity).eq(update.getId()) .update(); } } //找出入参有但数据库没有的 benefitCode List<String> voOnlyBenefitCodes = voBenefitCodes.stream() .filter(code -> !dbBenefitCodes.contains(code)) .collect(Collectors.toList()); if (!voOnlyBenefitCodes.isEmpty()) { List<IdentityBenefitRelation> relations = new ArrayList<>(); //插入身份权益表 for (String benefitCode : voOnlyBenefitCodes) { //找到code对应的config BenefitItem result = update.getMatchBenefits().stream() .filter(item -> benefitCode.equals(item.getCode())) .findFirst() .orElseThrow(() -> new NoSuchElementException("没找到code:" + benefitCode)); if (result == null) continue; JSONObject config = result.getConfig(); IdentityBenefitRelation relation = new IdentityBenefitRelation(); relation.setOperator(idUser); relation.setIdIdentity(update.getId()); relation.setBenefitCode(benefitCode); relation.setBenefitConfig(JSONObject.toJSONString(config)); relation.setTimeCreate(now); relation.setTimeUpdate(now); relations.add(relation); } identityBenefitRelationDao.insertBatch(relations); } return true; } /** * 添加身份 * @param add * @return */ @Override @Transactional public Boolean addIdentity(ArguAddIdentity add, Long idUser) { LocalDateTime now = LocalDateTime.now(); Identity identity = new Identity(); String uuid = UUID.randomUUID().toString().replace("-", ""); identity.setCode(uuid); identity.setName(add.getName()); identity.setDescription(add.getDescription()); identity.setOperator(idUser); identity.setTimeCreate(now); identity.setTimeUpdate(now); identity.setMarkType(add.getMarkType()); identityAdminDao.insert(identity); Long id = identity.getId(); List<IdentityBenefitRelation> relations = new ArrayList<>(); //插入身份权益表 for (BenefitItem benefitItem : add.getMatchBenefits()) { String benefitCode = benefitItem.getCode(); JSONObject config = benefitItem.getConfig(); IdentityBenefitRelation relation = new IdentityBenefitRelation(); relation.setOperator(idUser); relation.setIdIdentity(id); relation.setBenefitCode(benefitCode); relation.setBenefitConfig(JSONObject.toJSONString(config)); relation.setTimeCreate(now); relation.setTimeUpdate(now); relations.add(relation); } identityBenefitRelationDao.insertBatch(relations); return true; } /** * 更改权益 * @param update * @return */ @Override public Boolean updateBenefit(ArguUpdateBenefit update, Long idUser) { UpdateChain.of(Benefit.class) .set(Benefit::getName,update.getName()) .set(Benefit::getOperator,idUser) .set(Benefit::getDescription,update.getDescription()) .set(Benefit::getTimeUpdate, LocalDateTime.now()) .set(Benefit::getPic, JSONObject.toJSONString(update.getPic())) .set(Benefit::getConfig,JSONObject.toJSONString(update.getConfig())) .where(Benefit::getCode).eq(update.getCode()) .update(); return true; } private BenefitInfo convertToBenefitInfo(BenefitInfoSub benefitInfoSub) { BenefitInfo benefitInfo = new BenefitInfo(); benefitInfo.setId(benefitInfoSub.getId()); benefitInfo.setCode(benefitInfoSub.getCode()); benefitInfo.setName(benefitInfoSub.getName()); benefitInfo.setDescription(benefitInfoSub.getDescription()); return benefitInfo; } private List<IdentityInfo> convertToIdentityInfo(List<IdentityInfoSub> records) { List<IdentityInfo> identityInfoList = new ArrayList<>(); for (IdentityInfoSub sub : records) { IdentityInfo info = new IdentityInfo(); info.setId(sub.getId()); info.setName(sub.getName()); info.setDescription(sub.getDescription()); info.setBenefit(sub.getBenefit()); identityInfoList.add(info); } return identityInfoList; } } 把这里能抽出来的使用泛型写成公共的
07-26
D:\JAVA\jdk\bin\java.exe "-javaagent:D:\IDEA\IntelliJ IDEA 2023.3.4\lib\idea_rt.jar=51321:D:\IDEA\IntelliJ IDEA 2023.3.4\bin" -Dfile.encoding=UTF-8 -classpath D:\code\java\javaweb\javaweb3\out\production\javaweb3;D:\code\java\javaweb\javaweb3\lib\mysql-connector-java-8.0.15.jar;D:\code\java\javaweb\javaweb3\lib\druid-1.1.12.jar com.hz.jdbc03.utils.Test java.sql.SQLSyntaxErrorException: In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'lianxi2.a.subject'; this is incompatible with sql_mode=only_full_group_by at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:970) at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1020) at com.hz.jdbc03.dao.DBUtils.query(DBUtils.java:52) at com.hz.jdbc03.dao.impl.StudentUserImpl.findAll(StudentUserImpl.java:111) at com.hz.jdbc03.utils.Test.main(Test.java:54) java.lang.NullPointerException: Cannot invoke "java.sql.ResultSet.next()" because "rs" is null at com.hz.jdbc03.dao.impl.StudentUserImpl.findAll(StudentUserImpl.java:114) at com.hz.jdbc03.utils.Test.main(Test.java:54) java.lang.NullPointerException: Cannot invoke "java.sql.ResultSet.close()" because "rs" is null at com.hz.jdbc03.dao.impl.StudentUserImpl.findAll(StudentUserImpl.java:126) at com.hz.jdbc03.utils.Test.main(Test.java:54) List<StudentUsermax> list = stuDents.findAll(); for (StudentUsermax studentUsermax : list) { System.out.println(studentUsermax); } package com.hz.jdbc03.dao.impl; import com.hz.jdbc03.dao.DBUtils; import com.hz.jdbc03.dao.StuDents; import com.hz.jdbc03.pojo.StudentUser; import com.hz.jdbc03.pojo.StudentUsermax; import com.hz.jdbc03.pojo.StudentUserresult; import java.sql.*; import java.util.ArrayList; import java.util.List; //实现接口 public class StudentUserImpl implements StuDents{ DBUtils dbUtils = new DBUtils(); public int addStudent(StudentUser studentUser) { String sql = "INSERT INTO student (studentNo, studentName, loginPwd, gender, gradeId, phone, address, bornDate, email) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"; return dbUtils.update(sql,studentUser.getStudentNo(), studentUser.getStudentName(), studentUser.getLoginPwd(), studentUser.getGender(), studentUser.getGradeId(), studentUser.getPhone(), studentUser.getAddress(), studentUser.getBornDate(), studentUser.getEmail()); } @Override public int updatePwd(int studentId, String loginPwd) { String sql = "UPDATE student SET loginPwd = ? WHERE studentId = ?"; return dbUtils.update(sql,loginPwd,studentId); } public void findStudent(String studentName, String studentpwd){ String sql = "select a.* from student a join grade b on a.gradeId = b.gradeId where studentName = ? and loginPwd = ?"; ResultSet rs = dbUtils.query(sql,studentName,studentpwd); try { if(rs.next()){ StudentUser stu = new StudentUser(); stu.setStudentid(rs.getInt("studentId")); stu.setStudentName(rs.getString("studentName")); stu.setLoginPwd(rs.getString("loginPwd")); stu.setGender(rs.getString("gender")); stu.setGradeId(rs.getInt("gradeId")); stu.setPhone(rs.getString("phone")); stu.setAddress(rs.getString("address")); stu.setBornDate(rs.getString("bornDate")); stu.setEmail(rs.getString("email")); System.out.println(stu); } } catch (Exception e) { e.printStackTrace(); }finally { try { rs.close(); } catch (Exception e) { e.printStackTrace(); } } } public void delete(int[] studentId){ try { dbUtils.conn.setAutoCommit(false); String sql = "delete from student where studentId = ?"; PreparedStatement ps = dbUtils.conn.prepareStatement(sql); for (int id : studentId) { ps.setInt(1, id); ps.addBatch(); ps.executeBatch(); dbUtils.conn.commit(); if(dbUtils.ps != null){ dbUtils.ps.close(); } } } catch (Exception e) { e.printStackTrace(); }finally { dbUtils.close(); } } public List<StudentUsermax> findAll( ){ List<StudentUsermax> list = new ArrayList<>(); String sql = "SELECT \n" + " a.subject AS k_name, \n" + " b.studentName AS name_a, \n" + " a.examDate AS time,\n" + " max(a.studentResult) AS max_a\n" + " FROM result a \n" + " LEFT JOIN student b ON a.studentNo = b.studentNo\n" + " LEFT JOIN (SELECT studentNo, `subject`, MAX(studentResult) AS max_res\n" + " FROM result \n" + " GROUP BY studentNo, `subject` \n" + " )temp ON a.studentNo = temp.studentNo \n" + " AND a.`subject` = temp.`subject` \n" + " AND a.studentResult = temp.max_res\n" + " WHERE temp.studentNo IS NOT NULL;"; ResultSet rs = dbUtils.query(sql,null); List<StudentUsermax> list1 = new ArrayList<>(); try { while(rs.next()){ StudentUsermax max = new StudentUsermax(); max.setSubject(rs.getString("k_name")); max.setStudentName(rs.getString("name_a")); max.setStudentResult(rs.getInt("max_a")); max.setExamDate(rs.getString("time")); list1.add(max); } } catch (Exception e) { e.printStackTrace(); }finally { try { rs.close(); } catch (Exception e) { e.printStackTrace(); } } return list; } }
07-22
package com.example.demo.service.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.UUID; import cn.hutool.core.thread.ThreadFactoryBuilder; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.demo.dao.entity.WExecuteHost; import com.example.demo.dao.entity.WHostProcess; import com.example.demo.dao.entity.WPersonalHost; import com.example.demo.dao.mapper.WExecuteHostMapper; import com.example.demo.request.ProcessRequest; import com.example.demo.service.WExecuteHostService; import com.example.demo.service.WHostProcessService; import com.example.demo.service.WPersonalHostService; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.interceptor.TransactionAspectSupport; import javax.annotation.PreDestroy; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Queue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; @Service public class WExecuteHostServiceImpl extends ServiceImpl<WExecuteHostMapper, WExecuteHost> implements WExecuteHostService { @Autowired private WPersonalHostService wPersonalHostService; @Autowired private WHostProcessService wHostProcessService; @Data private static class UserSession { private Process cmdProcess; private volatile boolean isProcessRunning; private String sessionId; private String logFilePath; private final Queue<String> logBuffer = new ConcurrentLinkedQueue<>(); private static final int BATCH_SIZE = 50; // 批量写入阈值 // 命令执行状态锁 private final AtomicBoolean isExecuting = new AtomicBoolean(false); } private final Map<String, UserSession> userSessions = new ConcurrentHashMap<>(); private final SimpMessagingTemplate messagingTemplate; // 异步日志写入线程池 private static final ExecutorService LOG_WRITER_POOL = Executors.newCachedThreadPool( new ThreadFactoryBuilder().setNamePrefix("log-writer-").build()); // 日志刷新调度器 private static final ScheduledExecutorService LOG_FLUSH_SCHEDULER = Executors.newSingleThreadScheduledExecutor(); public WExecuteHostServiceImpl(SimpMessagingTemplate messagingTemplate) { this.messagingTemplate = messagingTemplate; startLogFlushService(); } // 初始化日志刷新服务 private void startLogFlushService() { LOG_FLUSH_SCHEDULER.scheduleAtFixedRate(() -> { userSessions.values().forEach(session -> { if (!session.getLogBuffer().isEmpty()) { List<String> batch = CollUtil.newArrayList(session.getLogBuffer()); session.getLogBuffer().clear(); asyncWriteLog(session.getLogFilePath(), String.join("\n", batch)); } }); }, 0, 1, TimeUnit.SECONDS); } @Override public void executeCommand(String command, String host, String userId) { // 0. ABORT命令特殊处理(优先处理终止请求) if ("ABORT".equalsIgnoreCase(command)) { handleAbort(userId); return; } // 1. 权限校验 if (!validateUserHost(userId, host)) { sendError("无权访问该主机", userId); return; } // 2. 检查用户当前会话状态 UserSession session = userSessions.get(userId); if (session != null && session.isExecuting.get()) { sendError("已有命令执行中,请等待完成或使用ABORT终止", userId); return; } // 3. 创建新会话(带原子状态检查) session = userSessions.computeIfAbsent(userId, key -> { UserSession newSession = createNewSession(userId, host); if (newSession != null) { newSession.isExecuting.set(true); // 标记为执行中 } return newSession; }); if (session == null) return; // 4. 写入日志并执行命令 try { // 确保获得执行锁 if (!session.isExecuting.compareAndSet(true, true)) { sendError("命令执行冲突,请重试", userId); return; } session.getLogBuffer().offer("——————————————— " + DateUtil.now() + " ———————————————"); // 发送命令到进程 IoUtil.write(session.getCmdProcess().getOutputStream(), Charset.forName("gbk"), true, command + "\n"); } catch (Exception e) { session.isExecuting.set(false); // 发生异常时释放锁 sendError("命令发送失败: " + e.getMessage(), userId); } } @Override public Boolean isCommandExecuting(String userId) { UserSession session = userSessions.get(userId); return session != null && session.isExecuting.get(); } @Override public void handleAbort(String userId) { UserSession session = userSessions.get(userId); if (session == null || session.getCmdProcess() == null) { sendError("没有活动的命令进程", userId); return; } try { long pid = session.getCmdProcess().pid(); System.out.println("Attempting to kill process with PID: " + pid); // 使用 taskkill 命令终止进程 ProcessBuilder taskKill = new ProcessBuilder("taskkill", "/F", "/T", "/PID", String.valueOf(pid)); Process killProcess = taskKill.start(); // 等待命令执行完成 int exitCode = killProcess.waitFor(); System.out.println("taskkill exit code: " + exitCode); if (exitCode == 0) { // 进程终止成功 session.isExecuting.set(false); cleanupSession(userId); messagingTemplate.convertAndSend("/topic/commandOutput/" + userId, "✔️" + "进程已通过 taskkill 终止 (PID: " + pid + ")"); messagingTemplate.convertAndSend("/topic/commandOutput/" + userId, ""); messagingTemplate.convertAndSend("/topic/commandOutput/" + userId, System.getProperty("user.dir") + ">"); } else { // 进程终止失败 sendError("终止进程失败,错误码: " + exitCode, userId); } } catch (IOException | InterruptedException e) { System.err.println("Error killing process: " + e.getMessage()); sendError("终止进程失败: " + e.getMessage(), userId); } } @Override public String startProcess(ProcessRequest processRequest) { try { // 数据库表新增数据 String p13 = processRequest.getP13().trim(); String processName = processRequest.getProcessName().trim(); String productNumber = processRequest.getProductNumber().trim(); String executeHost = processRequest.getExecuteHost().trim(); String department = processRequest.getDepartment().trim(); String version = processRequest.getVersion().trim(); if (StrUtil.isEmpty(p13) || StrUtil.isEmpty(processName) || StrUtil.isEmpty(productNumber) || StrUtil.isEmpty(executeHost) || StrUtil.isEmpty(department) || StrUtil.isEmpty(version)) { return "新增进程失败。"; } WHostProcess wHostProcess = new WHostProcess(); wHostProcess.setP13(p13); wHostProcess.setProcessName(processName); wHostProcess.setProductNumber(productNumber); wHostProcess.setHost(executeHost); wHostProcess.setPid(null); wHostProcess.setDepartment(department); wHostProcess.setState("离线"); wHostProcess.setVersion(version); wHostProcess.setBeginTime(new Date()); boolean saveResult = wHostProcessService.save(wHostProcess); if (saveResult) { LambdaQueryWrapper<WPersonalHost> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper .eq(WPersonalHost::getExecuteHost, processRequest.getExecuteHost()) .eq(WPersonalHost::getSharedHost, processRequest.getSharedHost()); WPersonalHost wPersonalHost = wPersonalHostService.getOne(queryWrapper); // 执行py启动命令 //todo 后续动态 String pythonEXEPath = "D:\\miniforge\\envs" + File.separator + p13 + File.separator + "python" + wPersonalHost.getPythonEnv() + File.separator + "python.exe"; String mainPyPath = System.getProperty("user.dir") + File.separator + "python-package" + File.separator + executeHost + File.separator + p13 + File.separator + "test" + File.separator + "main.py"; executeCommand(pythonEXEPath + " " + mainPyPath, processRequest.getExecuteHost(), processRequest.getP13()); return "正在启动项目..."; } } catch (Exception e) { e.printStackTrace(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } return "新增进程失败。"; } private boolean validateUserHost(String userId, String executeHost) { LambdaQueryWrapper<WPersonalHost> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(WPersonalHost::getP13, userId) .eq(WPersonalHost::getExecuteHost, executeHost) .eq(WPersonalHost::getState, "在线"); return wPersonalHostService.getOne(queryWrapper) != null; } private UserSession createNewSession(String userId, String executeHost) { try { UserSession session = new UserSession(); session.setSessionId(UUID.randomUUID().toString()); session.setLogFilePath(initLogFile(userId, executeHost)); // 启动CMD进程(带唯一标题) ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/k", "title " + generateUniqueTitle(userId)); session.setCmdProcess(pb.redirectErrorStream(true).start()); // 启动输出监听线程 startOutputThread(session, userId); return session; } catch (IOException e) { sendError("进程启动失败: " + e.getMessage(), userId); return null; } } private String initLogFile(String userId, String executeHost) { // 1. 构建基础路径(使用File.separator) String baseDir = FileUtil.normalize( System.getProperty("user.dir") + File.separator + "command-log"); // 2. 构建安全路径(统一使用File.separator) String safePath = FileUtil.normalize( baseDir + File.separator + userId + File.separator + executeHost + File.separator + "项目名称"); // 3. 安全校验(现在路径分隔符一致) if (!safePath.startsWith(baseDir)) { throw new SecurityException("非法日志路径: " + safePath); } // 4. 创建目录(自动处理路径分隔符) FileUtil.mkdir(safePath); // 5. 生成日志文件 String logFileName = DateUtil.today() + ".log"; return FileUtil.touch(safePath + File.separator + logFileName).getAbsolutePath(); } private void startOutputThread(UserSession session, String userId) { new Thread(() -> { try (BufferedReader reader = new BufferedReader( new InputStreamReader(session.getCmdProcess().getInputStream(), "GBK"))) { String line; while ((line = reader.readLine()) != null) { messagingTemplate.convertAndSend("/topic/commandOutput/" + userId, line); session.getLogBuffer().offer(line); } } catch (Exception e) { sendError("输出流异常: " + e.getMessage(), userId); } finally { session.isExecuting.set(false); // 命令结束释放锁 cleanupSession(userId); // 通知前端命令执行结束 messagingTemplate.convertAndSend("/topic/commandOutput/" + userId, "⏹ 该命令执行已结束"); } }).start(); } private void asyncWriteLog(String logFilePath, String content) { CompletableFuture.runAsync(() -> { try { // 替换掉日志文件中没用的信息,如多余的路径信息 String currentDir = System.getProperty("user.dir"); String escapedDir = currentDir.replace("\\", "\\\\"); String regex = "(?m)^\\s*" + escapedDir + ">(?!\\S)\\s*"; // 创建 Pattern 和 Matcher 对象 Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(content); // 检查是否存在匹配的模式 if (matcher.find()) { // 如果存在匹配,则进行替换 String cleaned = content.replaceAll(regex, ""); FileUtil.appendString(cleaned + System.lineSeparator(), logFilePath, "GBK"); } else { FileUtil.appendString(content + System.lineSeparator(), logFilePath, "GBK"); } } catch (Exception e) { System.err.println("日志写入失败: " + e.getMessage()); } }, LOG_WRITER_POOL); } private void cleanupSession(String userId) { UserSession session = userSessions.remove(userId); if (session != null) { try { if (session.getCmdProcess() != null) { session.getCmdProcess().destroyForcibly(); } // 强制将剩余日志写入文件(新增代码) if (!session.getLogBuffer().isEmpty()) { asyncWriteLog(session.getLogFilePath(), String.join("\n", session.getLogBuffer())); session.getLogBuffer().clear(); } } catch (Exception ignored) { } } } @PreDestroy public void cleanup() { LOG_FLUSH_SCHEDULER.shutdown(); LOG_WRITER_POOL.shutdown(); userSessions.forEach((userId, session) -> { try { if (session.getCmdProcess() != null) { session.getCmdProcess().destroyForcibly(); } } catch (Exception ignored) { } }); userSessions.clear(); } /** * 发送错误日志 */ private void sendError(String message, String userId) { try { messagingTemplate.convertAndSend("/topic/commandOutput/" + userId, "❌" + message); } catch (Exception ignored) { } } /** * 生成cmd窗口唯一id */ private String generateUniqueTitle(String userId) { return "CMD_SESSION_" + userId + "_" + System.currentTimeMillis(); } } 仔细阅读我的代码,现在有个bug,我执行下面的main.py文件,会报错请输入你的名字: 发生未知错误: EOF when reading a line import random import sys from datetime import datetime def generate_random_number(min_val=1, max_val=100): """ 生成一个指定范围内的随机整数 参数: min_val (int): 最小值,默认为1 max_val (int): 最大值,默认为100 返回: int: 随机生成的整数 """ return random.randint(min_val, max_val) def check_even_odd(number): """ 检查一个数字是奇数还是偶数 参数: number (int): 要检查的数字 返回: str: "偶数" 或 "奇数" """ return "偶数" if number % 2 == 0 else "奇数" def greet_user(name): """ 向用户问好 参数: name (str): 用户名 """ print(f"你好, {name}! 当前时间是: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") def main(): """ 主函数 """ print("欢迎使用随机数生成器!") try: user_name = input("请输入你的名字: ") greet_user(user_name) count = int(input("你想生成多少个随机数? (1-10): ")) if count < 1 or count > 10: print("请输入1到10之间的数字!") return for i in range(count): num = generate_random_number() print(f"随机数 #{i+1}: {num} ({check_even_odd(num)})") print("感谢使用!") except ValueError: print("错误: 请输入有效的数字!") except KeyboardInterrupt: print("\n程序被用户中断") except Exception as e: print(f"发生未知错误: {e}") if __name__ == "__main__": main()
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值