书店管理系统(Servlet+MySQL)登录与注册功能篇

书店管理系统(Servlet+MySQL)

这个工程主要是对之前的一些总结吧,尽可能地用上所学的所有功能来实现,具体代码稍后也会上传到Github上。

在前端上并没有用上CSS等技术,只用上了基础的HTML和部分JavaScript,这是因为这一篇文章注重于功能的具体实现而不是美观。在美观方面,我更倾向于在完成所有的工作之后,再一点点优化。而且我对于CSS的了解也不是很深,就不在这里献丑了。

这个小练习应用的主要技术是Servlet,当然还有与Servlet紧密结合,密不可分的JSP,MySQL只涉及最基础的语法和应用,而且为了方便操作,我主要是使用DBeaver客户端对MySQL进行操作,这样的操作大大提升了效率,而且更为直观。

其他工具是EclipseEE(2021.9)+JDK14+Tomcat9.0。Tomcat10.0以后的版本变化太大,和我从图书馆借来的教材区别过多,所以没有采用最新的技术。

总体上是跟着教材<电子工业出版社>出版的《JavaWeb程序设计》的设计思路,这本书的作者是张磊和丁香乾老师。这本教材给我的感受颇深,尤其要感谢这两位老师。

1.数据库设计

​ 建立一个数据库bookshop,数据库中实现两个表,表中的数据分别如下

表1:主要用于实现用户的登录和注册(名字主键)
在这里插入图片描述

表2:实现图书的信息输入,是系统的主体部分,主要实现图书的展示,线上的下单,还有后台的处理.

在这里插入图片描述

2.先实现数据库连接,JDBC的基石,DAO类

"D:\Friedrich Hsing’s Documents\JDBC配置文件\数据库操作类(实现).txt"

我把这个文件的代码复制了一份,放置在这个地址下,方便之后取用。

数据库相关的代码放置在包com.db中。包括DAO,UserDao及其BookDao

主要实现四个方法

这些方法的具体运行原理并不重要,重要的是应用并根据这个文件写出个性化配置的数据库连接类

  1. public Connection getConn(String server, String dbname, String user, String pwd)

    这个方法实现数据库和程序之间的关系

    这些参数的内容都将在web.xml文件中进行声明,

    key value

    在JDBC类中通过

    ServletContext ctx=this.getServletContext();
    String value=ctx.getInitParameter("key");
    

    这两句代码实现,实现将这些信息传递到JDBC类的代码中。

  2. public int executeUpdate(String prepareSql, String[] param)

    实现数据的删改增操作,其中prepareSql指的是SQL语法,param数组指的是替换掉SQL语句中的“?”字符

    返回一个int数据,executeUpdate 的返回值是一个整数,指示受影响的行数。

    一般返回数字>0时,我们默认为操作成功

  3. public ResultSet executeQuery(String preparedSql, String[] param)

    实现数据的查询,返回这个数据库查询中的结果。

  4. public void closeAll()

    资源释放

至此,完成了数据库连接类,下面开始进行第一个功能的实现

3.注册与登录功能实现

第一步,实现对象封装:User类

主要参数:对应数据库userdetail的属性一一对应,再实现getting方法和setting方法。

第二步,实现数据库连接类个性化配置,UserDao类

UserDao类实现对DAO类的继承extends。在这个基础上,先构思一下UserDao具体操作的流程和功能。

注意所有操作的逻辑归根两个:删改增+查找

  1. 添加新用户
  2. 通过名字查找用户所有信息
  3. 通过确认名字删除用户
  4. 更改已注册用户信息
  5. 获得所有用户数据

注意:所有的方法都要记得最后实现closeAll资源关闭,推荐使用try-catch-finally结构最后实现closeAll

实现功能1:添加新用户

对应方法:public boolean AddUser(User user)

SQL指令:INSERT INTO userdetail(username,userpass,role,regtime)values(?,?,?,?)

具体步骤:this.executeUpdate(sql, new String[] {user.getUsername(), user.getUserpass(),""+ user.getRole(), user.getRegtime()});

前面的sql代表SQL指令,后面的数组将具体的值(value)取代前面的“?”字符实现机器识别的SQL指令。然后连接数据库实现具体功能。

注意:String与String数据之间用“,”隔开,但是int数据前需要添加""+结构才可以被识别

实现功能2:查找用户

对应方法:public User getUserByName(String name)

SQL指令:SELECT * FROM userdetail WHERE username=?

具体步骤:ResultSet rs=this.executeQuery(sql, new String[] {name});

rs是Java中的通用结果集,需要通过方法getString或者getInt转换成通用数据结构,再将这些数据进行封装,得到一个User对象user

要点:数据类型转化+数据封装

最后将这个user返回。

实现功能3:删除用户

原理基本和新增一样,就是SQL指令要修改一下

对应方法:public boolean delUser(String name)

SQL指令:DELETE FROM userdetail WHERE username=?

具体步骤:this.executeUpdate(sql, new String[] {name});

实现功能4:修改用户信息

(通过名字先获得用户初始信息)

对应方法:public boolean editUser(User user)

对应指令:UPDATE userdetail SET userpass=?,role=?,regtime=?,lognum=?WHERE username=?

具体步骤:this.executeUpdate(sql, new String[] {user.getUsername(), user.getUserpass(), ""+user.getRole(),user.getRegtime()});

注意:这里的”?“与param数组的参数不是一一对应的了,而是存在一定的顺序。名字(获取信息的来源)是放在第一位的

由于总体上的设计,我认为通过姓名实现对用户的查找是比较科学的(其实还可以通过ID账号,但是这只是个联系,实验的范围原则上不会太大),所以再数据库的设计上,我就实现了设置名字为表主键操作逻辑。

返回所有用户的操作逻辑和后面书籍操作一致,所以一并放在后面写。

那现在,第一个功能的数据库设置基本告一段落,现在马上进行Servlet的编写和配置

第三步,在Servlet之前,先写一个拦截器,实现一些基础设置

这个系统中有很多的Servlet文件,所以写一个拦截器实现一些重叠的功能。典型的就是设置response和request的字符类型为UTF-8的操作。这样的操作基本上每一个Servlet文件都需要应用到,一个一个的写效率太过低下,所以统一写一个拦截器效果比较好。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
	// TODO Auto-generated method stub
	// place your code here
	request.setCharacterEncoding("UTF-8");
	response.setContentType("text/html; charset=utf-8");
	// pass the request along the filter chain
	chain.doFilter(request, response);
}

放置在包com.filter中,这个包主要放置拦截器。

第四步,Servlet+JSP实现注册功能

1.Servlet设计

实现注册,主要用的就是数据库插入信息的功能。所以要注意import定制的数据库操作类

实现应用数据库操作类主要分成几个步骤

  1. 从web.xml得到包括数据库的服务器+数据库名+用户名+用户密码//具体使用数据库哪个数据表通常通过使用具体的DAO类中的SQL语法实现的
  2. 从request中获取需要的参数,并封装出一个User类
  3. 实现连接数据库的getConn方法
  4. 实现连接数据库类的AddUser方法

以下是主要doGet方法实现

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("连接servlet成功!");
		PrintWriter out=response.getWriter(); 
		String username=request.getParameter("username");
		String pwd=request.getParameter("password");
		String role=request.getParameter("role");
		Date curtime=new Date();
		SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyy-MM-dd hh:mm:ss");
		String regtime=dateFormat.format(curtime);
		User user=new User();
		user.setUsername(username);
		user.setUserpass(pwd);
		user.setRegtime(role);
		user.setRegtime(regtime);
		ServletContext ctx=this.getServletContext();
		String server=ctx.getInitParameter("server");
		String dbname=ctx.getInitParameter("dbname");
		String dbuser=ctx.getInitParameter("user");
		String dbpwd=ctx.getInitParameter("pwd");
		UserDao dao=new UserDao();
		try {
			dao.getConn(server, dbname, dbuser, dbpwd);
			if(dao.AddUser(user)){
				out.println("Add user successed!");
			}else {
				out.println("Fuck! failed again!");
			}
		}catch(ClassNotFoundException e) {
			e.printStackTrace();
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
2.JSP设计

几个设计上的注意要点吧。

  1. 表单注意和Servlet紧密结合设计,action参数的设置。表单id为regist,表单name为adduserpage。
  2. 用户类型原则上分成两类:普通用户和管理员。这一对应数据库中的role(权限)参数,数据类型为int。所以我们设计一个选项框
用户类型:<input type="radio" name="role" value="0" checked>普通用户&nbsp;`
		<input type="radio" name="role" value="1">管理员

3.初次之外,在提交之前设计一个JavaScript程序用于判断输入信息是否正常。

<input type="button" value="一键提交" onclick="MyChecked()">

对应的JavaScript程序如下:

将html中的表单传入JavaScript进行判断,如果出现问题再使用alert弹窗。再JavaScript进行提交submit()操作。

技术上的重点在于对document.表单(.参数).操作格式的应用

<script type="text/javascript">
	function MyChecked()
	{
		var id=   document.adduserpage.username.value;
		var pwd=  document.adduserpage.password.value;
		var repwd=document.adduserpage.repassword.value;
	    if(id==null||id=="")
						alert("您的用户名不能为空!");
		else if(pwd==null||pwd=="")
						alert("您的密码设置不能为空!");
		else if(repwd==null||repwd=="")
						alert("请输入确认密码");
		else if(pwd!=repwd)
						alert("确认密码与初始密码不同!");	
		else
			document.adduserpage.submit();
    }
 </script>

顺手又写了一个一键重置,对应代码如下

	<input type="button" value="一键重置" onclick="reSet()">
function reSet()
	{
		document.getElementById("regist").reset();
	}

至此,网站的用户注册效果基本实现。

在实现之后我又想多添加一个功能,那就是实现管理员用户注册时不直接进入数据库(或者先不授权?),而是提交一个申请。等待数据库端通过指令集方式更改。这个功能涉及到对于数据库的重新设计,先不实现了。

第五步,Servlet+JSP实现登录功能

在写这篇文章的时候发现实现登录功能的Servlet还没有结合个性化的数据库操作类UserDao升级,还是根据通用性DAO的落后版本,所以刚刚又花费了10分钟解决了一下,顺便增加了判断登陆失败原因的判断,例如是密码输入错误还是压根就没有注册。

1.Servlet设计

基本上和第四步一样。连接数据库,获得前端数据情况,判断是否账号密码一致。如果不一致,顺便给出不一致的原因。

在判断账号和密码是否一致的这个逻辑设计如下:

先通过UserDao实现通过前端输入的名字查找用户。

将查找出的用户的信息中的密码部分取出来,与前端输入的密码进行对比。

顺便如果无法查出这个用户,这说明尚未注册。

具体代码如下:2.0版本,基于全新个性化定制设计的UserDao进行重写

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		ServletContext context=this.getServletContext();
		PrintWriter out=response.getWriter();
		String username=request.getParameter("username");
		String userpass=request.getParameter("password");
		String server=context.getInitParameter("server");
		String dbname=context.getInitParameter("dbname");
		String user=context.getInitParameter("user");
		String pwd=context.getInitParameter("pwd");
		User tempuser=new User();
		UserDao dao=new UserDao();
		try {
			dao.getConn(server, dbname, user, pwd);
			tempuser=dao.getUserByName(username);
			if(tempuser!=null) {
				String password=tempuser.getUserpass();
				if(password.equals(userpass)) {
					System.out.println("success");
					out.println("success");
				}else {
					System.out.println("password is wrong");
					out.println("password is wrong");
				}
			}else {
				System.out.println("we can't find this user");
				out.println("database cannot find the user");
			}
		}catch(ClassNotFoundException e) {
			e.printStackTrace();
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
2.JSP设计

其实对于有手就行的JSP设计没有什么需要注意的地方。

JSP对应表单name为loginpage

<script type="text/javascript">
	function LoginSubmit()
	{
		var id= document.loginpage.username.value;
		var pwd=document.loginpage.password.value;
		if(id==null||id=="")
			{
				alert("请填写用户名!");
			}
		else if(pwd==null||pwd=="")
			{
				alert("请填写密码!");
			}
		else
			document.loginpage.submit();
	}
</script>

至此,这个网站的注册和登录功能就全部实现了。

在上述代码设计的过程中,我主要在意的是尽可能按照个性化定制的DAO进行全部重新设计.虽然可以仅仅依靠基础的DAO类实现对数据库的操作,但是我想要尽可能避免出现在Servlet程序中出现SQL指令的行为,因为这样并不易于实现代码的长期维护,而且实现个性化DAO也有利于逻辑上的清晰。

除此之外,在进入图书管理代码的设计之前,需要将整个过程的逻辑先考虑清楚。

需要实现哪些功能?

  1. 搜索数据库中相应图书(按照出版社,书名,ISBN进行检索)(搜索引擎效果)
  2. 实现书店全部图书展示
  3. 判断当前用户身份,如果是管理员允许实现新添图书,下撤图书的功能。

版权声明:本文为weixin_51282350原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。