JQuery校验用户名

一、相比于之前的是连接数据库而检查

head里面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
function checkUserName(){

//1.获取输入框的内容
var name=$("#name").val(); //通过$("#找用户的那个框框标签")

//2.发送请求(使用post方式)
$.post("/day16/checkUserNameServlet",{name:name},function(data,status){

//Servlet传过来的数字
if(data==1) //数据库有的写1
{
//alert("用户名已经存在");
$("#span01").html("<font color='red'>用户名已经存在了</font>"); //使用post和get的JQuery赋值代码
}
else //数据库没有的写2
{
//alert("用户名可以使用");
$("#span01").html("<font color='blue'>用户名可以使用</font>");
}
});

}

</script>

body里面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<table border="1" width="400px">
<tr>
<td>用户名:</td>
<td><input type="text" name="name" id="name" onblur="checkUserName()"><span id="span01"></span></td> <!-- 失去焦点就要弹出 -->
</tr>
<tr>
<td>密码:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td>简介:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="注册"></td>
</tr>
</table>

输入admin数据库里面有:

输入不存在的数据:


二、JQ和ajax方式对比

只有jsp页面不同:

JQuery基本用法

一、load

使用步骤:

1
2
3
4
5
6
7
8
9
1. 因为是js库:所以要通过srcipt导入包
2. 通过${"#名字"}的方式获取到jsp页面的一行内容
3. 然后load方法里面两个参数
3.1 第一个要写Servlet地址
3.2 要写function(responseText,statusTXT,xhr){}
responseText:包含调用成功的结果内容
statusTXT:包含调用状态
xhr:包含XMLHttpRequest对象
4. 然后可以通过$("#名字").val("responseText")的方式给哪一行标签设置值;

使用固定格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
function load(){
//$("#text01") 相当于 document.getElementById("text01");
$("#text01").load("/day16/DemoServlet02",function(responseText,statusTXT,xhr){ //responseText:包含调用成功的结果内容 statusTXT:包含调用状态 xhr包含XMLHttpRequest对象
//alert("jieguo:"+responseText);
$("#text01").val("responseText");
});
}
</script>
</head>
<body>

<h3><a href="" onclick="load()">使用JQuery执行load方法</a></h3>
<input type="text" id="text01">
</body>

Servlet代码:

1
2
3
4
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("给你数据");
}

二、get

使用步骤:

1
2
3
4
5
6
7
1. 因为是js库:所以要通过srcipt导入包
2. 通过${"#名字"}的方式获取到jsp页面的一行内容
3. 通过$.get("Serlvet相对地址",function(data,status){})
4. 最重要的三种赋值问题:
//$("#div01").html(data); //html() 一般和font标签有关 可以写html代码
//$("#div01").text("data"+data); //text()
//$("#div01").val(data); //val() 元素里面有value属性

使用固定格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="js/jquery-1.11.3.min.js"></script>

<script type="text/javascript">
function get(){
//$("#div01") 相当于 document.getElementById("text01");
$.get("/day16/DemoServlet02",function(data,status){
alert("结果是:"+data);
$("#div01").html(data); //html() 一般和font标签有关
//$("#div01").text("data"+data); //text()
//$("#div01").val(data); //val() 元素里面有values的属性值
});
}
</script>

</head>
<body>
<input type="button" onclick="get()" value="使用JQuery演示get方法">
<div id="div01" style="width:100px; height:100px; border:1px solid blue>
</div>
</body>

打开页面之后点击按钮-弹出Servlet传过来data:

然后关闭弹窗之后通过赋值会把内容给蓝框里面:


三、post

使用步骤:

1
2
3
4
5
6
7
1. 因为是js库:所以要通过srcipt导入包
2. 通过${"#名字"}的方式获取到jsp页面的一行内容
3. 通过$.post("Serlvet相对地址",{写传的数据},function(data,status){})
4. 最重要的三种赋值问题:
//$("#div01").html(data); //html() 一般和font标签有关 可以写html代码
//$("#div01").text("data"+data); //text()
//$("#div01").val(data); //val() 元素里面有value属性

使用固定格式:

1
2
3
4
5
6
7
8
<script type="text/javascript">
function get(){
//$("#div01") 相当于 document.getElementById("text01");
$.post("/day16/DemoServlet02", {name:"zhangsan",age:18},function(data,status){ //相当于把ajax里面get的servlet后面?name 这种形式改了
$("#div01").html(data);
});
}
</script>

四、总结语法格式

  • load

    $("#元素id").load(url地址);
    
    $("#div1").load(serlvet); ---> 使用的get请求,回来赋值的时候, 使用text();去赋值
  • get

    语法格式 : $.get(URL,callback);    
使用案例: $.get("/day16/DemoServlet02"  , function(data ,status) {
    $("#div01").text(data);
});
  • post

    语法格式:$.post(URL,data,callback);
function post() {
    $.post("/day16/DemoServlet02", {name:"zhangsan",age:18},function(data,status) {
        //想要放数据到div里面去。 --- 找到div
        $("#div01").html(data);
    });
}

Ajax实现校验用户名

一、搭建环境

1.新建jsp页面

新建jsp页面(主要代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<table border="1" width="400px">
<tr>
<td>用户名:</td>
<td><input type="text" name="name" id="name"></td> <span id="span01"></span>
</tr>
<tr>
<td>密码:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td>简介:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="注册"></td>
</tr>
</table>

jsp页面:

2.建立数据库(添加jar和xml配置文件)

需要导入DBUtils和C3P0数据池的jar文件以及数据池配置文件xml(修改数据库为user)

C3P0数据池配置文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>

<!-- default-config 默认的配置, -->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property> <!-- 要和不用配置文件的set方法的后面一样 -->
<property name="jdbcUrl">jdbc:mysql://localhost/user?characterEncoding=utf-8</property>
<property name="user">root</property>
<property name="password">njdxrjgc7777777.</property>


<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>

<!-- This app is massive! -->
<named-config name="oracle"> <!-- oracle数据库用 -->
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property>

<!-- intergalactoApp adopts a different approach to configuring statement caching -->
<property name="maxStatements">0</property>
<property name="maxStatementsPerConnection">5</property>

<!-- he's important, but there's only one of him -->
<user-overrides user="master-of-the-universe">
<property name="acquireIncrement">1</property>
<property name="initialPoolSize">1</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">5</property>
<property name="maxStatementsPerConnection">50</property>
</user-overrides>
</named-config>

</c3p0-config>

数据库建立如下(以前的校验都是if判断):


二、逻辑实现

使用MVC模式解决问题:


三、 具体分析

对于实现的分析图:


四、具体代码如下:

最终实现代码框架:

UserDao类:

1
2
3
4
5
public interface UserDao {

//检测用户名是否存在
boolean checkUserName(String username) throws SQLException;
}

UserDaoImpl类:

1
2
3
4
5
6
7
8
9
10
11
public class UserDaoImpl implements UserDao {
@Override
public boolean checkUserName(String username) throws SQLException{
//使用DBUtils的类
QueryRunner runner=new QueryRunner(JDBCUtil02.getDataSource()); //要从JDBCUtil02获取数据池对象

//执行sql语句
String sql="select count(*) from t_user where name=?"; //使用聚合函数count查出来就只有username一个属性
Long result=(Long) runner.query(sql,new ScalarHandler(),username); //第一个为sql语句 第二个返回值 第三个是传入的值username
return result>0;
}

checkUserNameServlet类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class checkUserNameServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//数据库有中文
request.setCharacterEncoding("UTF-8");

//1.获取name--然后通过面向接口的方式调用方法--通过sql语句聚集函数得到username是否存在
String name=request.getParameter("name");
System.out.println("name="+name);

UserDao dao = new UserDaoImpl();
boolean isExist=dao.checkUserName(name); //如果是true(daoImpl的值是1)--匹配到了

//2.通知页面-- 到底有没有
if(isExist)
{
response.getWriter().println(1); //存在
}
else
{
response.getWriter().println(2); //不存在
}
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}

主页demo03.jsp代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">

function ajaxFunction(){ <!--拷贝写好的创建对象的方法 -->
var xmlHttp;
try{ // Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e){
try{// Internet Explorer
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e){
try{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e){}
}
}
return xmlHttp;
}

function checkUserName(){
//获取输入框的值
var name=document.getElementById("name").value;

//1.创建xmlhttprequest对象
var request=ajaxFunction();

//2.发送请求
request.open("POST","/day16/checkUserNameServlet",true);

//注册状态改变监听,获取服务器传送过来的数据
request.onreadystatechange=function(){
if(request.readyState==4&&request.status==200) // 已经能够正常处理 && 判断状态码是不是200
{
var data=request.responseText;
if(data==1){
document.getElementById("span01").innerHTML="<font color='red'>用户名已经存在!</font>";
}
else{
document.getElementById("span01").innerHTML="<font color='red'>用户名可以使用!</font>";
}
}
}

//如果是post方式就必须要添加头 --说明提交的数据类型是一个经过url编码的form表单数据
request.setRequestHeader("Content-type","application/x-www-form-urlencoded"
request.send("name="+name);

}
</script>
</head>

<body>
<table border="1" width="400px">
<tr>
<td>用户名:</td>
<td><input type="text" name="name" id="name" onblur="checkUserName()"><span id="span01"></span></td> <!-- 失去焦点就要弹出 -->
</tr>
<tr>
<td>密码:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td>简介:</td>
<td><input type="text" name=""></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="注册"></td>
</tr>
</table>
</body>
</html>

最终输入一个用户名会提示判断,并且在java控制台输出结果:


Ajax

一、Ajax概述

Asynchronous Javascript And XML异步JavaScript和XML
并不是新的技术,只是把原有的技术,整合到一起而已。

1.使用CSS和XHTML来表示。
2. 使用DOM模型来交互和动态显示。
3.使用XMLHttpRequest来和服务器进行异步通信。
4.使用javascript来绑定和调用。
  • 作用:

    刷新局部内容


二、数据请求 Get

创建一个demo01.jsp页面:主要去写浏览器点击按钮后通过ajax方式获得数据请求,servlet得到反馈。

数据请求中的Get思路:

1
2
3
4
5
6
1.在body里面写一个点击按钮 onclick="get()"
2.在head里面引入js代码写get()方法具体实现。
2.1 主要是去创建对象(调用我们写好的ajaxFunction()方法 ---在F盘的jar文件内)
2.2 使用open()方法可以添加数据--发送请求
2.3 使用request.onreadystatechange=function(){}--判断是不是准备好了
2.4 使用send()方法

jsp页面的主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>

<script type="text/javascript"> <!--使用jS文件-->

function ajaxFunction(){ <!--拷贝写好的创建对象的方法 -->
var xmlHttp;
try{ // Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e){
try{// Internet Explorer
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e){
try{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e){}
}
}
return xmlHttp;
}

function get(){
//1.创建xmlhttprequest对象
var request=ajaxFunction(); <!--调用写好的创建对象的方法 -->
//2.发送请求
request.open("GET","/day16/DemoSerlvet01?name=aa&age=18",true); // 第一个参数:get/post 第二个:相对路径 默认从 项目开始 所以只用写servlet的代码 第三个: true(异步) /false(同步)

//3.获取响应数据
request.onreadystatechange=function(){
if(request.readyState==4&&request.status==200) // (4)已经能够正常处理 && 判断状态码是不是200
{
alert(request.responseText); //弹出信息
}
}
request.send();
}

</script>
</head>

<body>
<h3><a href="" onclick="get()">使用Ajax方式发送Get请求</a></h3>
</body>

DemoSerlvet01主要去写输出:

1
2
3
4
5
6
7
8
9
10
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取传入的信息
String name = request.getParameter("name");
String age = request.getParameter("age");
System.out.println(name+" "+age);

//通过alert的方式弹出
response.setContentType("text/html;charset=utf-8"); //response解决方法加一行代码 而request可以加代码/tomcat永久更改(之前博客写过方法)
response.getWriter().write("啊啊");
}

最终点击jsp页面的一行弹出alert提示:java控制台输出获取的信息


三、数据请求 Post

跟get的差距:

  1. 只是在open里面要是传输数据需在send()里面写。
  2. 传输数据必须现有头部
1
2
3
4
5
6

//如果是post方式就必须要添加头 --说明提交的数据类型是一个经过url编码的form表单数据
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");

//post不能根据open带过去
request.send("name=aa&age=18");

与get方法的前三步骤一样(不带参数):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function post(){
//1.创建xmlhttprequest对象
var request=ajaxFunction(); <!--调用写好的创建对象的方法 -->
//2.发送请求
request.open("POST","/day16/DemoSerlvet01",true); // 第一个参数:get/post 第二个:相对路径 默认从 项目开始 所以只用写servlet的代码 第三个: true(异步) /false(同步)

//3.获取响应数据
request.onreadystatechange=function(){
if(request.readyState==4&&request.status==200) // 已经能够正常处理 && 判断状态码是不是200
{
alert(request.responseText);
}
}

//如果是post方式就必须要添加头 --说明提交的数据类型是一个经过url编码的form表单数据
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");

//post不能根据open带过去
request.send("name=aa&age=18");
}

主要代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>

<script type="text/javascript"> <!--使用jS文件-->

function ajaxFunction(){ <!--拷贝写好的创建对象的方法 -->
var xmlHttp;
try{ // Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e){
try{// Internet Explorer
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e){
try{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e){}
}
}
return xmlHttp;
}

function post(){
//1.创建xmlhttprequest对象
var request=ajaxFunction(); <!--调用写好的创建对象的方法 -->
//2.发送请求
request.open("POST","/day16/DemoSerlvet01","true"); // 第一个参数:get/post 第二个:相对路径 默认从 项目开始 所以只用写servlet的代码 第三个: true(异步) /false(同步)

//3.获取响应数据
request.onreadystatechange=function(){
if(request.readyState==4&&request.status==200) // 已经能够正常处理 && 判断状态码是不是200
{
alert(request.responseText);
}
}

//如果是post方式就必须要添加头 --说明提交的数据类型是一个经过url编码的form表单数据
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");

//post不能根据open带过去
request.send("name=aa&age=18");
}

</script>
</head>
<body>
<h3><a href="" onclick="post()">使用Ajax方式发送Post请求</a></h3>
</body>

DemoSerlvet01主要去写输出:

1
2
3
4
5
6
7
8
9
10
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取传入的信息
String name = request.getParameter("name");
String age = request.getParameter("age");
System.out.println(name+" "+age);

//通过alert的方式弹出
response.setContentType("text/html;charset=utf-8"); //response解决方法加一行代码 而request可以加代码/tomcat永久更改(之前博客写过方法)
response.getWriter().write("啊啊");
}

四、部分方法解析#

创建xmlhttprequest对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function ajaxFunction(){     <!--拷贝写好的创建对象的方法 -->
var xmlHttp;
try{ // Firefox, Opera 8.0+, Safari
xmlHttp=new XMLHttpRequest();
}
catch (e){
try{// Internet Explorer
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e){
try{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e){}
}
}
return xmlHttp;
}

open()方法

  1. 第一个参数: GET/POST
  2. 第二个参数: 相对地址(相对于localhost:8080中的8080) 一般是 “/项目名/servlet名字” (GET的方式可以直接?name=lisi&age=18;而POST的方式只能在send里面写,而且要加头)
  3. 第三个参数: true(异步)/false(同步)
1
request.open("GET","/day16/DemoSerlvet01?name=aa&age=18",true);

onreadystatechange=function(){}–判断状态##

1
2
3
4
5
6
7
//固定的格式:
request.onreadystatechange=function(){
if(request.readyState==4&&request.status==200) // 已经能够正常处理 && 判断状态码是不是200
{
alert(request.responseText); //配合request.responseText使用
}
}

readystate状态集:

status的状态集:

send()方法

1
2
3
4
5
6
7
8
9
10
	//如果是post方式就必须要添加头  --说明提交的数据类型是一个经过url编码的form表单数据
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");

//post不能根据open带过去
request.send("name=aa&age=18");

// -----------------------------------------------

//get方式
request.send();

学生管理系统(2.0)

一、数据库准备

数据库SQL语句:

1
2
3
4
5
6
7
8
9
10
11
CREATE DATABASE stus;
USE stus;
CREATE TABLE stu (
sid INT PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR (20),
gender VARCHAR (5),
phone VARCHAR (20),
birthday DATE,
hobby VARCHAR(50),
info VARCHAR(200)
);

Navicat配合mysql直接可视化:


二、环境搭建(Dao)#

1. 先写index.jsp页面

2. 写一个StudentListServlet类去进行查询学生信息—弹出到list.jsp页面

3. 写一个Student类(封装):里面写所有数据库的属性以及set和get方法

4. 写dao层里面的StudentDao类:里面去写要完成什么方法

5. 写dao.impl里面的StudentDaoImpl类:具体去写连接数据库等操作


三、环境搭建(Dao实现)

1.需要连接开源数据池和连接数据库:
所以要引入c3p0和DBUtils的jar以及连接数据库的jar包,还有就是要有c3p0开源数据池的配置文件。

2. 建立Util包,里面放写好的JDBCUtil02(简化的JDBC连接类)

3. StudentDaoImpl类里面去完成写当时的连接数据库查询的三步


四、环境搭建(Service层)

1. 新建service接口和实现类–和dao以及daoimpl代码一样(为了service去找dao)

2. 在Serlvet代码内增加StudentService service=new StudentServiceImpl()(为了servlet找service)


五、查询所有学生#

1. 完善Servlet类

1
2
3
4
5
6
7
8
9
//1.查询出所有学生
StudentService service=new StudentServiceImpl(); //Servlet去找service 然后他会去找dao层
List<Student> list = service.findAll(); //找到查询方法

//2.先把数据存到作用域中
request.setAttribute("list", list);

//3.有结果了--跳转
request.getRequestDispatcher("list.jsp").forward(request, response);

2. 写跳转的list.jsp页面

1
2
3
4
1.在body里面建立2*8的表格:
第一行写标题(姓名、性别等)
第二行要用JSP里面学过的JSTL语言配合EL表达式循环出所有的结果
2.导入所需要用的jstl.jar和standard.jar包

六、添加学生

1. 通过主页面list.jsp的添加href要去找添加的界面,因此写一个add.jsp页面

2. 接下来完成servlet(1.获取客户端提交的信息 2.添加到数据库 3.跳转到list.jsp的主页面)

3. 需要去找dao层的studentDao写insert()方法

4. 然后去impl里面去实现insert()方法
和之前的查询一样都是两步:第一步通过JDBCUtil02导入连接;第二步通过update的方法导入信息

5.更改service层代码–添加和dao一层的代码,但是在impl里面建立dao的对象

6. 更改Add.servlet层代码–添加到数据库

注意事项

  1. 需要更改eclipse和mysql的编码格式都为UTF-8
  2. 需要注意爱好需要用数组然后转字符串输出(不然就只能显示一个)

七、删除学生

1. 设置点击超链接弹出一个询问框,如果点击确定–删除成功

1
<a href="#" onclick="doDelete(${stu.sid})">删除</a>

2. 让超链接执行js方法–触发servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<script type="text/javascript">

function doDelete(sid) {
var flag = confirm("是否确定删除?"); //提示语
if(flag){
//表明点了确定。 访问servlet。 在当前标签页上打开 超链接,
//window.location.href="DeleteServlet?sid="+sid;
location.href="DeleteServlet?sid="+sid;
}
}

</script>

```
**3. js点击确定--会获取到sid,然后给sid跳转到servlet**

**4. servlet收到了请求 ---> service,service ---> dao**

---

# 八、更新学生 #

** 1.和之前的操作差不多都是dao和service
去写方法,impl去写实际功能。**

** 2.在list.jsp要通过按钮href标签`EditServlet?sid=${stu.sid}`去找sid然后相当于弹出一个edit的jsp页面展示原来的信息,然后根据更改提交给原来的展示所有的StudentListServet之后在弹出list.jsp页面**


---

# 九、模糊查询 #

**要将list的表格通过form提交,然后里面的sql语句要用拼凑的方法。**

```
String sql="select * from stu where 1=1"; //啥也不选就提交就这样的sql语句
List<String> list=new ArrayList<String>(); //存放传入的sname/sgender

//拼装
if(!TextUtil.isEmpty(sname))
{
sql=sql+" and sname like ?";
list.add("%"+sname+"%"); //因为like在前面 所以要用%包起来
}
if(!TextUtil.isEmpty(sgender))
{
sql=sql+" and gender=?";
list.add(sgender);
}

十、分页(还未实现 可以再F盘的jar文件找源码)

  • 物理分页 (真分页)

来数据库查询的时候,只查一页的数据就返回了。

 优点 内存中的数据量不会太大

缺点:对数据库的访问频繁了一点。

SELECT * FROM stu LIMIT    5 OFFSET 2 (一次性五条 相对与之前的而言)
  • 逻辑分页 (假分页)

一口气把所有的数据全部查询出来,然后放置在内存中。

优点: 访问速度快。

缺点: 数据库量过大,内存溢出。

十一、代码完整上传至其他仓库(Student management system)

JSP开发模式

一、元数据(Meata data )

描述数据的数据 String sql , 描述这份sql字符串的数据叫做元数据

数据库元数据 DatabaseMetaData
参数元数据 ParameterMetaData
结果集元数据 ResultSetMetaData


二、两种JSP开发模式

  • JSP+JAVABean

    jsp里面要直接写java代码(<%%>),维护起来比较麻烦,并且jsp的页面代码也比较臃肿。
  • JSP+JAVABean+Servlet(MVC模式)

    M:model 模型层---封装根据JAVA Bean java类 EJB
    V:view  视图层---jsp用于显示
    C:controller 控制层---Servlet接收页面,找模型层处理,然后响应数据出去

DBUtils

一、改写JDBCUtil代码(一直调用的类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package util;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class JDBCUtil2 {

static ComboPooledDataSource dataSource =new ComboPooledDataSource();

//获取连接对象
public static Connection getConn() throws SQLException{
return dataSource.getConnection(); //已经更改为和C3P0有关的ComboPooledDataSource类
}

// 释放资源(数据库连接池最后需要释放资源)
public static void release(Connection conn , Statement st , ResultSet rs){
closeRs(rs);
closeSt(st);
closeConn(conn);
}
public static void release(Connection conn , Statement st ){
closeSt(st);
closeConn(conn);
}


private static void closeRs(ResultSet rs){
try {
if(rs != null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}

private static void closeSt(Statement st){
try {
if(st != null){
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
st = null;
}
}

private static void closeConn(Connection conn){
try {
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
}

二、开源DBUtils的使用步骤

  1. 导入commons-dbutils-1.4.jar文件
  2. 新建类主要是使用QueryRunner类去加载C3P0开源数据池ComboPooledDataSource类的对象,然后调用QueryRunner类的方法就可以。

增删查改的方法:

1
2
3
4
//针对增加、删除、修改
//qu.update(sql);
//针对查询
//qu.query(sql, rsh);

三、DBUtils的增删改(1行)

步骤分析

1
2
3
4
5
6
7
8
//1.使用两种数据池中其中一种的C3P0开源数据池---通过对象去获取数据池 
ComboPooledDataSource dataSource =new ComboPooledDataSource();

//2.获取连接进行sql操作---通过DBUtils专有的QueryRunner类去接开源数据池的对象
QueryRunner qu=new QueryRunner(dataSource); //只是去简化了CRUD的代码

//3.增加/删除/插入 这三种方式只需要一行的update方法 ---要更改的参数前面写?,后面写具体值
qu.update("insert into account values(null,?,?)","aa",1000);

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package dbutils;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class TestDBUtils {

@Test
public void testinsert() throws SQLException { //测试插入功能

//1.使用两种数据池中其中一种的C3P0开源数据池
ComboPooledDataSource dataSource =new ComboPooledDataSource();

//2.获取连接进行sql操作
QueryRunner qu=new QueryRunner(dataSource); //只是去简化了CRUD的代码

//3.增加
//qu.update("insert into account values(null,?,?)","aa",1000);

//3.删除
//qu.update("delte from account where id=?",5);

//3.更新
//qu.update("update account set money=? where id=?",1000000,6);
}
}

四、DBUtils查询(2行)

查询单条

1. ResultSetHandler()匿名内部类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//3.查询单条  查询到的数据还是由那个result里面,然后调用下面的handle方法(手动封装)

Account account=qu.query("select * from account where id=?",new ResultSetHandler<Account>() { //使用匿名内部类

@Override
public Account handle(ResultSet rs) throws SQLException {
Account account=new Account(); //创建一个Account类对象
while(rs.next())
{
String name=rs.getString("name"); //rs获取name
int money = rs.getInt("money"); //rs获取money

account.setName(name); //对象设置name
account.setMoney(money); //对象设置money
}
return account;
}
},6);

System.out.println(account.toString()); //调用Account类的输出方法(Account类写获取name和money的方法等)

2. BeanHandler()匿名内部类:

1
2
3
4
5

/*
Account account=qu.query("select * from account where id=?",new BeanHandler<Account>(Account.class),2); ////使用第一种方式下面的BeanHandler<T>的方式匿名内部类
System.out.println(account.toString()); //调用Account类的输出方法(Account类写获取name和money的方法等)
*/

查询所有

** BeanListHandler()**

1
2
3
4
5
List<Account> list=qu.query("select * from account",new <AcBeanListHandlercount>(Account.class));  //Account.class可以自己封装---类的字节码获取类的实例
for(Account account:list)
{
System.out.println(account.toString()); //调用Account类的输出方法(Account类写获取name和money的方法等)
}

五、完整代码(3部分)

具体实现代码框架(红色√):

第一部分:要用C3P0数据池必须要配置xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>

<!-- default-config 默认的配置, -->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property> <!-- 要和不用配置文件的set方法的后面一样 -->
<property name="jdbcUrl">jdbc:mysql://localhost/bank</property>
<property name="user">root</property>
<property name="password">njdxrjgc7777777.</property>


<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>

<!-- This app is massive! -->
<named-config name="oracle"> <!-- oracle数据库用 -->
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property>

<!-- intergalactoApp adopts a different approach to configuring statement caching -->
<property name="maxStatements">0</property>
<property name="maxStatementsPerConnection">5</property>

<!-- he's important, but there's only one of him -->
<user-overrides user="master-of-the-universe">
<property name="acquireIncrement">1</property>
<property name="initialPoolSize">1</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">5</property>
<property name="maxStatementsPerConnection">50</property>
</user-overrides>
</named-config>

</c3p0-config>

第二部分:具体实现的TestDBUtils类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package dbutils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import demain.Account;
public class TestDBUtils {
@Test
public void testinsert() throws SQLException { //测试插入功能
//1.使用两种数据池中其中一种的C3P0开源数据池
ComboPooledDataSource dataSource =new ComboPooledDataSource(); //一定要记得导入c3p0-config.xml文件(配置文件)

//2.获取连接进行sql操作
QueryRunner qu=new QueryRunner(dataSource); //只是去简化了CRUD的代码

//3.增加
//qu.update("insert into account values(null,?,?)","aa",1000);

//3.删除
//qu.update("delte from account where id=?",5);

//3.更新
//qu.update("update account set money=? where id=?",1000000,6);

//3.查询单条 查询到的数据还是由那个result里面,然后调用下面的handle方法(手动封装)
/*
Account account=qu.query("select * from account where id=?",new ResultSetHandler<Account>() { //使用匿名内部类

@Override
public Account handle(ResultSet rs) throws SQLException {
Account account=new Account(); //创建一个Account类对象
while(rs.next())
{
String name=rs.getString("name"); //rs获取name
int money = rs.getInt("money"); //rs获取money

account.setName(name); //对象设置name
account.setMoney(money); //对象设置money
}
return account;
}
},6);
System.out.println(account.toString());
*/

//3.查询单条
/*
Account account=qu.query("select * from account where id=?",new BeanHandler<Account>(Account.class),2); ////使用第一种方式下面的BeanHandler<T>的方式匿名内部类
System.out.println(account.toString());
*/

//3.查询所有的信息
List<Account> list=qu.query("select * from account",new BeanListHandler<Account>(Account.class)); //Account.class可以自己封装---类的字节码获取类的实例
for(Account account:list)
{
System.out.println(account.toString());
}

}
}

第三部分:要生成和存取的Account类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package demain;

public class Account {

private String name; //写数据库的两个属性
private int money;

//下面是两个属性的set和get方法

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}

//输出的tostring方法

@Override
public String toString() {
return name+" "+money;
}

}

结果展示:


数据库连接池

一、数据库连接池

1.数据库的连接对象创建工作,比较消耗性能。

2.一开始现在内存中开辟一块空间(集合) , 一开先往池子里面放置 多个连接对象。 后面需要连接的话,直接从池子里面去。不要去自己创建连接了。 使用完毕,要记得归还连接。确保连接对象能循环利用。


二、自定义数据库连接池

步骤分析:

使用单元Junit测试

  1. 首先导入之前写好的JDBCUtil类和外部文件jdbc.properties还有jar文件。

  2. 新建一个MyDataSource类:
    需要继承DataSource类–实现所有方法(我们只需要完成getConnection()方法)–只需要管连接池对外公布的获取连接的方法getConnection()。
    2.1 建立MyDataSource方法:先往池子里面放10个连接(建立list集合存放),使用JDBCUtil.getConn()去获取连接,通过循环和add方法连续添加10个连接。
    2.2 在连接池对外公布的获取连接的方法中去通过remove移除(取连接)
    2.3 最后写一个方法addBack():用完之后归还。

  3. 如果现在链接不够的话,就要在取之前判断是否为0,如果不够就要for循环继续add()。

  4. 在项目处右键–构建路径–右边选Add Library–添加Junit4选项

  5. 新建测试的TestPool类:
    5.1 需要建立MyDataSource对象然后调用getConnection()连接
    5.2 写sql语句 –MyDataSource对象调用prepareStatement去检测SQL语句
    5.3 检测sql语句之后调用对应的executeUpdate()语句
    5.4 finally里面要写关于sql操作之后关闭对象–还需要通过对象调用addBack()方法

具体代码:

JDBCUtil类代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package util;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtil {

static String driverClass = null;
static String url = null;
static String name = null;
static String password= null;

static{
try {
//1. 创建一个属性配置对象
Properties properties = new Properties();
InputStream is = new FileInputStream("jdbc.properties");

//使用类加载器,去读取src底下的资源文件。 后面在servlet
// InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
//导入输入流。
properties.load(is);

//读取属性
driverClass = properties.getProperty("driverClass");
url = properties.getProperty("url");
name = properties.getProperty("name");
password = properties.getProperty("password");

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 获取连接对象
* @return
*/
public static Connection getConn(){
Connection conn = null;
try {
Class.forName(driverClass);
//静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver());
//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb");
//2. 建立连接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。
conn = DriverManager.getConnection(url, name, password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}

/**
* 释放资源
* @param conn
* @param st
* @param rs
*/
public static void release(Connection conn , Statement st , ResultSet rs){
closeRs(rs);
closeSt(st);
closeConn(conn);
}
public static void release(Connection conn , Statement st ){
closeSt(st);
closeConn(conn);
}


private static void closeRs(ResultSet rs){
try {
if(rs != null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}

private static void closeSt(Statement st){
try {
if(st != null){
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
st = null;
}
}

private static void closeConn(Connection conn){
try {
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
}

jdbc.properties代码(只需要更改数据库的名字)

1
2
3
4
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/bank
name=root
password=njdxrjgc7777777.

MyDataSource(实现DataSource类)代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package util;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.sql.DataSource;
/*
* 这是一个数据库连接池
* 一开始先往池子放10个连接
*
* 1.开始创建10个连接
*
* 2.取出去
*
* 3.拿回来
*
* 4.扩容
*
*/
public class MyDataSource implements DataSource{ //继承之后需要实现下面的方法(点击弹出)

List <Connection> list=new ArrayList<Connection>(); //建立list集合存放连接

public MyDataSource() { //添加10个连接
for(int i=0;i<10;i++)
{
Connection conn=JDBCUtil.getConn(); //提前拷贝JDBCUtil类和jdbc.properties外部文件和外部jar文件
list.add(conn); //add往里添加
}

}

//连接池对外公布的获取连接的方法
@Override
public Connection getConnection() throws SQLException {
//来拿连接的时候,先看看池子里面是否还有
if(list.size()==0) //如果没有了继续添加5个
{
for(int i=0;i<5;i++)
{
Connection conn=JDBCUtil.getConn(); //提前拷贝JDBCUtil类和jdbc.properties外部文件和外部jar文件
list.add(conn); //扩容
}
}

Connection conn = list.remove(0); //移除第一个(自动往前补) 相当于取连接
return conn;
}

public void addBack(Connection conn) { //自己写的在用完之后要归还的方法
list.add(conn); //add在加回去
}

//-------只需要看上面的连接方法----------

@Override
public PrintWriter getLogWriter() throws SQLException {
// TODO 自动生成的方法存根
return null;
}

@Override
public int getLoginTimeout() throws SQLException {
// TODO 自动生成的方法存根
return 0;
}

@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
// TODO 自动生成的方法存根
return null;
}

@Override
public void setLogWriter(PrintWriter arg0) throws SQLException {
// TODO 自动生成的方法存根

}

@Override
public void setLoginTimeout(int arg0) throws SQLException {
// TODO 自动生成的方法存根

}

@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
// TODO 自动生成的方法存根
return false;
}

@Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
// TODO 自动生成的方法存根
return null;
}


@Override
public Connection getConnection(String username, String password) throws SQLException {
// TODO 自动生成的方法存根
return null;
}

}

测试JUnit的TestPool代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Test;
public class TestPool {
@Test
public void testPool(){
Connection conn=null;
PreparedStatement ps =null;
MyDataSource my=new MyDataSource(); //调用我们写好的MyDataPool类

try {
conn = my.getConnection(); //第一步获取连接
String sql="insert into account values(4,'xilali',10)"; //第二步写sql语句
ps = conn.prepareStatement(sql); //第三步调用方法检测sql语句
ps.executeUpdate(); //调用方法对sql执行

} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {
try {
ps.close(); //关闭对象 替换了之前的JDBCUtil.release(conn,ps,rs);
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
//归还连接
my.addBack(conn); //用完之后一定要记得addBack归还连接
}
}
}

单元测试只是显示绿色/红色不通过—具体结果去看看数据库:


三、自定义数据库连接池存在的问题

  • 因为sun公司针对数据库连接池的定义没有用完返回的解决方案—->需要额外记住写addBack()方法

  • 单例

  • 不能面向接口编程

1
2
3
4
5
6
7
8
9
//面向对象编程
MyDataSource my=new MyDataSource(); //调用我们写好的MyDataSource类

//现在面向接口编程
DataSource dataSource = new MyDataSource(); //改成这样因为接口里面没有定义addBack方法
dataSource.addBack(); //会报错

//而且原来sun公司的Connection对于close()方法直接是关闭 ---我们需要直接改成返回连接
conn.colse();

四、解决存在的问题

  1. 修改接口中的那个close方法

  2. 原来的Connection对象的close方法,是真的关闭连接。

  3. 打算修改这个close方法,以后在调用close,并不是真的关闭,而是归还连接对象。


五、扩展方法

原有的方法逻辑,不是我们想要的。 想修改自己的逻辑

  1. 直接改源码—-无法实现。

  2. 继承—-必须得知道这个接口具体实现是谁。

  3. 使用装饰者模式(扩展一个类去更改方法)

  先是一个接口Waiter里面有service()方法,最后有一个Waitress类实现刚才的接口输出方法内容,但是现在可以通过建立WaitressWrap()方法去用构造方法获取接口对象,this获取对象,然后通过实现接口方法更改以前的操作。


六、装饰者模式–具体操作

我们新建ConnectionWrap类实现Connection接口的方法,但是只需要去更改close()和prepareStatement()方法。

1.只展示实现类ConnectionWrap类部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ConnectionWrap implements Connection{   //继承Connnection方法 修改它的close更改为 返回连接

Connection connection=null; //创建连接
List<java.sql.Connection> list;

public ConnectionWrap(java.sql.Connection conn, List<java.sql.Connection> list) { //构造方法
super();
this.connection =connection;
this.list=list;
}

@Override
public void close() throws SQLException { //更改了close()方法 ---变成了归还连接
list.add(connection);
}

@Override
public PreparedStatement prepareStatement(String sql) throws SQLException { //更改了里面的检验sql语句
return connection.prepareStatement(sql);
}

2.在MyDataSource类里面在取连接之前对connection对象进行调用COnnectionWrap类包装,

1
2
3
//抛出前,对对象进行包装
Connection connection=new ConnectionWrap(conn,list);
return connection;

3.在测试类之中以后就不用写归还的方法,而是直接写JDBCUtil的方法:

1
2
//归还连接
JDBCUtil.release(conn,ps);

七、开源连接池(DBCP/C3PO)

DBCP使用步骤:

###1. 导入对应的dbcp和pool的jar文件:

###2.1 不使用配置文件( BasicDataSource类):

思路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1.通过BasicDataSource类构件数据源对象
BasicDataSource dataSource = new BasicDataSource();

2.不使用配置文件---使用set方法添加那四行材料
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost/bank"); //jdbc:mysql://localhost/bank 主协议:子协议 ://本地/数据库
dataSource.setUsername("root");
dataSource.setPassword("njdxrjgc7777777.");

3.通过对象调用连接
conn = dataSource.getConnection(); //使用dataSource调用连接

4.书写SQL语句,然后去检验,添加,方法上传
String sql = "insert into account values(null , ? , ?)"; //sql插入语句
ps = conn.prepareStatement(sql); //检验sql语句

ps.setString(1, "admin"); //给下标1和2的设定具体的值
ps.setInt(2, 1000);

ps.executeUpdate(); //调用插入操作方法

5.finally最后使用JDBCUtil类的方法抓异常
JDBCUtil.release(conn, ps); //调用JDBCUtil类的方法

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package kaiyuan;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;
import util.JDBCUtil;
public class DBCPDemo {
@Test
public void testDBCP01(){
java.sql.Connection conn = null;
java.sql.PreparedStatement ps = null;
try {
//1. BasicDataSource类构建数据源对象
BasicDataSource dataSource = new BasicDataSource();

//连的是什么类型的数据库, 访问的是哪个数据库 , 用户名, 密码。。
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost/bank"); //jdbc:mysql://localhost/bank 主协议:子协议 ://本地/数据库
dataSource.setUsername("root");
dataSource.setPassword("njdxrjgc7777777.");

//2. 得到连接对象
conn = dataSource.getConnection(); //使用dataSource调用连接
String sql = "insert into account values(null , ? , ?)"; //sql插入语句
ps = conn.prepareStatement(sql); //检验sql语句

ps.setString(1, "admin"); //给下标1和2的设定具体的值
ps.setInt(2, 1000);

ps.executeUpdate(); //调用插入操作方法

} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps); //调用JDBCUtil类的方法
}
}
}

###2.2 使用配置文件( BasicDataSourceFactory类):

思路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1.通过BasicDataSourceFactory类构件数据源对象
BasicDataSourceDactory dataSource = new BasicDataSourceDactory();

2.使用配置文件-
//构造配置文件对象
Properties properties=new Properties();

//输入流加载文件(找到配置文件)
InputStream is=new FileInputStream("src//dbcpconfig.properties");
properties.load(is); //对象调用load加载文件(加载好)

DataSource dataSource = factory.createDataSource(properties); //输入流加载文件之后要用对象调用方法加载配置文件(加载到对象去)


3.通过对象调用连接(sun公司的DataSource)
conn = dataSource.getConnection(); //使用dataSource调用连接

4.书写SQL语句,然后去检验,添加,方法上传
String sql = "insert into account values(null , ? , ?)"; //sql插入语句
ps = conn.prepareStatement(sql); //检验sql语句

ps.setString(1, "liangchaowei"); //给下标1和2的设定具体的值
ps.setInt(2, 1020);

ps.executeUpdate(); //调用插入操作方法

5.finally最后使用JDBCUtil类的方法抓异常
JDBCUtil.release(conn, ps); //调用JDBCUtil类的方法

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package kaiyuan;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;
import util.JDBCUtil;
public class DBCPDemo02 {

@Test
public void testDBCP02() throws Exception{

//和之前的代码一样
java.sql.Connection conn = null;
java.sql.PreparedStatement ps = null;
try {
//1. BasicDataSourceFactory类构建数据源对象(因为有可以加载配置文件的方法)
BasicDataSourceFactory factory=new BasicDataSourceFactory();

//构造配置文件对象
Properties properties=new Properties();
//输入流加载文件
InputStream is=new FileInputStream("src//dbcpconfig.properties");
properties.load(is); //输入流加载配置文件

DataSource dataSource = factory.createDataSource(properties); //输入流加载文件之后要用对象调用方法加载配置文件

//2. 得到连接对象
conn = dataSource.getConnection(); //使用dataSource调用连接
String sql = "insert into account values(null , ? , ?)"; //sql插入语句
ps = conn.prepareStatement(sql); //检验sql语句

ps.setString(1, "liangchaowei"); //给下标1和2的设定具体的值
ps.setInt(2, 1020);

ps.executeUpdate(); //调用插入操作方法

} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps); //调用JDBCUtil类的方法
}

}
}

dbcpconfig.properties配置文件(放在src下面设置好连接池的连接初始化/最大数等等):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/bank
username=root
password=njdxrjgc7777777.

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

#<!-- 最大空闲连接 -->
maxIdle=20

#<!-- 最小空闲连接 -->
minIdle=5

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000


#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

J3P0使用步骤:

###1. 导入对应的c3p0-0.9.1.2.jar文件:

###2.1 不使用配置文件方式(ComboPooledDataSource类)

思路:

1
和DBCP数据池的不实用配置文件方式一样,只不过一个是BasicDataSource类、另外一个是ComboPooledDataSource类

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Connection conn = null;
PreparedStatement ps = null;
try {
//1. 创建datasource
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//2. 设置连接数据的信息

dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost/bank");
dataSource.setUser("root");
dataSource.setPassword("root");

//2. 得到连接对象
conn = dataSource.getConnection();
String sql = "insert into account values(null , ? , ?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "admi234n");
ps.setInt(2, 103200);

ps.executeUpdate();

} catch (Exception e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}

###2.2 使用配置文件方式(ComboPooledDataSource)

思路:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1.需要导入c3p0-config.xml解析文件(名字不能更改!!!!)

2.跟以前的相比只需要第一步new一个ComboPooledDataSource对象
ComboPooledDataSource dataSource=new ComboPooledDataSource();

3.然后通过对象getConnection()获得连接。
conn = dataSource.getConnection();

4.新建sql语句,通过连接检验sql语句,添加下标内容,调用插入语句
String sql = "insert into account values(null , ? , ?)"; //sql插入语句
ps = conn.prepareStatement(sql); //检验sql语句

ps.setString(1, "adminsan"); //给下标1和2的设定具体的值
ps.setInt(2, 1050);

ps.executeUpdate(); //调用插入操作方法

5.finally最后调用JDBCUtil类方法
JDBCUtil.release(conn, ps); //调用JDBCUtil类的方法

c3p0-config.xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>

<!-- default-config 默认的配置, -->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property> <!-- 要和不用配置文件的set方法的后面一样 -->
<property name="jdbcUrl">jdbc:mysql://localhost/bank</property>
<property name="user">root</property>
<property name="password">njdxrjgc7777777.</property>


<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property> <!-- 关于连接池的细节设计 -->
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>

<!-- This app is massive! -->
<named-config name="oracle"> <!-- oracle数据库用 -->
<property name="acquireIncrement">50</property>
<property name="initialPoolSize">100</property>
<property name="minPoolSize">50</property>
<property name="maxPoolSize">1000</property>

<!-- intergalactoApp adopts a different approach to configuring statement caching -->
<property name="maxStatements">0</property>
<property name="maxStatementsPerConnection">5</property>

<!-- he's important, but there's only one of him -->
<user-overrides user="master-of-the-universe">
<property name="acquireIncrement">1</property>
<property name="initialPoolSize">1</property>
<property name="minPoolSize">1</property>
<property name="maxPoolSize">5</property>
<property name="maxStatementsPerConnection">50</property>
</user-overrides>
</named-config>

</c3p0-config>

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package kaiyuaner;
import java.sql.SQLException;
import javax.sql.CommonDataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import util.JDBCUtil;
public class C3P0Demo {

@Test
public void C3P0Demo01(){
java.sql.Connection conn = null;
java.sql.PreparedStatement ps = null;
try {

//1.只需要new一个对象(找路径什么的C3P0帮你完成)
ComboPooledDataSource dataSource=new ComboPooledDataSource(); //xml里面有两种数据库(默认会找default-config分支) 如果需要用oracle数据库就("oracle")

//2. 得到连接对象
conn = dataSource.getConnection(); //使用dataSource调用连接
String sql = "insert into account values(null , ? , ?)"; //sql插入语句
ps = conn.prepareStatement(sql); //检验sql语句

ps.setString(1, "adminsan"); //给下标1和2的设定具体的值
ps.setInt(2, 1050);

ps.executeUpdate(); //调用插入操作方法

} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps); //调用JDBCUtil类的方法
}

}
}
,