一、需求设计
本文设计的的应用模式如下图所示(注册过程大同小异,此处略过):
当以游客身份访问时:
当登陆过后,再次在当前浏览器中访问时:
⚠️注意:本文的设定是不关闭当前浏览器,再次访问该网站则自动登陆,若关闭了当前浏览器,重新开启新的浏览器进行访问,那么需要重新登陆(此处一旦登陆,某段时间内可记住密码)。当然,很多网站关闭浏览器退出后,再开启新浏览器进行访问仍能保持登陆状态,这在功能上也就是使用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} <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概念以及功能。
相关推荐
JavaEE源代码 jaxen-1.1-beta-7JavaEE源代码 jaxen-1.1-beta-7JavaEE源代码 jaxen-1.1-beta-7JavaEE源代码 jaxen-1.1-beta-7JavaEE源代码 jaxen-1.1-beta-7JavaEE源代码 jaxen-1.1-beta-7JavaEE源代码 jaxen-1.1-...
javaee-api-8.0-javadoc.jar,这是javaee1.8api的jar包,解压后可用javadoc2chm制作成chm帮助文档。
JavaEE源代码 struts2-core-2.0.11JavaEE源代码 struts2-core-2.0.11JavaEE源代码 struts2-core-2.0.11JavaEE源代码 struts2-core-2.0.11JavaEE源代码 struts2-core-2.0.11JavaEE源代码 struts2-core-2.0.11JavaEE源...
JavaEE源代码 struts2-spring-plugin-2.0.11JavaEE源代码 struts2-spring-plugin-2.0.11JavaEE源代码 struts2-spring-plugin-2.0.11JavaEE源代码 struts2-spring-plugin-2.0.11JavaEE源代码 struts2-spring-plugin-...
JavaEE源代码 commons-logging-1.0.4JavaEE源代码 commons-logging-1.0.4JavaEE源代码 commons-logging-1.0.4JavaEE源代码 commons-logging-1.0.4JavaEE源代码 commons-logging-1.0.4JavaEE源代码 commons-logging-...
JavaEE源代码 commons-collections-2.1.1JavaEE源代码 commons-collections-2.1.1JavaEE源代码 commons-collections-2.1.1JavaEE源代码 commons-collections-2.1.1JavaEE源代码 commons-collections-2.1.1JavaEE源...
JavaEE(Java Platform, Enterprise Edition)是一个开源的、跨平台的应用服务器标准,它包含了多个技术规范,如Servlet、JSP、EJB(Enterprise JavaBeans)、JPA(Java Persistence API)和JMS(Java Message ...
java javaee-api-6.0-5
JavaEE入门
JavaEE 5.1.2是这个平台的一个特定版本,发布于2007年,提供了对Web服务、事务处理、数据库连接、EJB(Enterprise JavaBeans)等关键功能的支持。 在Java开发中,JMS(Java Message Service)是一个重要的组件,...
根据提供的文件信息,这里将基于标题“JavaEE入门视频教程资源分享”以及描述中的提示来展开相关的JavaEE知识点介绍。 ### JavaEE概述 Java Platform, Enterprise Edition(JavaEE)是Sun Microsystems公司为满足...
javaweb/javaEE常用jar包,亲测可用,导入到java工程中使用
通过研究这套源码,开发者不仅可以了解到JavaEE各个组件的基本用法,还可以掌握如何将这些组件集成到一个完整的应用中,以及如何进行测试和部署。这对于提升JavaEE开发者的实践能力和项目经验非常有帮助。同时,配合...
Java EE 5是这个平台的一个重要版本,它在2006年发布,带来了许多改进和新特性,旨在简化开发过程并提高生产力。在这个“javaee5-doc-api”压缩包中,包含的是Java EE 5的官方API文档,对于开发者来说是一份非常重要...
JavaEE源代码 dom4j-1.6.1JavaEE源代码 dom4j-1.6.1JavaEE源代码 dom4j-1.6.1JavaEE源代码 dom4j-1.6.1JavaEE源代码 dom4j-1.6.1JavaEE源代码 dom4j-1.6.1JavaEE源代码 dom4j-1.6.1JavaEE源代码 dom4j-1.6.1JavaEE源...
3. **2020-03版本**: 这个版本代表了2020年3月发布的一个重要更新,其中可能包括性能优化、新的API、修复的bug和增强的功能。Eclipse社区定期发布新版本,以保持与最新的Java技术同步,并持续提升用户体验。 4. **...
【Javaee --- 学生成绩管理系统】是一个基于JavaEE技术平台开发的应用,主要目标是实现对学校学生成绩的有效管理和分析。这个系统利用了JavaEE的多层次架构,包括前端展示层、业务逻辑处理层以及数据访问层,以实现...
netbeans-7.1.2-ml-javaee-windows.part2
JavaEE源代码 jstl-1.2JavaEE源代码 jstl-1.2JavaEE源代码 jstl-1.2JavaEE源代码 jstl-1.2JavaEE源代码 jstl-1.2JavaEE源代码 jstl-1.2JavaEE源代码 jstl-1.2JavaEE源代码 jstl-1.2JavaEE源代码 jstl-1.2JavaEE源...