JavaEE入门看这个系列真的就够了(一)----登陆

一、需求设计

本文设计的的应用模式如下图所示(注册过程大同小异,此处略过):

当以游客身份访问时:

当登陆过后,再次在当前浏览器中访问时:

⚠️注意:本文的设定是不关闭当前浏览器,再次访问该网站则自动登陆,若关闭了当前浏览器,重新开启新的浏览器进行访问,那么需要重新登陆(此处一旦登陆,某段时间内可记住密码)。当然,很多网站关闭浏览器退出后,再开启新浏览器进行访问仍能保持登陆状态,这在功能上也就是使用Cookie和Session的区别,后文会提到!

本文介绍第一个功能:登陆功能!

二、具体实现

(1)项目框架

网站设计的一个经典模式就是MVC模式:1).M,Model,表示模型层,用很多属性来描述一个类,这个类就是模型,比如,一个简单的用户模型就是用户名和密码,于是我们可以用一个UserBean类来表述这个用户模型,同时还包括持久层的对数据库的操作;2).V,views,表示视图层,即给用户展示的界面,在JavaEE中,jsp文件完成V的作用;3)C,controller,控制器,控制页面处理和跳转的主逻辑。

本文使用的JavaEE是jsp+servlet+javabean,并没有使用更高级的框架。为了充分结合MVC的设计模式,我们将Intellij idea中的工程目录建成如下图结构(此处参考基于Servlet+JSP+JavaBean开发模式的用户登录注册,该文中对给基于MVC模式的jsp+servlet+javabean网站设计介绍得非常详细,也是本文一个主要参考来源):

从以上结构,我们可以进行一下分类(这个分类并不一定准确,但一定程度上可以帮助我们理解程序):
总的来说,就是domain建立User的用户模型,同时Dao层实现对用户模型的数据库操作;controller实现后台逻辑,比如登陆成功跳转首页、登陆失败跳转失败页面,而其他如service等是登陆等逻辑过程的具体实现,是支持controller实现的必要部分;最后jsp文件作为展示页面。具体在Intellij idea中创建一个JavaEE项目的方法如下:

1>.如果你是学生,那么使用你的学生邮箱很容易就能在Jetbrains上注册一个学生账号,那么无论是Intellij idea还是PyCharm这样的神器,你都可以免费使用专业版了!打开Intellij idea后,创建一个新的工程,然后
选择“Java Enterprise”中的“Web Application(3.1)”,然后选择工程的路径和工程名字,我把这个工程叫做“MyLab”。
新建后的工程结构如下图所示,那么现在就是要按照前文中的项目结构进行修改。

主要修改的地方是1)src文件夹中按照上文中的目录结构进行修改(其实并非每个项目都要这么麻烦的建立各个package,只是为了更好地凸显出MVC模式的层次结构以及更好的管理项目,所以才这么干。实际情况应该具体情况具体分析!)2)在web文件夹下的WEB-INFO文件夹下新建“classes”和“lib”文件夹,这是java编译后文件的目录以及程序中使用的包的目录,当然,在未设置之前,这两个文件夹是啥功能也没有的,于是,还要做以下设置:打开“File”,选择“Project Structure”,选择“modules”,先选择“Paths”项,选中“Use modules compile output path”,然后将“Output path”和“Test output path”的路径都选择刚新建的“classes”目录,这样一来,编译后的.class文件都将生成在“classes”文件夹中
这当然没完,还需要设置程序使用包的路径“lib”,如下图选择好JAR包路径!
实际上,上述两部添加“classes”和“lib”并不一定是必须的,但是,为了接下来的方便,我们按照这个框架来写,是一个非常明智的选择!
 接下来就是要配置Tomcat服务器,首先新建一个Tomcat本地服务器,点击“Run”选项,选择“Edit Configurations”,按照下图所示,新建一个服务器。
然后选择上图的“Configure..”,配置你本地的Tomcat路径,即可(这个服务器名字自取)!

最后,我们要为这个项目配置一个访问路径,仍在“ Configurations”中,选择“Deployment”,选中项目的“war exploded”(这就是整个项目的部署文件),更改“Application context”

到此为止,网站初期的工作就全部完成了!接下来可以开始编写咱们的登陆网站!

(2)功能实现

接下来,本文将分功能来介绍具体实现。

1>.登陆功能(从登陆,熟悉JavaEE的MVC)

该功能主要流程是:游客在界面上写入用户名和密码,点击登录按钮,后台读取数据库进行用户登录验证,验证成功则进入到登录界面。首先我们可以先看看界面是什么样子的。

登陆前:

                                                                         图1 登陆前界面

登陆前的index.jsp视图:

<%@ page import="domain.UserBean,web_listener.PeopleListner" %><%--
  Created by IntelliJ IDEA.
  User: lps
  Date: 2017/3/3
  Time: 下午3:53
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>首页</title>
</head>
<body>
<h1 align="center">3033工作室</h1>
<hr>
当前在线人数:<%= PeopleListner.getActiveSessions()%>
<br>
<%
    //通过session判断当前是否已经是登陆状态
    UserBean user;
    user = (UserBean) request.getSession().getAttribute("user");
    if (user == null)
    {
%>
<a href="login.jsp">请登陆</a>
<%
}
else
{
%>
欢迎${user.username}
&nbsp;
&nbsp;
&nbsp;
<a href="${pageContext.request.contextPath }/LogoutServlet" >注销</a>
<%
    }
%>
<br>
<a href="usercansee.jsp">游客请先登录再查看</a>
</body>
</html>

 登陆界面(这是在bootstrap上下载的源码):

                                                                           图2 登陆界面

登陆界面login.sp视图:

<%--
  Created by IntelliJ IDEA.
  User: lps
  Date: 2017/3/1
  Time: 下午10:10
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="en">

<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap Login Form Template</title>

    <!-- CSS -->
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:400,100,300,500">
    <link rel="stylesheet" href="assets/bootstrap/css/bootstrap.min.css">
    <link rel="stylesheet" href="assets/font-awesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="assets/css/form-elements.css">
    <link rel="stylesheet" href="assets/css/style.css">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
    <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

    <!-- Favicon and touch icons -->
    <link rel="shortcut icon" href="assets/ico/favicon.png">
    <link rel="apple-touch-icon-precomposed" sizes="144x144" href="assets/ico/apple-touch-icon-144-precomposed.png">
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="assets/ico/apple-touch-icon-114-precomposed.png">
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="assets/ico/apple-touch-icon-72-precomposed.png">
    <link rel="apple-touch-icon-precomposed" href="assets/ico/apple-touch-icon-57-precomposed.png">

</head>

<body>

<%       //通过cookie找到最近时间内登陆的用户,实现保存密码
    String username = "";
    String password = "";
    //获取当前站点的所有Cookie
    Cookie[] cookies = request.getCookies();
    for (int i = 0; i < cookies.length; i++) {//对cookies中的数据进行遍历,找到用户名、密码的数据
        if ("username".equals(cookies[i].getName())) {
            username = cookies[i].getValue();
        } else if ("password".equals(cookies[i].getName())) {
            password = cookies[i].getValue();
        }
    }
%>
<!-- Top content -->
<div class="top-content">

    <div class="inner-bg">
        <div class="container">
            <div class="row">
                <div class="col-sm-8 col-sm-offset-2 text">
                    <h1><strong>Bootstrap</strong> Login Form</h1>
                    <div class="description">
                        <p>
                            This is a free responsive login form made with Bootstrap.
                            Download it on <a href="http://azmind.com"><strong>AZMIND</strong></a>, customize and use it as you like!
                        </p>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-6 col-sm-offset-3 form-box">
                    <div class="form-top">
                        <div class="form-top-left">
                            <h3>Login to our site</h3>
                            <p>Enter your username and password to log on:</p>
                        </div>
                        <div class="form-top-right">
                            <i class="fa fa-key"></i>
                        </div>
                    </div>
                    <div class="form-bottom">
                        <form role="form" action="mylogin" method="post" class="login-form">
                            <div class="form-group">
                                <label class="sr-only" for="form-username">Username</label>
                                <input type="text" name="username" placeholder="Username..." class="form-username form-control" id="form-username" value=<%=username%>>
                            </div>
                            <div class="form-group">
                                <label class="sr-only" for="form-password">Password</label>
                                <input type="password" name="password" placeholder="Password..." class="form-password form-control" id="form-password" value=<%=password%>>
                            </div>
                            <button type="submit" class="btn">Sign in!</button>
                        </form>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-sm-6 col-sm-offset-3 social-login">
                    <h3>...or login with:</h3>
                    <div class="social-login-buttons">
                        <a class="btn btn-link-1 btn-link-1-facebook" href="#">
                            <i class="fa fa-facebook"></i> Facebook
                        </a>
                        <a class="btn btn-link-1 btn-link-1-twitter" href="#">
                            <i class="fa fa-twitter"></i> Twitter
                        </a>
                        <a class="btn btn-link-1 btn-link-1-google-plus" href="#">
                            <i class="fa fa-google-plus"></i> Google Plus
                        </a>
                    </div>
                </div>
            </div>
        </div>
    </div>

</div>


<!-- Javascript -->
<script src="assets/js/jquery-1.11.1.min.js"></script>
<script src="assets/bootstrap/js/bootstrap.min.js"></script>
<script src="assets/js/jquery.backstretch.min.js"></script>
<script src="assets/js/scripts.js"></script>

<!--[if lt IE 10]>
<script src="assets/js/placeholder.js"></script>
<![endif]-->

</body>

</html>

该部分还有一些css,js的引用这里不作阐述,文后会给出源码。本文不对前端过多介绍。 

登陆后:

图3 登陆后界面

该部分与登陆前的index.jsp一致,只是利用了session对当前用户是否处于登陆状态进行了判断,最后显示不同的信息(游客显示“请登陆”按钮,用户显示“欢迎***”,隐藏“请登陆”按钮)。
 接下来,再来看看登陆功能是怎么实现的:

首先,我们在图1登陆前界面中点击请登陆按钮,界面即跳转到登陆界面图2。现在要实现的登陆功能即输入用户名和密码,后台在数据库中查找匹配,匹配成功则跳转到登陆后的页面图3,否则提示密码错误,并且一定时间后跳转回登陆界面图2。

我们尽量遵循MVC模式来讲解配置过程:

(1)M:我们来配置用户的模型,首先在mysql数据库中查看用户的字段信息:

根据该用户表的字段信息,我们在domain这个package中定义UserBean.java来表示用户的模型。

package domain;

/**
 * Created by lps on 2017/3/2.
 */
/**
 * 用户类
 * Created by lps on 2017/3/1.
 */
public class UserBean {
    private String username;
    private String password;

    public UserBean()
    {

    }

    public UserBean(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

那么,对于持久层,我们应该围绕用户模型对数据库进行操作,实现如下:

首先,需要配置JDBC的JAR包,由于上文已经将lib配置成JAR包访问路径,那么只需要将mysql-connector-java-5.1.40-bin.jar包复制到lib下即可;

配置完成后,我们在utils的package中定义一个数据库工具类,得到一个可用的数据库连接对象connection:

package utils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * Created by lps on 2017/3/3.
 */

public class DataBaseUtil {
    public DataBaseUtil() {
    }

    /**
     * 开启数据库,得到数据库对象
     * @return 数据库对象
     */
    public static Connection getConnection() {
        Connection connection = null;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            String sqle = "jdbc:mysql://localhost:3306/user_manage";
            connection = DriverManager.getConnection(sqle, "root", "683683");
            return connection;
        } catch (ClassNotFoundException var2) {
            var2.printStackTrace();
        } catch (SQLException var3) {
            var3.printStackTrace();
        }
        return connection;
    }

    /**
     * 关闭数据库
     * @param connection 数据库对象
     */
    public static void closeConnection(Connection connection) {
        if(connection != null) {
            try {
                connection.close();
            } catch (SQLException var2) {
                var2.printStackTrace();
            }
        }

    }
 接着,我们在dao的package中定义dao层的接口类型(我们需要验证用户信息,即查看某用户名和某密码对在数据库中是否存在)
package dao;

import domain.UserBean;

/**
 * Created by lps on 2017/3/2.
 */
public interface UserDao {
    //用户登陆验证
    public boolean getUser(UserBean user);
    //某用户名是否已存在
    public boolean isUserExist(String username);
    //将用户存入数据库
    public void saveUser(UserBean user);
}
 然后实现 在dao_impl的package中实现UserDao接口
package dao_impl;

import dao.UserDao;
import domain.UserBean;
import utils.DataBaseUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Created by lps on 2017/3/2.
 */
public class UserDaoImpl implements UserDao{
    /**
     * 登陆验证
     * @param user
     * @return true 验证成功 false 验证失败
     */
    public boolean getUser(UserBean user) {
        String username = user.getUsername();
        String password = user.getPassword();
        Connection conn = DataBaseUtil.getConnection();
        String sql = "select password from user_info WHERE username=?";
        try{
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setString(1, username);
            ResultSet resultSet = ps.executeQuery();
            //没有该用户,返回false
            if (!resultSet.next()) {
                return false;
            }
            //开始验证用户密码
            String real_password = resultSet.getString("password");
            //密码验证失败
            if (!password.equals(real_password))
            {
                return false;
            }
        }catch(SQLException e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }finally {
            DataBaseUtil.closeConnection(conn);
        }
        return true;
    }

    /**
     * 用户名是否已存在
     * @param username
     * @return
     */
    public boolean isUserExist(String username)
    {
        //连接数据库
        Connection connection = DataBaseUtil.getConnection();
        String sql = "select * from user_info where username=?";
        //访问数据库
        try
        {
            PreparedStatement ps = connection.prepareStatement(sql);
            ps.setString(1,username);
            //查询是否有该用户
            ResultSet rs = ps.executeQuery();
            if(!rs.next())
            {
                return false;
            }
        }catch(SQLException e) {//捕捉异常
            System.out.println(e.toString());
            e.printStackTrace();
        }finally {//关闭数据库
            DataBaseUtil.closeConnection(connection);
        }
        return true;
    }

    /**
     * 新注册用户,存入数据库
     * @param user
     */
    public void saveUser(UserBean user)
    {
        //得到数据库
        Connection connection = DataBaseUtil.getConnection();
        String sql = "insert into user_info values(?,?)";
        try{
            PreparedStatement ps = connection.prepareStatement(sql);
            ps.setString(1,user.getUsername());
            ps.setString(2,user.getPassword());
            //更新数据库
            ps.executeUpdate();
        }catch (SQLException e){
            e.printStackTrace();
        }finally {
            DataBaseUtil.closeConnection(connection);
        }
    }
}
 到此,用户模型以及dao层对用户模型进行操作的实现就结束了!这也可以看作是M的实现!

(2)V部分实际上就是上文中提到的jsp页面;

(3)C:主逻辑是在此实现

 首先,拿到前端的数据后,我们用一个servlet服务来统一管理,在web_controller中定义一个登陆的控制器LoginServlet

package web_controller;

import domain.UserBean;
import service.BusinessService;
import service_impl.BusinessServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by lps on 2017/3/3.
 */
public class LoginServlet extends HttpServlet{
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response) throws ServletException, IOException
    {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        UserBean user = new UserBean();
        user.setUsername(username);
        user.setPassword(password);
        BusinessService service = new BusinessServiceImpl();
        if(service.login(user)) {
            //存入cookie:name,password
            Cookie nameCookie = new Cookie("username", username);
            //设置Cookie的有效期:3天
            nameCookie.setMaxAge(60*60*24*3);
            Cookie pwdCookie = new Cookie("password", password);
            pwdCookie.setMaxAge(60*60*24*3);
            response.addCookie(nameCookie);
            response.addCookie(pwdCookie);
            //设置页面显示信息
            request.setAttribute("info", "登陆成功!欢迎您的访问!");
            //用户信息存入session,供当前访问使用
            request.getSession().setAttribute("user",user);
            //请求转发(带信息,而重定向是丢失信息的)
            request.getRequestDispatcher("index.jsp").forward(request, response);
        } else {//登陆失败
            request.setAttribute("info", "登陆失败!请确认后再尝试!");
            request.getRequestDispatcher("message.jsp").forward(request, response);
        }
    }
}
 为了方便管理,我们使用一个service服务接口来对前端数据、底层数据库访问以及逻辑操作进行封装, 在service的package中定义服务接口BusinessService
package service;

import domain.UserBean;

/**
 * Created by lps on 2017/3/3.
 */
public interface BusinessService {
    public boolean login(UserBean user);
}
在service_ipml的package中实现BusinessService接口
package service_impl;

import dao.UserDao;
import dao_impl.UserDaoImpl;
import domain.UserBean;
import service.BusinessService;

/**
 * Created by lps on 2017/3/3.
 */
public class BusinessServiceImpl implements BusinessService{
    private UserDao dao = new UserDaoImpl();
    @Override
    public boolean login(UserBean user) {
        return dao.getUser(user);
    }
}
 以上就是所有登陆相关的Java代码。

为了使得Servlet生效(实际上就是点击按钮后,能运行servlet中的doPost方法),我们还需要配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">


    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>web_controller.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/mylogin</url-pattern>
    </servlet-mapping>


</web-app>
 配置方法:如上所示,<servlet>和<servlet-mapping>中的<servlet-name>必须对应,<servlet-class>即servlet的java路径,记得带上包名,<url-pattern>对应的是前端的点击事件映射,也就是前端的点击事件就是通过这个映射来找到对应的servlet(表单中的action项)。

至此,登陆部分的实现已经完成了!

我们来结合程序回顾一下整个登陆过程的流程:

输入用户名、密码,点击登陆按钮 ----> 表单事件action:mylogin找到servlet配置的<url-pattern>:/mylogin, 后台LoginServlet的doPost方法被触发 ----> 调用BusinessService方法进行用户验证 ----> dao层操作数据库进行用户验证 ----> LoginServlet对结果进行处理(如页面跳转,session保存等)。

 下文将介绍----注销以及注销过程中用到的一些JavaEE概念以及功能。


 

 
 

 
 


 
 
 


 

猜你喜欢

转载自lps-683.iteye.com/blog/2360233