JavaWeb17-案例之ajax(Java真正的全棧開發)
案例 & ajax
一.案例
1. 生成訂單操作分析
先看下訂單頁面:
分析下訂單表需要那些欄位
id 收貨人(receiverName) 收貨地址(receiverAddress) 收貨人電話(receiverPhone) 總計(totalPrice)
分析下表之間的關係
這裡面涉及到三張表,分別是使用者表,訂單表,商品表.他們之間的關係為
使用者表和訂單表之間是一對多的關係
訂單表和商品表之間是多對多的關係
表的設計:
在訂單表中新增一個使用者id,表示使用者和訂單的關係
新增一張中間表,表示訂單和商品的關係
中間表的欄位 訂單oid 商品pid 購買商品數量buynum 商品小計littleprice
建立表
使用者表
create table user(
id int primary key AUTO_INCREMENT,
username varchar(20),
password varchar(20)
);
訂單表(新增一個外來鍵)
create table orders(
id varchar(50) primary key,
receivername varchar(20),
receiveraddress varchar(100),
receiverphone varchar(20),
totalprice double,
user_id int
);
中間表(訂單項表 orderitem)
create table orderitem(
oid varchar(50),
pid varchar(50),
buynum int,
littleprice double,
primary key(oid,pid)
);
生成訂單的過程,
先把收貨人資訊及使用者id存入訂單表(receiver... 訂單id 使用者id 商品總價)
把購物車裡的商品及數量放到訂單項表中(訂單id 商品id 購買數量 小計)
最後修改商品表中的數量
以上三個操作必須在一個事務控制範圍內
2. 生成訂單操作實現
保證使用者登入
編寫javabean(訂單bean,訂單項bean)
訂單bean
private String id; private String receiverName; private String receiverAddress; private String receiverPhone; private Double totalPrice; private User user; private List<OrderItem> items;
訂單項實體bean
private Order order;
private Product product;
private Integer buyNum;
private Double littlePrice;
使用者實體:user
private Integer id;
private String username;
private String password;
訂單生成
保證使用者登入
從cart.jsp點選”結賬”按鈕開始
跳轉到order.jsp(取出購物車裡面商品資訊及使用者資訊,還需自己錄入收貨資訊)
點選提交訂單,傳送請求到createOrderSevlet(主要邏輯如下)
Order order=new Order();
try {
//封裝收貨人資訊及訂單總價
BeanUtils.populate(order, request.getParameterMap());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
//手動設定訂單id
order.setId(UUIDUtils.getId());
order.setUser((User)request.getSession().getAttribute("user"));
//設定商品集合
List<OrderItem> list=new ArrayList<OrderItem>();
Map<Product,Integer> cart = (Map<Product, Integer>) request.getSession().getAttribute("cart");
for (Product p : cart.keySet()) {
list.add(new OrderItem(order, p, cart.get(p), p.getPrice()*cart.get(p)));
}
order.setItems(list);
注意:事務然後呼叫orderservice新增訂單
public void addOrder(Order order) {
try {
DataSourceUtils.startTransaction();
//新增訂單
orderDao orderDao = new orderDao();
orderDao.addOrder(order);
//新增訂單項
OrderItemDao oiDao=new OrderItemDao();
oiDao.addOrderItem(order);
//修改商品表
ProductDao pDao=new ProductDao();
pDao.updateProductPnum(order);
} catch (SQLException e) {
e.printStackTrace();
try {
DataSourceUtils.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally{
try {
DataSourceUtils.commitAndRelease();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
新增訂單(orderDao)
public void addOrder(Order order) throws SQLException {
QueryRunner runner=new QueryRunner();
String sql="insert into orders values (?,?,?,?,?,?);";
runner.update(DataSourceUtils.getConnection(), sql, order.getId(),
order.getReceiverName(),order.getReceiverAddress(),
order.getReceiverPhone(),order.getTotalPrice(),
order.getUser().getId());
}
新增訂單項(orderItemDao)
public void addOrderItem(Order order) throws SQLException {
QueryRunner runner=new QueryRunner();
String sql="insert into orderitem values(?,?,?,?);";
Object[][] params=new Object[order.getItems().size()][4];
for (int i = 0; i < order.getItems().size(); i++) {
OrderItem item = order.getItems().get(i);
params[i][0]=item.getOrder().getId();
params[i][1]=item.getProduct().getId();
params[i][2]=item.getBuyNum();
params[i][3]=item.getLittlePrice();
}
runner.batch(DataSourceUtils.getConnection(), sql, params);
}
修改商品數量(productDao)
public void updateProductPnum(Order order) throws SQLException {
//修改當前訂單裡的所含商品的數量
QueryRunner runner = new QueryRunner();
String sql="update products set pnum = pnum - ? where id = ?";
Object[][] params=new Object[order.getItems().size()][2];
for (int i = 0; i < order.getItems().size(); i++) {
OrderItem item = order.getItems().get(i);
params[i][0]=item.getBuyNum();
params[i][1]=item.getProduct().getId();
}
runner.batch(DataSourceUtils.getConnection(), sql, params);
}
二.ajax
1. ajax介紹
AJAX即“Asynchronous Javascript And XML”(非同步JavaScript和XML),是指一種建立互動式網頁應用的網頁開發技術。
AJAX 是一種用於建立快速動態網頁的技術。
通過在後臺與伺服器進行少量資料交換,AJAX 可以使網頁實現非同步更新。這意味著可以在不重新載入整個網頁的情況下,對網頁的某部分進行更新。傳統的網頁(不使用 AJAX)如果需要更新內容,必須過載整個網頁頁面。
ajax作用:
AJAX不是一種新的程式語言,而是一種用於建立更好更快以及互動性更強的Web應用程式的技術。
使用Javascript向伺服器提出請求並處理響應而不阻塞使用者!核心物件XMLHTTPRequest。通過這個物件,您的 JavaScript 可在不過載頁面的情況與Web伺服器交換資料。
AJAX 在瀏覽器與 Web 伺服器之間使用非同步資料傳輸(HTTP 請求),這樣就可使網頁從伺服器請求少量的資訊,而不是整個頁面。
AJAX 可使因特網應用程式更小、更快,更友好。
2. ajax入門案例
獲取XMLHttpRequest物件
對於不同的瀏覽器,獲取方式有區別(從文件上粘過來)
function getXMLHttpRequest() {
var xmlhttp;
if (window.XMLHttpRequest) {// code for all new browsers
xmlhttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {// code for IE5 and IE6
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return xmlhttp;
}
設定回撥函式(onreadystatechange)
xmlHttp.onreadystatechange=function(){};
目的是伺服器端響應完成後,瀏覽器端可以知道,並完成後續工作。
open操作
xmlHttp.open(“GET”,”/day/ajax”);
設定訪問的資源路徑以及請求方式
send操作
xmlhttp.send(null);
傳送請求
回撥函式編寫
在第二步的回撥函式內完成操作。
3. XMLHttpRequest之API詳解
Ajax 的核心是 JavaScript 物件 XmlHttpRequest。該物件在 Internet Explorer 5 中首次引入,它是一種支援非同步請求的技術。簡而言之,XmlHttpRequest 使您可以使用 JavaScript 向伺服器提出請求並處理響應,而不阻塞使用者。XMLHttpRequest 物件提供了對 HTTP 協議的完全的訪問,包括做出 POST 和 HEAD 請求以及普通的 GET 請求的能力。XMLHttpRequest 可以同步或非同步地返回 Web 伺服器的響應,並且能夠以文字或者一個 DOM 文件的形式返回內容。
onreadystatechange屬性
當XMLHttpRequest物件的狀態改變時會呼叫的一個函式.
readyState屬性
對於XMLHttpRequest物件,它有一個屬性readyState,它有五個狀態
0建立XMLHttpRequest物件.
1當open時
2當send時
3響應頭已經返回,但響應正文沒有完成,也就是響應沒有完全完成.
4響應完成了
一般情況下,在回撥的函式中,我們都是判斷
if(xmlhttp.readyState==4&&xmlhttp.status==200)
來接收伺服器端響應的資訊.
status屬性
由伺服器返回的 HTTP 狀態程式碼,如 200 表示成功,而 404 表示 "Not Found" 錯誤。當 readyState 小於 3 的時候讀取這一屬性會導致一個異常。
responseText屬性
目前為止為伺服器接收到的響應體(不包括頭部),或者如果還沒有接收到資料的話,就是空字串。
如果 readyState 小於 3,這個屬性就是一個空字串。當 readyState 為 3,這個屬性返回目前已經接收的響應部分。如果 readyState 為 4,這個屬性儲存了完整的響應體。
如果響應包含了為響應體指定字元編碼的頭部,就使用該編碼。否則,假定使用 Unicode UTF-8。
responseXML屬性
對請求的響應,解析為 XML 並作為 Document 物件返回。
open方法
初始化 HTTP 請求引數,例如 URL 和 HTTP 方法,但是並不傳送請求。
xmlhttp.open(請求方式,url);
請求方式: POST GET
路徑:客戶端路徑 格式 /工程名/資源路徑
如果是GET方式,想要向伺服器傳送請求,並且攜帶請求引數,可以直接在url後面連線。
如果是POST方式,想要向伺服器傳送請求,並且攜帶請求引數,我們需要在send時傳遞引數
send方法
傳送 HTTP 請求,使用傳遞給 open() 方法的引數,以及傳遞給該方法的可選請求體。
如果請求方式是post,並且要攜帶引數,可以通過send的引數來傳遞
setRequestHeader方法
向一個開啟但未傳送的請求設定或新增一個 HTTP 請求。
如果請求方式是POST,並且要攜帶引數,需要設定一個請求頭.
setRequestHeader("CONTENT-TYPE","application/x-www-form-urlencoded");
中文亂碼問題
get請求需要在傳送請求的時候對中文進行編碼,如下:
伺服器端處理方式和之前request的處理亂碼方式一樣.
4. 案例-驗證使用者名稱是否重複
5. 案例-商品資訊模糊查詢
a. 修改頁面(menu_search.jsp),在這個頁面的搜尋欄新增ajax請求
給搜尋框新增鍵盤彈起事件,傳送ajax請求,將輸入的值出給後臺
b. 編寫後臺功能
接受ajax傳送過來的值
查詢資料庫(dao使用ColumnListHandler)
生成響應資訊
c. 效果如下
前臺程式碼
//模糊匹配
function searchName(d){
var xmlhttp;
if (window.XMLHttpRequest) {// code for all new browsers
xmlhttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {// code for IE5 and IE6
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//回撥函式
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4 && xmlhttp.status == 200){
var data=xmlhttp.responseText;
if(data!=null && data!=""){
var arr=data.split(/s*,s*/);
var cDiv=document.getElementById("content");
cDiv.innerHTML="";
for(var i=0;i<arr.length;i++){
cDiv.innerHTML+=("<div onmouseover='changeColor1(this)' onmouseout='changeColor2(this)' onclick='setName(this)'>"+arr[i]+"</div>");
}
cDiv.style.display="block";
}
}
}
//open
xmlhttp.open("GET", "${pageContext.request.contextPath}/findProductByName?name="+window.encodeURI(d.value));
//send
xmlhttp.send();
}
//放上去變色 為了展示效果好看 新增顏色
function changeColor1(d){
d.style.backgroundColor="#fff";
}
//離開之後恢復原色
function changeColor2(d){
d.style.backgroundColor="#999";
}
//將選中的值賦給文字框
function setName(d){
document.getElementById("name").value=d.innerHTML;
//設定完值之後將div隱藏
document.getElementById("content").style.display="none";
}
後臺程式碼
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//獲取引數
String name = request.getParameter("name");
name=new String(name.getBytes("iso8859-1"),"utf-8");
if(name==null || name.trim().length()==0){
return;
}
//呼叫service
ProductService service=new ProductService();
List<Object> names=null;
try {
names = service.findProductByName(name);
} catch (SQLException e) {
e.printStackTrace();
}
if(names!=null && names.size()>0){
String names_ = names.toString();
response.getWriter().write(names_.substring(1,names_.length()-1));
}
}
6. json介紹與入門
json介紹
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。它基於JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一個子集。 JSON採用完全獨立於語言的文字格式,但是也使用了類似於C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的資料交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成(網路傳輸速度)。
json格式
JSON結構有兩種結構
json簡單說就是javascript中的物件和陣列,所以這兩種結構就是物件和陣列兩種結構,通過這兩種結構可以表示各種複雜的結構
u 物件:物件在js中表示為“{}”括起來的內容,資料結構為 {key:value,key:value,...}的鍵值對的結構,在面向物件的語言中,key為物件的屬性,value為對應的屬性值,所以很容易理解,取值方法為 物件.key 獲取屬性值,這個屬性值的型別可以是 數字、字串、陣列、物件幾種。
u 陣列:陣列在js中是中括號“[]”括起來的內容,資料結構為 ["java","javascript","vb",...],取值方式和所有語言中一樣,使用索引獲取,欄位值的型別可以是 數字、字串、陣列、物件幾種。
經過物件、陣列2種結構就可以組合成複雜的資料結構了。
7. jsonlib外掛介紹
jsonlib介紹
Json-lib 是一個 Java 類庫(官網:http://json-lib.sourceforge.net/)可以實現如下功能:
•轉換 javabeans, maps, collections, java arrays 和 XML 成為 json 格式資料
•轉換 json 格式資料成為 javabeans 物件
Json-lib 需要的 jar 包
•commons-beanutils-1.8.3.jar
•commons-collections-3.2.1.jar
•commons-lang-2.6.jar
•commons-logging-1.1.1.jar
•ezmorph-1.0.6.jar
•json-lib-2.4-jdk15.jar
jsonlib常用api
陣列,Collection集合轉換成json資料使用 JsonArray.fromObject(物件);
Map,javaBean轉換成json資料使用 JsonObject.fromObject(物件);
如果不想讓javaBean中的資料出現在json中.
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setExcludes(new String[]{"price"});
JSONObject jsonObject = JSONObject.fromObject(p1, jsonConfig);
System.out.println(jsonObject);
注意:
如果伺服器端返回的資料格式是json格式,那麼我們在瀏覽器端得到資料時
需要使用eval函式將字串轉換成json物件.
var msg=xmlhttp.responseText;
var obj=eval(msg);
有的時候通過eval轉換時,得不到一個json物件,這時做以下操作
var obj=eval("("+msg+")");
8. 案例-使用json來完成商品資訊模糊查詢操作實現