1. 程式人生 > 其它 >JavaWeb17-案例之ajax(Java真正的全棧開發)

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來完成商品資訊模糊查詢操作實現