java-web

web開發

原型設計服務:墨刀網**javascript

Java Web知識體系大綱

[TOC]php

0 前言

1 JAVA WEB

1.1 http協議

1.2 servlet技術

1.3 會話技術(Cookie&Session)

1.3.1 客戶端會話技術

1.3.2 服務器端會話技術

1.4 jsp技術

1.4.1 jsp技術基礎

1.4.1.1 jsp原理

1.4.1.2 jsp指令

1.4.1.3 jsp腳本片斷

1.4.1.4 jsp表達式

1.4.2 el表達式

el表達式(expression language,el),html

  • 能夠輕鬆訪問存放在域對象中的bean對象及屬性
  • 結合JSTL,能夠輕鬆訪問集合中的元素
  • 能夠作簡單的邏輯判斷
  • 調用java方法

1.4.2.1 讀取數據

  1. 讀取基本數據類型
<%-- 存放基本數據類型到request域--%>
<%
    String data="abcd";
    request.setAttribute("data",data);
%>
<%-- 使用el從request中取得數據--%>
存放的數據是:${data}
  1. 讀取對象類型

    ①簡單對象前端

<%-- 
    存放對象類型數據類型到request域
    Person類:
        -String:name
        —int:age
--%>
<%
    Person p = new Person();
    request.setAttribute("person",p);
%>
<%-- 使用el從request中取得數據--%>
存放person對象及其屬性:${person.name} ${person.age}

​ ②複雜對象:存在對象聚合java

<%-- 
    存放複雜對象類型數據類型到request域
    Address類:
        —String: city
        —String: province 
    Person類:
        -String:name
        —int:age
        -Address:address
--%>
<%
    Person p = new Person();
    p.setName("lr");
    p.setAge(24);
    Address a = new Address();
    a.setProvince("Shanghai"); // 建立地址
    p.setAddress(a);           // 地址賦值給person
    request.setAttribute("person",p);
%>
<%-- 使用el從request中取得數據--%>
存放person對象及其屬性:    ${person.name} ${person.age} 
                      ${person.address.province}
                      ${person.address.city}
  1. 讀取List集合
<%
    List list = new ArrayList();
    list.add(new Person("john"));
    list.add(new Person("peter"));
    list.add(new Person("andrew"));
    request.setAttribute("list",list);
%>
<%-- 使用el從request中取得數據--%>
    ${list[0].name}  ${list[1].name}
  1. 讀取Map集合
<%
    Map map = new HashMap();
    map.put("aa",new Person("john"));
    map.put("bb",new Person("andrew"));
    map.put("cc",new Person("peter"));
    map.put("111",new Person("lucy"));
    request.setAttribute("m",map);
%>
<%-- 使用el從request中取得數據--%>
    ${map["aa"].name}  ${map["bb"].name} ${map["cc"].name}
    ${map.aa.name} ${map.bb.name} ${map.cc.name}
<!-- 若是關鍵字是數字開頭,必須用下面寫發-->
<!-- 使用el表達式取數據時候,一般用.號,若是.號取不出來,則用[]號 -->
    ${map["111"].name}
  1. 訪問指定域對象的數據及其餘web對象
${pageScope.user.name}
${requesetScope.user.name}
${sessionScoope.user.name}
${applicationScope.user.name}

<%-- 獲取客戶端請求參數,param是一個Map對象,--%>
<%--其中每一個請求參數給定一個值 --%>
<%-- http://localhost:8080/login.jsp?username=aa & password=123 --%>
${param}           
${param.username} ${param.password}

<%-- 獲取客戶端請求參數,paramValues是一個Map對象,--%>
<%-- 其中每一個請求參數給定多個值 --%>
<%-- http://localhost:8080/login.jsp?username=liuyun & username=rongbo --%>
${paramValues}    
${paramValues.username[0]}
${paramValues.username[1]}

${header}          
${header.Host}  ${header['Accept-Language']}
${headerValues}   

<%--cookie對象是一個Map對象,存放的是‘關鍵字映射到Cookie對象’的entry --%>
${cookie}          <%-- Map對象 --%> 
${cookie.JSESSIONID.name}
${cookie.JSESSIONID.vlaue}

<%--web.xml中配置了參數 --%>
<%-- 
    <context-param>
        <param-name>db</param-name>
        <param-value>url-db</param-value>
    </context-param>
--%>
${initParam}       
${initParam.db}

1.4.2.2 邏輯判斷

<%--完成數據回顯,大量使用二元表達式--%>
<%--radio表單回顯--%>
<% 
    request.setAttribute("gender", "male");
%>
<input type="radio" name="gender" value="male" checked=${gender=='male'?'checked':''}/>
<input type="radio" name="gender" value="female" checked=${gender=='female'?'checked':''} /> 

<%--checkbox表單回顯--%>

<%--判斷list集合是否爲空--%>
${empty(list)}

1.4.2.3 *調用java代碼

1.4.3 jsp標籤庫JSTL

  1. 導包:jstl standard
  2. 使用jsp指令,導入jstl的uri,並指定前綴: <%@taglib uri="#" prefix="c"/>mysql

    : 進入standard.jar->meta-inf: c.tld文件中,描述表述庫文件

<%@taglib uri="#"    prefix="c"/>
<%------------------------------------------------------%>
<%--迭代map集合中的數據--%>
<%------------------------------------------------------%>
<%
    List list = new ArrayList();
    list.add(new Person("john"));
    list.add(new Person("peter"));
    list.add(new Person("andrew"));
    request.setAttribute("list",list);
%>
<c:forEach var="person" items="${list}">
    ${person.name};
</c:forEach>

<%------------------------------------------------------%>
<%--迭代map集合中的數據--%>
<%------------------------------------------------------%>
<%
    Map map = new HashMap();
    map.put("aa",new Person("john"));
    map.put("bb",new Person("andrew"));
    map.put("cc",new Person("peter"));
    map.put("111",new Person("lucy"));
    request.setAttribute("m",map);
%>
<%-- 對Map集合,本質上是對Map.entrySet放回的集合進行迭代--%>
<c:forEach item="entry" items="${map}">
    ${entry.key}:${entry.value.name}
</c:forEach>

<%------------------------------------------------------%>
<%--測試條件是否成立--%>
<%------------------------------------------------------%>
<c:if test="${user!=null}">
    歡迎您${user.username}
</c:if>
<c:if test="${user==null}">
    <input type="text" name="username"/>
    <input type="password" name="password"/>
    <input type="submit" value="登陸"/>
</c:if>

1.4.4 jsp自定義標籤庫

1.5 WEB開發模式

1.5.1 Model1(Jsp+JavaBean)

1.5.2 Model2(JSP+Servlet+JavaBean)

1.5.3 WEB三層架構

1.5.3.1 概述

1.5.3.2 web層

web三層架構充分借鑑了MVC設計模式,優化程序結構,其中web層包括了:git

  1. web層控制器servlet,控制器servlet調用業務邏輯層代碼完成業務邏輯,不一樣的業務有不一樣的控制器
  2. web層控制jsp的servlet,經過接受客戶端請求,同利用請求轉發技術到jsp頁面,從而返回web頁面
  3. web層還包括web層工具類,負責從request請求中得到參數數據,
1.5.3.2.1 隱藏jsp的servlet
1.5.3.2.2 控制器servlet

1.5.3.3 service層

1.5.3.4 dao層

1.5.4 「MVC設計模式」和「WEB三層架構」之概念淺析

1.5.5 「前臺、後臺」和「前端、後端」概念淺析

2 SSH&SSM

2.1 概述

2.1 Struts2

2.2 Hibernates

2.3 Spring4

2.4 springMVC

2.5 MyBaits

2.6 SSH框架整合(Struts2+Spring+Hibernate)

2.7 SSM框架整合(Struts2+SpringMVC+MyBaits)

3 MySql

3.1 安裝和配置

3.1.1 安裝

Latin1是ISO-8859-1的別名,有些環境下寫做Latin-1。ISO-8859-1編碼是單字節編碼,向下兼容ASCII,其編碼範圍是0x00-0xFF,0x00-0x7F之間徹底和ASCII一致,0x80-0x9F之間是控制字符,0xA0-0xFF之間是文字符號。web

3.1.2 配置

3.2 SQL語言

3.2.1 DDL

3.2.1.1 庫操做

  1. 建立庫
/*
 * CREATE DATABASE [IF NOT EXISTS] db_name [[create_specification] 
 *                                        [,create_specification]...]
 * create_specification:
 *     [DEFAULT] CHARACTER SET charset_name | [DEFAULT] COLLATE collation_name
 */
 create database mydb1;
 
 create database mydb2 character set utf8; -- 指定字符集,utf8, 不是utf-8

 create database mydb2 character set utf8 collate utf8_general_ci; --指定字符集、排序規則
 
 show create database mydb2;  --查看建立庫的細節
  1. 刪除庫
drop database mydb1;
  1. 修改庫
/*
/*
 * CREATE DATABASE [IF NOT EXIST] db_name [[alter_specification] 
 *                                        [,alter_specification]...]
 * alter_specification:
 *     [DEFAULT] CHARACTER SET charset_name | [DEFAULT] COLLATE collation_name
 * 注意:不能修改庫名
 */
 alter database mydb2 character set utf8;
 show create database mydb2;
  1. 備份庫

mysqldump -u 用戶名 -p 數據庫名 > 文件名.sql (windows命令)正則表達式

  1. 恢復庫

第一種方法算法

/**
 * source 文件名.sql 
 */
 create database tt;
 user tt;
 create table a{
     name varchar(20) 
 };
 insert into a(name) values('aaaa');
 select * from a;

mysql -u root -p tt > c:tt.sql (window命令 導出)

drop dababase tt; --刪除庫
--恢復庫,只能恢復數據,不能恢復庫,所以必須從新新建庫
--1.建立庫
create database tt;  --建庫
user tt;             --進入庫tt
source c:\a.sql;     --恢復數據

第二種方法

mysql -uroot -proot tt<c:a.sql (windows命令)

3.2.1.2 表操做

  1. 建立表
/* CREATE TABLE table_name
 * {
 *    field1 datatype,
 *    filed2 datatype,
 *    filed3 datatype
 * }character set charset_name collate collation_name;
 * 
 * datatype:
 * 文本、二進制:
 *            char(size)            ------定長
 *            varchar(size)         ------變長
 *            blob(最大64k)   longblob -----變長
 *            text    longtext          -----變長,大文本
 * 日期時間:date  datetime timestamp   -----變長
 
 * 注意:實際開發過程當中,容量很大的數據(好比音頻、視頻等)不會存放到數據庫中,而是存放到文件系統。
 * 緣由:解決數據庫連接資源。讀取超大容量數據,鏈接佔用的時間長。
 */
 create table employee
 {
     id int,
     name varchar(40),
     sex varchar(4),
     entry_date date,
     job varchar(40),
     salary decimal(8,2),
     resume text
 };
 show tables;                ----查看全部表
 show create table employee;----顯示指定表的建立細節
 desc employee ;            ----查看錶結構
  1. 修改表
/* 
 * 1.修改表:增長列、修改列數據類型、刪除列、修改列名
 * ALTER TABLE table_name 
 *         ADD     column datatype [default_expr] [,column datatype]...;
 *         MODIFY  column datatype [default_expr] [,column datatype]...;
 *         DTOP    column;
 *        CHANGE COLUMN old_name new_name data_type; 
 * 2. 修改表名    
 * RENAME TABLE table_name to table_name_1
 *
 * 3. 修改表的字符集
 * ALTER TABLE table_name character set utf8
 * 
 * 4. 刪除表
 * DROP TABLE table_name;
 */
 alter table employee add image blob;----增長大頭貼列,存放大頭貼圖片
 alter table employee modify job varchar(60);----修改job列
 alter table employee drop sex;----刪除類
 rename table employee; ----從新命名錶(庫不能重命名,可是表能夠)
 alter table employee character utf8;----修改字符集
 alter table employee change column name username varchar(30);----修改列名
  1. 刪除表
drop table employee;----刪除表

3.2.2 DML(crud之cud操做)

crud: crete read update delete

  1. insert(create)
/**
 * INSERT INTO tb_name[(filed1[, field2...])]
 * VALUES(value [,value...]);
 *
 * 細節:1. 表名後面的字段列表能夠不跟,這種狀況下,values必須按順序指定每一個字段的值
 *        2. 字符和日期必須被單引號''包含
 *      3. 插入空值:不指定值,或者指定爲null
 *        4. insert into user(id) values(4)和insert into user(id) values('4')
 *            所以,全部的數值類型的值能夠加單引號,mysql能夠自動轉換爲相應類型的值
 */         
RENAME TABLE employee to user;
----注意沒有TABLE關鍵字
insert into user(id, username,birthday, entry_date, job, salary,resume) 
          values(1, 'andrew','2014-03-33','bb','2019-06-32',90,'aaaa');
  1. update
/** 
 * UPDATE tb_name 
 * SET col_name1=expr1 [,col_name2=expr2...]
 * [WHERE where_definition]
 */
 update employee set salary=3000 where name='張三';
 update employee set salary=1000,job='ccc' where name='andrew';
  1. delete
/** 
 * DELETE from tb_name 
 * [WHERE where_definition]
 * 注意:
 *    1.delete只能以記錄爲單位刪除;
 *    2.從一個表中刪除記錄將引發其餘表的參照完整性問題。在修改數據庫中的數據時,
 *      頭腦中應時刻不要忘記這個潛在的問題
 */
 delete from employee where name="andrew";
 delete from employee;     ----刪除全部記錄
 truncate table employee;  ----摧毀表,並從新構建表結構,速度快,在要刪除全部數據記錄的情形下

3.2.3 DQL(crud之r)

select(read),包括:select子句、where子句、from子句、order by子句、group by子句、having子句

使用source命令導入sql腳本

/** 
 * SELECT [DISTINCT] *[column1 [,column2...]]  FROM tb_name;
 */
 
 ----@file:定義sql腳本:c:\student.sql(能夠是其餘目錄)
 create table student
 {
     id int, 
     name varchar(20),
     chinese float,
     english float,
     math float
 };
 insert into student(id,name,chinese,english,math) values('1','andrew','22','90','97');
 insert into student(id,name,chinese,english,math) values('2','peter','100','90','97');
 insert into student(id,name,chinese,english,math) values('3','lily','67','90','97');
 insert into student(id,name,chinese,english,math) values('4','lucy','33','90','97');
 
 ----在客戶端,使用: source  c:\student.sql
 
 ----查詢
 select * from student;                    ----查詢全部
 select name,english from student;        ----查詢感興趣的字段
 select distinct english from student;    ----剔除重複數據

在select子句中使用表達式

/** 
 * SELECT   * {column1 | expression, column2 | expression,...}
 * FROM tabble;
 *
 * SELECT column as 別名 from table;
 */
 select name,(chinese+english+math) from student;             ----計算總分
 select name as 姓名,(chinese+english+math) as 分數 from student; ----添加別名
 select name 姓名,(chinese+english+math) 分數 from student; ----添加別名
 select *  from student where english>'90';
 select *  from student where name='andrew';
 select *  from student where (chinese+english+math)>'200';

where子句中使用運算符

/** 
 * 在where子句中使用運算符
 * 1.比較運算:
 *        >  >=  <  <=  =  <>
 *         BETWEEN ... AND ...  
 *      IN(set)
 *      LIKE 'pattern' ,這裏使用兩種通配符,%匹配一個或者多個字符,_匹配單個字符
 *      IS NULL
 * 2.邏輯運算:
 *        and 
 *        or 
 *        not
 */
select * from student where english>'80' and english<'90';----(80,90)
select * from student where english between '80' and '90'; ----[80,90]
select * from student where math in(80,90);
select * from student where math='80' or math='90';
select * from student where name like '李%';
select * from student where math>'80' and chinese>'80';

使用order by子句排序

/** 
 * 使用order by 子句
 *
 * SELECT   column1,column2...
 * FROM tabble 
 * ORDER BY column ASC|DESC;
 */
 select name,math from student order by math desc;
 select name, (chinese+english+math) as score from student order by score desc;

使用聚合函數

/**
 * 使用聚合函數:count,sum, avg, max, min
 * SELECT count(*) | count(列名) 
 * FROM table
 * [WHERE where_definition];
 */
 select count(*) from student; ----count聚合函數只會統計有值的數據
 select sum(english), sum(math) from student;
 select sum(english)/sum(*) from student;
 select avg(math) from student;

使用group by子句

select  product, sum(price)  from orders group by product;

使用having子句: 相似於where子句,可是where子句後不能跟聚合函數,可是having能夠

select  product from orders group by product having sum(product)>'100';

4 web開發典型業務邏輯

4.1 註冊登陸

使用mvc設計模式,結合web三層架構思想,開發註冊、登陸模塊。具體到項目代碼包組織以下:

domain

dao

service

web

——web.ui:hide jsp pages for users

——web.controller:calling service layer

——web.formbean: from jsp pages to controller

utils

Title:用戶註冊\n業務流程
瀏覽器->web.UI.\nRegisterUiServlet:訪問註冊頁面\nregister.jsp
web.UI.\nRegisterUiServlet->register.jsp:forward到\n/WEB-INF/jsp/register.jsp
register.jsp->瀏覽器:返回register.jsp\n生成的註冊頁面
瀏覽器->RegisterServlet:用戶填寫表單,\n提交到RegisterServlet
RegisterServlet->WebUtils:封裝request\n請求參數到Bean
WebUtils->WebUtils:調用BeanUtils.\ncopyProperty\n(destBean,key,value);
WebUtils->RegisterServlet:返回FormBean
RegisterServlet->RegisterServlet:form .\nvalidate
RegisterServlet->WebUtils:調用BeanUtils.\ncopyBean\n(key,value);
WebUtils->RegisterServlet:返回User \ndomain對象
RegisterServlet->BusinesService\nServlet:註冊
BusinesService\nServlet->BusinesService\nServlet:1.檢查用戶\n是否存在\n2.不存在\則註冊\n3.存在\n返回錯誤信息
BusinesService\nServlet->瀏覽器:返回login.jsp\n生成的登陸頁面

4.3 驗證碼

4.4 購物車

/**
 * 數據庫,
 * 1. 使用Map集合模擬數據庫;
 * 2. 初始數據經過靜態代碼塊添加到內存中Map集合
 */
package cn.itcast.DB;
import java.util.LinkedHashMap;
import java.util.Map;
import cn.itcast.domain.Book;
public class DB {
    private static Map map = new LinkedHashMap<String,Book>();
    static{
        map.put("1", new Book("1","java","lr","itcast",33.3f));
        map.put("2", new Book("2","php","lr","itcast",33.3f));
        map.put("3", new Book("3","spring","lr","itcast",33.3f));
        map.put("4", new Book("4","struts","lr","itcast",33.3f));
        map.put("5", new Book("5","hibernate","lr","itcast",33.3f));
    }
    
    public static Map getAll(){
        return map;
    }
}
/**
 * DAO層:
 */
import java.util.LinkedHashMap;
import java.util.Map;
import cn.itcast.DB.DB;
import cn.itcast.domain.Book;
public class BookDao {
    public Map getAll(){
        return DB.getAll();
    }
    public Book find(String id){
        return (Book) DB.getAll().get(id);
    }
}
/**
 * 實體類:包括Book、Cart、CartItem
 */
package cn.itcast.domain;
public class Book {
    String id;
    String name;
    String author;
    String description;
    float price;
    public Book(String id, String name, String author, String description,float price) {
        super();
        this.id = id;
        this.name = name;
        this.author = author;
        this.description = description;
        this.price = price;
    }
    /* 此處省略getters和setters方法
}
package cn.itcast.domain;
public class CartItem {
    private Book book;
    int quantity;
    float price;
}
package cn.itcast.domain;
import java.util.LinkedHashMap;
import java.util.Map;
public class Cart {
    private Map<String, CartItem> map = new LinkedHashMap();
    private float price;
    public void add(Book book){
        CartItem item = map.get(book.getId());
        if(item == null){
            item = new CartItem();
            item.setBook(book);
            item.setQuantity(1);
            map.put(book.getId(), item);
        }else{
            item.setQuantity(item.getQuantity()+1);
        }
    }
    public Map<String, CartItem> getMap() {
        return map;
    }
    public void setMap(Map<String, CartItem> map) {
        this.map = map;
    }
    public float getPrice() {
        float totalPrice = 0.0f;
        
        for(Map.Entry<String, CartItem> entry: map.entrySet()){
            totalPrice += entry.getValue().getPrice();
        }
        this.price = totalPrice;
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
}
/**
 * 業務邏輯層:
 */
package cn.itcast.serviceimpl;
import java.util.Map;
import cn.itcast.daoimpl.BookDao;
import cn.itcast.domain.Book;
import cn.itcast.domain.Cart;
public class BusinessService {
    BookDao dao = new BookDao();
    public Map getAll(){
        return dao.getAll();
    }
    public Book find(String id){
        return dao.find(id);
    }
    public void deleteCartItem(String id, Cart cart) {
        // TODO Auto-generated method stub
        cart.getMap().remove(id);
    }
    public void clearCart(Cart cart) {
        // TODO Auto-generated method stub
        cart.getMap().clear();
    }
    public void changeItemQuantity(String id, int quantity, Cart cart) {
        // TODO Auto-generated method stub
        cart.getMap().get(id).setQuantity(quantity);
    }
}
/**
 * web層——控制器servlet
 * @brief:
 *        1. web層控制器是頁面請求的web資源,控制器調用邏輯層進行處理,將處理結果結果轉發到jsp;
 *        2. 轉發到的jsp中,使用jstl、el表達式將數據從域中取出來用於顯示;
 *        3. jsp頁面中的javascript代碼和用戶交互,根據結果動態請求其餘web資源
 *        包括的Servlet:
 *                 ListBookServlet            對應‘瀏覽商品’連接訪問的資源
 *                 BuyServlet                 對應‘購買’連接對應的資源
 *                 ChangeQuantityServlet      對應‘數量input組件’對應的請求的資源
 *                 DeleteCartItemServlet      對應‘刪除’連接對應的資源
 *                 ClearCartServlet           對應‘清空購物車’連接對應的資源
 */
 // 具體servlet類省略
<%-- 瀏覽商品頁面 --%>
    <h1>書籍列表</h1>
    <table border="1" width="70%" align="center">
        <tr>
            <td>書名</td>
            <td>做者</td>
            <td>簡介</td>
            <td>價格</td>
            <td>操做</td>
        </tr>
        <c:forEach var="entry" items="${map }">
            <tr>
                <td>${entry.value.name }</td>
                <td>${entry.value.author }</td>
                <td>${entry.value.description }</td>
                <td>${entry.value.price }</td>
                <td>
                    <a href="${pageContext.request.contextPath }/BuyServlet?id=${entry.value.id }" target="_blank">購買</a>
                </td>
            </tr><br/>
        </c:forEach>
    
    </table>
<%--購物車頁面--%>
<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core"  prefix="c" %>
<!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 deleteItem(id){
        var b = window.confirm("您肯定刪除嗎?");
        if(b){
            window.location.href=href="${pageContext.request.contextPath }/DeleteItemServlet?id="+id;
        }
    }
    function clearcart(){
        var b = window.confirm("您肯定清空嗎?");
        if(b){
            window.location.href="${pageContext.request.contextPath }/ClearCartServlet";
        }
    }
    function changeQuantity(input, id, oldquantity){
        var quantity = input.value;
        
        if(isNaN(quantity)){
            alert("請輸入合法數字");
            input.value = oldquantity;
            return;
        }
        
        if(quantity < 0 || quantity != parseInt(quantity) ){
            alert("請輸入正整數");
            input.value = oldquantity;
            return;
        }
        
        var b = window.confirm(" 確認修改嗎爲"+quantity);
        if(b){
            window.location.href="${pageContext.request.contextPath}/ChangeQuantityServlet?id="+id+"&quantity="+quantity;
        }
        
    }
</script>

</head>
<body style="text-align:center;">
    <h1>書籍列表</h1>
    <c:if test="${empty(cart.map)}">
        您沒有購買任何商品
    </c:if>
    <c:if test="${!empty(cart.map)}">
    <table border="1" width="70%" align="center">
        <tr>
            <td>書名</td>
            <td>做者</td>
            <td>單價</td>
            <td>數量</td>
            <td>小計</td>
            <td>操做</td>
        </tr>
        <c:forEach var="entry" items="${cart.map }">
            <tr>
                <td>${entry.value.book.name }</td>
                <td>${entry.value.book.author }</td>
                <td>${entry.value.book.price }</td>
                <td>
                    <input type="text" name="quantity" value="${entry.value.quantity }"
                    onchange="changeQuantity(this,${entry.key },  ${entry.value.quantity })"/>
                    
                </td>
                <td>${entry.value.price }</td>
                <td>
                    <a href="javascript:vid(0)" onclick="deleteItem(${entry.key})">刪除</a>
                </td>
        </c:forEach>
        <tr>
            <td colspan="3">總價</td>
            <td colspan="2">${cart.price}</td>
            <td colspan="1">
                <a href="javascript:vid(0)" onclick="clearcart()">清空</a>
            </td>
        </tr>
    
    </table>
    </c:if>
</body>
</html>

4.5 在線支付

附錄

關鍵代碼

1 DAO層:dom4j操做xml的工具類

/**
 * 這裏導報必須導入dom4j的document類
 * @author lr
 *
 */
public class XmlUtils {
    private static String xmlPath = null;
    static{
        xmlPath = XmlUtils.class.getClassLoader().getResource("users.xml").getPath();
        System.out.println(xmlPath);
    }
    
    
    public static Document getDocument() throws DocumentException{
        SAXReader reader = new SAXReader();
        Document document = reader.read(new File(xmlPath));
        return document;
    }
    
    public static void write2Xml(Document document) throws IOException{
            XMLWriter writer = new XMLWriter(
                new FileWriter( xmlPath)
            );
            writer.write( document );
            writer.close();
    }
}

2 Service層:生成md5碼

/**
 * 1.使用消息摘要算法生成md5碼,而後使用base64算法編碼
 * 2.md5碼生成採用消息摘要算法類 MessageDigest
 * 3.生成base64碼,採用 Base64
 */
public class ServiceUtils {
    public static String md5(String data){
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte[] md5 = md.digest(data.getBytes());
            /*
             * md5摘要太長,採用base64進行編碼
             * 1.使用BASE64Encoder,but jdk not support this deprecated class and method
             * 2.使用Base64來得到Encoder
             */
            Base64.Encoder encoder = Base64.getEncoder();
            return encoder.encodeToString(md5);
            
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

3 Web層:request中的form表單數據封裝到formbean;frombean->domain bean

/**
 * @method:public static <T> T request2Bean(HttpServletRequest request, Class<T> cls)
 * @brief:
 *  第一個關鍵點;將request中的property拷貝到bean中去,要使用到beanutils包中的靜態方法,拷貝特定屬性
 * <T>是類型參數的形式參數,調用過程當中類型經過T傳入
 * @author lr
 * 
 * 關鍵點:使用BeanUtils的copyProperties時,之能拷貝bean裏面的基本數據類型,要將form中的String日期
 *        拷貝到Domain bean的Date屬性中去,必需要寫轉換器
 *        ConvertUtils.register(Converter c,Class cls)
 */
public class WebUtils {
    public static <T> T request2Bean(HttpServletRequest request, Class<T> cls) {
        // 1.create an T instance
        T bean;
        try {
            bean = cls.newInstance();
            
            // 2. copy propertys in request to new bean
            Enumeration<String> e = request.getParameterNames();
            while(e.hasMoreElements()){
                String name = e.nextElement();
                String value = request.getParameter(name);
                BeanUtils.copyProperty(bean, name,value);
            }
            
        } catch (Exception e) {
            throw new RuntimeException();
        }
        return bean;
    }
    public static String generatieID(){
        return UUID.randomUUID().toString();
    }
    public static void copyBean(Object src, Object dest){
        ConvertUtils.register(new Converter() {
            
            public Object convert(Class type, Object value) {
                // TODO Auto-generated method stub
                if(value==null){
                    return null;
                }
                
                String str = (String)value;
                if(str.equals(""))
                    return null;
                
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    return df.parse(str);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    throw new RuntimeException(e);
                }
            
            }
        }, Date.class);
        try {
            BeanUtils.copyProperties(dest, src);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            throw new RuntimeException(e);
        } 
    }
}

4 使用dom4j搜索xml節點的關鍵用法

/**
 * xpath常見模式:
 * 1.查找屬性值爲指定值的user節點:
 *    "//user[@username='"+username+"' and @password='"+password+"']" 用戶名、密碼爲指定值
 *    "//user[@username='"+username+"']" 用戶名爲指定值
 */
public class UserDaoImpl {
    public void add(User user){
        try {
            Document document = XmlUtils.getDocument();
            
            /*
             * get the root element
             */
            Element root = document.getRootElement();
            Element e = root.addElement("user");
            e.setAttributeValue("id",user.getId());
            e.setAttributeValue("username", user.getUsername());
            e.setAttributeValue("password", user.getPassword());
            e.setAttributeValue("birthday", user.getBirthday() == null?"":user.getBirthday().toLocaleString());
            XmlUtils.write2Xml(document);
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    /*
     * find user according to specified usenrmae and password
     */
    public User find(String username, String password){
        User user = null;
        try {
            Document document = XmlUtils.getDocument();
            Element e = (Element)document.selectSingleNode(
                    "//user[@username='"+username+"' and @password='"+password+"']");
            if(e == null)
                return null;
            user = new User();
            user.setId(e.attributeValue("id"));
            user.setUsername(e.attributeValue("username"));
            user.setPassword(e.attributeValue("password"));
            user.setEmail(e.attributeValue("email"));
            user.setBirthday(new Date());
            
            
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return user;
    }
    /*
     * find if user exist
     */
    public boolean find(String username){
        try {
            Document document = XmlUtils.getDocument();
            Element e = (Element)document.selectSingleNode("//user[@username='"+username+"']");
            if(e == null)
                return false;
            
        } catch (DocumentException e) {
            // TODO Auto-generated cach block
            e.printStackTrace();
        }
        return true;
    }
}

5 formbean中的驗證算法(正則表達式)

/**
    * 正則表達式的\w在java字符串中,寫成\\w; 
    * 典型的模式:
    * 1.郵箱:"\\w+@\\w+(\\.\\w+)+",其中\\w表示字母、數字、下劃線,例如lr@whu.edu.cn
    * 2.用戶名3-8個字母:"[a-zA-Z]{3,8}"
    * 3.密碼3-8位字母:"\\d{3,8}"
    *
    */
    public boolean validate(){
        boolean isOK =true;
        /*
         * username
         * 不容許爲空,所以必須加trim,由於""和"    "是等同,所以用trim修剪空格
         */
        if(this.username == null || this.username.trim().equals("")){
            isOK = false;
            errs.put("username", "username can not be empty");
        }else{
            if(!username.matches("[a-zA-Z]{3,8}")){
                isOK = false;
                errs.put("username", "用戶名必須是3-8位字母");
            }
        }
        
        /*
         * password
         * 不容許爲空,所以必須加trim,由於""和"    "是等同,所以用trim修剪空格
         */
        if(this.password == null || this.password.trim().equals("")){
            isOK = false;
            errs.put("password", "password can not be empty");
        }else{
            if(!password.matches("\\d{3,8}")){
                isOK = false;
                errs.put("password", "password must be 3-8 digits");
            }
        }
        /*
         * password2
         * 不容許爲空,所以必須加trim,由於""和"    "是等同,所以用trim修剪空格
         */
        if(this.password2 == null || this.password2.trim().equals("")){
            isOK = false;
            errs.put("password2", "password2 can not be empty");
        }else{
            if(!password.equals(password2)){
                isOK = false;
                errs.put("password2", "password2 not equals passwords");
            }
        }
        /*
         * email
         * 不容許爲空,所以必須加trim,由於""和"    "是等同,所以用trim修剪空格
         */
        if(this.email == null || this.email.trim().equals("")){
            isOK = false;
            errs.put("email", "email can not be empty");
        }else{
            if(!email.matches("\\w+@\\w+(\\.\\w+)+")){
                isOK = false;
                errs.put("email", "not the correct email format");
            }
        }
        /**
         * birthday can be empty,but if not empty ,it must be al valid value
         */
        if(!(this.birthday== null) && !this.birthday.trim().equals("")){
            try{
                DateLocaleConverter dlc = new DateLocaleConverter();
                dlc.convert(this.birthday,"yyyy-MM-dd");
            }catch(ConversionException e){
                isOK = false;
                errs.put("birthday", "format is invalid");
            }
        } 
        return isOK;
    }

6 使用UUID生惟一ID

public static String generatieID(){
        return UUID.randomUUID().toString();
    }

7 String到Date的轉換

/**
 * birthday can be empty,but if not empty ,it must be al valid value
 *
 * DateLocaleConverter 和 SimpleDateFormat
 *
 * 1. 使用DateLocaleConverter,convert方法轉換非法字符串拋出異常
 * 2. 肯定字符串表示的日前是合法日期前提下,可使用SimpleDateFormat
 */
if(!(this.birthday== null) && !this.birthday.trim().equals("")){
    try{
        DateLocaleConverter dlc = new DateLocaleConverter();
        // 利用convert方法拋異常的特性,驗證參數合法性
        dlc.convert(this.birthday,"yyyy-MM-dd"); 
    }catch(ConversionException e){
        isOK = false;
        errs.put("birthday", "format is invalid");
    }
} 

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
try {
    return df.parse(str);    // parse字符串
} catch (Exception e) {
    // TODO Auto-generated catch block
    throw new RuntimeException(e);
}

mysql客戶端亂碼問題

插入數據亂碼

問題描述:數據庫爲採用utf8字符集,在客戶端插入中文數據,顯示插入錯誤

緣由分析:客戶端默認採用gb2312字符集,數據庫採用的非gb2312,客戶端輸入發送給數據庫

解決思路:告訴數據庫客戶端採用gb2312編碼

myql>show variables like 'chara%'
mysql>set character_set_client=gb2312;
mysql>insert into employee(username) values('張三');
myql>select * from employee;

取出數據亂碼

問題描述:數據庫採用utf字符集,客戶端正確插入了中文數據到表中,在客戶端查詢時輸出爲亂碼

緣由分析:數據庫按照utf8查詢到了數據,送到客戶端,可是客戶端以gb2312解析後顯示

解決思路:要想查看時不亂碼

myql>show variables like 'chara%';
myql>set character_set_results=gb2312;
myql>select * from employee;

配置客戶端永久不顯示亂碼

修改安裝目錄下的my.ini文件,CLIENT SECTION部分的:default-character-set=gb2312

#修改配置文件
#修改安裝目錄下的my.ini文件,
#CLIENT SECTION部分的:default-character-set=utf8
#省略
# CLIENT SECTION
# ----------------------------------------------------------------------
#
# The following options will be read by MySQL client applications.
# Note that only client applications shipped by MySQL are guaranteed
# to read this section. If you want your own MySQL client program to
# honor these values, you need to specify it as an option during the
# MySQL client library initialization.
#
[client]
port=3306

[mysql]
default-character-set=utf8

# SERVER SECTION
# ----------------------------------------------------------------------
#
# The following options will be read by the MySQL Server. Make sure that
# you have installed the server correctly (see above) so it reads this 
# file.
#
[mysqld]
# The TCP/IP Port the MySQL Server will listen on
port=3306

#Path to installation directory. All paths are usually resolved relative to this.
basedir="D:/Program Files (x86)/MySQL/MySQL Server 5.0/"

#Path to the database root
datadir="D:/Program Files (x86)/MySQL/MySQL Server 5.0/Data/"

# The default character set that will be used when a new schema or table is
# created and no character set is defined
default-character-set=utf8

#省略
相關文章
相關標籤/搜索