BS通信模型
B/S 结构项目中, 浏览器(Browse)负责把用户的请求和参数通过网络发送给服务器(Server)。
服务端使用 Servlet(多种服务端技术的一种)接收请求,并将处理结果返回给浏览器。
浏览器在 html,jsp 上呈现数据,混合使用 css, js 帮助美化页面,或响应事件。
1.0-全局刷新 和 局部刷新
全局刷新: 整个浏览器被新的数据覆盖。 在网络中传输大量的数据。 浏览器需要加载,渲染页面。
全局刷新原理:
1) 必须由浏览器亲自向服务端发送请求协议包。
2) 这个行为导致服务端直接将【响应包】发送到浏览器内存中
3) 这个行为导致浏览器内存中原有内容被覆盖掉
4) 这个行为导致浏览器在展示数据时候,只有响应数据可以展示
局部刷新: 在浏览器的内部,发起请求,获取数据,只改变页面中的部分内容。 其余的页面无需加载和渲染。在网络中数据传输量少, 用户体验效果好。
(浏览器在展示数据时,此时在窗口既可以看到本次的响应数据, 同时又可以看到浏览器内存中原有数据)
局部刷新原理:
1) 不能由浏览器发送请求给服务端
2) 浏览器委托浏览器内存中一个脚本对象代替浏览器发送请求.
3) 这个行为导致导致服务端直接将【响应包】发送脚本对象内存中
4) 这个行为导致脚本对象内容被覆盖掉,但是此时浏览器内存中绝大部分内容没有收到任何影响.
5) 这个行为导致浏览器在展示数据时候,同时展示原有数据和响应数据
2.0-AJAX技术概述
全称:"Asynchronous JavaScript and XML" "异步的 JavaScript 和 XML"
作用:使用Ajax技术实现局部刷新的功能效果。
原理:通过使用JavaScript 语法创建异步对象 XMLHttpRequest ,并操作 异步对象,向服务器发送请求 或 从获取服务端发送来的XML或JSON格式的数据, 更新页面的dom对象,最后在浏览器中进行解析展示。
说明:ajax请求的目的是需要获取服务器端的数据。
1)AJAX是在 2005年被Jesse James Garrett提出的新术语,用来描述一种使用现有技术集合混合使用的一种‘新’方法。而并非一门编程语言。 是一种在无需重新加载整个网页的情况下,能够更新部分页面内容(局部更新 )的新方法。AJAX 不仅需要前端的技术,同时需要后端(服务器)的配合。服务器需要提供数据,数据是 AJAX 请求的响应结果。
2)ajax包含的技术主要包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest。 核心是javascript 和 xml 。
浏览器内建的 XMLHttpRequest 对象 : ( 负责 从 web 服务器发送请求, 接收响应数据)
JavaScript 和 HTML、 DOM : (负责显示或使用数据)
XML: 是一种在网络中的传输的数据格式。(负责发送和接收的数据格式,现在主流使用 json数据传输格式)
3)局部刷新使用的核心对象是 XMLHttpRequest【异步对象】。(由该对象负责局部刷新)
4)异步对象使用JavaScript语法进行创建和使用,异步对象存在于浏览器内存中。
5)浏览器内存中可以存在多个异步对象。每一个异步对象都可以独自向服务器发送请求,和 从服务器中获取数据。
6)使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作。
《百度百科》
1)Ajax这个术语源自描述从基于 Web 的应用到基于数据的应用。
2)Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。
2.1-AJAX的工作流程
- 网页中发生一个事件(页面加载、按钮点击)
- 由 JavaScript 创建 XMLHttpRequest 对象
- XMLHttpRequest 对象向 web 服务器发送请求
- 服务器处理该请求
- 服务器将响应发送回网页
- 由 JavaScript 读取响应
- 由 JavaScript 执行正确的动作(比如更新页面)
3.0-XMLHttpRequest 异步对象概述
概 述
在局部刷新,需要创建一个对象,代替浏览器发起请求的行为,这个对象存在内存中。
代替浏览器发起请求并接收响应数据。这个对象叫做异步请求对象。
全局刷新是同步行为 [浏览器数据会全部更新], 局部刷新是异步行为 [浏览器数据没有全部更新]
这个异步对象用于在后台与服务器交换数据。XMLHttpRequest 就是我们说的异步对象。
1)-所有现代的浏览器都支持 XMLHttpRequest 对象。
2)-XMLHttpRequest 对象用于在后台与服务器交换数据。
3)-XMLHttpRequest 对象的作用:
- 在不重新加载页面的情况下更新网页;
- 在页面已加载后从服务器请求数据;
- 在页面已加载后从服务器接收数据;
- 在后台向服务器发送数据;
详细教程:https://www.w3school.com.cn/xml/xml_http.asp
3.1-XMLHttpRequest 异步对象的属性
readyState属性
———— 表示异步对象请求的状态变化 (有0~4 五个值)
0: 创建异步对象, 执行new XMLHttpRequest();时。
1: 初始异步请求对象, 执行xmlHttpRequest.open( );时。
2: 发送请求, 执行xmlHttpRequest.send();时。
3: 从服务器端获取了数据,此时是3。 注意3是异步对象内部使用, 表示获取了原始的数据。(开发人员一般不用3这个值)
4:异步对象把接收的数据处理完成后。 此时开发人员在状态值是4的时候来处理数据。(在4状态时候,开发人员应该做什么 ?—— 拿到数据之后,更新当前页面。)
status属性
———— 表示网络请求的状况的。
200,当status==200时,表示网络请求是成功的。
404,当status==404时,表示请求访问不到服务器资源。
500,当status==500时,表示服务器代码出错。
responseText属性
———— 获取服务器端返回获的字符串形式的响应数据。
var data = xmlHttpRequest.responseText;
responseXML属性
———— 获得 XML 形式的响应数据。
var data = xmlHttpRequest.responseXML;
3.2-使用XMLHttpRequest对象的步骤
1) 创建异步对象
// 1)-创建异步对象
var xmlHttp = new XMLHttpRequest();
2) 给异步对象绑定 onreadystatechange 事件
onreadystatechange 是一个事件句柄。它的值 (state_Change) 是一个函数的名称,当 XMLHttpRequest 对象的状态发生改变时,会触发此函数。
状态从 0 (uninitialized) 到 4 (complete) 进行变化。仅在状态为 4 时,我们才执行代码。
需要为这个事件指定一个函数, 在函数中处理状态的变化。当异步对象发起请求 或 获取了数据都会触发这个事件。
通过该事件可以获取异步对象发送请求或获取数据的状态。
// 2)-为异步对象绑定onreadystatechange事件,处理请求的状态变化。
xmlHttpRequest.onreadystatechange= function(){
}
3) 初始异步请求对象
———xmlHttpRequest.open( String method,String url,boolean async);
// 3)-初始异步请求对象。采用get提交方式,访问loginServlet且携带相关的参数
xmlHttpRequest.open("get", "loginServlet?name=james&pwd=123",true);
method参数:请求的类型;GET 或 POST
url参数: 服务器端的访问地址。可以携带相关的参数。
async参数: true(异步)或 false(同步)。该参数规定请求是否异步处理。默认的true值代表异步请求,false值表示同步请求。
异步处理请求: 使用异步对象发起请求之后,脚本会在 send() 方法之后继续执行,而不等待来自服务器的响应。即不用等待数据处理完毕,就可以执行其他操作。
同步处理请求:异步对象必须处理完成请求,从服务端获取数据后,才能执行send()之后的代码。任意时刻只能执行一个请求。onreadystatechange 事件使代码复杂化了。但是这是在没有得到服务器响应的情况下,防止代码停止的最安全的方法。通过把该参数设置为 "false",可省去额外的onreadystatechange代码。若在请求失败时是否执行其余的代码无关紧要,则么可以使用该参数。
4) 使用异步对象发送请求
// 4)-异步对象向服务器发送请求
xmlHttpRequest.send( );
5) 接收并处理服务端的数据
如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或responseXML 属性。
responseText:获得字符串形式的响应数据
responseXML:获得 XML 形式的响应数据
需要注意的是:第5步中的代码需要写在第2步之中。
// 2)-为异步对象绑定onreadystatechange事件,处理请求的状态变化。 xmlHttpRequest.onreadystatechange= function(){ //5)-【处理服务器端的数据,更新当前页面】 //异步对象已成功获取到了服务端的数据 ,且 当网络请求是成功的状态。 if(xmlHttpRequest.readyState == 4 && xmlHttpRequest.status== 200 ){ //获取到的是服务端发送来的数据。 var data = xmlHttpRequest.responseText; //更新页面DOM对象的内容。 document.getElementById("name").value= data; } }
4.1-全局刷新案例:计算用户BMI值
方案1 (借助请求域空间进行存储处理数据)
代码思路:BmiServlet的处理数据,借助请求域空间进行存储。并且请求转发到result.jsp页面中,向用户进行数据展示。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>全局刷新计算BMI</title> </head> <body> <p>全局刷新计算BMI</p> <form action="bmiServlet" method="post"> 姓名:<input type="text" name="name"/><br/> 身高:<input type="text" name="height"/>(M)<br/> 体重:<input type="text" name="weight"/>(KG)<br/> <input type="submit" value="计算BMI值" > </form> </body> </html>
1 package com.penguin1024.controller; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import java.io.IOException; 8 9 public class BmiServlet extends HttpServlet { 10 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 11 // 覆盖此请求体中使用的字符编码的名称。(解决post提交产生的中文请求参数问题) 12 request.setCharacterEncoding("utf-8"); 13 14 // 获取用户提交的请求参数信息 15 String nameStr = request.getParameter("name"); 16 String heightStr = request.getParameter("height"); 17 String weightStr = request.getParameter("weight"); 18 19 // 需要先将字符串类型的heightStr 和 weightStr ,转为float类型。 20 Float height = Float.valueOf(heightStr); 21 Float weight = Float.valueOf(weightStr); 22 23 // 再按照公式计算BMI值。 体质指数(BMI)=体重(千克)除以身高(平方米) 24 Float bmi = weight/(height*height); 25 26 27 // 准备一个空字符串,用于提示用户信息。 28 String msg = ""; 29 // 计算用户BMI值所对应的范围 30 if( bmi <= 18.5) { 31 msg = "您比较瘦"; 32 } else if( bmi > 18.5 && bmi <= 23.9 ){ 33 msg = "您的bmi是正常的"; 34 } else if( bmi >24 && bmi <=27){ 35 msg = "您的身体比较胖"; 36 } else { 37 msg = "您的身体肥胖"; 38 } 39 40 // 拼接字符串提示信息 41 msg = nameStr + "先生/女士。 您的BMI值是:"+ bmi + " ———— "+ msg; 42 43 // 将字符串类型msg变量,存储到request域中。(用于让对应的jsp页面使用EL表达式获取,并展示数据给用户) 44 request.setAttribute("msg",msg); 45 46 // 请求转发到result.jsp页面中 47 request.getRequestDispatcher("/result.jsp").forward(request,response); 48 } 49 50 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 51 this.doPost(request,response); 52 } 53 }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>BMI结果界面</title> </head> <body> <p>显示bmi计算结果</p> <h3>${msg}</h3> </body> </html>
方案2 (借助标准输出流对象,将提示信息输出到浏览器)
代码思路:BmiPrintServlet不借助域空间存储数据,直接借助标准输出流对象,将提示信息输出到浏览器。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>全局刷新计算BMI</title> </head> <body> <p>全局刷新计算BMI</p> <form action="bmiPrintServlet" method="post"> 姓名:<input type="text" name="name"/><br/> 身高:<input type="text" name="height"/>(M)<br/> 体重:<input type="text" name="weight"/>(KG)<br/> <input type="submit" value="计算BMI值" > </form> </body> </html>
1 package com.penguin1024.controller; 2 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7 import java.io.IOException; 8 import java.io.PrintWriter; 9 10 public class BmiPrintServlet extends HttpServlet { 11 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 12 // 覆盖此请求体中使用的字符编码的名称。(解决post提交产生的中文请求参数问题) 13 request.setCharacterEncoding("utf-8"); 14 15 // 获取用户提交的请求参数信息 16 String nameStr = request.getParameter("name"); 17 String heightStr = request.getParameter("height"); 18 String weightStr = request.getParameter("weight"); 19 20 // 需要先将字符串类型的heightStr 和 weightStr ,转为float类型。 21 Float height = Float.valueOf(heightStr); 22 Float weight = Float.valueOf(weightStr); 23 24 // 再按照公式计算BMI值。 体质指数(BMI)=体重(千克)除以身高(平方米) 25 Float bmi = weight/(height*height); 26 27 28 // 准备一个空字符串,用于提示用户信息。 29 String msg = ""; 30 // 计算用户BMI值所对应的范围 31 if( bmi <= 18.5) { 32 msg = "您比较瘦"; 33 } else if( bmi > 18.5 && bmi <= 23.9 ){ 34 msg = "您的bmi是正常的"; 35 } else if( bmi >24 && bmi <=27){ 36 msg = "您的身体比较胖"; 37 } else { 38 msg = "您的身体肥胖"; 39 } 40 41 // 拼接字符串提示信息 42 msg = nameStr + "先生/女士。 您的BMI值是:"+ bmi + " ———— "+ msg; 43 44 45 // 如果尚未提交响应,则设置发送到客户机的响应的内容类型 46 // 且将发送到客户端的响应的字符编码(MIME字符集)设置为UTF-8。 47 // 能解决响应中的中文乱码问题。 48 response.setContentType("text/html;charset=utf-8"); 49 50 // 获取标准输出流对象,该对象可以向客户端发送字符文本。 51 PrintWriter out = response.getWriter(); 52 // 输出数据 53 out.println(msg); 54 // 清空缓存 55 out.flush(); 56 // 关闭流 57 out.close(); 58 59 } 60 61 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 62 this.doPost(request,response); 63 } 64 }
访问:
4.2-Ajax局部刷新案例:计算用户BMI值
使用ajax技术实现局部刷新功能效果的代码思路
1-新建index.jsp,创建和使用XMLHttpRequest异步对象。(5个步骤)
1).创建
2).绑定事件
3).初始请求
4).发送请求
5).处理服务端发送的数据
2-创建服务器的BmiAjaxServlet.java,接收并处理来自异步对象发送的请求数据, 并把处理之后的数据通过标准输出流输出给异步对象。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Ajax局部刷新计算BMI</title> <script type="text/javascript"> // 使用浏览器内存中的异步对象,代替浏览器发起请求。异步对象使用js创建和管理的。 function doAjax() { // 1-创建异步请求对象 var xmlHttpRequest= new XMLHttpRequest(); // 2-绑定onreadystatechange事件 xmlHttpRequest.onreadystatechange = function () { //异步对象已成功获取到了服务端的数据 ,且 当网络请求是成功的状态。 if (xmlHttpRequest.readyState==4 && xmlHttpRequest.status ==200){ // 获取服务器发送来的数据 var data = xmlHttpRequest.responseText; // 更新dom对象,更新页面数据 document.getElementById("mydata").innerText = data; } } // 3-初始异步请求对象 (初始化请求数据) // 获取dom对象的value值 var name = document.getElementById("name").value; var height = document.getElementById("height").value; var weight = document.getElementById("weight").value; // JavaScript 中的encodeURI(String uri) 函数作用:可把字符串作为 URI 进行编码。 // JavaScript 中的decodeURI(String uri) 函数作用:可对encodeURI(String uri) 编码过的 URI 进行解码。 name = encodeURI(name); alert(name); // 结果是 %E8%83%96%E4%BC%81%E9%B9%85 // 按照格式拼接需要携带的请求参数 var parameter = "name="+name+"&height="+height+"&weight="+weight; xmlHttpRequest.open("get","${pageContext.request.contextPath}/bmiAjaxServlet?"+parameter,true) // 4-向服务器发送请求 xmlHttpRequest.send(); } </script> </head> <body> <p>局部刷新ajax-计算bmi</p> <div> <!-- ajax局部刷新没有使用<form>提交 --> 姓名:<input type="text" id="name" /> <br/> 身高:<input type="text" id="height" /> <br/> 体重:<input type="text" id="weight" /> <br/> <input type="button" value="计算bmi" onclick="doAjax()"> <br/> <br/> <div id="mydata">等待加载数据....</div> </div> </body> </html>
package com.penguin1024.controller; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; public class BmiAjaxServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 覆盖此请求体中使用的字符编码的名称。(解决post提交产生的中文请求参数问题) request.setCharacterEncoding("utf-8"); // 获取用户提交的请求参数信息 String nameStr = request.getParameter("name"); String heightStr = request.getParameter("height"); String weightStr = request.getParameter("weight"); // 需要先将字符串类型的heightStr 和 weightStr ,转为float类型。 Float height = Float.valueOf(heightStr); Float weight = Float.valueOf(weightStr); // 再按照公式计算BMI值。 体质指数(BMI)=体重(千克)除以身高(平方米) Float bmi = weight/(height*height); // 准备一个空字符串,用于提示用户信息。 String msg = ""; // 计算用户BMI值所对应的范围 if( bmi <= 18.5) { msg = "您比较瘦"; } else if( bmi > 18.5 && bmi <= 23.9 ){ msg = "您的bmi是正常的"; } else if( bmi >24 && bmi <=27){ msg = "您的身体比较胖"; } else { msg = "您的身体肥胖"; } // 拼接字符串提示信息 msg = nameStr + "先生/女士。 您的BMI值是:"+ bmi + " ———— "+ msg; // 如果尚未提交响应,则设置发送到客户机的响应的内容类型 // 且将发送到客户端的响应的字符编码(MIME字符集)设置为UTF-8。 // 能解决响应中的中文乱码问题。 response.setContentType("text/html;charset=utf-8"); // 获取标准输出流对象,该对象可以向客户端发送字符文本。 PrintWriter out = response.getWriter(); // 输出数据 (响应ajax需要的数据,使用HttpServletResponse输出数据) out.println(msg); // 清空缓存 out.flush(); // 关闭流 out.close(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
JS代码中的中文请求参数的传输问题?
JavaScript 中的encodeURI(String uri) 函数:可把字符串作为 URI 进行编码。
JavaScript 中的decodeURI(String uri) 函数:可对encodeURI(String uri) 编码过的 URI 进行解码。
如:alert(encodeURI("胖企鹅")); 的执行结果是 %E8%83%96%E4%BC%81%E9%B9%85
4.3-Ajax局部刷新案例:根据省份id获取省份名称,并局部更新界面信息。
1-环境搭建
0)-DOS命令行窗口mysql中文显示乱码问题解决方法:
产生原因:MySQL的默认编码是Latin1,不支持中文,因此需要修改MySQL的默认编码。只需修改mysql安装目录下的my.ini 配置文件的两处地方即可:
1)-创建数据库 fatpenguin
create database fatpenguin;
2)-使用创建好的数据库,并在该数据库中添加两张表:province (省份信息表)
use fatpenguin;
province省份表:
CREATE TABLE `province` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL COMMENT '省份名称', `jiancheng` varchar(255) DEFAULT NULL COMMENT '简称', `shenghui` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
3)-查看province表中的数据
4)-创建javaweb项目
在web/WEB-INF目录下手动创建lib目录 和 classes目录。并在lib目录中放置mysql的驱动jar包并打开 Project Structure 进行相关的工程结构设置 。 (参照IDEA设置博客)
2-编写代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>ajax根据省份id获取名称</title> <script type="text/javascript"> // 使用浏览器内存中的异步对象,代替浏览器发起ajax请求,传递参数给服务器, 服务器返回数据。 //1.创建异步对象 (异步对象使用js创建和管理的。) function search() { // 1-创建异步请求对象 var xmlHttpRequest= new XMLHttpRequest(); // 2-绑定onreadystatechange事件 xmlHttpRequest.onreadystatechange = function () { // 5-对从服务端中返回的数据做相关处理 // 判断:若 异步对象已成功获取到了服务端的数据 ,且 当网络请求是成功的状态的情况下。 if (xmlHttpRequest.readyState==4 && xmlHttpRequest.status ==200){ // 获取服务器发送来的数据 var data = xmlHttpRequest.responseText; // 更新dom对象,更新页面数据 document.getElementById("proname").value = data; } } // 3-初始异步请求对象 (初始化请求数据) //获取proid文本框的值 (用户在界面中输入的值) var proid = document.getElementById("proid").value; // 使用js中的函数encodeURI(String uri) 对字符串 进行编码 (可以解决JS中的中文参数乱码问题) proid = encodeURI(proid); xmlHttpRequest.open("get","${pageContext.request.contextPath}/queryProviceServlet?proid="+proid,true); // 4-向服务器发送请求 xmlHttpRequest.send(); } </script> </head> <body> <p>AJAX根据省份id编号获取省份名称:</p> <table> <tr> <td>省份编号:</td> <td><input type="text" id="proid"/> <input type="button" value="搜索" onclick="search()" /> </td> </tr> <tr> <td>省份名称:</td> <td><input type="text" id="proname" /></td> </tr> </table> </body> </html> index.jsp
package com.penguin1024.utils; import java.sql.*; // 定义连接数据库的JDBC工具类 // 注意事项:工具类中的 可能产生异常的代码 不使用try..catch方式处理,一般使用抛出的方式。 // 因为使用try...catch方式进行处理。代码一旦发生异常,工具类的调用者不好定位到发生异常的代码。 public class JdbcUtil { // 静态代码块 static { try { // 1-在JdbcUtil类加载时,加载mysql数据库的驱动 Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 声明一个成员变量Connection对象 ,且需定义为静态成员 (该代码由下列方法中的代码思考之后,添加的) // 静态方法中只能访问静态成员,不能访问到实例成员。 static Connection conn = null; // 2-定义:获取数据库连接Connection对象的方法 // 注意:Connection 是java.sal.Connection(接口)。为什么? —— 面向接口编程,好处是不用在乎该连接是由谁实现的 public static Connection getConnection() throws SQLException { String user = "jdbc:mysql://localhost:3306/fatpenguin"; String url = "root"; String password = "111"; //重点注意: //思考什么时候需要创建Connection接口对象?每次使用时候都需要创建新的连接吗? //当conn = null时,才需要创建一个新的Connection接口对象。 // Connection conn = null;错误。不能在此处将conn变量定义为局部变量。 // 这样的写的话,下面的判断结果永远是false值。 // 因此需要将在类中定义为静态成员: private static Connection conn = null; // conn值为null,或conn被关闭时,需要重新创建Connection对象。 // 如果Connection对象为null,或者Connection对象已经被关闭掉的情况下 if (conn == null || conn.isClosed() ){ // 满足以上条件,则创建新的Connection对象。 conn = DriverManager.getConnection(user, url, password); } return conn; } // 3-定义:关闭相关资源 public static void close(Connection conn, Statement stmt, ResultSet rs) throws SQLException { // 关闭资源1 // 如果conn不等于null,且conn也没有被关闭的情况下。 if (conn != null && !conn.isClosed()) { conn.close(); // 关闭 } // 关闭资源2 if (stmt != null && !conn.isClosed()) { stmt.close(); // 关闭 } // 关闭资源3 if (rs != null && !conn.isClosed()) { rs.close(); // 关闭 } } } JdbcUtil.java
package com.penguin1024.dao; import com.penguin1024.utils.JdbcUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // 对数据库中的数据执行相关的操作 public class ProvinceDao { // 根据用户输入的省份id,查询出该id值所对应的省份名称 public String queryProvinceNameById(Integer provinceid){ Connection conn = null; PreparedStatement ps = null; ResultSet res = null; // 定义一个空字符串,用于接收查询出来的省份名称 String name = ""; try { // 1-借助编写好的JdbcUtil工具类,获取Connection 数据库连接对象 conn = JdbcUtil.getConnection(); // 2-编写SQL语句框架 String sql = "select name from province where id = ?"; // 3-对SQL语句框架进行预编译处理 (避免SQL注入情况的产生) ps = conn.prepareStatement(sql); // 4-对SQL语句框架中的占位符,设置具体的参数值 ps.setInt(1,provinceid); // 5-执行SQL语句,并接收返回的结果集 res = ps.executeQuery(); // 6-遍历处理查询结果集 while (res.next()){ // 获取这条数据中,字段名为"name"的值 name = res.getString("name"); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { try { // 7-借助编写好的JdbcUtil工具类,关闭相关资源 JdbcUtil.close(conn,ps,res); } catch (SQLException throwables) { throwables.printStackTrace(); } } // 8-返回省份id编号所对应的省份名称 return name; } } ProvinceDao.java
package com.penguin1024.controller; import com.penguin1024.dao.ProvinceDao; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; // 执行相关的业务逻辑操作 public class QueryProviceServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 定义一个字符串类型变量,用于接收查询到的省份名称。 String provinceName ="默认没有数据"; // 1-对请求参数做相关处理 // 覆盖此请求体中使用的字符编码的名称。 (解决post方式的中文乱码问题) request.setCharacterEncoding("utf-8"); // 接收来自Ajax异步对象发送来的请求参数 String proidStr = request.getParameter("proid"); // 将字符串类型的省份id编号,转换为Integet类型 Integer provinceId = Integer.valueOf(proidStr); // 2-访问Dao层对象,从数据库中查询数据 // 判断条件: // 用户在查询界面中输入的不是空字符串 // 且输入的id编号在转换为Integer类型之后的值不为null // 且转换为Integer类型的结果是在[1-9]区间的整数 if( !"".equals(proidStr.trim()) && provinceId != null && (provinceId>=1 && provinceId<=9)) { // 创建dao对象 ProvinceDao dao = new ProvinceDao(); // 调用dao对象的方法 — —根据用户添加的省份id编号,到数据库中查找出该编号对应的省份名称 provinceName = dao.queryProvinceNameById(provinceId); }else { provinceName = "请输入合法的省份编号!!!"; } // 3-向发送请求的Ajax异步请求对象返回查询到的结果 //使用HttpServletResponse输出数据 // servlet返回给浏览器的是文本数据类型, 告诉浏览器采用utf-8字符集进行解码 (解决响应的中文乱码问题) response.setContentType("text/html;charset=utf-8"); // 获取标准输出流 PrintWriter out = response.getWriter(); // 往标准输出流中写入的数据,会被响应到发出相应请求的Ajax异步对象中。 out.println(provinceName); // 清空缓存 out.flush(); // 关闭流 out.close(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
注意事项:
1)index.jsp的编写步骤:最先编写登录界面的前端显示内容(body标签中的内容),再搭建好Ajax代码的1-4步代码。 Ajax代码中的第5步骤代码留在最后编写,也就是编写完QueryProviceServlet.java代码之后再进行编写。
2)mysql建表语句中问题:
Mysql中如果表和表之间建立的外键约束,则无法删除表及修改表结构。
解决方法:在Mysql中取消外键约束: 添加代码 SET FOREIGN_KEY_CHECKS=0; 然后将原来表的数据导出到sql语句,重新创建此表后,再把数据使用sql导入,然后再设置外键约束:SET FOREIGN_KEY_CHECKS=1;
3-测试查询结果
输入合法的1-9的整数编号值,显示结果如下:
若输入1-9之外的整数值,显示结果如下:
若在省份编号栏中,输入空字符串 或 中文,则程序会报500错误。(程序抛出异常)
4.4-Ajax局部刷新案例:根据省份id获取省份信息,并局部更新界面信息。
1-环境搭建
1)创建javaweb项目。
操作:
在web/WEB-INF目录下手动创建lib目录 和 classes目录。并在lib目录中并添加mysql驱动 以及 json相关的jar包,并打开 Project Structure 进行相关的工程结构设置 。
2)fatpenguin数据库中准备两张表 province表 和 city表。
province表:
CREATE TABLE `province` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL COMMENT '省份名称', `jiancheng` varchar(255) DEFAULT NULL COMMENT '简称', `shenghui` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8
city表:
CREATE TABLE `city` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `provinceid` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
注意事项:city表中的 provinceid字段作为 外键,代表的是省份表的主键的值
2-代码编写
package com.penguin1024.utils; import java.sql.*; // 定义连接数据库的JDBC工具类 // 注意事项:工具类中的 可能产生异常的代码 不使用try..catch方式处理,一般使用抛出的方式。 // 因为使用try...catch方式进行处理。代码一旦发生异常,工具类的调用者不好定位到发生异常的代码。 public class JdbcUtil { // 静态代码块 static { try { // 1-在JdbcUtil类加载时,加载mysql数据库的驱动 Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 声明一个成员变量Connection对象 ,且需定义为静态成员 (该代码由下列方法中的代码思考之后,添加的) // 静态方法中只能访问静态成员,不能访问到实例成员。 static Connection conn = null; // 2-定义:获取数据库连接Connection对象的方法 // 注意:Connection 是java.sal.Connection(接口)。为什么? —— 面向接口编程,好处是不用在乎该连接是由谁实现的 public static Connection getConnection() throws SQLException { String user = "jdbc:mysql://localhost:3306/fatpenguin"; String url = "root"; String password = "111"; //重点注意: //思考什么时候需要创建Connection接口对象?每次使用时候都需要创建新的连接吗? //当conn = null时,才需要创建一个新的Connection接口对象。 // Connection conn = null;错误。不能在此处将conn变量定义为局部变量。 // 这样的写的话,下面的判断结果永远是false值。 // 因此需要将在类中定义为静态成员: private static Connection conn = null; // conn值为null,或conn被关闭时,需要重新创建Connection对象。 // 如果Connection对象为null,或者Connection对象已经被关闭掉的情况下 if (conn == null || conn.isClosed() ){ // 满足以上条件,则创建新的Connection对象。 conn = DriverManager.getConnection(user, url, password); } return conn; } // 3-定义:关闭相关资源 public static void close(Connection conn, Statement stmt, ResultSet rs) throws SQLException { // 关闭资源1 // 如果conn不等于null,且conn也没有被关闭的情况下。 if (conn != null && !conn.isClosed()) { conn.close(); // 关闭 } // 关闭资源2 if (stmt != null && !conn.isClosed()) { stmt.close(); // 关闭 } // 关闭资源3 if (rs != null && !conn.isClosed()) { rs.close(); // 关闭 } } }
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>使用json格式的数据</title> <script type="text/javascript"> // 使用浏览器内存中的异步对象,代替浏览器发起ajax请求,传递参数给服务器, 服务器返回数据。 //1.创建异步对象 (异步对象使用js创建和管理的。) function search() { // 1-创建异步请求对象 var xmlHttpRequest= new XMLHttpRequest(); // 2-绑定onreadystatechange事件 xmlHttpRequest.onreadystatechange = function () { // 5-对从服务端中返回的数据做相关处理 // 判断:若 异步对象已成功获取到了服务端的数据 ,且 当网络请求是成功的状态的情况下。 if (xmlHttpRequest.readyState==4 && xmlHttpRequest.status ==200){ // 获取服务器发送来的数据 (在此处,传递过来的是一个json格式的字符串) var data = xmlHttpRequest.responseText; //JavaScript中的eval(string)函数执行括号中的代码, 把json字符串转为json对象 var jsonobj = eval("(" + data + ")"); // 调用自定义的数据处理函数:来更新dom对象,更新页面数据 callback(jsonobj); } } // 3-初始异步请求对象 (初始化请求数据) //获取proid文本框的值 (用户在界面中输入的值) var proid = document.getElementById("proid").value; // 使用js中的函数encodeURI(String uri) 对字符串 进行编码 (可以解决JS中的中文参数乱码问题) proid = encodeURI(proid); xmlHttpRequest.open("get","${pageContext.request.contextPath}/queryProviceServlet?proid="+proid,true); // 4-向服务器发送请求 xmlHttpRequest.send(); } // 定义一个函数,来处理服务器端返回的数据 function callback(json){ document.getElementById("proname").value = json.name; document.getElementById("projiancheng").value=json.jiancheng; document.getElementById("proshenghui").value= json.shenghui; } </script> </head> <body> <p>ajax请求使用json格式的数据</p> <table> <tr> <td>省份编号:</td> <td><input type="text" id="proid"> <input type="button" value="搜索" onclick="search()"> </td> </tr> <tr> <td>省份名称:</td> <td><input type="text" id="proname"></td> </tr> <tr> <td>省份简称:</td> <td><input type="text" id="projiancheng"></td> </tr> <tr> <td>省会名称:</td> <td><input type="text" id="proshenghui"></td> </tr> </table> </body> </html>
package com.penguin1024.entity; // 定义Province实体类 public class Province { private Integer id; private String name; private String jiancheng; private String shenghui; // 提供无参构造方法 public Province() { } // 提供set/get 方法 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getJiancheng() { return jiancheng; } public void setJiancheng(String jiancheng) { this.jiancheng = jiancheng; } public String getShenghui() { return shenghui; } public void setShenghui(String shenghui) { this.shenghui = shenghui; } }
package com.penguin1024.dao; import com.penguin1024.entity.Province; import com.penguin1024.utils.JdbcUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; // 对数据库中的数据执行相关的操作 public class ProvinceDao { // 根据用户输入的省份id,查询出该id值所对应的省份信息(返回值是一个完整的实体类Province对象) public Province queryProvinceById(Integer provinceid){ Connection conn = null; PreparedStatement ps = null; ResultSet res = null; // 声明一个Province类型的成员变量 Province province = null; try { // 1-借助编写好的JdbcUtil工具类,获取Connection 数据库连接对象 conn = JdbcUtil.getConnection(); // 2-编写SQL语句框架 String sql = "select id,name,jiancheng,shenghui from province where id = ?"; // 3-对SQL语句框架进行预编译处理 (避免SQL注入情况的产生) ps = conn.prepareStatement(sql); // 4-对SQL语句框架中的占位符,设置具体的参数值 ps.setInt(1,provinceid); // 5-执行SQL语句,并接收返回的结果集 res = ps.executeQuery(); // 6-遍历处理查询结果集 while (res.next()){ // 创建实体类Province province = new Province(); // 为实体类的"id"属性 赋值 province.setId(res.getInt("id")); // 为实体类的"name"属性 赋值 province.setName(res.getString("name")); // 为实体类的"jiancheng"属性 赋值 province.setJiancheng(res.getString("jiancheng")); // 为实体类的"shenghui"属性 赋值 province.setShenghui(res.getString("shenghui")); } } catch (SQLException throwables) { throwables.printStackTrace(); }finally { try { // 7-借助编写好的JdbcUtil工具类,关闭相关资源 JdbcUtil.close(conn,ps,res); } catch (SQLException throwables) { throwables.printStackTrace(); } } // 8-返回省份id编号所对应的省份信息(即一个完整的Province对象) return province; } }
package com.penguin1024.controller; import com.fasterxml.jackson.databind.ObjectMapper; import com.penguin1024.dao.ProvinceDao; import com.penguin1024.entity.Province; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; // 执行相关的业务逻辑操作 public class QueryProviceServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 定义一个字符串类类型的 默认值 {} :表示json格式的数据 String jsonStr = "{}"; // 1-对请求参数做相关处理 // 覆盖此请求体中使用的字符编码的名称。 (解决post方式的中文乱码问题) request.setCharacterEncoding("utf-8"); // 接收来自Ajax异步对象发送来的请求参数 String proidStr = request.getParameter("proid"); // 将字符串类型的省份id编号,转换为Integet类型 Integer provinceId = Integer.valueOf(proidStr); // 2-访问Dao层对象,从数据库中查询数据 // 用户在查询界面中输入的不是空字符串 // 且输入的id编号在转换为Integer类型之后的值不为null if( proidStr.trim().length() >0 && provinceId != null ) { // 创建dao对象 ProvinceDao dao = new ProvinceDao(); // 调用dao对象的方法 — —根据用户添加的省份id编号,到数据库中查找出该编号对应的省份对象 Province province = dao.queryProvinceById(provinceId); //需要使用jackson工具类 把 Provice对象转为json格式的字符串 ObjectMapper om = new ObjectMapper(); jsonStr = om.writeValueAsString(province); } // 3-向发送请求的Ajax异步请求对象返回查询到的结果 //把获取的数据,通过网络传给ajax中的异步对象,响应结果数据 //指定服务器端(servlet)返回给浏览器的是json格式的数据,并通知浏览器使用使用utf-8编码(解决响应的中文乱码问题) response.setContentType("application/json;charset=utf-8"); // 获取标准输出流 PrintWriter out = response.getWriter(); // 往标准输出流中写入的数据,会被响应到发出相应请求的Ajax异步对象的responseText属性中。 out.println(jsonStr); // 清空缓存 out.flush(); // 关闭流 out.close(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } }
3-结果查询
输入编号,点击搜索,显示出对应的结果:
相关资料:
《王鹤讲AJAX》