Java项目:通讯聊天程序(java+swing)
2021/12/11 17:19:35
本文主要是介绍Java项目:通讯聊天程序(java+swing),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Java实现的群聊程序,还可以发送文件,今天这个小程序只能聊天,不能发文件,功能非常简单,可在局域网内实现互相聊天,源码已经打包成了jar文件,可以在有Java环境的电脑上直接双击运行
登录页面:
/** * * @author YY */ public class LoginFrm extends javax.swing.JFrame { /** * 皮肤 */ static { try { // LookAndFeel lf = new SubstanceAutumnLookAndFeel(); // LookAndFeel lf = new SubstanceChallengerDeepLookAndFeel(); // LookAndFeel lf = new Plastic3DLookAndFeel(); // LookAndFeel lf = new PlasticLookAndFeel(); LookAndFeel lf = new PlasticXPLookAndFeel(); UIManager.setLookAndFeel(lf); } catch (UnsupportedLookAndFeelException e) { e.printStackTrace(); } } /** * 版本序列号 */ private static final long serialVersionUID = -2989784724450522952L; // 验证码的String类型 private String imageCode; private User user; /** Creates new form LoginFrm */ public LoginFrm(User user) { this.user = user; initComponents(); this.setLocationRelativeTo(null); fillImageCode(); if (user != null) { this.jtf_username.setText(this.user.getusername()); this.jpw_password.setText(this.user.getpassword()); } } public void setUser(User user) { this.user = user; } /** * 填充验证码图片 */ private void fillImageCode() { // this.jl_checkImage.setIcon(new ImageIcon("images/check.jpeg")); // this.repaint(); // jl_checkImage.setIcon(new ImageIcon(ImageIO.read(new // File("images/check.jpeg")))); ImageCodeUtil imageCodeUtil = ImageCodeUtil.getImageCodeUtil(); jl_checkImage.setIcon(new ImageIcon(imageCodeUtil.getBufferedImage())); imageCode =imageCodeUtil.sRand; } // GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code"> private void initComponents() { jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); jtf_username = new javax.swing.JTextField(); jpw_password = new javax.swing.JPasswordField(); jLabel4 = new javax.swing.JLabel(); jtf_check = new javax.swing.JTextField(); jl_checkImage = new javax.swing.JLabel(); jb_login = new javax.swing.JButton(); jb_cancle = new javax.swing.JButton(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("\u7528\u6237\u767b\u5f55"); jLabel1.setFont(new java.awt.Font("宋体", 0, 24)); jLabel1.setText("\u5ba2\u6237\u5173\u7cfb\u7ba1\u7406\u7cfb\u7edf"); jLabel2.setText("\u7528\u6237\u540d\uff1a"); jLabel3.setText("\u5bc6 \u7801\uff1a"); jLabel4.setText("\u9a8c\u8bc1\u7801\uff1a"); jb_login.setText("\u767b\u5f55"); jb_login.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_loginActionPerformed(evt); } }); jb_cancle.setText("\u53d6\u6d88"); jb_cancle.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_cancleActionPerformed(evt); } }); javax.swing.GroupLayout layout = new javax.swing.GroupLayout( getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addGap(108, 108, 108) .addComponent( jLabel1)) .addGroup( layout.createSequentialGroup() .addGap(78, 78, 78) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup( layout.createSequentialGroup() .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.TRAILING) .addComponent( jLabel2) .addComponent( jLabel3) .addComponent( jLabel4)) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.TRAILING, false) .addGroup( javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup() .addComponent( jtf_check, javax.swing.GroupLayout.PREFERRED_SIZE, 71, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent( jl_checkImage)) .addComponent( jpw_password, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 157, Short.MAX_VALUE) .addComponent( jtf_username, javax.swing.GroupLayout.Alignment.LEADING))) .addGroup( layout.createSequentialGroup() .addComponent( jb_login) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent( jb_cancle))))) .addContainerGap(79, Short.MAX_VALUE))); layout.setVerticalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addGap(34, 34, 34) .addComponent(jLabel1) .addGap(53, 53, 53) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent( jtf_username, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(18, 18, 18) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent( jpw_password, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(28, 28, 28) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent( jtf_check, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(jl_checkImage)) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED, 38, Short.MAX_VALUE) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jb_login) .addComponent(jb_cancle)) .addContainerGap())); pack(); }// </editor-fold> // GEN-END:initComponents private void jb_cancleActionPerformed(java.awt.event.ActionEvent evt) { int i = JOptionPane.showConfirmDialog(this, "确定退出系统?", "确认信息", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (i == 0) { this.dispose(); } } private void jb_loginActionPerformed(java.awt.event.ActionEvent evt) { String userName = this.jtf_username.getText(); String password = new String(this.jpw_password.getPassword()); String checkCode = this.jtf_check.getText(); if (StringUtil.isEmpty(userName)) { JOptionPane.showMessageDialog(this, "用户名不能为空!"); return; } if (StringUtil.isEmpty(password)) { JOptionPane.showMessageDialog(this, "密码不能为空"); return; } if (!checkCode.equals(imageCode)) { JOptionPane.showMessageDialog(this, "验证码错误"); // this.fillImageCode(); // this.jl_checkImage.updateUI(); // this.pack(); return; } User user = new User(userName, password); UserEbi userEbi = UserEbiFactory.getUserEbi(); User currentUser = userEbi.login(user); if (currentUser == null) { JOptionPane.showMessageDialog(this, "用户名或密码错误!"); return; } // System.out.println("登录成功"); this.dispose(); new MainFrm(currentUser).setVisible(true); } /** * @param args * the command line arguments */ public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new LoginFrm(null).setVisible(true); } }); } // GEN-BEGIN:variables // Variables declaration - do not modify private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JButton jb_cancle; private javax.swing.JButton jb_login; private javax.swing.JLabel jl_checkImage; private javax.swing.JPasswordField jpw_password; private javax.swing.JTextField jtf_check; private javax.swing.JTextField jtf_username; // End of variables declaration//GEN-END:variables }
用户信息页面:
public class UserSerInterFrm extends javax.swing.JInternalFrame { /** * */ private static final long serialVersionUID = -8462503234613628488L; private PageBean bean = null; /** Creates new form UserSerInterFrm */ public UserSerInterFrm() { initComponents(); this.setLocation(230, 130); this.fillRole(); QueryInfo info = new QueryInfo(); info.setPagesize(9); this.fillTable(info); } private void fillRole() { DefaultComboBoxModel dcm = (DefaultComboBoxModel) this.jcb_role .getModel(); dcm.removeAllElements(); List<Role> list = RoleEbiFactory.getRoleEbo().getRole(); for (Role role : list) { dcm.addElement(role); } } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ //GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code"> private void initComponents() { jScrollPane1 = new javax.swing.JScrollPane(); jtb_user = new javax.swing.JTable(); jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); jtf_username = new javax.swing.JTextField(); jtf_password = new javax.swing.JTextField(); jcb_role = new javax.swing.JComboBox(); jb_modify = new javax.swing.JButton(); jb_del = new javax.swing.JButton(); jb_end = new javax.swing.JButton(); jb_nextpage = new javax.swing.JButton(); jb_previouspage = new javax.swing.JButton(); jb_start = new javax.swing.JButton(); jb_add = new javax.swing.JButton(); jLabel4 = new javax.swing.JLabel(); setClosable(true); setIconifiable(true); setTitle("\u7528\u6237\u7ba1\u7406"); jtb_user.setModel(new javax.swing.table.DefaultTableModel( new Object[][] { }, new String[] { "编号", "用户名", "角色" }) { boolean[] canEdit = new boolean[] { false, false, false }; public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit[columnIndex]; } }); jtb_user.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseClicked(java.awt.event.MouseEvent evt) { jtb_userMouseClicked(evt); } }); jScrollPane1.setViewportView(jtb_user); jLabel1.setText("\u7528\u6237\u540d\uff1a"); jLabel2.setText("\u5bc6 \u7801\uff1a"); jLabel3.setText("\u89d2 \u8272\uff1a"); jcb_role.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" })); jb_modify.setText("\u4fee\u6539"); jb_modify.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_modifyActionPerformed(evt); } }); jb_del.setText("\u5220\u9664"); jb_del.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_delActionPerformed(evt); } }); jb_end.setText("\u672b\u9875"); jb_end.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_endActionPerformed(evt); } }); jb_nextpage.setText("\u4e0b\u4e00\u9875"); jb_nextpage.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_nextpageActionPerformed(evt); } }); jb_previouspage.setText("\u4e0a\u4e00\u9875"); jb_previouspage.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_previouspageActionPerformed(evt); } }); jb_start.setText("\u9996\u9875"); jb_start.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_startActionPerformed(evt); } }); jb_add.setText("\u65b0\u5efa"); jb_add.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jb_addActionPerformed(evt); } }); jLabel4.setText("jLabel4"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout( getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addGroup( javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap( 87, Short.MAX_VALUE) .addComponent( jb_start) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( jb_previouspage) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( jb_nextpage) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( jb_end) .addGap(39, 39, 39)) .addGroup( layout.createSequentialGroup() .addContainerGap() .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addComponent( jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 359, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent( jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 271, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(28, 28, 28))) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup( layout.createSequentialGroup() .addComponent( jLabel1) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( jtf_username, javax.swing.GroupLayout.PREFERRED_SIZE, 125, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup( layout.createSequentialGroup() .addComponent( jLabel2) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( jtf_password)) .addGroup( layout.createSequentialGroup() .addComponent( jLabel3) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( jcb_role, javax.swing.GroupLayout.PREFERRED_SIZE, 75, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGroup( layout.createSequentialGroup() .addComponent( jb_add) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( jb_modify) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent( jb_del))) .addContainerGap(20, Short.MAX_VALUE))); layout.setVerticalGroup(layout .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup( layout.createSequentialGroup() .addContainerGap() .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 199, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(jLabel4) .addGap(4, 4, 4) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jb_end) .addComponent(jb_nextpage) .addComponent(jb_previouspage) .addComponent(jb_start) .addComponent(jb_del) .addComponent(jb_modify) .addComponent(jb_add)) .addContainerGap(45, Short.MAX_VALUE)) .addGroup( javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() .addContainerGap(99, Short.MAX_VALUE) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent( jtf_username, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(26, 26, 26) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent( jtf_password, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(26, 26, 26) .addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent( jcb_role, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(98, 98, 98))); pack(); }// </editor-fold> //GEN-END:initComponents private void jtb_userMouseClicked(java.awt.event.MouseEvent evt) { DefaultTableModel tableModel = (DefaultTableModel) jtb_user.getModel(); int selectRows = jtb_user.getSelectedRows().length;// 取得用户所选行的行数 int selectedRowIndex = jtb_user.getSelectedRow(); // 取得用户所选单行 if (selectRows == 1) { String id = tableModel.getValueAt(selectedRowIndex, 0).toString(); User user = UserEbiFactory.getUserEbi().search(id); this.jtf_username.setText(user.getusername()); this.jtf_password.setText(user.getpassword()); // Role[] role = (Role[]) this.jcb_role.getSelectedObjects(); // for (Role r: role) { // if (r.getId()==user.getid()) { // this.jcb_role.setSelectedItem(r); // } // } for (int i = 0; i < this.jcb_role.getItemCount(); i++) { Role role = (Role) this.jcb_role.getItemAt(i); if (role.getId() == user.getroleid()) { this.jcb_role.setSelectedIndex(i); } } } } private void jb_endActionPerformed(java.awt.event.ActionEvent evt) { QueryInfo info = new QueryInfo(); info.setCurrentpage(bean.getTotalpage()); info.setPagesize(9); fillTable(info); } private void jb_nextpageActionPerformed(java.awt.event.ActionEvent evt) { QueryInfo info = new QueryInfo(); info.setCurrentpage(bean.getNextpage()); info.setPagesize(9); fillTable(info); } private void jb_previouspageActionPerformed(java.awt.event.ActionEvent evt) { QueryInfo info = new QueryInfo(); info.setCurrentpage(bean.getPreviouspage()); info.setPagesize(9); fillTable(info); } private void jb_startActionPerformed(java.awt.event.ActionEvent evt) { QueryInfo info = new QueryInfo(); info.setCurrentpage(1); info.setPagesize(9); fillTable(info); } private void jb_modifyActionPerformed(java.awt.event.ActionEvent evt) { DefaultTableModel tableModel = (DefaultTableModel) jtb_user.getModel(); int selectRows = jtb_user.getSelectedRows().length;// 取得用户所选行的行数 int selectedRowIndex = jtb_user.getSelectedRow(); // 取得用户所选单行 if (selectRows == 1) { BigDecimal userId = (BigDecimal) tableModel.getValueAt( selectedRowIndex, 0); String username = this.jtf_username.getText(); String password = this.jtf_password.getText(); Role role = (Role) this.jcb_role.getSelectedItem(); BigDecimal roleId = role.getId(); User user = new User(userId, username, password, roleId); boolean b = UserEbiFactory.getUserEbi().update(user); if (b) { JOptionPane.showMessageDialog(this, "修改成功!"); } else { JOptionPane.showMessageDialog(this, "修改失败!"); } } } private void jb_addActionPerformed(java.awt.event.ActionEvent evt) { String username = this.jtf_username.getText(); String password = this.jtf_password.getText(); User user = new User(username, password, new BigDecimal(5)); boolean b = UserEbiFactory.getUserEbi().add(user); if (b) { JOptionPane.showMessageDialog(this, "添加成功!"); } else { JOptionPane.showMessageDialog(this, "添加失败!"); } } private void jb_delActionPerformed(java.awt.event.ActionEvent evt) { int i = JOptionPane.showConfirmDialog(this, "确认删除此条记录?", "确认信息", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (i == 0) { DefaultTableModel tableModel = (DefaultTableModel) jtb_user .getModel(); int selectRows = jtb_user.getSelectedRows().length;// 取得用户所选行的行数 int selectedRowIndex = jtb_user.getSelectedRow(); // 取得用户所选单行 if (selectRows == 1) { String userId = tableModel.getValueAt(selectedRowIndex, 0) .toString(); boolean b = UserEbiFactory.getUserEbi().del(userId); if (b) { JOptionPane.showMessageDialog(this, "删除成功!"); } else { JOptionPane.showMessageDialog(this, "删除失败!"); } } } } @SuppressWarnings({ "unchecked", "rawtypes" }) private void fillTable(QueryInfo info) { // 获取表格模型 DefaultTableModel dtm = (DefaultTableModel) this.jtb_user.getModel(); // 清空表格 dtm.setRowCount(0); // 获取业务层接口实现类对象 UserEbi userEbi = UserEbiFactory.getUserEbi(); // 查询数据 bean = userEbi.search(info); // 获取封装数据的集合 List list = bean.getList(); // 遍历集合并向表格填充数据 for (Object object : list) { Vector v = new Vector(); User user = (User) object; v.add(user.getid()); v.add(user.getusername()); v.add(user.getRolename()); dtm.addRow(v); } this.jLabel4.setText("共" + bean.getTotalrecord() + "条记录-共" + bean.getTotalpage() + "页-当前第" + bean.getCurrentpage() + "页"); } //GEN-BEGIN:variables // Variables declaration - do not modify private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JButton jb_add; private javax.swing.JButton jb_del; private javax.swing.JButton jb_end; private javax.swing.JButton jb_modify; private javax.swing.JButton jb_nextpage; private javax.swing.JButton jb_previouspage; private javax.swing.JButton jb_start; private javax.swing.JComboBox jcb_role; private javax.swing.JTable jtb_user; private javax.swing.JTextField jtf_password; private javax.swing.JTextField jtf_username; // End of variables declaration//GEN-END:variables }
这篇关于Java项目:通讯聊天程序(java+swing)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南