Java后台登录注册管理系统

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/binbinqq86/article/details/81746294

转载请注明出处:https://blog.csdn.net/binbinqq86/article/details/81746294

项目简介

本文是笔者自己学习后台开发打响的第一枪,也是后台开发最基础的了,记得刚毕业的时候做过一个web项目,一直到今天都没有再了解过这方面,如今重新拾起,感觉还是需要多了解一些后端的东西,如果一直停留在移动端和前端,知识面未必太过狭窄。这次主要就是做了一个简易版的用户登录注册管理系统,实现了基本的增删查改,当然还有很多不完善的地方,后续随着学习的深入再去逐渐深入和完善。

环境搭建

本项目开发的环境为Mac10.12.6系统,jdk选择的是1.8

ide的选择

ide的话,由于我之前开发Android用的是eclipse,知道它也可以做web项目,不过后来谷歌推出Android Studio后,eclipse就立刻被鄙视下去了,jetBrains公司所推出的IntelliJ IDEA(以下简称idea),在智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超常的,可以说你用过之后,就不想再回到eclipse时代了,不过如果你还是喜欢用eclipse,两者的项目也是可以相互转换的,它的旗舰版本还支持HTML,CSS,PHP,MySQL,Python等。免费版只支持Java等少数语言。该公司还推出了PyCharm、DataGrip、PhpStorm、WebStorm等众多ide工具,可以说非常好用和强大。下载地址如下:https://www.jetbrains.com/idea/download/
这里写图片描述

版本的话,这里要注意一下,我们选择红框的这个版本,它包含的功能更全面,右边的是免费版,但是功能有限,不能去部署tomcat服务器。

数据库相关

数据库这里我们就选择mysql8.0.12社区版本,官网下载地址如下:https://dev.mysql.com/downloads/mysql/

我们选择dmg安装版本即可。安装完成之后会在设置里面生成快捷键,可以进去启动和停止mysql服务:

当然也可以通过命令行去启动,这里我们把mysql配置到环境变量里面去,这样方便一些,打开/etc/profile文件,在里面添加如下一行即可:

export PATH=$PATH:/usr/local/mysql-8.0.12-macos10.13-x86_64/bin

启动服务就可以不用进到bin目录下再输入命令了,每个平台的命令不一样,这里不再赘述。当然你也可以用其他查看数据库的软件比如navicat premium,datagrip,idea自带的database来建立和查看数据库,不过最好建议用命令行的方式去操作这些,过度依赖ide,不是一个好的习惯,毕竟后面数据库crud操作都是sql语句,包括建表什么的,所以说还是用命令比较好,这里推荐去w3school看看基本的教程就可以了,后面可以在学习的过程中慢慢去熟练。

tomcat相关

tomcat就是用来部署我们的web程序的容器,我们的项目可以在里面去跑,说白了就是服务器。我们去官网下载即可,这里我选择的是8.0版本,下载地址如下:https://tomcat.apache.org/download-80.cgi
我们选择如下红框内的去下载:
这里写图片描述

下载后直接解压即可,无需安装,然后配置到环境变量:

export PATH=$PATH:/Users/tb/Library/apache-tomcat-8.0.53/bin

然后打开终端,运行startup.sh即可打开tomcat服务,在浏览器输入http://localhost:8080即可打开tomcat首页,代表已经成功了。如需更改端口号,打开config目录下的server.xml配置即可,另外我们需要添加一个默认用户,同样打开config目录下,找到tomcat-users.xml文件,添加如下即可:


<role rolename="manager-gui"/>
<user username="admin" password="admin" roles="manager-gui"/>

然后重启服务,我们就可以用admin登录了。

开始

上述都是基本的准备工作,下面我们就可以开始真正的编码了,打开idea,新建工程:

然后下一步选择工程目录和项目名称,完成即可。项目目录结构如下:
这里写图片描述

接下来我们在web.xml里面添加如下:

<welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

这个就代表我们的首页了,接下来我们配置一下服务器:
这里写图片描述
我们选取这里的Edit Configurations…,打开窗口:

注意:如果这里看不到tomcat选项,一个原因就是开头说的idea版本问题,另外就是需要安装一个插件:
这里写图片描述
我们点击Local后,配置如下:

Deployment标签中配置如下:
这里写图片描述

配置完成后,我们点击右上角的绿色三角形运行按钮,启动服务器,可以在这里查看日志:
这里写图片描述

然后,我们启动浏览器输入http://localhost:8090,就可以看到我们的首页了:
这里写图片描述

JDBC封装

上面我们已经部署好服务器,并且可以运行我们的程序了,下面我们就开始真正的编码业务,首先就是数据库这块了,我们的源码目录结构如下:
这里写图片描述
JdbcUtil就是我们封装的数据库工具类:

/**
 * @author tb
 * @time 2018/8/14 下午5:07
 * @des 获取数据库连接对象
 */
public class JdbcUtil {
    //mysql驱动包名
    private static final String DRIVER_NAME = "com.mysql.cj.jdbc.Driver";
    //数据库名称
    private static final String DB_NAME = "tb";
    //数据库连接地址
    private static final String URL = "jdbc:mysql://localhost:3306/" + DB_NAME + "?characterEncoding=utf8&useSSL=false&serverTimezone=GMT";
    //用户名
    private static final String USER_NAME = "root";
    //密码
    private static final String PASSWORD = "tb123=root";

    /**
     * @return
     */
    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName(DRIVER_NAME);//注意要把jdbc的jar包放到tomcat的lib目录下
            connection = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
            if(connection!=null){
                System.out.println("connection to the database is success......");
            }else{
                System.out.println("connection to the database is failure......");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

这里有个注释,就是我们项目里面首先需要引入mysql提供的jdbc的jar包,官网下载地址如下:https://dev.mysql.com/downloads/connector/j/5.0.html
这里写图片描述

下载之后,得到一个jar包,放到工程的lib目录下,然后加入引用即可,另外我们需要放一份到我们的tomcat的lib目录下,否则后面在网页上调用servlet的时候,操作数据库tomcat会找不到jdbc的驱动类。

DAO封装

dao就是用来操作数据库的一个对象,我们做如下封装:

/**
 * @author tb
 * @time 2018/8/14 下午5:02
 * @des 所有crud的抽象
 */
public interface IDao<T> {
    /**
     * 向数据库增加n条数据
     *
     * @param list 需要插入的数据集合
     * @return 返回受影响的条数
     */
    int[] create(List<T> list);

    /**
     * 向数据库查询数据
     *
     * @param o 需要查询的条件
     * @return 返回查到的数据集合
     */
    List<T> read(Object o);

    /**
     * 向数据库更新数据
     *
     * @param list 需要更新的数据集合
     * @return 返回受影响的条数
     */
    int[] update(List<T> list);

    /**
     * 向数据库删除数据
     *
     * @param list 需要删除数据的条件集合
     * @return 返回受影响的条数
     */
    int[] delete(List<Object> list);
}

写一个抽象接口,这样不同的对象都可以使用,下面是具体实现,

/**
 * @author tb
 * @time 2018/8/14 下午5:08
 * @des 用户操作相关
 */
public class UserDaoImpl implements IDao<User> {
    private Connection connection;
    private PreparedStatement preparedStatement;

    public static UserDaoImpl getInstance() {
        return SingletonInstance.instance;
    }

    private static class SingletonInstance {
        private static final UserDaoImpl instance = new UserDaoImpl();
    }

    private UserDaoImpl() {
        connection = JdbcUtil.getConnection();
        String sql = "create table if not exists user" +
                "(userId int(10) auto_increment primary key," +
                "userName varchar(20) not null," +
                "nickName varchar(20) null," +
                "password varchar(20) not null," +
                "role int(5) default '0' not null," +
                "constraint userName unique (userName)" +
                ") DEFAULT CHARSET=utf8mb4";//支持emoji表情
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.closeQuietly(connection, preparedStatement);
        }

        List<User> list=read(null);
        if(list!=null&&list.size()>0){
            for (User u:list) {
                if(u.userName.equals("admin")){
                    return;
                }
            }
        }
        //添加一个默认的管理员
        List<User> l=new ArrayList<>();
        User u=new User();
        u.userName="admin";
        u.nickName="admin";
        u.role=-1;
        u.password="admin";
        l.add(u);
        create(l);
    }

    @Override
    public int[] create(List<User> list) {
        String sql = "insert into user(userName,nickName,password,role) values(?,?,?,?)";
        try {
            if (connection == null || connection.isClosed()) {
                connection = JdbcUtil.getConnection();
            }
            preparedStatement = connection.prepareStatement(sql);
            for (User user : list) {
                preparedStatement.setString(1, user.userName);
                preparedStatement.setString(2, user.nickName);
                preparedStatement.setString(3, user.password);
                preparedStatement.setInt(4, user.role);
                preparedStatement.addBatch();
            }
            return preparedStatement.executeBatch();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.closeQuietly(connection, preparedStatement);
        }
        return null;
    }

    @Override
    public List<User> read(Object o) {
        List<User> list = new ArrayList<>();
        ResultSet resultSet;
        String sql = "select * from user where userName=?";
        if (o == null) {
            sql = "select * from user";
        }
        try {
            if (connection == null || connection.isClosed()) {
                connection = JdbcUtil.getConnection();
            }
            preparedStatement = connection.prepareStatement(sql);
            if (o != null) {
                preparedStatement.setString(1, String.valueOf(o));
            }
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                User user = new User();
                user.userName = resultSet.getString("userName");
                user.nickName = resultSet.getString("nickName");
                user.password = resultSet.getString("password");
                user.userId = resultSet.getInt("userId");
                user.role = resultSet.getInt("role");
                list.add(user);
            }
            return list;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.closeQuietly(connection, preparedStatement);
        }
        return null;
    }

    @Override
    public int[] update(List<User> list) {
        String sql = "update user set nickName=?,password=?,role=? where userName=?";
        try {
            if (connection == null || connection.isClosed()) {
                connection = JdbcUtil.getConnection();
            }
            preparedStatement = connection.prepareStatement(sql);
            for (User user : list) {
                preparedStatement.setString(1, user.nickName);
                preparedStatement.setString(2, user.password);
                preparedStatement.setInt(3, user.role);
                preparedStatement.setString(4, user.userName);
                preparedStatement.addBatch();
            }
            return preparedStatement.executeBatch();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.closeQuietly(connection, preparedStatement);
        }
        return null;
    }

    @Override
    public int[] delete(List<Object> list) {
        String sql = "delete from user where userName=?";
        try {
            if (connection == null || connection.isClosed()) {
                connection = JdbcUtil.getConnection();
            }
            preparedStatement = connection.prepareStatement(sql);
            for (Object o : list) {
                preparedStatement.setString(1, String.valueOf(o));
                preparedStatement.addBatch();
            }
            return preparedStatement.executeBatch();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.closeQuietly(connection, preparedStatement);
        }
        return null;
    }
}

我们采用懒汉式的静态内部类单例,构造函数里面去对数据库的user表来一个初始化,并添加一个默认的admin用户,我们来查询一下,看看表结构:
这里写图片描述

这里我们的数据库和表都采用utf8mb4编码格式,可以用来支持中文和emoji表情。crud我们均采用preparedStatement来防止sql注入,提高效率。

Junit编写

crud都写好了,下面就来编写测试用例来验证一下,我们需要引入juint的插件,然后新建一个test文件夹,右键选择Make Directory As/Test Resource Root,把它转化为源码测试目录,可以看到颜色就会改变,然后在需要测试的类名上按下Alt+enter键,选择create test,
这里写图片描述
这里写图片描述
选择需要测试的方法,就会自动为我们创建如下目录和测试类:
这里写图片描述
接下来我们直接写测试代码即可:

public class UserDaoImplTest {

    private UserDaoImpl userDao = UserDaoImpl.getInstance();
    private List<User> list = new ArrayList<>();


    @Before
    public void init() {
        list.clear();
        User user1 = new User();
        user1.password = "1";
        user1.userName = "user1";
        list.add(user1);

        User user2 = new User();
        user2.password = "2";
        user2.userName = "user2";
        list.add(user2);

        User user3 = new User();
        user3.password = "3";
        user3.userName = "user3";
        list.add(user3);
    }

    @Test
    public void create() {
        int[] res=userDao.create(list);
        assertEquals(3,res.length);
    }

    @Test
    public void read() {
        List<User> l=userDao.read("user1");
        assertEquals(1,l.size());
        assertEquals("user1",l.get(0).userName);
    }

    @Test
    public void update() {
        List<User> l=userDao.read("user1");
        l.get(0).nickName="haha";
        int[] i=userDao.update(l);
        assertEquals(1,i.length);
    }

    @Test
    public void delete() {
        List<Object> l=new ArrayList<>();
        l.add("user3");
        l.add("user2");
        int[] i=userDao.delete(l);
        assertEquals(2,i.length);
    }
}

需要测试哪个方法,点击下图红圈的按钮即可,测试通过就代表没问题,不然就要重新检查代码了
这里写图片描述

jsp编写

下面开始编写我们的页面:
这里写图片描述
这里我们统一放到user文件夹下面方便管理,分别对应登录,修改,增加注册页面,首页我们放在了外边,具体代码就不在这里贴出了,都是基本的js和html,感兴趣的可以去下载源码查看(文章最后会给出源码)。

servlet编写

有了页面,就需要去跟数据库交互了,这里就用到了servlet(当然也可以在jsp页面中操作数据库,但这么做不好),他就是负责数据库跟页面之间交互的,就是mvp模式中的p。我们以登录为例:

/**
 * @author tb
 * @time 2018/8/15 下午4:46
 * @des 用户登录
 */
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doGet(req, resp);
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //必须注释掉,里面已经resp.sendError了
//        super.doPost(req, resp);
        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");//写入数据库防止乱码
        //此处对应JSP中的标签名,必须是name属性
        String userName = req.getParameter("userName");
        String password = req.getParameter("password");
        List<User> list = UserDaoImpl.getInstance().read(userName);
        if (list != null && list.size() > 0 && password.equals(list.get(0).password)) {
            System.out.println("登录成功==="+list.get(0).toString());
            //登录成功后,就将用户存储到session中
            //登陆成功,我是重定向到其它页面,重定向request作用域不能延伸
            //所以这里我要用session才可以把成功的信息传递给index.jsp
            req.getSession().setAttribute("user", list.get(0));
            req.getSession().setAttribute("welcome", userName);
            resp.sendRedirect("index.jsp");
        } else {
            System.out.println("=========登录失败========");
            //登陆失败,我用的是转发,转发request作用域是连续的,所以我这里可以用request传递失败的信息给jsp页面
            req.setAttribute("msg", userName + "登录失败");
            req.getRequestDispatcher("/user/login.jsp").forward(req, resp);
        }
    }
}

这里有几个重要的点都写在注释里面了,可以参考一下代码。另外需要注意都就是在web.xml中配置servlet的时候,路径引起的问题。

<servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.tb.system.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <!--
        实际访问的路径,默认是web文件夹下面,如果页面在其他目录下,需要加上该目录
        如果在web下面,直接/LoginServlet就可以
        -->
        <!--<url-pattern>/user/LoginServlet</url-pattern>-->
        <!--
        或者直接把表单指向地址写成这样:action="<%=request.getContextPath()%>/LoginServlet"
        <%=request.getContextPath()%>指向当前默认目录,就是部署服务器配置的Application context
        -->
        <url-pattern>/LoginServlet</url-pattern>
    </servlet-mapping>

可以看到注释里面所说的,而jsp中对应的就是这样(第三行):

<body>
<h1 align="center">用户登录</h1>
<form action="<%=request.getContextPath()%>/LoginServlet" method="post">
    <table align="center">
        <tr>
            <td width="80" align="right">用户名:</td>
            <td>
                <input id="userName" name="userName" type="text" placeholder="请输入用户名"/>
            </td>
        </tr>
        <tr>
            <td width="80" align="right">密码:</td>
            <td>
                <input id="password" name="password" type="password" placeholder="请输入密码"/>
            </td>
        </tr>
    </table>
    <p></p>
    <div align="center">
        <input name="login" value="登录" type="submit" class="inputText" style="color: #000000" onclick="return check()">

    </div>
</form>
</body>

运行结果

现在重新部署一下我们的程序,就可以看到如下运行结果了:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

写在最后

到此一个简易的用户登录注册管理系统就实现了,这里只是一个练习项目,如果需要在实际中去应用,还需要很多修改的地方,而且现在都是在用ssm框架去做,所以可以当作一个入门来看,中间也碰到了很多问题,一点一点摸索,花了三四天时间才做完,最后给出源码下载地址:


源码下载

猜你喜欢

转载自blog.csdn.net/binbinqq86/article/details/81746294