ServerSocket+Swing+SQL Server2008聊天系统(好友私聊,聊天室群聊)

MonsterChatRoom(怪聊聊天系统)


  • 本系统采用ServerSocket+Swing+SQL Server2008编写

  • 主要分为三个模块:登录模块,用户信息展示模块,聊天模块

登录模块

登录界面相关的操作
如上图所见:后台采用账户名为唯一标识,通过其获取数据库中的数据;登录主界面,实现了三个相关的界面,和记住密码,保存在数据库中,方便下次登录;密码找回,如果账号存在,下面的信息填写中与数据库注册信息核对两条以上,那么密码框向用户开启可编辑状态,重新找回密码成功!

  • 主界面的部分代码 :
package com.hz.view;

import java.awt.*;
import java.awt.event.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import com.hz.bean.Account;
import com.hz.bean.User;
import com.hz.client.Client;
import com.hz.db.DbHelp;
import com.hz.thread.*;
import com.hz.util.AccountDatabaseUtil;
import com.hz.util.UserDatabaseUtil;

/**
 * 登录界面
 * 
 * @author ztw
 * 
 *         2016-12-4
 */
public class UserLoginView extends JFrame {

    // 获取当前屏幕的宽和高
    private final int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    private final int height = Toolkit.getDefaultToolkit().getScreenSize().height;
    // 设置窗口的宽和高
    private final int windowWidth = 430;
    private final int windowHeight = 330;

    private JPanel upJPanel, belowJPanel; //centerJPanel;

    private JButton loginButton;
    private ImageIcon icon;

    private JPasswordField passField;

    private JLabel rightLabel, rightLabel2, leftDownLabel, rightDownLabel,
            smImgLabel,centerLabel;

    private JCheckBox remember;// 记住密码
    private JCheckBox automaticLogin;// 自动登录

    private JComboBox<String> accountComboBox;
    // private List<String> accountNameList;
    private List<Account> accountNameList;

    private String accountContent;// 获取账户框的值
    private String passContent;// 获取密码框的值
    // 菜单弹出事件
    private JPopupMenu popupMenu;
    // 用户封装类
    private User user;

    private UserDatabaseUtil util;

    public UserLoginView() throws HeadlessException {
        Window();
        upWindowJPanel();
        headJPanel();
        accountComboBox();
        passField();
        rightLabel();
        windowJCheckBox();
        belowWindowJPanel();
        this.add(upJPanel);
        this.add(centerLabel);
        this.add(accountComboBox);
        this.add(passField);
        this.add(rightLabel);
        this.add(rightLabel2);
        this.add(remember);
        this.add(automaticLogin);
        this.add(belowJPanel);

    }

    /**
     * 顶级窗口设置方法
     */
    public void Window() {
        this.setTitle("MonsterChat");
        // 设置窗口图标
        Image img = Toolkit.getDefaultToolkit().getImage("image\\sprout01.png");
        this.setIconImage(img);
        this.setBackground(Color.BLUE);
        // 设置窗体位置和大小
        this.setBounds((width - windowWidth) / 2, (height - windowHeight) / 2,
                windowWidth, windowHeight);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(false);// 设置窗体不可改变大小
        Container container = getContentPane();
        container.setLayout(null);
        this.setBackground(Color.red);
        this.setUndecorated(true);// 去掉窗口的装饰
        // 采用指定的窗口装饰
        this.getRootPane().setWindowDecorationStyle(JRootPane.WIDTH);
        this.setVisible(true);
    }

    /**
     * 上面面板方法
     */
    public void upWindowJPanel() {

        upJPanel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {

                icon = new ImageIcon("image\\tree.gif");
                Dimension dim = getSize();
                g.drawImage(icon.getImage(), 0, 0, dim.width, dim.height, null);
            }
        };
        upJPanel.setBounds(0, 0, windowWidth, 155);

    }

    /**
     * 头像按钮方法
     */
    public void headJPanel() {
        //面板绘图
//      centerJPanel = new JPanel() {
//          @Override
//          protected void paintComponent(Graphics g) {
//
//              icon = new ImageIcon(account.getAccount_icon());
//              System.out.println(icon);
//              Dimension dim = getSize();
//              g.drawImage(icon.getImage(), 0, 0, dim.width, dim.height, null);
//          }
//      };
        account = (Account) accountDatabaseUtil.getByID(accountName);
        if(account != null){
            icon = new ImageIcon(account.getAccount_icon());
        }
        centerLabel = new JLabel(icon);
        centerLabel.setBounds(40, 168, 80, 80);
        centerLabel.setLayout(null);
        // 实例化弹出菜单
        popupMenu = new JPopupMenu();
        // 增加菜单项到菜单上
        popupMenu.add(new JMenuItem("我在线上",
                new ImageIcon("image\\online01.png")));
        popupMenu
                .add(new JMenuItem("Q我吧", new ImageIcon("image\\smile01.png")));
        popupMenu.addSeparator();
        popupMenu.add(new JMenuItem("离开", new ImageIcon("image\\clock01.png")));
        popupMenu.add(new JMenuItem("忙碌", new ImageIcon("image\\wait01.png")));
        popupMenu.add(new JMenuItem("请勿打扰", new ImageIcon(
                "image\\disturb01.png")));
        popupMenu.addSeparator();
        popupMenu
                .add(new JMenuItem("隐身", new ImageIcon("image\\conceal01.png")));
        smImgLabel = new JLabel(new ImageIcon("image\\cancel01.png"));
        smImgLabel.setBounds(67, 67, 12, 12);
        smImgLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                popupMenu.show(e.getComponent(), e.getX(), e.getY());
            }

            @Override
            public void mousePressed(MouseEvent e) {
                smImgLabel.setBounds(68, 68, 12, 12);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                smImgLabel.setBounds(67, 67, 12, 12);
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                smImgLabel.setIcon(new ImageIcon("image\\cancel02.png"));
            }

            @Override
            public void mouseExited(MouseEvent e) {
                smImgLabel.setIcon(new ImageIcon("image\\cancel01.png"));
            }
        });
        centerLabel.add(smImgLabel);
    }

    private AccountDatabaseUtil accountDatabaseUtil = new AccountDatabaseUtil();
    private Account account;

    /**
     * 记录登录账户
     */
    private void recordInformation() {

        accountNameList = new ArrayList<Account>();
        try {
            rs = accountDatabaseUtil.getAll();
            while (rs.next()) {
                account = new Account(rs.getString(2));
                accountNameList.add(account);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    List<String> list;
    String accountName;
    private String accountContentIndex;

    /**
     * 账户框方法
     */
    public void accountComboBox() {

        recordInformation();
        list = new ArrayList<String>();
        for (Account account : accountNameList) {
            accountName = account + "";// 把对象类型Account转换成字符串类型数据
            list.add(accountName);
        }
        Object[] obj = list.toArray();
        if (obj.length >= 3) {
            String[] proList = { (String) obj[obj.length - 1],
                    (String) obj[obj.length - 2], (String) obj[obj.length - 3] };
            accountComboBox = new JComboBox<String>(proList);
        } else if (obj.length < 3 && obj.length >= 1) {
            String[] proList = { (String) obj[obj.length - 1],(String) obj[obj.length - 2] };
            accountComboBox = new JComboBox<String>(proList);
        }else if(obj.length==2){
            String[] proList = { (String) obj[obj.length - 1] };
            accountComboBox = new JComboBox<String>(proList);
        }else{
            String[] proList = {"MM私聊欢迎您!"};
            accountComboBox = new JComboBox<String>(proList);
        }
        accountComboBox.setBounds(135, 168, 185, 28);
        accountComboBox.setEditable(true);// 响应键盘输入事件

        accountComboBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                accountContent = accountComboBox.getSelectedItem().toString();

            }
        });
        accountComboBox.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                accountContent = accountComboBox.getSelectedItem().toString();
            }
        });
        // 获取可编辑框的值
        accountContent = (String) accountComboBox.getSelectedItem();
    }

    /**
     * 密码框方法
     */
    String content;

    public void passField() {
        // 根据Id获取密码
        account = (Account) accountDatabaseUtil.getByID(accountName);
        //当账户信息不等于NULL时,获取密码
        if(account != null){
            passField = new JPasswordField(account.getAccount_password());
        }else{
            passField = new JPasswordField();
        }
        passField.setBounds(135, 196, 185, 28);
        passField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                super.keyReleased(e);
                char[] chars = passField.getPassword();// 获得密码框的密码
                passContent = new String(chars);
            }
        });
        char[] chars = passField.getPassword();// 获得密码框的密码
        passContent = new String(chars);
    }
    /**
     * 右标签方法
     */
    public void rightLabel() {

        rightLabel = new JLabel("注册账号");
        rightLabel.setBounds(330, 175, 55, 15);
        rightLabel.setForeground(new Color(0, 129, 255));

        rightLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                breakRegisterWindom();
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                rightLabel.setForeground(new Color(130, 194, 255));

            }

            @Override
            public void mouseExited(MouseEvent e) {
                rightLabel.setForeground(new Color(0, 129, 255));

            }
        });
        rightLabel2 = new JLabel("找回密码");
        rightLabel2.setBounds(330, 202, 55, 15);
        rightLabel2.setForeground(new Color(0, 129, 255));
        rightLabel2.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                breakRetrievePassword();
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                rightLabel2.setForeground(new Color(130, 194, 255));

            }

            @Override
            public void mouseExited(MouseEvent e) {
                rightLabel2.setForeground(new Color(0, 129, 255));

            }
        });
    }
    /**
     * 找回密码界面跳转
     */
    private void breakRetrievePassword() {
        new retrievePasswordThread().start();
    }

    /**
     * 注册界面跳转
     */
    public void breakRegisterWindom() {
        new registerThread().start();
    }

    /**
     * 窗口复选框方法
     */
    private boolean flag = false;

    public void windowJCheckBox() {

        remember = new JCheckBox("记住密码");
        remember.setBounds(132, 233, 80, 15);
        remember.setForeground(Color.gray);
        // 根据数据库的值判断是否选中
        account = (Account) accountDatabaseUtil.getByID(accountName);

        if (account != null && account.getAccount_remember().equals("true")) {
            flag = true;
        }
        remember.setSelected(flag);
        automaticLogin = new JCheckBox("自动登录");
        automaticLogin.setBounds(248, 233, 80, 15);
        automaticLogin.setForeground(Color.gray);

    }

    /**
     * 下面面板、按钮方法
     */
    private ResultSet rs;// 结果集

    public void belowWindowJPanel() {
        belowJPanel = new JPanel();
        belowJPanel.setBounds(0, 255, windowWidth, 75);
        belowJPanel.setLayout(null);
        loginButton = new JButton(new ImageIcon("image\\safety.png"));
        loginButton.setBounds(135, 5, 185, 30);
        loginButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                util = new UserDatabaseUtil();// 调用数据库工具类
                user = util.selectName(accountContent);
                accountDatabaseUtil = new AccountDatabaseUtil();// 记录账户密码
                // 判断账户密码是否为空,并提示
                if (((accountContent != null && !accountContent.equals("")))
                        && (passContent != null && !passContent.equals(""))) {

                    savePasswordInfo(user);//是否保存密码信息

                } else if ((accountContent == null || accountContent.equals(""))
                        && (accountContentIndex == null || accountContentIndex
                                .equals(""))) {

                    JOptionPane.showMessageDialog(null, "账户名不能为空!", 
                            "温馨提示",
                            JOptionPane.PLAIN_MESSAGE, 
                            new ImageIcon("image\\sprout01.png"));
                } else if (passContent == null || passContent.equals("")) {
                    JOptionPane.showMessageDialog(UserLoginView.this, "密码不能为空!", 
                            "温馨提示",
                            JOptionPane.PLAIN_MESSAGE, 
                            new ImageIcon("image\\sprout01.png"));
                }

            }


        });

        leftDownLabel = new JLabel(new ImageIcon("image\\user01.png"));
        leftDownLabel.setBounds(10, 15, 25, 25);
        leftDownLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                new loginRecordThread().start();
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                leftDownLabel.setIcon(new ImageIcon("image\\user02.png"));
            }

            @Override
            public void mouseExited(MouseEvent e) {
                leftDownLabel.setIcon(new ImageIcon("image\\user01.png"));
            }
        });
        rightDownLabel = new JLabel(new ImageIcon("image\\qrCode01.png"));
        rightDownLabel.setBounds(390, 15, 25, 25);
        rightDownLabel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                rightDownLabel.setIcon(new ImageIcon("image\\qrCode02.png"));
            }

            @Override
            public void mouseExited(MouseEvent e) {
                rightDownLabel.setIcon(new ImageIcon("image\\qrCode01.png"));
            }
        });
        belowJPanel.add(leftDownLabel);
        belowJPanel.add(loginButton);
        belowJPanel.add(rightDownLabel);

    }
    /**
     * 判断是否保存密码信息
     * @param user
     */
    private void savePasswordInfo(User user) {
        if (user != null) {
            String user_name = user.getUser_name().trim();
            String user_password = user.getUser_password().trim();
            String user_icon = user.getUser_icon();
            // 判断记住密码否选中
            if (remember.isSelected()) {
                account = new Account(user_name, user_password,
                        "true",user_icon,"true");

            } else {
                account = new Account(user_name, "", "false",user_icon,"false");
            }

            if ((accountContent.equals(user_name))
                    && (passContent.equals(user_password))) {

                accountDatabaseUtil.doAdd(account);
                breakWindom();// 界面跳转

            } else {
                JOptionPane.showMessageDialog(UserLoginView.this, "密码错误!",
                        "温馨提示", JOptionPane.PLAIN_MESSAGE,
                        new ImageIcon("image\\sprout01.png"));
            }
        } else {
            JOptionPane.showMessageDialog(UserLoginView.this, "用户名不存在!", 
                    "温馨提示",JOptionPane.PLAIN_MESSAGE, 
                    new ImageIcon("image\\sprout01.png"));
        }               
    }

    /**
     * 主界面跳转
     */
    public void breakWindom() {
        this.dispose();
        // 启动线程
        Client client = new Client(user);
        client.start();
        new ListMainView(user, client);

    }
}

信息展示模块

用户信息展示
如上图所述;

  • 主界面部分代码
package com.hz.view;

import java.awt.*;
import java.awt.event.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.*;
import com.hz.bean.User;
import com.hz.client.Client;
import com.hz.entertainment.Lattice.Maze;
import com.hz.thread.ChatRoomThread;
import com.hz.thread.PrivyThread;
import com.hz.util.DateFormatUtil;
import com.hz.util.FriendsDatabaseUtil;

/**
 * 列表主界面
 * 
 * @author ztw
 * 
 *         2016-12-4
 */
public class ListMainView extends JFrame {

    // 获取屏幕的宽和高
    private final int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    private final int height = Toolkit.getDefaultToolkit().getScreenSize().height;
    // 设置窗口的宽和高
    private final int windowWidth = 278;
    private final int windowHeight = 600;

    private JPanel headPanel, mainPanel, belowPanel;
    private JButton headButton, game;
    private JLabel Namelabel, signature, addFriends;
    private JTree tree;
    private Box box = Box.createVerticalBox();

    private User user;

    private Set<User> users = new HashSet<>();

    private List<User> list;

    private Font f2 = new Font("Georgia", Font.PLAIN, 16);

    private Font f1 = new Font("方正舒体", Font.PLAIN, 24);

    public ListMainView() throws HeadlessException {
        initWindow();
        headPanelWindow();
        MainWindow();
    }

    private Client client;

    public ListMainView(User user, Client client) throws HeadlessException {
        this.user = user;
        this.client = client;
        initWindow();
        headPanelWindow();
        MainWindow();
    }

    public void MainWindow() {

        mainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        mainPanel.setBackground(Color.white);
        box.add(Box.createVerticalStrut(86));
        box.add(mainPanel);

        belowPanel = new JPanel();

        game = new JButton("---娱乐一分钟,幸福快乐生活一辈子!---");
        game.setForeground(Color.GREEN);
        box.add(game);
        game.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                new latticeMaze(user).start();
            }
        });
        DefaultMutableTreeNode node = new DefaultMutableTreeNode("联系人列表");
        // 子目录
        DefaultMutableTreeNode node_1 = new DefaultMutableTreeNode("都识的好友呵");
        node.add(node_1);
        /*
         * 遍历好友列表
         */
        FriendsDatabaseUtil util = new FriendsDatabaseUtil();
        list = (List<User>) util.getByID("" + user.getUser_id());
        for (User user : list) {
            DefaultMutableTreeNode node_1_1 = new DefaultMutableTreeNode(user);
            node_1.add(node_1_1);
        }

        tree = new JTree(node);
        mainPanel.add(tree);
        this.add(box);
        box.add(Box.createVerticalStrut(5));
        listenerTree();

    }

    class latticeMaze extends Thread {
        private User user;

        public latticeMaze(User user) {
            this.user = user;
        }

        @Override
        public void run() {
            Maze maze = new Maze(user);
            maze.start();
        }
    }

    /**
     * 对树子叶监听
     */
    public void listenerTree() {
        tree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                TreePath path = tree.getPathForLocation(e.getX(), e.getY());
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) path
                        .getLastPathComponent();
                Object object = node.getUserObject();
                if (e.getClickCount() == 2 && node.isLeaf()
                        && object instanceof User) {
                    User toUser = (User) object;
                    breakWindom(toUser);
                }
            }
        });
    }

    /**
     * 页面跳转
     * 
     * @param name
     */
    public void breakWindom(User toUser) {
        // this.dispose();关闭当前窗口
        new PrivyThread(toUser, user, client).start();
    }

    /**
     * 框架初始化
     */
    public void initWindow() {
        this.setTitle("登录");
        // 设置窗体位置和大小
        this.setBounds((int) ((width - windowWidth) * 1.0 / 1.1),
                ((height - windowHeight) / 9), windowWidth, windowHeight);
        this.setLayout(new BorderLayout(3, 1));
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setUndecorated(true);// 去掉窗口的装饰
        this.getRootPane().setWindowDecorationStyle(JRootPane.WIDTH);
        this.setResizable(false);// 设置窗体不可改变大小
        // 设置窗口图标
        Image img = Toolkit.getDefaultToolkit().getImage("image\\sprout01.png");
        this.setIconImage(img);
        this.setVisible(true);

    }

    private JLabel sm1, sm2;

    /**
     * 顶部面板
     */
    public void headPanelWindow() {

        headPanel = new JPanel(null) {
            @Override
            protected void paintComponent(Graphics g) {
                ImageIcon icon = new ImageIcon("image\\main\\cloud02.png");
                Dimension dim = getSize();
                g.drawImage(icon.getImage(), -100, 0, dim.width, dim.height,
                        null);
            }
        };
        headPanel.setBounds(0, 0, width, 86);
        this.add(headPanel);
        headButton = new JButton(new ImageIcon(user.getUser_icon()));
        headButton.setBounds(10, 16, 60, 60);
        listenerMonsterChat();
        headPanel.add(headButton);

        Namelabel = new JLabel(user.getUser_nickname(), new ImageIcon(
                "image\\cancel01.png"), 4);
        Namelabel.setBounds(80, 16, 60, 15);
        headPanel.add(Namelabel);

        signature = new JLabel(user.getLog_autograph());
        signature.setBounds(80, 40, 140, 15);
        signature.setForeground(new Color(173, 173, 173));
        headPanel.add(signature);

        sm1 = new JLabel("MCR: " + user.getUser_money());
        sm1.setForeground(Color.yellow);
        sm1.setBounds(80, 60, 100, 20);
        sm1.setFont(f2);
        sm2 = new JLabel("币");
        sm2.setFont(f1);
        sm2.setForeground(Color.yellow);
        sm2.setBounds(180, 60, 25, 20);

        addFriends = new JLabel(new ImageIcon("image\\main\\user01.png"));
        addFriends.setBounds(235, 55, 25, 25);
        addFriends.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                new ChatRoomThread(user).start();

            }

            @Override
            public void mouseEntered(MouseEvent e) {
                addFriends.setIcon(new ImageIcon("image\\main\\user02.png"));
            }

            @Override
            public void mouseExited(MouseEvent e) {
                addFriends.setIcon(new ImageIcon("image\\main\\user01.png"));
            }
        });
        headPanel.add(addFriends);
        headPanel.add(sm1);
        headPanel.add(sm2);



        // 关闭窗口时事件  
        this.addWindowListener(new WindowAdapter() {  
            public void windowClosing(WindowEvent e) {  
                JOptionPane.showMessageDialog(ListMainView.this, "确定要退出程序?",
                        "温馨提示", JOptionPane.PLAIN_MESSAGE,
                        new ImageIcon("image\\sprout01.png"));
                System.exit(0);// 退出程序  
            }  
        }); 
    }

    /**
     * 头像点击监听
     */
    private void listenerMonsterChat() {

        headButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                new UserUpdate(user).start();

            }
        });

        headButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                new UserInfo(user).start();
            }

            @Override
            public void mouseExited(MouseEvent e) {
                new UserInfo(user).stop();

                infoShow.dispose();
            }

        });
    }

    private UserInfoShow infoShow;

    class UserInfo extends Thread {
        User user = null;

        public UserInfo(User user) {
            this.user = user;
        }

        @Override
        public void run() {
            infoShow = new UserInfoShow(user);
        }
    }

    class UserUpdate extends Thread {
        User user = null;

        public UserUpdate(User user) {
            this.user = user;
        }

        @Override
        public void run() {
            new UserUpdateInformation(user.getUser_nickname(),
                    user.getUser_sex(), user.getUser_icon(),
                    user.getUser_email(), user.getUser_money(),
                    user.getRegister_date(), user.getLog_autograph(), user);
        }
    }

}

主聊天程序

  • 私聊
    私人聊天
    如上图:好友之间可以进行私人聊天,当然,这里的离线消息,也是可以接收到的
    ,同时界面的历史记录用户也是可以获取到的,后台都有记录

  • 群聊房间
    群聊房间
    (这里采用了网上一兄弟的界面绘制) 如上图:不管是否好友的关系,只要注册了用户,就可以和所有用户进行通信,(这里开启了一个单独的子服务端口)服务器也可以进行监听所有消息,可以对所有用户发送消息

    数据库表结构
    本项目,采用SQL Server2008数据库做后台,共四张简单表结构组成

信息修改设计

主要针对用户的基本信息结构设计

项目结构
如上图:整个项目的目录结构

因为代码量比较大,所以没有全部贴出,有需要的可以去我的资源中下载整个项目源码包括(项目源码,后台数据库,PPT简介)!

因为是个人原创耗时一个礼拜,所以请赏5个金币吧!感谢了!
下载地址:http://download.csdn.net/detail/qq_33624284/9708767

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值