一 Javaweb 專案中常見的思想、思路從哪去、原則 反思回顧:
1 分層;
2 封裝;
3 發現問題本質,方法解決轉化
4 字串的拼接
5 一張表一個dao類一個servlet
6 根據隱含引數判斷資料來源
7 資料放在哪,從哪取
8 命名統一 規範問題
二 針對上述介紹中,部分一般性規律:
1 分層;常見為src中
com.example.dao //資料訪問層
com.example.daoimpl
com.example.entity(或者com.example.bean) //實體層 域模型層
com.example.service //業務邏輯層
com.example.service.impl
com.example.util //工具類層
com.example.web.cotroller //表現層
com.example.web.filter
com.example.web.formbean
com.example.web.listener
com.example.web.ui
com.example.util.test //工具測試類層
webRoot 中
js css jsp html imgs 等等,要注意分門別類存放
2 封裝 面向物件的思維方式,共同的部分要抽取出來
三 建立一個新的Javaweb 專案
利用eclipse hbuilder 等建立一個Java web 專案,其中需要注意的地方
1、專案中,在建立src裡的包層時,需要注意包層的名稱需要用小寫字母
2、包層的命名是 com為二級域名 example為三級域名,這個一般是公司域名倒寫+名稱
3、導包 導庫 將用到的的第三方包 、庫匯入相應的資料夾
比如需要將資料庫驅動程式jar包匯入 web-inf 下的lib資料夾中
4、注意各處的字元編碼是否統一,建議為utf-8
5、需要在清單檔案中配置的專案要記得配置
四 常見的問題及分析:
1 資料庫的連線(此處以MyEclipse 連線本地Oracle資料庫 為例):
(1)如何在MyEclipse 中連線Oracle資料庫?
準備階段:首先要在本地計算機上正確安裝
擴充套件:具體的安裝過程中可能出現一些問題比如:
1 為何資料庫提示無法安裝?
如果你的電腦之前安裝過Oracle 資料庫,在清理過程中未徹底清理乾淨會出現此問題,這裡需要特別注意的是,Oracle 資料庫特別霸道 變態,只要電腦中目前無論任何的資料夾、登錄檔等各種地方有一個與Oracle資料庫相關的檔案,都意味著未清理乾淨,具體我百度到了一個地址,介紹還算不錯可以根據上面提示保證完全清理乾淨
https://wenku.baidu.com/view/df5196f3ba0d4a7302763ac7.html
http://blog.csdn.net/oceanaut/article/details/3863222
2 開啟資料庫需要的服務
連線資料庫之前,一定要確保Oracle資料庫的相關服務開啟,否則無法使用,因為Oracle資料庫沒有介面顯示,來證明是否開啟,所以要檢查oracle資料庫最基本的服務是否開啟
2 在使用Oracle資料庫管理軟體時,要Oracle資料庫的賬號 密碼,怎麼填?是多少?
這個在你安裝Oracle資料庫時需要填寫的,所以在安裝Oracle資料庫時,要特別注意讓你填寫的東西 賬號和密碼一定要記住,這裡要填的賬號 密碼就是當時填寫的
軟體連線部分: 開啟eclipse———>點選上方的window選項——>open perspective-->MyEclipse Database Explore在左側單擊右鍵,出現一個連線資料庫的資訊列表單,driverManager templates: 資料庫驅動程式的型別,這個會有MySQL sqlserver oracle 等各版本選項
driver name:這個隨便填寫,作為資料庫的名稱
Connection URl: 連線資料庫的地址 jdbc:axiondb:<database-name>[:<database-directory>] 大致都類似於這個,尖括號為必填項,方括號可不寫
user name;使用者名稱 這個就是你使用資料庫的賬號
password:密碼 也好理解
driver jars: 這個就是你使用的資料庫驅動程式的jar包的路徑,可以通過檔案選擇功能找到,(並且這個jar包是需要複製貼上到web專案中——>web Root ——>WEB-INF——>lib資料夾內)driver className:這個在你完成上一步之後會自動生成
到此就填寫可以了,直接下一步或者完成就可。左邊會產生一個伺服器樣式的資料夾,雙擊,正常會在該圖示下產生檔案,不報錯,應該就是連線成功了
3 當然每個專案中需要有一個dao方法,連線資料庫,具體的Java程式碼寫法,後面介紹
(2)在專案的dao層中,要寫一個與資料庫進行連線的具體方法BaseDao的單獨的類或者一個方法具體程式碼參考如下。(為了在本文件書寫自動有提示,讓類的內容顯示有層次感,於是寫在script中,因為script中接
受Java程式碼)
<script type="text/javascript">
public class BaseDao{ //定義基本的BaseDao 類
//定義連線資料庫用到的基本引數 包括驅動程式名,驅動程式的url 資料庫使用者名稱、密碼
String driver="";
String url="";
String username="";
String password="";
//建立連線資料用到的基本類物件 包括連線物件Connection conn sql語句預編譯物件PreparedStatement pst 呼叫資料庫返回結果集 ResultSet sql語句
Connection conn=null;
PreparedStatement pst=null;
Resultset res=null;
String sql=null;
try{
//在Java虛擬機器中載入資料庫連線驅動程式 簡稱 載入驅動
Class.forName(driver);
//呼叫驅動程式管理器連線資料庫的方法連線資料庫 亦稱 獲取連線
conn=DriverManager.getConnection(url,username,password);
}catch(Exception e){
e.printStactrace();
}
//關閉資料庫連線資源的方法
public int closeAll(Connection conn,PreparedStatement pst,ResultSet res){
//如果不為空,表示處於連線狀態,所以關閉資源
if (res!=null) {
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (pst!=null) {
try {
pst.close();
} catch (SQLException e) {
e.printStackTrace();
return 0;
}
}
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
return 0;
}
}
return 1; //告訴呼叫者是否關閉資源成功
}
public int executeUpdate(String sql,Object...params){
//預編譯語句的通用方法,
int result=0;
conn=getConnection(); //獲取資料庫連線
try {
pst=conn.prepareStatement(sql); // 對sql語句進行預編譯操作
for (int i = 0; i < params.length; i++) {
//動態將sql語句的片段集合化為一句
pst.setObject(i+1, params[i]);
}
pst.executeUpdate(); //執行sql語句
} catch (SQLException e) {
e.printStackTrace();
}finally{
this.closeAll(conn, pst, res);
}
return result;
}
}
</script>
2 對於專案的分析
(1)
3 資料庫中表的設計
資料庫一般的三正規化是要遵循的。
欄位的取值範圍的考慮
4 在資料庫中建立表的方法
因為不同的資料庫,一些細節方面略有不同,但是都有一些共通的地方
(1)利用資料庫管理軟體工具直接按照分析好的表結構,進行建表
對於主鍵等的設定,一般命名格式為
主鍵名為 pk_表名_欄位名,
外來鍵名為 fk_參考的表名_欄位名
(2)利用sql語句在Java程式碼中進行建立
5 如何在Oracle 資料庫中設定欄位自增(比如主鍵id int 型別 自增為例)
oracle 資料庫中,沒有直接設定欄位自增的控制元件,如果涉及,需要利用序列的形式進行
設定,具體方法以pl/sql 軟體為例,假如需要設定以student 表中主鍵id(int)自增為例
在左側sequences ——>右鍵單擊——>new 建立一張序列表,序列表表名的命名格式為
seq_原表表名_自增欄位名 seq_student_id
而在dao層新增資料的方法中,id列則不需要從外界獲取值,新增方法的sql語句格式為
sql="insert into 表名(主鍵id,欄位名2,..,欄位名n) value(序列表表名.nextval,?,?,...?)";
例如:
sql="insert into student(id,name,age,..,address) value(seq_student_id.nextVal,?,?,...,?)"
在建立序列表時,注意內容的填寫,以原表中新建,還未新增資料,且以int型別自增為例,序列表的填寫
owner system (表示資料庫使用者名稱) next number 1 (因為原表中沒有資料,從1開始)
Name seq_student_id (此處為序列表表名) increatment by 1 (表示每次自動增加1)
min value 1 (表示id從1 開始) Cache size 20 (表示數字的位數)
max value (此處不填預設為某個最大數值)
該處填寫完,即表示序列表已經建立完成,不需要其他操作
6 當軟體連線完資料庫後,一般會開始新建一個web專案,然後在其中開始寫實體類 資料庫基本的增刪改查的方法
實體類對應於資料庫中的實體 包括常見的set get方法。
完成訪問資料庫的方法,為了更顯層次,會建立介面dao dao對應的實現類
實現類中有基本的增刪改查方法,如果可能,還可能需要建立根據條件進行查詢、模糊查詢等方法,這些應該在專案分析中考慮到。
7 建立使用者介面 html 或者jsp 檔案
在webRoot 下面建立 資料夾 js css imgs 方便對各種資原始檔進行管理
新建立html 或者jsp 檔案時,注意更改字符集,
8 建立html(靜態網頁) jsp(動態網頁)中需要注意的問題:
(1) 注意網頁佈局和樣式、 程式碼的分層獨立
(2) 注意網頁中應該記得匯入與該網頁相關的css js jQuery 等相關的檔案
9 建立好網頁之後,即可開始書寫業務邏輯層,完成前後臺的邏輯對接
10 網頁佈局中 div css 浮動 定位 清除浮動之間有哪些規律?
11 書寫服務層的一般邏輯:
(1) 從網頁獲取暗含的請求引數、判斷邏輯需求,根據需求確定服務類別,因為一張表可能對應一個服務類,裡面有多個服務
(2) 獲取請求頁面的請求引數(這裡的請求引數和業務相關)reques.getParameter("");
(3) 呼叫相應的dao層的方法
(4) 根據dao方法返回的結果,進行業務處理
12 書寫服務層是最常見的字元編碼問題如何解決?
(1) 利用過濾器,直接將所有相關的配置進行字元過濾處理
(2) 將涉及到的所有可能出現亂碼等問題的地方進行字元設定處理
常見的情景有:
a 服務類裡,第一件事,加入 request.setCharsetEncording("utf-8");
b 每項服務中,如果涉及將資料庫中的資料取出來,傳到網頁,則設定響應物件 response.setCharsetEncording("utf-8");
13 專案中,日期類的格式轉換問題,怎麼解決?
(一)如果bean 中實體類匯入的包是Java.util 包,則以學生類 student 為例:
1、實體類中的日期set get方法各自的書寫
2、dao 中,新增add 方法中,關於日期的項 語句書寫
3、servlet中,
(1)完成新增含有日期的資料的功能時, 從網頁html 或者jsp 時,獲取請求引數
String time=request.getParameter("birthday_day");
//假設網頁上生日是通過input標籤 name="birthday_day"傳入
//因為網頁傳過來的都是字串,所以此句是一定的。
Student student=new Student();
student.setBirthday(?);
StudentDao dao=new StudentDao();
dao.add(student);
(2)完成根據條件查詢資料,從資料庫中查詢到資料後的處理;
StudentDao dao=new StudentDao();
List<Student> list=dao.find();
//如果此處是將查詢到的list 作為結果返回到jsp介面
request.setAttribute("result",list);
request.getRequestDispatcher("index.jsp").forward(request,response);
4、網頁中
(二)如果bean 中實體類匯入的包是Java.sql 包,則以學生類 student 為例:
1、實體類中的日期set get 方法各自的書寫
2、dao 中,新增add 方法中,關於日期的項 語句書寫
3、servlet中,
(1)完成新增含有日期的資料的功能時, 從網頁html 或者jsp 時,獲取請求引數
String time=request.getParameter("birthday_day");
//假設網頁上生日是通過input標籤 name="birthday_day"傳入
//因為網頁傳過來的都是字串,所以此句是一定的。
Student student=new Student();
student.setBirthday(?);
StudentDao dao=new StudentDao();
dao.add(student);
(2)完成根據條件查詢資料,從資料庫中查詢到資料後的處理;
StudentDao dao=new StudentDao();
List<Student> list=dao.find();
//如果此處是將查詢到的list 作為結果返回到jsp介面
request.setAttribute("result",list);
request.getRequestDispatcher("index.jsp").forward(request,response);
4、 網頁中
14 請求轉發與重定向有何區別?
請求轉發:伺服器行為,request.getRequsetDispatcher().forward(requset,response);是一次請求,轉發後請求物件會儲存,位址列的URL地址不會改變。(伺服器內部轉發,所有客戶端看不到位址列的改變)
重定向:客戶端行為,response.sendRedirect(),從本質上講等同於兩次請求,前一次的請求物件不會保持,位址列的URL地址會改變。
(1) 位址列中是否發生變化?
請求轉發地址不改變
(2) 哪個可以攜帶請求引數?
請求轉發可以攜帶
深入細解:
HTTP中的重定向和請求轉發的區別
一、呼叫方式
我們知道,在servlet中呼叫轉發、重定向的語句如下:
request.getRequestDispatcher("new.jsp").forward(request, response);
//轉發到new.jsp
response.sendRedirect("new.jsp"); //重定向到new.jsp
在jsp頁面中你也會看到通過下面的方式實現轉發:
<jsp:forward page="apage.jsp" />
當然也可以在jsp頁面中實現重定向:
<%response.sendRedirect("new.jsp"); %> //重定向到new.jsp
二、本質區別
解釋一 一句話,轉發是伺服器行為,重定向是客戶端行為。為什麼這樣說呢,這就要看兩個動作的工作流程:
轉發過程:客戶瀏覽器傳送http請求——》web伺服器接受此請求——》呼叫內部的一個方法在容器內部完成請求處理和轉發動作——》將目標資源傳送給客戶;在這裡,轉發的路徑必須是同一個web容器下的url,其不能轉向到其他的web路徑上去,中間傳遞的是自己的容器內的request。在客戶瀏覽器路徑欄顯示的仍然是其第一次訪問的路徑,也就是說客戶是感覺不到伺服器做了轉發的。轉發行為是瀏覽器只做了一次訪問請求。
重定向過程:客戶瀏覽器傳送http請求——》web伺服器接受後傳送302狀態碼響應及對應新的location給客戶瀏覽器——》客戶瀏覽器發現是302響應,則自動再發送一個新的http請求,請求url是新的location地址——》伺服器根據此請求尋找資源併發送給客戶。在這裡location可以重定向到任意URL,既然是瀏覽器重新發出了請求,則就沒有什麼request傳遞的概念了。在客戶瀏覽器路徑欄顯示的是其重定向的路徑,客戶可以觀察到地址的變化的。重定向行為是瀏覽器做了至少兩次的訪問請求的。
解釋二
重定向,其實是兩次request 第一次,客戶端request A,伺服器響應,並response回來,告訴瀏覽器,你應該去B。這個時候IE可以看到地址變了,而且歷史的回退按鈕也亮了。重定向可以訪問自己web應用以外的資源。在重定向的過程中,傳輸的資訊會被丟失。
例子:
response.sendRedirect("loginsuccess.jsp");
請求轉發是伺服器內部把對一個request/response的處理權,移交給另外一個對於客戶端而言,它只知道自己最早請求的那個A,而不知道中間的B,甚至C、D。傳輸的資訊不會丟失。
例子:
RequestDispatcher dis=request.getRequestDispatcher(“loginsuccess.jsp”);
Dis.forward(request,response);
解釋三
假設你去辦理某個執照
重定向:你先去了A局,A局的人說:“這個事情不歸我們管,去B局”,然後,你就從A退了出來,自己乘車去了B局。
轉發:你先去了A局,A局看了以後,知道這個事情其實應該B局來管,但是他沒有把你退回來,而是讓你坐一會兒,自己到後面辦公室聯絡了B的人,讓他們辦好後,送了過來。
15 如何確定用請求轉發還是重定向?
瞭解上述詳細內容後,對於簡單的問題,一般可遵循這個原則:
(1)在服務中,對於一般的查詢性質的,用請求轉發,其他的多數時候用重定向(到本服務,執行本servlet中的某個服務)
(2)如果需要傳遞引數,除了使用者登入賬號、密碼等可以用cookie (response.sendRedirect();request.getSession())進行設定,其他一般的用請求轉發;
(3) 不需要傳遞引數的,一般為重定向;
16 頁面轉換,如何準確使用絕對路徑和相對路徑?
"/" 表示根目錄,也就是專案中
"../" 表示到上一級目錄
在jsp頁面中,為了防止因為絕對路徑因檔案移動等產生問題,一般都會使用相對路徑,而不是絕對路徑,基本上在所有的jsp的介面中都加入類似這種相對路徑的引用語句,當然如下,還可以進行適當的修改
第一句利用請求物件request 獲取當前路徑的getContextPath();
第二句 request.getScheme() 返回當前連結使用的協議;比如,一般應用返回http;SSL返回https;
複習一下request 的常用方法:
request.getSchema()可以返回當前頁面使用的協議,http 或是 https;
request.getServerName()可以返回當前頁面所在的伺服器的名字;
request.getServerPort()可以返回當前頁面所在的伺服器使用的埠,就是80;
request.getContextPath()可以返回當前頁面所在的應用的名字;
<%
String path = request.getContextPath();
String basePath=request.getScheme()+"://"+request.getServerName()+":"+
request.getServerPort()+path+"/";
%>
而在<head></head>標籤內部通過以下方式引用
<base href="<%=basePath%>">
17 如何修改tomcat配置,解決中文亂碼問題?
在開發過程中,遇到中文亂碼的問題。以前的解決辦法是:用JAVA程式碼進行轉換,今天請教了一下公司的高手,給出的解決方案是:修改Tomcat的配置檔案也可以解決這個問題。
具體的解決方案是:
1.在Tomcat目錄下找到server.xml檔案,找到程式碼:
<Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
2. 把上面的程式碼註釋掉,用下面的程式碼代替:
<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/>
3. 注意Tomcat的埠號,我的Tomcat的埠品號是 80,所以 port="80"。請你修改成你自己的Tomcat的埠號。
18 如何修改eclipse 或者myeclipse 中的字符集問題?
開啟windows——> preferences——>general——>workSpace
19 如何設定eclipse 或者myeclipse 中自動提示資訊功能?
開啟windows——> preferences——>Java——>editors
開啟windows——> preferences——>xml——>editors
20 單元測試:
注意:測試用例是用來達到測試想要的預期結果,而不能測試出程式的邏輯錯誤。
①測試方法上必須使用@Test進行修飾
②測試方法必須使用public void 進行修飾,不能帶任何的引數
③新建一個原始碼目錄來存放我們的測試程式碼,即將測試程式碼和專案業務程式碼分開
④測試類所在的包名應該和被測試類所在的包名保持一致
⑤測試單元中的每個方法必須可以獨立測試,測試方法間不能有任何的依賴
⑥測試類使用Test作為類名的字尾(不是必須)
⑦測試方法使用test作為方法名的字首(不是必須)
2.JUnit常用註解
* @Test:將一個普通的方法修飾成為一個測試方法
@Test(expected=XX.class)
@Test(timeout=毫秒)
* @BeforeClass:它會在所有的方法執行前被執行,static修飾
* @AfterClass:它會在所有的方法執行結束後被執行,static修飾
* @Before:會在每一個測試方法被執行前執行一次
* @After:會在每一個測試方法執行後被執行一次
* @Ignore:所修飾的測試方法會被測試執行器忽略
* @RunWith:可以更改測試執行器 org.junit.runner.Runner
1.1 測試程式碼和專案程式碼分開
結構應如下:包名要一致;最好以Test作為測試類字尾;最好以test作為測試方法字首。
在Java中,一般是建立一個與src同層次的資原始檔夾,命名為test 在其中建立和src中一樣的包名,並且建立和src中相應包下相同的類,只是鑑於習慣,會將這裡的類名命名為在原類名基礎上加個Test而已
在測試類裡,假設測試src資料夾下,com.examlple.dao 包下 StudentDao 類中的public int add(Student student),方法,則需要寫的就是
在專案中與src同層,建立一個test 資原始檔夾,其中建立一個com.example.dao 包,在包中建立一個StudentDaoTest類, 類中寫入
@Test //註解,必須寫
public void testadd(){ //方法必須以public void 修飾,加方法名其中,不得帶任何引數
Student stu=new Student(); //因為被測試的方法需要一個引數
stu.setid="小明";
StudentDao dao=new StudentDao();
int abc=dao.add(stu);
Assert.assertEquals(3,abc); //呼叫該方法 斷言 第一個引數是預期值,第二個引數是實際測驗值
}
21 sql語句防注入如何做?
22 sql 基本語句:
原則:
---先在主表新增資料,再在子表新增資料
---先刪除子表資料,再刪除主表資料
查詢語句:
-select<*|列名,...列名> from 表名 where 條件1 and 條件2......
例:
select t.*, t.rowid from student t
select *from student
select name,id from student
select name "姓名",id as 編號 from student
select * from student where id ='U003'--等值條件查詢
select * from student where name like '孫%'--模糊查詢,查詢孫開頭的
select * from student where name like '%悟%'
select * from student where name like '_悟_'
select * from student where name like '_悟_'and site like '222%'
select * from student where name like '_悟_'or phone like '%888%'
select * from student where id='U002'or ID='u005'or id='U004'
select * from student where id in('U002','u005','U004')
新增語句:
nsert into 表名(欄位名1,欄位名2,...,欄位名n) values(引數值1,引數值2,...引數值n);
insert into student (id,name,age,phone,gender,email,site,address) values ('U010','李四',22,'44444','男','[email protected]','555.com','四海');
修改語句:
update 表名 set 欄位名1=引數值,欄位名2=引數值,..where 條件
update 表名 set 欄位名1=引數值,欄位名2=引數值,..where 欄位名i=引數值i
update student set name='111',phone='110' where name like '_悟_'
刪除語句:
delete from 表名 where 條件;
delete from score where student_id='U001';
23