第一步:
1、为项目配置 Tomcat 为 server:
2、导入 mysql的jar包 到项目目录中:
第二步:编码
1、数据库连接类ConnectMysql.java代码:
1 package com.testing.mysql;
2
3 import java.sql.Connection;
4 import java.sql.DriverManager;
5
6 public class ConnectMysql {
7 //设置连接的成员变量
8 public Connection conn;
9 //数据库的远程连接地址、用户名和密码,此处是我自己的虚拟机里面的MySQL数据库(库名为test_project)和虚拟机的登录用户名、密码
10 public static final String DBURL="jdbc:mysql://192.168.112.128:3306/test_project?useUnicode=true&autoReconnect=true&characterEncoding=utf-8";
11 public static final String DBUSER="root";
12 public static final String DBPWD="123456";
13 //构造方法
14 public ConnectMysql() { //此处也可以将地址、用户名、密码作为参数传入,后期调用时就可以参数化调用这个方法
15 try {
16 Class.forName("com.mysql.jdbc.Driver");
17 conn = DriverManager.getConnection(DBURL, DBUSER, DBPWD);
18 //设置连接的超时时间
19 DriverManager.setLoginTimeout(10);
20 } catch (Exception e) {
21 // TODO Auto-generated catch block
22 e.printStackTrace();
23 }
24 }
25 }
2、创建UseMysql的类:
1 package com.testing.mysql;
2
3 import java.sql.CallableStatement;
4 import java.sql.Connection;
5 import java.sql.ResultSet;
6 import java.sql.ResultSetMetaData;
7 import java.sql.SQLException;
8 import java.sql.Statement;
9 import java.util.HashMap;
10 import java.util.Map;
11
12 public class UseMysql {
13
14 // 数据库连接对象
15 private Connection ct;
16
17 // 构造函数中初始化这个数据库连接对象
18 public UseMysql(Connection conn) {
19 ct = conn;
20 }
21
22
23
24
25 /**
26 * @param name登录用户名
27 * @return 返回查询信息的结果集合
28 */
29 public Map<String, String> getUserInfo(String name) {
30 String sql = "SELECT * FROM userinfo where username='" + name + "';";
31 System.out.println(sql);
32 // 保存查询结果的集合
33 ResultSet rs = null;
34 // 声明statement对象,通过这个对象查询数据库
35 Statement sm;
36 try {
37 // 通过数据库连接实例化statement对象
38 sm = ct.createStatement();
39 // 执行查询
40 rs = sm.executeQuery(sql);
41
42 // 创建map存储表中信息
43 Map<String, String> map = new HashMap<String, String>();
44
45 // 设置读取结果的循环控制变量,代表获取的数据的行数
46 int j = 1;
47
48 /*
49 * rs!=null说明sql语句执行查找成功,有内容返回。 rs.next()代表着集合当中还有下一个元素(一行的数据),并且读取该行的值。
50 * 如果sql查询不止一条语句(有用户名重名的情况),则可以用while循环取这些值
51 */
52 while (rs != null && rs.next()) {
53 // 元组数据代表数据库查询结果中的一行,通过rsmd来获取数据的列数
54 ResultSetMetaData rsmd = rs.getMetaData();
55 // 注意sql中的列从1开始,遍历一行数据中的每列内容,并以键值对形式存储到map中去
56 for (int i = 1; i <= rsmd.getColumnCount(); i++) {
57 // 展示的信息去除密码列和用户名列
58 if (!(rsmd.getColumnName(i).equals("pwd") || rsmd.getColumnName(i).equals("username")))
59 // 将每一列的名称和数据作为键值对存放到map当中,将行数拼接到键里
60 map.put(rsmd.getColumnName(i) + j, rs.getString(i));
61 }
62 System.out.println(map.toString());
63
64 // 行数自增
65 j++;
66 }
67 // 关闭statement对象和查询结果集合对象,释放资源
68 sm.close();
69 rs.close();
70 return map;
71 } catch (Exception e) {
72 // TODO: handle exception
73 }
74 return null;
75 }
76
77
78
79
80
81 /**
82 * 通过查询语句验证登录结果的登录方法,如果能够查询到结果,则说明登录成功
83 *
84 * @param 登录用户名name
85 * @param 登录密码password
86 * @return 返回登录是否成功的布尔值,成功为true,失败为false
87 */
88 public boolean Login(String name, String pwd) {
89
90 String sql = "SELECT * FROM userinfo WHERE username='" + name + "' AND pwd='" + pwd + "';";
91
92 // 声明数据库连接状态statement对象,通过这个对象查询数据库
93 Statement sm;
94 // 设置一个变量来保存查询结果集
95 ResultSet rs = null;
96
97 try {
98 // 通过数据库连接实例化一个statement对象sm
99 sm = ct.createStatement();
100
101 // 执行查询语句
102 rs = sm.executeQuery(sql);
103
104 // rs!=null说明sql语句执行查找成功,有内容返回,
105 // 封装的方法rs.next()代表着集合当中还有下一个元素(一行的数据),并且读取该行的值。
106 if (rs != null && rs.next()) {
107
108 // 元组数据代表数据库查询结果中的一行。
109 ResultSetMetaData rsmd = rs.getMetaData();
110
111 // 声明一个map来存储一条记录中的内容
112 HashMap<String, String> map = new HashMap<String, String>();
113
114 // 注意sql中的列从1开始,遍历一条记录中的每列内容,并以键值对形式存储到map中去
115 for (int i = 1; i <= rsmd.getColumnCount(); i++) {
116 // 从第一列开始遍历一条记录中的每一列,将对应的键值对存储到map当中
117 map.put(rsmd.getColumnName(i), rs.getString(i));
118 }
119 System.out.println(map.toString());
120 // 关闭statement对象和查询结果集合对象,释放资源
121 sm.close();
122 rs.close();
123 // 如果查询结果不为空,就返回登录成功
124 return true;
125 }
126 // 如果查询结果为空,也要关闭对象释放资源
127 sm.close();
128 rs.close();
129 } catch (SQLException e) {
130 }
131 // try建立查询失败或者查询结果为空都会执行到这里,返回false
132 return false;
133 }
134
135
136
137
138 /**
139 * 通过 存储过程 验证登录结果的登录方法,如果能够查询到结果,则说明登录成功 使用存储过程进行验证时,sql语句不再重新编译,可以防止sql注入
140 *
141 * @param 登录用户名name
142 * @param 登录密码password
143 * @return 返回登录是否成功的布尔值,成功为true,失败为false
144 */
145 public boolean PLogin(String name, String pwd) {
146 try {
147 // 创建调用存储过程的对象,参数用?号代替,不要直接传递参数
148 CallableStatement cm = ct.prepareCall("{call login(?,?)}");
149 // 通过set方法传递存储过程用到的参数,1和2代表第几个参数,name和pwd代表参数值
150 cm.setString(1, name);
151 // cm.setInt(1, 1);
152 cm.setString(2, pwd);
153 // 获取查询结果
154 ResultSet rs = cm.executeQuery();
155 // 处理查询结果,与之前的方法一致,不再重复添加注释了
156 if (rs != null && rs.next()) {
157 ResultSetMetaData rsmd = rs.getMetaData();
158 HashMap<String, String> map = new HashMap<String, String>();
159 for (int i = 1; i <= rsmd.getColumnCount(); i++) {
160 map.put(rsmd.getColumnName(i), rs.getString(i));
161 }
162 System.out.println(map.toString());
163 cm.close();
164 rs.close();
165 return true;
166 }
167 cm.close();
168 rs.close();
169 } catch (SQLException e) {
170 // TODO Auto-generated catch block
171 // e.printStackTrace();
172 }
173 return false;
174 }
175
176 }
3、登录的后台 LoginTry.java 代码:
1 package com.testing.login;
2
3 import java.io.IOException;
4 import java.util.Map;
5 import java.util.regex.Matcher;
6 import java.util.regex.Pattern;
7
8 import javax.servlet.ServletException;
9 import javax.servlet.annotation.WebServlet;
10 import javax.servlet.http.HttpServlet;
11 import javax.servlet.http.HttpServletRequest;
12 import javax.servlet.http.HttpServletResponse;
13
14 import com.testing.mysql.ConnectMysql;
15 import com.testing.mysql.UseMysql;
16
17 /**
18 * Servlet implementation class LoginTry
19 */
20 @WebServlet("/LoginTry")
21 public class LoginTry extends HttpServlet {
22 private static final long serialVersionUID = 1L;
23
24 /**
25 * @see HttpServlet#HttpServlet()
26 */
27 public LoginTry() {
28 super();
29 // TODO Auto-generated constructor stub
30 }
31
32 /**
33 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
34 * response)
35 */
36 protected void doGet(HttpServletRequest request, HttpServletResponse response)
37 throws ServletException, IOException { ........
38
39
40 /**
41 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
42 * response)
43 */
44 protected void doPost(HttpServletRequest request, HttpServletResponse response)
45 throws ServletException, IOException {
46 // TODO Auto-generated method stub
47
48 // 返回值编码的修改
49 response.setContentType("text/html;charset=UTF-8");
50 // 收到的参数的编码修改
51 request.setCharacterEncoding("UTF-8");
52
53 String user = request.getParameter("userid"); //“userid”要与前端form表单中的用户名的<input>元素的name属性对应
54 String pwd = request.getParameter("pwds"); //“pwds”要与前端form表单中的密码的<input>元素的name属性对应
55
56 //声明一个数据库查询结果实例
57 Map<String, String> userinfo;
58
59 //设置正则匹配模式,进行用户名和密码的正则过滤
60 String regEx = "[^a-zA-Z0-9_-]";
61 Pattern p = Pattern.compile(regEx);
62 // 调用pattern对象p的mathcer方法,生成一个匹配matcher对象
63 Matcher m = p.matcher(user);
64 Matcher m1 = p.matcher(pwd);
65 //设置返回信息的变量res
66 String res = "{";
67
68 // 判断用户名密码不为空
69 if (user != null && pwd != null) {
70 // 判断长度3~16位
71 if (user.length() > 2 && user.length() < 17 && pwd.length() > 2 && pwd.length() < 17) {
72 // 判断不包含特殊字符
73 if (!m.find() && !m1.find()) {
74
75 // 创建sql连接,以及实例化UseMysql类型
76 ConnectMysql connSql = new ConnectMysql();
77 UseMysql mySql = new UseMysql(connSql.conn);
78 //使用创建的对象来调用UseMysql类中的Login(user,pwd)方法并将返回的布尔结果作为判断值
79 if (mySql.Login(user, pwd)) {
80 res += "\"status\":200,\"msg\":\"恭喜您,登录成功!\"}";
81 userinfo = mySql.getUserInfo(user);
82 } else {
83 res += "\"status\":3000,\"msg\":\"用户名密码不匹配!\"}";
84 }
85
86 } else {
87 res += "\"status\":3003,\"msg\":\"用户名密码不能包含特殊字符!\"}";
88 }
89 } else {
90 res += "\"status\":3004,\"msg\":\"用户名密码长度必须是3至16位!\"}";
91 }
92 } else {
93 res += "\"status\":3005,\"msg\":\"用户名密码长度不能为空!\"}";
94 }
95 // 接口返回信息,返回信息中显示本次请求时的sessionID
96 response.getWriter().append(res);
97
98 }
99
100 }
4、前端界面 index.html 代码:
1 <!doctype html>
2 <html>
3 <head>
4 <meta http-equiv="content-type" content="text/html" charset="utf-8">
5 <title>zzp的网页</title>
6
7 <!--接下来引入JQuery最小版本的库文件 -->
8 <script src="jquery.min.js" type="text/javascript"></script>
9 <!-- 接下来引入自己写的js库文件 -->
10 <script src="test.js" type="text/javascript"></script>
11
12 </head>
13
14
15 <body >
16 <h1 align="center">Hello HTML</h1>
17
18 <form id="loginForm" method="post" action="./LoginTry">
19 <div id="info" style="text-align:center">
20 <p>请输入您的账号:</p>
21 <input type="text" name="userid" placeholder="登录名" />
22 <br/>
23 <p>请输入您的密码:</p>
24 <input type="password" name="pwds" placeholder="密码" />
25 <br/><br/>
26
27 <!-- 下面这一句原本是为了使用form表单的方式来调用post方法的 -->
28 <!-- <input type="submit" value="开始登录"> -->
29
30 <!-- 使用“登录”按钮的onclick事件来调用js文件,执行post方法的异步请求 -->
31 <input type="button" onclick="javascript:loginJS()" value="登录" />
32 </div>
33 </form>
34
35 </body>
36 </html>
5、用到的js代码:
1 /**
2 * 点击登录界面中“登录”按钮会调用的js方法
3 */
4
5 function loginJS() {
6
7 // 定义一个存放URL的变量,指定请求的接口地址
8 var AjaxURL = "http://localhost:8080/LoginInterServlet/LoginTry";
9
10 $.ajax({
11 url : AjaxURL,
12 type : "post", // 采用post方法
13 dataType : "json", // 请求和返回的参数格式;如果是非json格式需要使用text格式
14 // 获取id=loginForm的form表单中的参数
15 data : $('#loginForm').serialize(),
16
17 // 当接口调用成功时,执行success中的方法,result参数指的是接口返回的信息
18 success : function(result) {
19 // result[***]表示的是对应的键经过 解析后的值
20 // alert("status:"+result["status"]+", "+result["msg"]);
21
22 //如果登录成功,将id=“info”的元素改为接口返回值中“msg”信息
23 $('#info')[0].innerText=result["msg"];
24 },
25
26 // 当接口调用失败时,执行error中的方法
27 error : function() {
28 alert("服务器忙……请稍后重试!");
29 }
30 });
31
32 }
运行验证:
结果截图:
eclipse的控制台运行后的结果截图:
数据库中数据截图: